Commit 03e8e848 authored by Georg Schaefer's avatar Georg Schaefer
Browse files

Merge branch 'develop' into feature/particle_system

parents 0476fd60 208c4ad1
title : GDW
title : GDW
borderless : false
fullscreen : false
width : 800
......@@ -15,11 +15,24 @@ camAngle : -50
victim_damping : 1
victim_mass : 1
map_load_timer : 0
test_ui : false
mapGenDebug : false
player_move_left_key : A
player_move_left_key2 : Left
player_move_left_cbutton : LEFT
player_move_left_caxis : RIGHTX
player_move_right_key : D
beam_normal_mouse : Left
beam_inverse_mouse : Right
player_move_right_key2 : Right
player_move_right_cbutton : RIGHT
player_move_right_caxis : RIGHTX
beam_normal_key : Q
beam_normal_mbutton : Left
beam_normal_caxis : LEFTTRIGGER
beam_inverse_key : E
beam_inverse_mbutton : Right
beam_inverse_caxis : RIGHTTRIGGER
place_item_key : Space
state_switch_key : Esc
test_ui : false
place_item_mbutton : Middle
place_item_cbutton : A
state_switch_key : Escape
state_switch_cbutton : START
......@@ -6,6 +6,7 @@
namespace gdw {
class engine;
class ray;
class game_input_manager {
public:
......@@ -15,6 +16,8 @@ public:
void update(float dt);
glm::vec3 get_world_mouse_pos();
void render_ray(ray* r, float length, float radius, glm::vec3 color);
void process_beam_collision(ray& r, glm::vec3 &ray_unnormalized, float &beam_velocity, float &ray_length_, bool &asteroid_hit, int &portal_type, float &remaining_ray_length);
private:
void handle_key_input(float dt);
void handle_mouse_input(float dt);
......
......@@ -6,7 +6,6 @@ enum item_type {
magnet_field,
emp,
accelerator,
portal,
type_count
};
......
......@@ -7,9 +7,29 @@
#include <ecs/entity.hpp>
#include <time.h>
#include <rendering/staticmesh_component.hpp>
#include <vector>
namespace gdw {
struct accelerator_type {
accelerator_type(){}
accelerator_type(unsigned long long m, unsigned long long l, unsigned long long r):
main(m), left(l), right(r), alive_timer(0.f){}
unsigned long long main;
unsigned long long left;
unsigned long long right;
float alive_timer;
};
struct emp_type {
emp_type(){}
emp_type(unsigned long long m):
main(m), alive_timer(0.f){}
unsigned long long main;
float alive_timer;
};
class player_item_manager {
public:
player_item_manager(engine& engine);
......@@ -22,9 +42,14 @@ public:
srand(time(0) * time(0));
equipped_item_ = static_cast<item_type>(rand() % 4);
}
void update(float dt);
private:
engine& engine_;
item_type equipped_item_;
std::vector<accelerator_type*> accelerators_;
std::vector<emp_type*> emps_;
};
} //Namespace gdw
......
......@@ -5,6 +5,7 @@
#include <memory>
#include <glm/glm.hpp>
#include <mapgen/maploader.hpp>
#include <gameplay/weapon_type.h>
namespace gdw {
......@@ -26,6 +27,9 @@ public:
entity* player();
entity* camera();
entity* cannon();
entity* blue_portal();
entity* yellow_portal();
void create_victim(float z);
void update(float dt);
......@@ -33,11 +37,19 @@ public:
void create_asteroid(glm::vec3 pos, std::string mesh_name, float scale, glm::vec3 rotation);
void create_item(glm::vec3 pos, int type);
void destroy_victim(glm::vec3 item_spawn_pos, unsigned long long id);
void destroy_all_victims();
void destroy_all_asteroids();
maploader& get_maploader() {return maploader_;}
weapon_type weapon() {return weapon_type_;}
void set_weapon(weapon_type type) {weapon_type_ = type;}
void create_blue_portal(glm::vec3 world_pos);
void create_yellow_portal(glm::vec3 world_pos);
bool level_build() {return is_level_build_;}
private:
engine& engine_;
std::vector<unsigned long long> victims_;
......@@ -49,12 +61,19 @@ private:
unsigned long long cannon_;
unsigned long long deathstar_;
unsigned long long blue_portal_;
unsigned long long yellow_portal_;
std::vector<glm::vec3> items_to_create;
//Player Attributes
const float player_speed_;
weapon_type weapon_type_;
maploader maploader_;
float map_load_timer_;
bool is_level_build_;
};
} //Namespace gdw
......
#ifndef __WEAPON_TYPE__
#define __WEAPON_TYPE__
enum class weapon_type {
tractor_beam,
portal_gun
};
#endif
......@@ -25,8 +25,8 @@ namespace gdw{
bool active = false;
};
//if you add here, add also a maping in makeMaping() in input.cpp
enum class inputMaping {
//if you add here, add also a mapping in makeMapping() in input.cpp
enum class inputMapping {
state_switch,
player_move_left,
player_move_right,
......@@ -35,19 +35,14 @@ namespace gdw{
place_item
};
enum class inputType{
key,
mouse,
controller_button,
key_and_controller_button/*,
controller_axis*/
};
struct inputMapingStruct {
inputType type;
SDL_Keycode keyCode;
int mouseCode;
SDL_GameControllerButton controllerCode;
struct inputMappingStruct {
unsigned int type = 0;
bool negativAxis = false;
SDL_Keycode keyCode1 = 0;
SDL_Keycode keyCode2 = 0;
int mbuttonCode = -1;
SDL_GameControllerButton cbuttonCode = SDL_CONTROLLER_BUTTON_INVALID;
SDL_GameControllerAxis caxisCode = SDL_CONTROLLER_AXIS_INVALID;
};
class engine;
......@@ -56,6 +51,16 @@ namespace gdw{
std::string controllerDBPath_ = "input/gamecontrollerdb.txt";
static float constexpr controllerAxisMax_ = 32767.f;
static float constexpr controllerAxisDeadZone_ = .3f;
/**inputMappingStruct.type for key*/
static unsigned int constexpr key1 = 0x01;
static unsigned int constexpr key2 = 0x02;
/**inputMappingStruct.type for mouse button*/
static unsigned int constexpr mbutton = 0x04;
/**inputMappingStruct.type for controller button*/
static unsigned int constexpr cbutton = 0x08;
/**inputMappingStruct.type for controller axis*/
static unsigned int constexpr caxis = 0x10;
public:
input(engine& engine);
~input();
......@@ -68,42 +73,41 @@ namespace gdw{
* should called once per game loop, at the end*/
void reset();
/**Returns true every frame, as long as it is down - NOT FOR MULTI CONTROLLER*/
bool isPressed(inputMapping id);
/**Returns true once it is pressed - NOT FOR MULTI CONTROLLER*/
bool isDown(inputMapping id);
/**Returns true once it is released - NOT FOR MULTI CONTROLLER*/
bool isReleased(inputMapping id);
/**Returns true every frame, as long as the key is down.*/
private:
int isKeyDown(SDL_Keycode key) noexcept {return keyState_[SDL_GetScancodeFromKey(key)];};
public:
int isKeyDown(inputMaping key) noexcept {return isKeyDown(getKeyCodeByMaping(key));};
int isKeyDown(inputMapping key) noexcept {return isKeyDown(getKeyCodeByMapping(key, 1)) || isKeyDown(getKeyCodeByMapping(key, 2));};
/**Returns true once the key is pressed*/
private:
bool isKeyPressed(SDL_Keycode key) noexcept {return keyMap_[key]==1;};
public:
bool isKeyPressed(inputMaping key) noexcept {return isKeyPressed(getKeyCodeByMaping(key));};
bool isKeyPressed(inputMapping key) noexcept {return isKeyPressed(getKeyCodeByMapping(key, 1)) || isKeyPressed(getKeyCodeByMapping(key, 2));};
/**Returns true once the key is released*/
private:
bool isKeyReleased(SDL_Keycode key) noexcept {return keyReleasedMap_[key] && !keyState_[SDL_GetScancodeFromKey(key)];};
public:
bool isKeyReleased(inputMaping key) noexcept {return isKeyReleased(getKeyCodeByMaping(key));};
bool isKeyReleased(inputMapping key) noexcept {return isKeyReleased(getKeyCodeByMapping(key, 1)) || isKeyReleased(getKeyCodeByMapping(key, 2));};
/**Returns true every frame, as long as the mouse button is down.*/
private:
bool isMouseButtonDown(int button) noexcept {return SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(button);};
public:
bool isMouseButtonDown(inputMaping button);
bool isMouseButtonDown(inputMapping button);
/**Returns true once the mouse button is pressed*/
private:
bool isMouseButtonPressed(int button) noexcept {return mouseMap_[button]==1;};
public:
bool isMouseButtonPressed(inputMaping button);
bool isMouseButtonPressed(inputMapping button);
/**Returns true once the mouse button is released*/
private:
bool isMouseButtonReleased(int button) noexcept {return mouseReleasedMap_[button];};
public:
bool isMouseButtonReleased(inputMaping button);
bool isMouseButtonReleased(inputMapping button);
public:
/**Returns a glm::vec2 with the x and y motion of the mouse wheel
* y is the motion a nomal mouse wheel can perform*/
glm::vec2 mouseWheel()noexcept{return mousePos_;};
......@@ -124,20 +128,28 @@ namespace gdw{
int mousePosY()noexcept{return mousePos_.y;};
/**Returns true every frame, as long as the controller button is down.*/
private:
bool isControllerButtonDown(SDL_GameControllerButton button, int nr = 0);
bool isControllerButtonDown(inputMaping button, int nr = 0) noexcept {return isControllerButtonDown(getControllerButtonCodeByMaping(button), nr);};
public:
bool isControllerButtonDown(inputMapping button, int nr = 0) noexcept {return isControllerButtonDown(getCButtonCodeByMapping(button), nr);};
/**Returns true once the controller button is pressed*/
private:
bool isControllerButtonPressed(SDL_GameControllerButton button, int nr = 0);
bool isControllerButtonPressed(inputMaping button, int nr = 0) noexcept {return isControllerButtonPressed(getControllerButtonCodeByMaping(button), nr);};
public:
bool isControllerButtonPressed(inputMapping button, int nr = 0) noexcept {return isControllerButtonPressed(getCButtonCodeByMapping(button), nr);};
/**Returns true once the controller button is released*/
private:
bool isControllerButtonReleased(SDL_GameControllerButton button, int nr = 0);
bool isControllerButtonReleased(inputMaping button, int nr = 0) noexcept {return isControllerButtonReleased(getControllerButtonCodeByMaping(button), nr);};
public:
bool isControllerButtonReleased(inputMapping button, int nr = 0) noexcept {return isControllerButtonReleased(getCButtonCodeByMapping(button), nr);};
/**Returns the value of that axis as a float between -1 and 1*/
private:
float controllerAxis(SDL_GameControllerAxis axis, int nr = 0);
//float controllerAxis(inputMaping axis, int nr = 0) noexcept {return getControllerAxisCodeByMaping(getControllerAxisCodeByMaping(axis), nr);};
public:
float controllerAxis(inputMapping axis, int nr = 0) noexcept {return controllerAxis(getCAxisCodeByMapping(axis), nr);};
/**Returns number of aktiv controllers*/
int controllerCount() noexcept {return controllers_.size();};
......@@ -148,15 +160,19 @@ namespace gdw{
std::shared_ptr<const asset> controllerDB_;
std::unordered_map<int, controller> controllers_;
std::map<gdw::inputMaping, gdw::inputMapingStruct> mapings_;
void makeMapings();
void addMaping(inputMaping id, inputType type, SDL_Keycode keyCode = -1, int mouseCode = -1, SDL_GameControllerButton controllerCode = SDL_CONTROLLER_BUTTON_INVALID);
SDL_Keycode getKeyCodeByMaping(inputMaping id);
int getMouseButtonCodeByMaping(inputMaping id);
SDL_GameControllerButton getControllerButtonCodeByMaping(inputMaping id);
SDL_GameControllerAxis getControllerAxisCodeByMaping(inputMaping id);
int getMouseButtonFromName(std::string name);
std::map<gdw::inputMapping, gdw::inputMappingStruct> mappings_;
void makeMappings();
bool isMappingOk(inputMappingStruct mapping, std::string name);
SDL_Keycode getKeyCodeByMapping(inputMapping id, int nr);
int getMButtonCodeByMapping(inputMapping id);
SDL_GameControllerButton getCButtonCodeByMapping(inputMapping id);
SDL_GameControllerAxis getCAxisCodeByMapping(inputMapping id);
int getMButtonFromName(std::string name);
SDL_Keycode getKeyFromName(std::string name);
SDL_GameControllerButton getCButtonFromName(std::string name);
SDL_GameControllerAxis getCAxisFromName(std::string name);
controller controller_;
engine &engine_;
......@@ -185,30 +201,30 @@ namespace gdw{
//CONTROLLER
void controllerUp(const SDL_ControllerButtonEvent &e);
void controllerDown(const SDL_ControllerButtonEvent &e);
void controllerAdd(const SDL_ControllerDeviceEvent &e);
void controllerRemove(const SDL_ControllerDeviceEvent &e);
void controllerRemapped(const SDL_ControllerDeviceEvent &e);
void controllerAxis(const SDL_ControllerAxisEvent &e);
void controllerAdded(const SDL_ControllerDeviceEvent &e);
void controllerRemoved(const SDL_ControllerDeviceEvent &e);
void controllerRemapped(const SDL_ControllerDeviceEvent &e) noexcept {log << "[input] controllerRemapped was triggerd but is not handelt" << std::endl;};
void controllerAxis(const SDL_ControllerAxisEvent &e) noexcept {/*handelt on another way, see: float controllerAxis(SDL_GameControllerAxis axis, int nr)*/};
//TEXTINPUT
void textEdit(const SDL_TextEditingEvent &e);
void textInput(const SDL_TextInputEvent &e);
void textEdit(const SDL_TextEditingEvent &e) noexcept {log << "[input] textInput was triggerd but is not handelt" << std::endl;};
void textInput(const SDL_TextInputEvent &e) noexcept {/*spams the log on every key input - not handelt*/};
//TOUCH
void touchMotion(const SDL_TouchFingerEvent &e);
void touchDown(const SDL_TouchFingerEvent &e);
void touchUp(const SDL_TouchFingerEvent &e);
void touchGesture(const SDL_MultiGestureEvent &e);
void touchComplexGesture(const SDL_DollarGestureEvent &e);
void touchGestureRecord(const SDL_DollarGestureEvent &e);
void touchMotion(const SDL_TouchFingerEvent &e) noexcept {log << "[input] touchMotion was triggerd but is not handelt" << std::endl;};
void touchDown(const SDL_TouchFingerEvent &e) noexcept {log << "[input] touchDown was triggerd but is not handelt" << std::endl;};
void touchUp(const SDL_TouchFingerEvent &e) noexcept {log << "[input] touchUp was triggerd but is not handelt" << std::endl;};
void touchGesture(const SDL_MultiGestureEvent &e) noexcept {log << "[input] touchGesture was triggerd but is not handelt" << std::endl;};
void touchComplexGesture(const SDL_DollarGestureEvent &e) noexcept {log << "[input] touchComplexGesture was triggerd but is not handelt" << std::endl;};
void touchGestureRecord(const SDL_DollarGestureEvent &e) noexcept {log << "[input] touchGestureRecord was triggerd but is not handelt" << std::endl;};
//JOYSTICK
void joyAdded(const SDL_JoyDeviceEvent &e);
void joyRemoved(const SDL_JoyDeviceEvent &e);
void joyHat(const SDL_JoyHatEvent &e);
void joyDown(const SDL_JoyButtonEvent &e);
void joyUp(const SDL_JoyButtonEvent &e);
void joyBall(const SDL_JoyBallEvent &e);
void joyAxis(const SDL_JoyAxisEvent &e);
void joyAdded(const SDL_JoyDeviceEvent &e) noexcept {/*controllerAdded*/};
void joyRemoved(const SDL_JoyDeviceEvent &e) noexcept {/*controllerRemoved*/};
void joyHat(const SDL_JoyHatEvent &e) noexcept {/*controllerDown / controllerUp*/};
void joyDown(const SDL_JoyButtonEvent &e) noexcept {/*controllerDown*/};
void joyUp(const SDL_JoyButtonEvent &e) noexcept {/*controllerUp*/};
void joyBall(const SDL_JoyBallEvent &e) noexcept {log << "[input] joyBall was triggerd but is not handelt" << std::endl;};
void joyAxis(const SDL_JoyAxisEvent &e) noexcept {/*controllerAxis*/};
//DROP
void drop(const SDL_DropEvent &e);
void drop(const SDL_DropEvent &e) noexcept {log << "[input] drop was triggerd but is not handelt" << std::endl;};
};
}
......
......@@ -11,6 +11,8 @@ namespace gdw {
class engine;
class movement_component;
class collision_component;
class sphere;
class ray;
class physics_system {
public:
......
......@@ -43,12 +43,12 @@ namespace gdw {
}
void AudioEventHandler::playStateUpdate(float deltaTime) {
if ((this->engine.input().isKeyPressed(inputMaping::player_move_left) || this->engine.input().isKeyPressed(inputMaping::player_move_right)) && !this->playerMoving) {
if ((this->engine.input().isPressed(inputMapping::player_move_left) || this->engine.input().isPressed(inputMapping::player_move_right)) && !this->playerMoving) {
this->channels["ship"] = this->engine.audio().queue_sound("engine", -1);
this->engine.audio().sound_volume(40, this->channels["ship"]);
this->playerMoving = true;
}
if (!this->engine.input().isKeyDown(inputMaping::player_move_left) && !this->engine.input().isKeyDown(inputMaping::player_move_right) && this->playerMoving) {
if (!this->engine.input().isDown(inputMapping::player_move_left) && !this->engine.input().isDown(inputMapping::player_move_right) && this->playerMoving) {
this->engine.audio().stop_sound(this->channels["ship"], 600);
this->playerMoving = false;
}
......
......@@ -21,7 +21,7 @@ void menu_state::on_enter() {
}
void menu_state::update(float dt) {
if (this->engine_.input().isKeyPressed(inputMaping::state_switch))
if (this->engine_.input().isPressed(inputMapping::state_switch))
this->engine_.game_state_machine().change_state<play_state>();
}
......
......@@ -44,7 +44,8 @@ play_state::~play_state() {}
void play_state::on_enter() {
this->engine_.audioEventHandler().trigger(AudioEventHandler::PLAY_STATE_ENTER);
engine_.game_play_system().level_manager().build_stage();
if(!engine_.game_play_system().level_manager().level_build())
engine_.game_play_system().level_manager().build_stage();
if (this->engine_.getConfig().get<bool>("test_ui", "")) {
auto w1 = engine_.ui_system().add_widget<box_widget>(100,100,500,500,glm::vec4(0.7,0.2,0.1,0.6));
auto w2 = w1->add_widget<box_widget>(100,100,500,500,glm::vec4(0.2,0.2,0.1,0.6));
......@@ -57,8 +58,7 @@ void play_state::update(float dt) {
engine_.game_play_system().update(dt);
this->engine_.audioEventHandler().playStateUpdate(dt);
if (this->engine_.input().isKeyPressed(inputMaping::state_switch))
if (this->engine_.input().isPressed(inputMapping::state_switch))
this->engine_.game_state_machine().change_state<menu_state>();
}
......
......@@ -9,6 +9,7 @@
#include <rendering/staticmesh_component.hpp>
#include <rendering/camera_component.hpp>
#include <physics/collision/ray.h>
#include <physics/collision/sphere.h>
#include <physics/physics_system.h>
#include <graphics/graphics_system.hpp>
#include <audio/audio.hpp>
......@@ -17,14 +18,13 @@
#include <audio/AudioEventHandler.hpp>
#include <util/logger.hpp>
#include <gameplay/item/player_item_manager.h>
#include <physics/collision/collision_component.h>
namespace gdw {
const float game_input_manager::maximum_movement_distance = 13.0f;
game_input_manager::game_input_manager(engine& engine):engine_(engine) {
}
game_input_manager::~game_input_manager() {
......@@ -76,11 +76,7 @@ namespace gdw {
constexpr float rotation_speed = 7.f;
constexpr float turn_rate_modifier = 4.5f;
if(input.isKeyPressed(inputMaping::place_item)){
log << "place_item" << std::endl;
}
if (input.isKeyDown(inputMaping::player_move_left) && player->position().x > -maximum_movement_distance) {
if (input.isDown(inputMapping::player_move_left) && player->position().x > -maximum_movement_distance) {
auto orientation = player->rotation()*glm::vec3(0,0,1);
auto diff = std::abs(orientation.x - (-1.f)) + std::abs(orientation.z - (0.f));
auto clamped = glm::clamp(diff/turn_rate_modifier, 0.f, 1.f);
......@@ -93,7 +89,7 @@ namespace gdw {
move->add_angular_force(glm::vec3(0.f, -rotation_speed*(std::pow(diff, 1.4f)) , 0.f));
}
if (engine_.input().isKeyDown(inputMaping::player_move_right) && player->position().x < maximum_movement_distance) {
if (engine_.input().isDown(inputMapping::player_move_right) && player->position().x < maximum_movement_distance) {
auto orientation = player->rotation()*glm::vec3(0,0,1);
auto diff = std::abs(orientation.x - (1.f)) + std::abs(orientation.z - (0.f));
auto clamped = glm::clamp(diff/turn_rate_modifier, 0.f, 1.f);
......@@ -107,7 +103,7 @@ namespace gdw {
}
// SET ITEM WITH SPACE KEY
if (input.isKeyDown(inputMaping::place_item)) {
if (input.isDown(inputMapping::place_item)) {
engine_.game_play_system().player_item_manager().place_item(get_world_mouse_pos());
}
}
......@@ -123,90 +119,218 @@ namespace gdw {
}
if(input.mouseWheelY() > 0.f) {
auto cam = engine_.game_play_system().level_manager().camera();
cam->position(cam->position()+glm::vec3(0,-1.f,-1.f));
}
if(input.isMouseButtonPressed(inputMaping::beam_normal)) {
if(input.isPressed(inputMapping::beam_normal)) {
engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_REVERSE_ACTIVATED);
}
if(input.isMouseButtonReleased(inputMaping::beam_normal)) {
if(input.isReleased(inputMapping::beam_normal)) {
engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_REVERSE_DEACTIVATED);
}
if(input.isMouseButtonPressed(inputMaping::beam_inverse)) {
if(input.isPressed(inputMapping::beam_inverse)) {
engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_ACTIVATED);
}
if(input.isMouseButtonReleased(inputMaping::beam_inverse)) {
engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_REVERSE_DEACTIVATED);
if(input.isReleased(inputMapping::beam_inverse)) {
engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_DEACTIVATED);
}
//LEFT && RIGHT CLICK
if(input.isMouseButtonDown(inputMaping::beam_normal) || input.isMouseButtonDown(inputMaping::beam_inverse)) {
auto intersection_point = get_world_mouse_pos();
auto cannon = level_manager.cannon();
auto cannon_pos = glm::vec3(cannon->position().x, 3.f, cannon->position().z);
ray r(cannon_pos, intersection_point);
//SPAWN LASER
auto v1 = glm::vec3(0,0,-1);
auto v2 = glm::normalize(r.destination-r.source);
auto angle = std::acos(glm::dot(v1, v2) / glm::length(v1) * glm::length(v2));
auto cross = glm::cross(v1, v2);
if(glm::length(cross) < 0.01f) return;
auto axis = glm::normalize(cross);
auto s = sin(angle/2.f);
auto qx = axis.x *s;
auto qy = axis.y *s;
auto qz = axis.z *s;
auto qw = cos(angle/2.f);
auto rot = glm::angleAxis(glm::radians(180.f), glm::vec3(0,1,0));
rot *= glm::quat(qw,qx,qy,qz);
auto ray_unnormalized = glm::vec3(1.f);
if (input.isMouseButtonDown(inputMaping::beam_normal)) {
ray_unnormalized = r.source - r.destination;
} else {
ray_unnormalized = r.destination - r.source;
}
switch(level_manager.weapon()) {
case weapon_type::tractor_beam: {
if(input.isDown(inputMapping::beam_normal) || input.isDown(inputMapping::beam_inverse)) {
auto intersection_point = get_world_mouse_pos();
auto cannon = level_manager.cannon();
auto cannon_pos = glm::vec3(cannon->position().x, 3.f, cannon->position().z);
ray r(cannon_pos, intersection_point);
//SPAWN LASER
auto v1 = glm::vec3(0,0,-1);
auto v2 = glm::normalize(r.destination-r.source);
auto angle = std::acos(glm::dot(v1, v2) / glm::length(v1) * glm::length(v2));
auto cross = glm::cross(v1, v2);
if(glm::length(cross) < 0.01f) return;
auto axis = glm::normalize(cross);
auto s = sin(angle/2.f);
auto qx = axis.x *s;
auto qy = axis.y *s;
auto qz = axis.z *s;
auto qw = cos(angle/2.f);
auto rot = glm::angleAxis(glm::radians(180.f), glm::vec3(0,1,0));
rot *= glm::quat(qw,qx,qy,qz);
auto ray_unnormalized = glm::vec3(1.f);
if (input.isDown(inputMapping::beam_normal)) {