Collision falksalt::collides(glm::vec4 rect, glm::vec2 start, glm::vec2 end) { std::vector<Collision> collisions(4); collisions[0] = intersects(start, end, rect.xy(), rect.xy() + glm::vec2(rect.z, 0)); collisions[0].side = Side::Up; collisions[1] = intersects(start, end, rect.xy() + glm::vec2(0, rect.w), rect.xy() + rect.zw()); collisions[1].side = Side::Down; collisions[2] = intersects(start, end, rect.xy(), rect.xy() + glm::vec2(0, rect.w)); collisions[2].side = Side::Left; collisions[3] = intersects(start, end, rect.xy() + glm::vec2(rect.z, 0), rect.xy() + rect.zw()); collisions[3].side = Side::Right; return closest(start, collisions); }
void TextEngineRenderer::Render() { GameState ¤t_state = updater.GetCurrentState(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); PushMatrix(); matrix_stack.back() *= glm::scale(glm::mat4(1), glm::vec3(glm::vec2(current_state.zoom * 0.1f), 1.0f)); matrix_stack.back() *= glm::translate(glm::mat4(1), glm::vec3(-current_state.camera_position, 0)); const glm::vec2 position = glm::vec2(current_state.player_body->GetPosition().x, current_state.player_body->GetPosition().y); fill = glm::vec4(0.0f, 0.5f, 0.3f, 0.5f); for (const auto &area : scene.areas) { if (area->invisible) { continue; } if (Shape::kAxisAlignedBoundingBox == area->shape) { DrawAxisAlignedBoundingBox(area->aabb); } else { DrawCircle(area->aabb.center(), area->aabb.radius()); } } fill = glm::vec4(1.0f, 0.0f, 0.0f, 0.5f); for (const auto &object : scene.objects) { if (object->invisible) { continue; } if (Shape::kAxisAlignedBoundingBox == object->shape) { DrawAxisAlignedBoundingBox(object->aabb); } else { DrawCircle(object->aabb.center(), object->aabb.radius()); } } const glm::mat4 normalized_to_reversed = glm::scale(glm::mat4(), glm::vec3(1.0f, -1.0f, 1.0f)); const glm::mat4 reversed_to_offset = glm::translate(glm::mat4(), glm::vec3(glm::vec2(1.0f), 0.0f)); const glm::mat4 offset_to_screen = glm::scale(glm::mat4(), glm::vec3(glm::vec2(0.5f), 1.0f)); const glm::mat4 screen_to_window = glm::scale(glm::mat4(), glm::vec3(width, height, 1.0f)); const glm::mat4 transform = (screen_to_window * offset_to_screen * reversed_to_offset * normalized_to_reversed * model_view * projection * matrix_stack.back()); const glm::mat4 transform2 = (screen_to_window * offset_to_screen * reversed_to_offset * model_view * projection * matrix_stack.back()); const auto inverse = glm::inverse(transform2); const glm::vec4 homogeneous = transform * glm::vec4(position, 0.0f, 1.0f); const glm::vec2 transformed = homogeneous.xy() / homogeneous.w; fill = glm::vec4(0.5f, 0.5f, 0.6f, 1.0f); PushMatrix(); matrix_stack.back() *= glm::translate(glm::mat4(1), glm::vec3(position, 0)); matrix_stack.back() *= glm::rotate(glm::mat4(1), current_state.player_body->GetAngle(), glm::vec3(0, 0, 1)); DrawRectangle(glm::vec2(0), glm::vec2(0.25f, 0.5f)); PopMatrix(); PopMatrix(); if (edit) { MaybeRebuildAttenuationShader(); if (current_state.selected_item) { attenuation3_program.Use(); attenuation3_program.Uniforms({ {u8"model_view_inverse", &inverse} }); const auto isaabb3 = Shape::kAxisAlignedBoundingBox == current_state.selected_item->shape; glUniform1i(attenuation3_program.GetUniformLocation(u8"selected_isaabb"), isaabb3); if (Shape::kAxisAlignedBoundingBox == current_state.selected_item->shape) { attenuation3_program.Uniforms({ {u8"selected_minimum_or_center", current_state.selected_item->aabb.minimum}, {u8"selected_maximum_or_radius", current_state.selected_item->aabb.maximum}, }); CHECK_STATE(!glGetError()); } else { attenuation3_program.Uniforms({ {u8"selected_minimum_or_center", current_state.selected_item->aabb.center()}, {u8"selected_maximum_or_radius", glm::vec2(current_state.selected_item->aabb.radius())}, }); CHECK_STATE(!glGetError()); } const auto attenuation3_coefficients = glm::vec3( current_state.selected_item->base_attenuation, current_state.selected_item->linear_attenuation, current_state.selected_item->quadratic_attenuation); attenuation3_program.Uniforms({ {u8"selected_attenuation", attenuation3_coefficients}, }); const auto color3 = glm::vec4(0, 0, 0, 0.125); attenuation3_program.Uniforms({ {u8"color", color3} }); attenuation_array.Bind(); glDrawArrays(attenuation.element_type, 0, attenuation.element_count); CHECK_STATE(!glGetError()); attenuation_program.Use(); attenuation_program.Uniforms({ {u8"model_view_inverse", &inverse} }); const auto isaabb = Shape::kAxisAlignedBoundingBox == current_state.selected_item->shape; glUniform1i(attenuation_program.GetUniformLocation(u8"selected_isaabb"), isaabb); if (Shape::kAxisAlignedBoundingBox == current_state.selected_item->shape) { attenuation_program.Uniforms({ {u8"selected_minimum_or_center", current_state.selected_item->aabb.minimum}, {u8"selected_maximum_or_radius", current_state.selected_item->aabb.maximum}, }); CHECK_STATE(!glGetError()); } else { attenuation_program.Uniforms({ {u8"selected_minimum_or_center", current_state.selected_item->aabb.center()}, {u8"selected_maximum_or_radius", glm::vec2(current_state.selected_item->aabb.radius())}, }); CHECK_STATE(!glGetError()); } const auto attenuation_coefficients = glm::vec3( current_state.selected_item->base_attenuation, current_state.selected_item->linear_attenuation, current_state.selected_item->quadratic_attenuation); attenuation_program.Uniforms({ {u8"selected_attenuation", attenuation_coefficients}, }); const auto color = glm::vec4(0, 0, 0, 0.5); attenuation_program.Uniforms({ {u8"color", color} }); attenuation_array.Bind(); glDrawArrays(attenuation.element_type, 0, attenuation.element_count); CHECK_STATE(!glGetError()); } } const auto mouse_position = 2.0f * mouse.get_cursor_position(); unsigned char mouse_buttons = 0; if (mouse.IsButtonDown(GLFW_MOUSE_BUTTON_1)) { mouse_buttons |= IMGUI_MBUT_LEFT; } if (mouse.IsButtonDown(GLFW_MOUSE_BUTTON_2)) { mouse_buttons |= IMGUI_MBUT_RIGHT; } if (edit) { imguiBeginFrame(mouse_position.x, height - mouse_position.y, mouse_buttons, 0); for (auto &area : scene.areas) { const glm::vec4 homogeneous = transform * glm::vec4(area->aabb.minimum.x, area->aabb.maximum.y, 0.0f, 1.0f); const glm::vec2 transformed = homogeneous.xy() / homogeneous.w; imguiDrawText(transformed.x, height - transformed.y, IMGUI_ALIGN_LEFT, area->name.c_str(), imguiRGBA(0, 0, 0)); } for (auto &object : scene.objects) { const glm::vec4 homogeneous = transform * glm::vec4(object->aabb.minimum.x, object->aabb.maximum.y, 0.0f, 1.0f); const glm::vec2 transformed = homogeneous.xy() / homogeneous.w; imguiDrawText(transformed.x, height - transformed.y, IMGUI_ALIGN_LEFT, object->name.c_str(), imguiRGBA(0, 0, 0)); } if (current_state.selected_item) { std::ostringstream name, constant, linear, quadratic; name << current_state.selected_item->name; imguiDrawText(10, height - 50, IMGUI_ALIGN_LEFT, name.str().c_str(), imguiRGBA(0, 0, 0)); constant << "c: " << current_state.selected_item->base_attenuation; imguiDrawText(10, height - 75, IMGUI_ALIGN_LEFT, constant.str().c_str(), imguiRGBA(0, 0, 0)); linear << "l: " << current_state.selected_item->linear_attenuation; imguiDrawText(10, height - 100, IMGUI_ALIGN_LEFT, linear.str().c_str(), imguiRGBA(0, 0, 0)); quadratic << "q: " << current_state.selected_item->quadratic_attenuation << std::endl; imguiDrawText(10, height - 125, IMGUI_ALIGN_LEFT, quadratic.str().c_str(), imguiRGBA(0, 0, 0)); } imguiEndFrame(); } imguiRenderGLDraw(width, height); }