Merge branch 'master' into CoolDeathAnimation
# Conflicts: # include/Engine/Rendering/ModelJob.h # resources/Shaders/ForwardPlus.frag.glsl # src/Engine/Rendering/DrawFinalPass.cpp # src/Engine/Rendering/RenderSystem.cpp
This commit is contained in:
@@ -3,6 +3,11 @@
|
||||
|
||||
const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid);
|
||||
|
||||
const std::string EntityWrapper::Name()
|
||||
{
|
||||
return World->GetName(ID);
|
||||
}
|
||||
|
||||
bool EntityWrapper::HasComponent(const std::string& componentName)
|
||||
{
|
||||
if (!Valid()) {
|
||||
@@ -22,18 +27,7 @@ EntityWrapper EntityWrapper::Parent()
|
||||
|
||||
EntityWrapper EntityWrapper::FirstChildByName(const std::string& name)
|
||||
{
|
||||
auto itPair = this->World->GetChildren(this->ID);
|
||||
if (itPair.first == itPair.second) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
for (auto it = itPair.first; it != itPair.second; ++it) {
|
||||
if (this->World->GetName(it->second) == name) {
|
||||
return EntityWrapper(this->World, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
return EntityWrapper::Invalid;
|
||||
return firstChildByNameRecursive(name, this->ID);
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType)
|
||||
@@ -108,3 +102,29 @@ EntityWrapper::operator bool()
|
||||
return this->Valid();
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name, EntityID parent)
|
||||
{
|
||||
if (!this->World->ValidEntity(parent)) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
auto itPair = this->World->GetChildren(parent);
|
||||
if (itPair.first == itPair.second) {
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
for (auto it = itPair.first; it != itPair.second; ++it) {
|
||||
std::string itName = this->World->GetName(it->second);
|
||||
if (itName == name) {
|
||||
return EntityWrapper(this->World, it->second);
|
||||
} else if (it->second != EntityID_Invalid) {
|
||||
EntityWrapper result = firstChildByNameRecursive(name, it->second);
|
||||
if (result != EntityWrapper::Invalid) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
#include "Core/Transform.h"
|
||||
|
||||
glm::mat4 Transform::AbsoluteTransformation(EntityWrapper entity)
|
||||
{
|
||||
glm::mat4 t = glm::mat4(1.f);
|
||||
|
||||
while (entity.Valid()) {
|
||||
t = glm::translate((glm::vec3&)entity["Transform"]["Position"]) * glm::toMat4(glm::quat((glm::vec3&)entity["Transform"]["Orientation"])) * glm::scale((glm::vec3&)entity["Transform"]["Scale"]) * t;
|
||||
entity = entity.Parent();
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
glm::vec3 Transform::AbsolutePosition(EntityWrapper entity)
|
||||
{
|
||||
return AbsolutePosition(entity.World, entity.ID);
|
||||
@@ -19,6 +31,19 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity)
|
||||
return position;
|
||||
}
|
||||
|
||||
glm::vec3 Transform::AbsoluteOrientationEuler(EntityWrapper entity)
|
||||
{
|
||||
glm::vec3 orientation;
|
||||
|
||||
while (entity.Valid()) {
|
||||
ComponentWrapper transform = entity["Transform"];
|
||||
orientation += (glm::vec3)transform["Orientation"];
|
||||
entity = entity.Parent();
|
||||
}
|
||||
|
||||
return orientation;
|
||||
}
|
||||
|
||||
glm::quat Transform::AbsoluteOrientation(EntityWrapper entity)
|
||||
{
|
||||
return AbsoluteOrientation(entity.World, entity.ID);
|
||||
@@ -62,6 +87,8 @@ glm::mat4 Transform::ModelMatrix(EntityWrapper entity)
|
||||
|
||||
glm::mat4 Transform::ModelMatrix(EntityID entity, World* world)
|
||||
{
|
||||
return AbsoluteTransformation(EntityWrapper(world, entity));
|
||||
|
||||
glm::vec3 position = Transform::AbsolutePosition(world, entity);
|
||||
glm::quat orientation = Transform::AbsoluteOrientation(world, entity);
|
||||
glm::vec3 scale = Transform::AbsoluteScale(world, entity);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Editor/EditorGUI.h"
|
||||
#include "Rendering/ESetCamera.h"
|
||||
|
||||
EditorGUI::EditorGUI(World* world, EventBroker* eventBroker)
|
||||
: m_World(world)
|
||||
@@ -305,6 +306,14 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci)
|
||||
}
|
||||
}
|
||||
|
||||
if (ci.Name == "Camera") {
|
||||
if (ImGui::Button("Activate")) {
|
||||
Events::SetCamera e;
|
||||
e.CameraEntity = entity;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ void EditorRenderSystem::Update(double dt)
|
||||
EntityWrapper entity(m_World, cModel.EntityID);
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World);
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World);
|
||||
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f);
|
||||
scene.ForwardJobs.push_back(modelJob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ bool EditorSystem::OnSetCamera(const Events::SetCamera& e)
|
||||
m_ActualCamera = e.CameraEntity;
|
||||
Events::SetCamera e2;
|
||||
e2.CameraEntity = m_EditorCamera;
|
||||
m_EventBroker->Publish(e2);
|
||||
//m_EventBroker->Publish(e2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ void Client::parsePlayersSpawned(Packet& packet)
|
||||
e.Player = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive<EntityID>()]);
|
||||
e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive<EntityID>()]);
|
||||
e.PlayerID = -1;
|
||||
e.PlayerName = packet.ReadString();
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ void Server::parseOnInputCommand(Packet& packet)
|
||||
Events::InputCommand e;
|
||||
e.Command = packet.ReadString();
|
||||
e.PlayerID = player; // Set correct player id
|
||||
e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID);
|
||||
e.Value = packet.ReadPrimitive<float>();
|
||||
m_EventBroker->Publish(e);
|
||||
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||
@@ -405,6 +406,8 @@ bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e)
|
||||
Packet packet = Packet(MessageType::OnPlayerSpawned);
|
||||
packet.WritePrimitive<EntityID>(e.Player.ID);
|
||||
packet.WritePrimitive<EntityID>(e.Spawner.ID);
|
||||
// We don't send PlayerID here because it will always be set to -1
|
||||
packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name);
|
||||
send(e.PlayerID, packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,10 @@ void DrawFinalPass::Draw(RenderScene& scene)
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(modelJob->DiffuseColor));
|
||||
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(modelJob->FillColor));
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), modelJob->FillPercentage);
|
||||
|
||||
|
||||
if (modelJob->DiffuseTexture != nullptr) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||
|
||||
@@ -4,6 +4,7 @@ RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRender
|
||||
: System(world, eventBroker)
|
||||
, m_Renderer(renderer)
|
||||
, m_RenderFrame(renderFrame)
|
||||
, m_World(world)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand);
|
||||
@@ -51,6 +52,12 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
|
||||
// Don't render the local player
|
||||
if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) {
|
||||
if (!entity.HasComponent("HealthHUD") && entity.Name() != "Crosshair" && entity.Name() != "Weapon") { //Should work but needs to be fixed. Should only render the things "childed" to the local player camera
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((entity.Name() == "Weapon" || entity.HasComponent("HealthHUD")) && !entity.IsChildOf(m_LocalPlayer)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -68,14 +75,42 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float fillPercentage = 0.f;
|
||||
glm::vec4 fillColor = glm::vec4(0);
|
||||
if(m_World->HasComponent(modelComponent.EntityID, "Fill")) {
|
||||
auto fillComponent = m_World->GetComponent(modelComponent.EntityID, "Fill");
|
||||
fillPercentage = (float)(double)fillComponent["Percentage"];
|
||||
fillColor = (glm::vec4)fillComponent["Color"];
|
||||
}
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, m_World);
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
if (m_World->HasComponent(modelComponent.EntityID, "ExplosionEffect")) {
|
||||
auto explosionEffectComponent = m_World->GetComponent(modelComponent.EntityID, "ExplosionEffect");
|
||||
std::shared_ptr<ExplosionEffectJob> explosionEffectJob = std::shared_ptr<ExplosionEffectJob>(new ExplosionEffectJob(explosionEffectComponent, model, m_Camera, modelMatrix, matGroup, modelComponent, m_World));
|
||||
std::shared_ptr<ExplosionEffectJob> explosionEffectJob = std::shared_ptr<ExplosionEffectJob>(new ExplosionEffectJob(
|
||||
explosionEffectComponent,
|
||||
model,
|
||||
m_Camera,
|
||||
modelMatrix,
|
||||
matGroup,
|
||||
modelComponent,
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage
|
||||
));
|
||||
jobs.push_back(explosionEffectJob);
|
||||
} else {
|
||||
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, m_World));
|
||||
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(
|
||||
model,
|
||||
m_Camera,
|
||||
modelMatrix,
|
||||
matGroup,
|
||||
modelComponent,
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage
|
||||
));
|
||||
jobs.push_back(modelJob);
|
||||
}
|
||||
}
|
||||
@@ -162,8 +197,8 @@ void RenderSystem::fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World*
|
||||
}
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(textComponent.EntityID, world);
|
||||
std::shared_ptr<TextJob> modelJob = std::shared_ptr<TextJob>(new TextJob(modelMatrix, font, textComponent));
|
||||
jobs.push_back(modelJob);
|
||||
std::shared_ptr<TextJob> textJob = std::shared_ptr<TextJob>(new TextJob(modelMatrix, font, textComponent));
|
||||
jobs.push_back(textJob);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -183,7 +218,6 @@ void RenderSystem::Update(double dt)
|
||||
m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera));
|
||||
}
|
||||
|
||||
//Only supports opaque geometry atm
|
||||
|
||||
RenderScene scene;
|
||||
scene.Camera = m_Camera;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "Core/EntityFileWriter.h"
|
||||
#include "Game/Systems/CapturePointSystem.h"
|
||||
#include "Game/Systems/WeaponSystem.h"
|
||||
#include "Game/Systems/PlayerHUD.h"
|
||||
#include "Game/Systems/LifetimeSystem.h"
|
||||
#include "../Engine/Rendering/AnimationSystem.h"
|
||||
|
||||
Game::Game(int argc, char* argv[])
|
||||
@@ -85,10 +87,13 @@ Game::Game(int argc, char* argv[])
|
||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
|
||||
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
|
||||
// Populate Octree with collidables
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<CollidableOctreeSystem>(updateOrderLevel, m_OctreeCollision);
|
||||
m_SystemPipeline->AddSystem<PlayerHUD>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
|
||||
|
||||
// Collision and TriggerSystem should update after player.
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<CollisionSystem>(updateOrderLevel, m_OctreeCollision);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "Systems/LifetimeSystem.h"
|
||||
|
||||
void LifetimeSystem::Update(double dt)
|
||||
{
|
||||
for (auto& e : m_Deletions) {
|
||||
m_World->DeleteEntity(e.ID);
|
||||
}
|
||||
m_Deletions.clear();
|
||||
}
|
||||
|
||||
void LifetimeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cLifetime, double dt)
|
||||
{
|
||||
if (dt == 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entity.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double& lifetime = cLifetime["Lifetime"];
|
||||
lifetime -= dt;
|
||||
|
||||
if (lifetime <= 0.0) {
|
||||
m_Deletions.push_back(entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "Game/Systems/PlayerHUD.h"
|
||||
|
||||
PlayerHUD::PlayerHUD(World* world, EventBroker* eventBrokerer)
|
||||
:System(world, eventBrokerer)
|
||||
, m_World(world)
|
||||
, m_EventBroker(eventBrokerer)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
PlayerHUD::~PlayerHUD()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PlayerHUD::Update(double dt)
|
||||
{
|
||||
auto healthHUDs = m_World->GetComponents("HealthHUD");
|
||||
if (healthHUDs == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& healthHUDComponent : *healthHUDs) {
|
||||
EntityWrapper entity = EntityWrapper(m_World, healthHUDComponent.EntityID);
|
||||
|
||||
EntityWrapper entityIDParent = entity;
|
||||
while (entityIDParent.Parent().Valid()) {
|
||||
entityIDParent = entityIDParent.Parent();
|
||||
|
||||
if (entityIDParent.HasComponent("Health")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entityIDParent.HasComponent("Health")) {
|
||||
|
||||
if (entity.HasComponent("Text")) {
|
||||
std::string s = "";
|
||||
s = s + std::to_string((int)(double)entityIDParent["Health"]["Health"]);
|
||||
s = s + "/";
|
||||
s = s + std::to_string((int)(double)entityIDParent["Health"]["MaxHealth"]);
|
||||
float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"];
|
||||
(glm::vec4&)entity["Text"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, 1.f);
|
||||
entity["Text"]["Content"] = s;
|
||||
}
|
||||
|
||||
if(entity.HasComponent("Fill")) {
|
||||
float healthPercentage = (double)entityIDParent["Health"]["Health"]/(double)entityIDParent["Health"]["MaxHealth"];
|
||||
(glm::vec4&)entity["Fill"]["Color"] = glm::vec4(1.0 - healthPercentage, 0.f, healthPercentage, 0.f);
|
||||
(double&)entity["Fill"]["Percentage"] = healthPercentage;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,10 +102,10 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
}
|
||||
|
||||
// TODO: Set the player name to whatever
|
||||
//EntityWrapper playerName = e.Player.FirstChildByName("PlayerName");
|
||||
//if (playerName.Valid()) {
|
||||
// playerName["Text"]["Content"] = ???;
|
||||
//}
|
||||
EntityWrapper playerName = e.Player.FirstChildByName("PlayerName");
|
||||
if (playerName.Valid()) {
|
||||
playerName["Text"]["Content"] = e.PlayerName;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -50,7 +50,8 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
|
||||
|
||||
// Set its position and orientation to that of the SpawnPoint
|
||||
spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID);
|
||||
spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID));
|
||||
// TODO: Quaternions, bitch
|
||||
//spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID));
|
||||
|
||||
return spawnedEntity;
|
||||
}
|
||||
|
||||
@@ -25,24 +25,68 @@ bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e)
|
||||
|
||||
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
{
|
||||
// Only shoot if the player is alive
|
||||
if (!m_LocalPlayer.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Command == "PrimaryFire" && e.Value > 0) {
|
||||
Events::Shoot eShoot;
|
||||
eShoot.Player = m_LocalPlayer;
|
||||
if (e.PlayerID == -1) {
|
||||
eShoot.Player = m_LocalPlayer;
|
||||
} else {
|
||||
eShoot.Player = e.Player;
|
||||
}
|
||||
m_EventBroker->Publish(eShoot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnShoot(const Events::Shoot& eShoot)
|
||||
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
|
||||
{
|
||||
if (!eShoot.Player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Weapon firing effects here
|
||||
|
||||
auto rayRed = ResourceManager::Load<EntityFile>("Schema/Entities/RayRed.xml");
|
||||
auto rayBlue = ResourceManager::Load<EntityFile>("Schema/Entities/RayBlue.xml");
|
||||
|
||||
EntityWrapper weapon = eShoot.Player.FirstChildByName("WeaponMuzzle");
|
||||
if (weapon.Valid()) {
|
||||
EntityWrapper ray;
|
||||
if ((ComponentInfo::EnumType)eShoot.Player["Team"]["Team"] == eShoot.Player["Team"]["Team"].Enum("Red")) {
|
||||
EntityFileParser parser(rayRed);
|
||||
EntityID rayID = parser.MergeEntities(m_World);
|
||||
ray = EntityWrapper(m_World, rayID);
|
||||
} else {
|
||||
EntityFileParser parser(rayBlue);
|
||||
EntityID rayID = parser.MergeEntities(m_World);
|
||||
ray = EntityWrapper(m_World, rayID);
|
||||
}
|
||||
|
||||
glm::mat4 transformation = Transform::AbsoluteTransformation(weapon);
|
||||
glm::vec3 scale;
|
||||
glm::vec3 translation;
|
||||
glm::quat orientation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(transformation, scale, orientation, translation, skew, perspective);
|
||||
|
||||
// Matrix to euler angles
|
||||
glm::vec3 euler;
|
||||
euler.y = glm::asin(-transformation[0][2]);
|
||||
if (cos(euler.y) != 0) {
|
||||
euler.x = atan2(transformation[1][2], transformation[2][2]);
|
||||
euler.z = atan2(transformation[0][1], transformation[0][0]);
|
||||
} else {
|
||||
euler.x = atan2(-transformation[2][0], transformation[1][1]);
|
||||
euler.z = 0;
|
||||
}
|
||||
|
||||
//LOG_DEBUG("rotation: %f %f %f", euler.x, euler.y, euler.z);
|
||||
(glm::vec3&)ray["Transform"]["Position"] = translation;
|
||||
(glm::vec3&)ray["Transform"]["Orientation"] = euler;
|
||||
//(glm::vec3&)ray["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(weapon);
|
||||
}
|
||||
|
||||
// Only run further picking code client-side!
|
||||
if (eShoot.Player != m_LocalPlayer) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user