2014-06-16 21:18:15 +02:00
|
|
|
#include "render_scene.h"
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/array.h"
|
|
|
|
#include "engine/blob.h"
|
|
|
|
#include "engine/crc32.h"
|
|
|
|
#include "engine/fs/file_system.h"
|
|
|
|
#include "engine/geometry.h"
|
|
|
|
#include "engine/json_serializer.h"
|
|
|
|
#include "engine/lifo_allocator.h"
|
|
|
|
#include "engine/log.h"
|
|
|
|
#include "engine/lua_wrapper.h"
|
|
|
|
#include "engine/math_utils.h"
|
|
|
|
#include "engine/mtjd/generic_job.h"
|
|
|
|
#include "engine/mtjd/job.h"
|
|
|
|
#include "engine/mtjd/manager.h"
|
|
|
|
#include "engine/profiler.h"
|
|
|
|
#include "engine/resource_manager.h"
|
|
|
|
#include "engine/resource_manager_base.h"
|
|
|
|
#include "engine/timer.h"
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2016-04-22 18:51:38 +02:00
|
|
|
#include "engine/engine.h"
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2016-02-23 19:46:43 +01:00
|
|
|
#include "lua_script/lua_script_system.h"
|
|
|
|
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/culling_system.h"
|
|
|
|
#include "renderer/material.h"
|
2016-01-22 01:11:04 +01:00
|
|
|
#include "renderer/material_manager.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/model.h"
|
2015-10-30 21:11:11 +01:00
|
|
|
#include "renderer/particle_system.h"
|
2016-02-23 19:46:43 +01:00
|
|
|
#include "renderer/pipeline.h"
|
2015-10-06 17:00:52 +02:00
|
|
|
#include "renderer/pose.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/renderer.h"
|
|
|
|
#include "renderer/shader.h"
|
|
|
|
#include "renderer/terrain.h"
|
|
|
|
#include "renderer/texture.h"
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2016-04-22 18:33:06 +02:00
|
|
|
#include "engine/universe/universe.h"
|
2015-12-02 01:37:53 +01:00
|
|
|
#include <cmath>
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
namespace Lumix
|
|
|
|
{
|
|
|
|
|
2015-07-24 22:38:11 +02:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
static const uint32 RENDERABLE_HASH = crc32("renderable");
|
|
|
|
static const uint32 POINT_LIGHT_HASH = crc32("point_light");
|
|
|
|
static const uint32 PARTICLE_EMITTER_HASH = crc32("particle_emitter");
|
|
|
|
static const uint32 PARTICLE_EMITTER_FADE_HASH = crc32("particle_emitter_fade");
|
2015-12-12 01:35:22 +01:00
|
|
|
static const uint32 PARTICLE_EMITTER_FORCE_HASH = crc32("particle_emitter_force");
|
2015-12-17 13:58:40 +01:00
|
|
|
static const uint32 PARTICLE_EMITTER_ATTRACTOR_HASH = crc32("particle_emitter_attractor");
|
2015-11-11 21:54:25 +01:00
|
|
|
static const uint32 PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH =
|
2015-11-08 11:44:20 +01:00
|
|
|
crc32("particle_emitter_linear_movement");
|
2016-02-24 20:46:14 +01:00
|
|
|
static const uint32 PARTICLE_EMITTER_SPAWN_SHAPE_HASH = crc32("particle_emitter_spawn_shape");
|
|
|
|
static const uint32 PARTICLE_EMITTER_PLANE_HASH = crc32("particle_emitter_plane");
|
2015-11-11 21:54:25 +01:00
|
|
|
static const uint32 PARTICLE_EMITTER_RANDOM_ROTATION_HASH =
|
2015-11-08 11:44:20 +01:00
|
|
|
crc32("particle_emitter_random_rotation");
|
2015-11-18 20:18:48 +01:00
|
|
|
static const uint32 PARTICLE_EMITTER_SIZE_HASH = crc32("particle_emitter_size");
|
2015-11-11 21:54:25 +01:00
|
|
|
static const uint32 GLOBAL_LIGHT_HASH = crc32("global_light");
|
|
|
|
static const uint32 CAMERA_HASH = crc32("camera");
|
|
|
|
static const uint32 TERRAIN_HASH = crc32("terrain");
|
2016-05-02 21:41:18 +02:00
|
|
|
static const uint32 BONE_ATTACHMENT_HASH = crc32("bone_attachment");
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
struct PointLight
|
|
|
|
{
|
2015-09-02 11:14:42 +02:00
|
|
|
Vec3 m_diffuse_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
Vec3 m_specular_color;
|
2016-02-10 12:09:09 +01:00
|
|
|
float m_diffuse_intensity;
|
|
|
|
float m_specular_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
Entity m_entity;
|
|
|
|
int m_uid;
|
|
|
|
float m_fov;
|
2015-09-09 02:18:09 +02:00
|
|
|
float m_attenuation_param;
|
2015-09-04 14:00:28 +02:00
|
|
|
float m_range;
|
2015-09-02 11:14:42 +02:00
|
|
|
bool m_cast_shadows;
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
struct GlobalLight
|
|
|
|
{
|
2015-12-07 21:49:27 +01:00
|
|
|
ComponentIndex m_uid;
|
2016-02-10 12:09:09 +01:00
|
|
|
Vec3 m_diffuse_color;
|
|
|
|
float m_specular_intensity;
|
2016-01-28 21:44:35 +01:00
|
|
|
Vec3 m_specular;
|
2016-02-10 12:09:09 +01:00
|
|
|
float m_diffuse_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
Vec3 m_ambient_color;
|
|
|
|
float m_ambient_intensity;
|
|
|
|
Vec3 m_fog_color;
|
|
|
|
float m_fog_density;
|
2015-10-17 00:18:47 +02:00
|
|
|
float m_fog_bottom;
|
|
|
|
float m_fog_height;
|
2015-07-21 20:10:50 +02:00
|
|
|
Entity m_entity;
|
2015-09-10 22:14:54 +02:00
|
|
|
Vec4 m_cascades;
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Camera
|
|
|
|
{
|
|
|
|
static const int MAX_SLOT_LENGTH = 30;
|
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
Entity entity;
|
|
|
|
float fov;
|
|
|
|
float aspect;
|
|
|
|
float near;
|
|
|
|
float far;
|
|
|
|
float ortho_size;
|
|
|
|
float screen_width;
|
|
|
|
float screen_height;
|
|
|
|
bool is_free;
|
|
|
|
bool is_ortho;
|
|
|
|
char slot[MAX_SLOT_LENGTH + 1];
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
struct BoneAttachment
|
|
|
|
{
|
|
|
|
Entity entity;
|
|
|
|
Entity parent_entity;
|
|
|
|
int bone_index;
|
|
|
|
Matrix relative_matrix;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
class RenderSceneImpl : public RenderScene
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
class ModelLoadedCallback
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
public:
|
|
|
|
ModelLoadedCallback(RenderSceneImpl& scene, Model* model)
|
|
|
|
: m_scene(scene)
|
|
|
|
, m_ref_count(0)
|
|
|
|
, m_model(model)
|
|
|
|
{
|
2015-12-10 23:33:21 +01:00
|
|
|
m_model->getObserverCb().bind<ModelLoadedCallback, &ModelLoadedCallback::callback>(
|
|
|
|
this);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
~ModelLoadedCallback()
|
|
|
|
{
|
2015-10-03 01:53:04 +02:00
|
|
|
m_model->getObserverCb().unbind<ModelLoadedCallback, &ModelLoadedCallback::callback>(
|
2015-08-27 23:59:36 +02:00
|
|
|
this);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
|
2016-01-10 13:41:12 +01:00
|
|
|
void callback(Resource::State old_state, Resource::State new_state)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
if (new_state == Resource::State::READY)
|
|
|
|
{
|
|
|
|
m_scene.modelLoaded(m_model);
|
|
|
|
}
|
2016-02-06 15:20:34 +01:00
|
|
|
else if (old_state == Resource::State::READY && new_state != Resource::State::READY)
|
2016-01-10 13:41:12 +01:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
m_scene.modelUnloaded(m_model);
|
2016-01-10 13:41:12 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
Model* m_model;
|
|
|
|
int m_ref_count;
|
|
|
|
RenderSceneImpl& m_scene;
|
2014-06-16 21:18:15 +02:00
|
|
|
};
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
public:
|
|
|
|
RenderSceneImpl(Renderer& renderer,
|
2015-08-27 23:59:36 +02:00
|
|
|
Engine& engine,
|
|
|
|
Universe& universe,
|
|
|
|
bool is_forward_rendered,
|
|
|
|
IAllocator& allocator)
|
2015-07-21 20:10:50 +02:00
|
|
|
: m_engine(engine)
|
|
|
|
, m_universe(universe)
|
|
|
|
, m_renderer(renderer)
|
|
|
|
, m_allocator(allocator)
|
|
|
|
, m_model_loaded_callbacks(m_allocator)
|
|
|
|
, m_renderables(m_allocator)
|
|
|
|
, m_cameras(m_allocator)
|
|
|
|
, m_terrains(m_allocator)
|
|
|
|
, m_point_lights(m_allocator)
|
|
|
|
, m_light_influenced_geometry(m_allocator)
|
|
|
|
, m_global_lights(m_allocator)
|
2016-03-10 19:32:48 +01:00
|
|
|
, m_debug_triangles(m_allocator)
|
2015-07-21 20:10:50 +02:00
|
|
|
, m_debug_lines(m_allocator)
|
2015-08-28 21:55:53 +02:00
|
|
|
, m_debug_points(m_allocator)
|
2015-07-21 20:10:50 +02:00
|
|
|
, m_temporary_infos(m_allocator)
|
|
|
|
, m_sync_point(true, m_allocator)
|
|
|
|
, m_jobs(m_allocator)
|
|
|
|
, m_active_global_light_uid(-1)
|
|
|
|
, m_global_light_last_uid(-1)
|
|
|
|
, m_point_light_last_uid(-1)
|
|
|
|
, m_is_forward_rendered(is_forward_rendered)
|
2015-07-24 22:38:11 +02:00
|
|
|
, m_renderable_created(m_allocator)
|
|
|
|
, m_renderable_destroyed(m_allocator)
|
2015-10-12 09:56:46 +02:00
|
|
|
, m_is_grass_enabled(true)
|
2015-12-12 00:46:27 +01:00
|
|
|
, m_is_game_running(false)
|
2015-10-30 21:11:11 +01:00
|
|
|
, m_particle_emitters(m_allocator)
|
2016-01-26 10:27:31 +01:00
|
|
|
, m_point_lights_map(m_allocator)
|
2016-05-02 21:41:18 +02:00
|
|
|
, m_bone_attachments(m_allocator)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-05-02 21:41:18 +02:00
|
|
|
m_is_updating_attachments = false;
|
|
|
|
m_universe.entityTransformed().bind<RenderSceneImpl, &RenderSceneImpl::onEntityMoved>(this);
|
|
|
|
m_universe.entityDestroyed().bind<RenderSceneImpl, &RenderSceneImpl::onEntityDestroyed>(this);
|
|
|
|
m_culling_system = CullingSystem::create(m_engine.getMTJDManager(), m_allocator);
|
2015-07-21 20:10:50 +02:00
|
|
|
m_time = 0;
|
2015-12-10 17:09:52 +01:00
|
|
|
m_renderables.reserve(5000);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-30 00:16:32 +01:00
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
~RenderSceneImpl()
|
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
auto& rm = m_engine.getResourceManager();
|
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(ResourceManager::MATERIAL));
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
m_universe.entityTransformed().unbind<RenderSceneImpl, &RenderSceneImpl::onEntityMoved>(this);
|
|
|
|
m_universe.entityDestroyed().unbind<RenderSceneImpl, &RenderSceneImpl::onEntityDestroyed>(this);
|
2014-10-30 00:16:32 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < m_model_loaded_callbacks.size(); ++i)
|
|
|
|
{
|
2015-10-30 21:11:11 +01:00
|
|
|
LUMIX_DELETE(m_allocator, m_model_loaded_callbacks[i]);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
2015-10-30 21:11:11 +01:00
|
|
|
LUMIX_DELETE(m_allocator, m_terrains[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, m_particle_emitters[i]);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-01-04 15:05:20 +01:00
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
for (auto& i : m_renderables)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
if (i.entity != INVALID_ENTITY && i.model)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
auto& manager = i.model->getResourceManager();
|
2016-02-06 10:58:50 +01:00
|
|
|
freeCustomMeshes(i, material_manager);
|
2015-12-10 20:27:51 +01:00
|
|
|
manager.get(ResourceManager::MODEL)->unload(*i.model);
|
|
|
|
LUMIX_DELETE(m_allocator, i.pose);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-10-15 20:46:01 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
CullingSystem::destroy(*m_culling_system);
|
|
|
|
}
|
2014-10-15 20:46:01 +02:00
|
|
|
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2015-12-17 13:58:40 +01:00
|
|
|
void resetParticleEmitter(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
m_particle_emitters[cmp]->reset();
|
|
|
|
}
|
|
|
|
|
2016-02-26 13:49:42 +01:00
|
|
|
|
2016-05-03 12:50:58 +02:00
|
|
|
ParticleEmitter* getParticleEmitter(ComponentIndex cmp) override
|
2015-12-16 23:42:23 +01:00
|
|
|
{
|
2016-01-17 14:09:27 +01:00
|
|
|
return m_particle_emitters[cmp];
|
2015-12-16 23:42:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-12 00:46:27 +01:00
|
|
|
void updateEmitter(ComponentIndex cmp, float time_delta) override
|
|
|
|
{
|
|
|
|
m_particle_emitters[cmp]->update(time_delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Universe& getUniverse() override { return m_universe; }
|
2014-11-05 19:01:56 +01:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
bool ownComponentType(uint32 type) const override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
return type == RENDERABLE_HASH || type == POINT_LIGHT_HASH ||
|
2015-08-27 23:59:36 +02:00
|
|
|
type == GLOBAL_LIGHT_HASH || type == CAMERA_HASH ||
|
|
|
|
type == TERRAIN_HASH;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-19 18:37:31 +02:00
|
|
|
|
|
|
|
|
2015-12-13 11:45:31 +01:00
|
|
|
ComponentIndex getComponent(Entity entity, uint32 type) override
|
|
|
|
{
|
|
|
|
if (type == RENDERABLE_HASH)
|
|
|
|
{
|
2016-01-17 15:14:28 +01:00
|
|
|
if (entity >= m_renderables.size()) return INVALID_COMPONENT;
|
2015-12-13 11:45:31 +01:00
|
|
|
return m_renderables[entity].entity != INVALID_ENTITY ? entity : INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
if (type == POINT_LIGHT_HASH)
|
|
|
|
{
|
|
|
|
for (auto& i : m_point_lights)
|
|
|
|
{
|
|
|
|
if (i.m_entity == entity) return i.m_uid;
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
if (type == GLOBAL_LIGHT_HASH)
|
|
|
|
{
|
|
|
|
for (auto& i : m_global_lights)
|
|
|
|
{
|
|
|
|
if (i.m_entity == entity) return i.m_uid;
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
if (type == CAMERA_HASH)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_cameras.size(); ++i)
|
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
if (!m_cameras[i].is_free && m_cameras[i].entity == entity) return i;
|
2015-12-13 11:45:31 +01:00
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
if (type == TERRAIN_HASH)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_terrains[i] && m_terrains[i]->getEntity() == entity) return i;
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
IPlugin& getPlugin() const override { return m_renderer; }
|
2015-01-04 15:05:20 +01:00
|
|
|
|
|
|
|
|
2015-12-12 00:46:27 +01:00
|
|
|
Int2 getParticleEmitterSpawnCount(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
Int2 ret;
|
|
|
|
ret.x = m_particle_emitters[cmp]->m_spawn_count.from;
|
|
|
|
ret.y = m_particle_emitters[cmp]->m_spawn_count.to;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterSpawnCount(ComponentIndex cmp, const Int2& value) override
|
|
|
|
{
|
|
|
|
m_particle_emitters[cmp]->m_spawn_count.from = value.x;
|
2016-03-06 12:54:29 +01:00
|
|
|
m_particle_emitters[cmp]->m_spawn_count.to = Math::maximum(value.x, value.y);
|
2015-12-12 00:46:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
void getRay(ComponentIndex camera_index,
|
2015-08-27 23:59:36 +02:00
|
|
|
float x,
|
|
|
|
float y,
|
|
|
|
Vec3& origin,
|
|
|
|
Vec3& dir) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
Camera& camera = m_cameras[camera_index];
|
|
|
|
origin = m_universe.getPosition(camera.entity);
|
|
|
|
|
|
|
|
float width = camera.screen_width;
|
|
|
|
float height = camera.screen_height;
|
|
|
|
if (width <= 0 || height <= 0)
|
|
|
|
{
|
|
|
|
dir = m_universe.getRotation(camera.entity) * Vec3(0, 0, 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
float nx = 2 * (x / width) - 1;
|
|
|
|
float ny = 2 * ((height - y) / height) - 1;
|
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
Matrix projection_matrix = getCameraProjection(camera_index);
|
|
|
|
Matrix view_matrix = m_universe.getMatrix(camera.entity);
|
|
|
|
|
|
|
|
if (camera.is_ortho)
|
|
|
|
{
|
|
|
|
float ratio = camera.screen_height > 0 ? camera.screen_width / camera.screen_height : 1;
|
|
|
|
origin += view_matrix.getXVector() * nx * camera.ortho_size * ratio
|
|
|
|
+ view_matrix.getYVector() * ny * camera.ortho_size;
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
view_matrix.inverse();
|
|
|
|
Matrix inverted = (projection_matrix * view_matrix);
|
|
|
|
inverted.inverse();
|
2016-04-17 21:47:54 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
Vec4 p0 = inverted * Vec4(nx, ny, -1, 1);
|
|
|
|
Vec4 p1 = inverted * Vec4(nx, ny, 1, 1);
|
2016-04-17 21:47:54 +02:00
|
|
|
p0 *= 1 / p0.w;
|
|
|
|
p1 *= 1 / p1.w;
|
|
|
|
dir = p1 - p0;
|
2015-07-21 20:10:50 +02:00
|
|
|
dir.normalize();
|
|
|
|
}
|
2014-08-21 01:22:57 +02:00
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
Frustum getCameraFrustum(ComponentIndex cmp) const override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
const Camera& camera = m_cameras[cmp];
|
|
|
|
Matrix mtx = m_universe.getMatrix(camera.entity);
|
2015-08-27 23:18:49 +02:00
|
|
|
Frustum ret;
|
2016-04-17 21:47:54 +02:00
|
|
|
float ratio = camera.screen_height > 0 ? camera.screen_width / camera.screen_height : 1;
|
|
|
|
if (camera.is_ortho)
|
|
|
|
{
|
|
|
|
ret.computeOrtho(mtx.getTranslation(),
|
|
|
|
mtx.getZVector(),
|
|
|
|
mtx.getYVector(),
|
|
|
|
camera.ortho_size * ratio,
|
|
|
|
camera.ortho_size,
|
|
|
|
camera.near,
|
|
|
|
camera.far);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-08-27 23:18:49 +02:00
|
|
|
ret.computePerspective(mtx.getTranslation(),
|
2016-04-17 21:47:54 +02:00
|
|
|
mtx.getZVector(),
|
|
|
|
mtx.getYVector(),
|
|
|
|
Math::degreesToRadians(camera.fov),
|
|
|
|
ratio,
|
|
|
|
camera.near,
|
|
|
|
camera.far);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
return ret;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
int getBoneAttachmentIdx(ComponentIndex cmp) const
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_bone_attachments.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_bone_attachments[i].entity == cmp) return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void updateBoneAttachment(const BoneAttachment& bone_attachment)
|
|
|
|
{
|
|
|
|
if (bone_attachment.parent_entity == INVALID_ENTITY) return;
|
|
|
|
ComponentIndex renderable = getRenderableComponent(bone_attachment.parent_entity);
|
|
|
|
if (renderable == INVALID_COMPONENT) return;
|
|
|
|
auto* parent_pose = getPose(renderable);
|
|
|
|
if (!parent_pose) return;
|
|
|
|
|
|
|
|
Matrix parent_entity_mtx = m_universe.getMatrix(bone_attachment.parent_entity);
|
|
|
|
int idx = bone_attachment.bone_index;
|
|
|
|
if (idx < 0 || idx > parent_pose->count) return;
|
|
|
|
Matrix bone_mtx;
|
|
|
|
parent_pose->rotations[idx].toMatrix(bone_mtx);
|
|
|
|
bone_mtx.setTranslation(parent_pose->positions[idx]);
|
|
|
|
m_universe.setMatrix(bone_attachment.entity, parent_entity_mtx * bone_mtx * bone_attachment.relative_matrix);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Entity getBoneAttachmentParent(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(cmp);
|
|
|
|
return m_bone_attachments[idx].parent_entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void updateRelativeMatrix(BoneAttachment& attachment)
|
|
|
|
{
|
|
|
|
if (attachment.parent_entity == INVALID_ENTITY) return;
|
|
|
|
if (attachment.bone_index < 0) return;
|
|
|
|
ComponentIndex renderable = getRenderableComponent(attachment.parent_entity);
|
|
|
|
if (renderable == INVALID_COMPONENT) return;
|
|
|
|
Pose* pose = getPose(renderable);
|
|
|
|
if (!pose) return;
|
|
|
|
ASSERT(pose->is_absolute);
|
|
|
|
if (attachment.bone_index >= pose->count) return;
|
|
|
|
Matrix bone_matrix;
|
|
|
|
pose->rotations[attachment.bone_index].toMatrix(bone_matrix);
|
|
|
|
bone_matrix.setTranslation(pose->positions[attachment.bone_index]);
|
|
|
|
|
|
|
|
Matrix inv_parent_matrix = m_universe.getMatrix(attachment.parent_entity) * bone_matrix;
|
|
|
|
inv_parent_matrix.inverse();
|
|
|
|
Matrix child_matrix = m_universe.getMatrix(attachment.entity);
|
|
|
|
attachment.relative_matrix = inv_parent_matrix * child_matrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-06 12:14:53 +02:00
|
|
|
Vec3 getBoneAttachmentPosition(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(cmp);
|
|
|
|
if (idx < 0) return {0, 0, 0};
|
|
|
|
return m_bone_attachments[idx].relative_matrix.getTranslation();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setBoneAttachmentPosition(ComponentIndex cmp, const Vec3& pos) override
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(cmp);
|
|
|
|
if (idx < 0) return;
|
|
|
|
return m_bone_attachments[idx].relative_matrix.setTranslation(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
int getBoneAttachmentBone(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(cmp);
|
|
|
|
if (idx < 0) return -1;
|
|
|
|
return m_bone_attachments[idx].bone_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setBoneAttachmentBone(ComponentIndex cmp, int value) override
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(cmp);
|
|
|
|
if (idx < 0) return;
|
|
|
|
m_bone_attachments[idx].bone_index = value;
|
|
|
|
updateRelativeMatrix(m_bone_attachments[idx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setBoneAttachmentParent(ComponentIndex cmp, Entity entity) override
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(cmp);
|
|
|
|
m_bone_attachments[idx].parent_entity = entity;
|
|
|
|
updateRelativeMatrix(m_bone_attachments[idx]);
|
|
|
|
}
|
|
|
|
|
2015-12-12 00:46:27 +01:00
|
|
|
void startGame() override
|
|
|
|
{
|
|
|
|
m_is_game_running = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void stopGame() override
|
|
|
|
{
|
|
|
|
m_is_game_running = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-17 23:28:20 +01:00
|
|
|
void update(float dt, bool paused) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2016-05-02 21:41:18 +02:00
|
|
|
if (m_is_game_running)
|
|
|
|
{
|
|
|
|
m_is_updating_attachments = true;
|
|
|
|
for (auto& bone_attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
updateBoneAttachment(bone_attachment);
|
|
|
|
}
|
|
|
|
m_is_updating_attachments = false;
|
|
|
|
}
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
m_time += dt;
|
2016-03-10 19:32:48 +01:00
|
|
|
for (int i = m_debug_triangles.size() - 1; i >= 0; --i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-03-10 19:32:48 +01:00
|
|
|
float life = m_debug_triangles[i].life;
|
2015-07-21 20:10:50 +02:00
|
|
|
if (life < 0)
|
2016-03-10 19:32:48 +01:00
|
|
|
{
|
|
|
|
m_debug_triangles.eraseFast(i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
life -= dt;
|
|
|
|
m_debug_triangles[i].life = life;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = m_debug_lines.size() - 1; i >= 0; --i)
|
|
|
|
{
|
|
|
|
float life = m_debug_lines[i].life;
|
|
|
|
if(life < 0)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
m_debug_lines.eraseFast(i);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
else
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
life -= dt;
|
2016-03-10 19:32:48 +01:00
|
|
|
m_debug_lines[i].life = life;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-08-28 21:55:53 +02:00
|
|
|
|
2016-03-10 19:32:48 +01:00
|
|
|
|
2015-08-28 21:55:53 +02:00
|
|
|
for (int i = m_debug_points.size() - 1; i >= 0; --i)
|
|
|
|
{
|
2016-03-10 19:32:48 +01:00
|
|
|
float life = m_debug_points[i].life;
|
2015-08-28 21:55:53 +02:00
|
|
|
if (life < 0)
|
|
|
|
{
|
2016-03-10 19:32:48 +01:00
|
|
|
m_debug_points.eraseFast(i);
|
2015-08-28 21:55:53 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
life -= dt;
|
2016-03-10 19:32:48 +01:00
|
|
|
m_debug_points[i].life = life;
|
2015-08-28 21:55:53 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-30 21:18:36 +01:00
|
|
|
|
2016-01-17 23:28:20 +01:00
|
|
|
if (m_is_game_running && !paused)
|
2015-10-30 21:18:36 +01:00
|
|
|
{
|
2015-12-12 00:46:27 +01:00
|
|
|
for (auto* emitter : m_particle_emitters)
|
|
|
|
{
|
|
|
|
if (!emitter) continue;
|
|
|
|
|
|
|
|
emitter->update(dt);
|
|
|
|
}
|
2015-10-30 21:18:36 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
|
|
|
|
void serializeBoneAttachments(OutputBlob& serializer)
|
|
|
|
{
|
|
|
|
serializer.write((int32)m_bone_attachments.size());
|
|
|
|
for (auto& attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
serializer.write(attachment.bone_index);
|
|
|
|
serializer.write(attachment.entity);
|
|
|
|
serializer.write(attachment.parent_entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void serializeCameras(OutputBlob& serializer)
|
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
serializer.write((int32)m_cameras.size());
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0, c = m_cameras.size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
Camera& camera = m_cameras[i];
|
2016-04-17 21:47:54 +02:00
|
|
|
serializer.write(camera.entity);
|
|
|
|
serializer.write(camera.far);
|
|
|
|
serializer.write(camera.fov);
|
|
|
|
serializer.write(camera.is_ortho);
|
|
|
|
serializer.write(camera.ortho_size);
|
|
|
|
serializer.write(camera.is_free);
|
|
|
|
serializer.write(camera.near);
|
|
|
|
serializer.writeString(camera.slot);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void serializeLights(OutputBlob& serializer)
|
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
serializer.write((int32)m_point_lights.size());
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0, c = m_point_lights.size(); i < c; ++i)
|
|
|
|
{
|
2015-11-08 11:44:20 +01:00
|
|
|
serializer.write(m_point_lights[i]);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
serializer.write(m_point_light_last_uid);
|
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
serializer.write((int32)m_global_lights.size());
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0, c = m_global_lights.size(); i < c; ++i)
|
|
|
|
{
|
2015-11-08 11:44:20 +01:00
|
|
|
serializer.write(m_global_lights[i]);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-11-11 21:54:25 +01:00
|
|
|
serializer.write((int32)m_global_light_last_uid);
|
|
|
|
serializer.write((int32)m_active_global_light_uid);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void serializeRenderables(OutputBlob& serializer)
|
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
serializer.write((int32)m_renderables.size());
|
2016-01-22 01:11:04 +01:00
|
|
|
for (auto& r : m_renderables)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
serializer.write(r.entity);
|
|
|
|
if(r.entity != INVALID_ENTITY)
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
serializer.write(r.layer_mask);
|
|
|
|
serializer.write(r.model ? r.model->getPath().getHash() : 0);
|
2016-02-01 15:13:00 +01:00
|
|
|
bool has_changed_materials = r.model && r.model->isReady() && r.meshes != &r.model->getMesh(0);
|
2016-01-22 01:11:04 +01:00
|
|
|
serializer.write(has_changed_materials ? r.mesh_count : 0);
|
|
|
|
if (has_changed_materials)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
|
|
|
{
|
2016-01-22 18:02:07 +01:00
|
|
|
serializer.writeString(r.meshes[i].material->getPath().c_str());
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2016-01-22 01:11:04 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void serializeTerrains(OutputBlob& serializer)
|
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
serializer.write((int32)m_terrains.size());
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_terrains[i])
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.write(true);
|
|
|
|
m_terrains[i]->serialize(serializer);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
else
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.write(false);
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-07 21:34:38 +01:00
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
void deserializeBoneAttachments(InputBlob& serializer, int version)
|
|
|
|
{
|
|
|
|
if (version <= (int)RenderSceneVersion::BONE_ATTACHMENTS) return;
|
|
|
|
|
|
|
|
int32 count;
|
|
|
|
serializer.read(count);
|
|
|
|
m_bone_attachments.resize(count);
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
serializer.read(m_bone_attachments[i].bone_index);
|
|
|
|
serializer.read(m_bone_attachments[i].entity);
|
|
|
|
serializer.read(m_bone_attachments[i].parent_entity);
|
|
|
|
updateRelativeMatrix(m_bone_attachments[i]);
|
|
|
|
m_universe.addComponent(
|
|
|
|
m_bone_attachments[i].entity, BONE_ATTACHMENT_HASH, this, m_bone_attachments[i].entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-12 00:46:27 +01:00
|
|
|
void deserializeParticleEmitters(InputBlob& serializer, int version)
|
2015-11-07 21:34:38 +01:00
|
|
|
{
|
|
|
|
int count;
|
|
|
|
serializer.read(count);
|
|
|
|
m_particle_emitters.resize(count);
|
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
bool is_emitter;
|
|
|
|
serializer.read(is_emitter);
|
|
|
|
ParticleEmitter* emitter = nullptr;
|
|
|
|
if (is_emitter)
|
|
|
|
{
|
|
|
|
emitter = LUMIX_NEW(m_allocator, ParticleEmitter)(
|
|
|
|
INVALID_ENTITY, m_universe, m_allocator);
|
2015-12-12 00:46:27 +01:00
|
|
|
emitter->deserialize(serializer,
|
|
|
|
m_engine.getResourceManager(),
|
|
|
|
version > (int)RenderSceneVersion::PARTICLE_EMITTERS_SPAWN_COUNT);
|
2015-11-07 21:34:38 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_HASH, this, i);
|
2015-11-08 11:44:20 +01:00
|
|
|
for (auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if (module->getType() == ParticleEmitter::AlphaModule::s_type)
|
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_FADE_HASH, this, i);
|
|
|
|
}
|
2015-12-18 21:23:51 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::ForceModule::s_type)
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_FORCE_HASH, this, i);
|
|
|
|
}
|
2015-12-18 21:23:51 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::SpawnShapeModule::s_type)
|
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_SPAWN_SHAPE_HASH, this, i);
|
|
|
|
}
|
|
|
|
else if (module->getType() == ParticleEmitter::AttractorModule::s_type)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_ATTRACTOR_HASH, this, i);
|
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::LinearMovementModule::s_type)
|
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH, this, i);
|
|
|
|
}
|
2015-12-16 21:26:19 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::PlaneModule::s_type)
|
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_PLANE_HASH, this, i);
|
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::RandomRotationModule::s_type)
|
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_RANDOM_ROTATION_HASH, this, i);
|
|
|
|
}
|
2015-11-18 20:18:48 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::SizeModule::s_type)
|
|
|
|
{
|
|
|
|
m_universe.addComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_SIZE_HASH, this, i);
|
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2015-11-07 21:34:38 +01:00
|
|
|
}
|
|
|
|
m_particle_emitters[i] = emitter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitters(OutputBlob& serializer)
|
|
|
|
{
|
|
|
|
serializer.write(m_particle_emitters.size());
|
|
|
|
for (auto* emitter : m_particle_emitters)
|
|
|
|
{
|
|
|
|
if (emitter)
|
|
|
|
{
|
|
|
|
serializer.write(true);
|
|
|
|
emitter->serialize(serializer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer.write(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void serialize(OutputBlob& serializer) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
serializeCameras(serializer);
|
|
|
|
serializeRenderables(serializer);
|
|
|
|
serializeLights(serializer);
|
|
|
|
serializeTerrains(serializer);
|
2015-11-07 21:34:38 +01:00
|
|
|
serializeParticleEmitters(serializer);
|
2016-05-02 21:41:18 +02:00
|
|
|
serializeBoneAttachments(serializer);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-02-15 15:50:24 +01:00
|
|
|
void deserializeRenderParams(InputBlob& serializer)
|
|
|
|
{
|
2016-02-26 13:49:42 +01:00
|
|
|
int dummy;
|
|
|
|
serializer.read(dummy);
|
2016-02-15 15:50:24 +01:00
|
|
|
int count;
|
|
|
|
serializer.read(count);
|
2016-02-26 13:49:42 +01:00
|
|
|
char tmp[32];
|
|
|
|
bool any = false;
|
2016-02-15 15:50:24 +01:00
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
2016-02-26 13:49:42 +01:00
|
|
|
any = true;
|
|
|
|
serializer.readString(tmp, lengthOf(tmp));
|
|
|
|
float value;
|
|
|
|
serializer.read(value);
|
2016-02-15 15:50:24 +01:00
|
|
|
}
|
|
|
|
serializer.read(count);
|
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
2016-02-26 13:49:42 +01:00
|
|
|
any = true;
|
|
|
|
serializer.readString(tmp, lengthOf(tmp));
|
|
|
|
Vec4 value;
|
|
|
|
serializer.read(value);
|
|
|
|
}
|
|
|
|
if(any)
|
|
|
|
{
|
|
|
|
g_log_warning.log("Renderer") << "Render params are deprecated";
|
2016-02-15 15:50:24 +01:00
|
|
|
}
|
|
|
|
}
|
2015-11-07 21:34:38 +01:00
|
|
|
|
2016-02-26 13:49:42 +01:00
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
void deserializeCameras(InputBlob& serializer, RenderSceneVersion version)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
int32 size;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
|
|
|
m_cameras.resize(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
Camera& camera = m_cameras[i];
|
2016-04-17 21:47:54 +02:00
|
|
|
serializer.read(camera.entity);
|
|
|
|
serializer.read(camera.far);
|
|
|
|
serializer.read(camera.fov);
|
|
|
|
serializer.read(camera.is_ortho);
|
|
|
|
if (version <= RenderSceneVersion::ORTHO_CAMERA)
|
|
|
|
{
|
|
|
|
camera.is_ortho = false;
|
|
|
|
camera.ortho_size = 10;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer.read(camera.ortho_size);
|
|
|
|
}
|
|
|
|
serializer.read(camera.is_free);
|
|
|
|
serializer.read(camera.near);
|
|
|
|
serializer.readString(camera.slot, sizeof(camera.slot));
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
if (!camera.is_free)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
m_universe.addComponent(m_cameras[i].entity, CAMERA_HASH, this, i);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-01-22 01:11:04 +01:00
|
|
|
void deserializeRenderables(InputBlob& serializer, RenderSceneVersion version)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
int32 size = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
2015-09-26 15:12:28 +02:00
|
|
|
for (int i = 0; i < m_renderables.size(); ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
if (m_renderables[i].entity != INVALID_ENTITY)
|
|
|
|
{
|
|
|
|
setModel(i, nullptr);
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
m_culling_system->clear();
|
|
|
|
m_renderables.clear();
|
|
|
|
m_renderables.reserve(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
auto& r = m_renderables.emplace();
|
2015-12-10 20:27:51 +01:00
|
|
|
serializer.read(r.entity);
|
|
|
|
ASSERT(r.entity == i || r.entity == INVALID_ENTITY);
|
|
|
|
r.model = nullptr;
|
|
|
|
r.pose = nullptr;
|
2016-02-06 00:44:43 +01:00
|
|
|
r.custom_meshes = false;
|
|
|
|
r.meshes = nullptr;
|
|
|
|
r.mesh_count = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
if(r.entity != INVALID_ENTITY)
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2015-12-10 21:56:17 +01:00
|
|
|
serializer.read(r.layer_mask);
|
2015-12-10 20:27:51 +01:00
|
|
|
r.matrix = m_universe.getMatrix(r.entity);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
uint32 path;
|
|
|
|
serializer.read(path);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-02-09 20:40:04 +01:00
|
|
|
if (path != 0)
|
|
|
|
{
|
|
|
|
auto* model = static_cast<Model*>(m_engine.getResourceManager()
|
|
|
|
.get(ResourceManager::MODEL)
|
|
|
|
->load(Path(path)));
|
|
|
|
setModel(r.entity, model);
|
|
|
|
}
|
2016-01-22 01:11:04 +01:00
|
|
|
|
|
|
|
if (version > RenderSceneVersion::RENDERABLE_MATERIALS)
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
int material_count;
|
|
|
|
serializer.read(material_count);
|
|
|
|
if (material_count > 0)
|
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
allocateCustomMeshes(r, material_count);
|
2016-01-22 01:11:04 +01:00
|
|
|
for (int j = 0; j < material_count; ++j)
|
|
|
|
{
|
|
|
|
char path[MAX_PATH_LENGTH];
|
|
|
|
serializer.readString(path, lengthOf(path));
|
|
|
|
Material* material = static_cast<Material*>(
|
|
|
|
m_engine.getResourceManager().get(ResourceManager::MATERIAL)->load(Path(path)));
|
2016-02-06 00:44:43 +01:00
|
|
|
r.meshes[j].material = material;
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2016-01-22 01:11:04 +01:00
|
|
|
|
|
|
|
m_universe.addComponent(r.entity, RENDERABLE_HASH, this, r.entity);
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void deserializeLights(InputBlob& serializer, RenderSceneVersion version)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
int32 size = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
2016-01-26 10:27:31 +01:00
|
|
|
m_point_lights_map.clear();
|
2015-07-21 20:10:50 +02:00
|
|
|
m_point_lights.resize(size);
|
|
|
|
m_light_influenced_geometry.clear();
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
m_light_influenced_geometry.push(Array<int>(m_allocator));
|
|
|
|
PointLight& light = m_point_lights[i];
|
2016-02-10 12:09:09 +01:00
|
|
|
if (version > RenderSceneVersion::SPECULAR_INTENSITY)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
|
|
|
serializer.read(light);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer.read(light.m_diffuse_color);
|
2016-02-10 12:09:09 +01:00
|
|
|
serializer.read(light.m_specular_color);
|
|
|
|
serializer.read(light.m_diffuse_intensity);
|
2015-11-08 11:44:20 +01:00
|
|
|
serializer.read(light.m_entity);
|
2016-02-10 12:09:09 +01:00
|
|
|
serializer.read(light.m_uid);
|
2015-11-08 11:44:20 +01:00
|
|
|
serializer.read(light.m_fov);
|
2016-02-10 12:09:09 +01:00
|
|
|
serializer.read(light.m_attenuation_param);
|
|
|
|
serializer.read(light.m_range);
|
2015-11-08 11:44:20 +01:00
|
|
|
serializer.read(light.m_cast_shadows);
|
2016-02-10 12:09:09 +01:00
|
|
|
uint8 padding;
|
|
|
|
for(int j = 0; j < 3; ++j) serializer.read(padding);
|
|
|
|
light.m_specular_intensity = 1;
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2016-01-26 16:49:47 +01:00
|
|
|
m_point_lights_map.insert(light.m_uid, i);
|
2015-11-08 11:44:20 +01:00
|
|
|
|
|
|
|
m_universe.addComponent(light.m_entity, POINT_LIGHT_HASH, this, light.m_uid);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
serializer.read(m_point_light_last_uid);
|
|
|
|
|
|
|
|
serializer.read(size);
|
|
|
|
m_global_lights.resize(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
GlobalLight& light = m_global_lights[i];
|
2016-01-28 21:44:35 +01:00
|
|
|
light.m_specular.set(0, 0, 0);
|
2016-02-10 12:09:09 +01:00
|
|
|
if (version > RenderSceneVersion::SPECULAR_INTENSITY)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
|
|
|
serializer.read(light);
|
|
|
|
}
|
2016-01-28 21:44:35 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
serializer.read(light.m_uid);
|
2016-02-10 12:09:09 +01:00
|
|
|
serializer.read(light.m_diffuse_color);
|
|
|
|
serializer.read(light.m_specular);
|
|
|
|
serializer.read(light.m_diffuse_intensity);
|
2016-01-28 21:44:35 +01:00
|
|
|
serializer.read(light.m_ambient_color);
|
|
|
|
serializer.read(light.m_ambient_intensity);
|
|
|
|
serializer.read(light.m_fog_color);
|
|
|
|
serializer.read(light.m_fog_density);
|
|
|
|
serializer.read(light.m_fog_bottom);
|
|
|
|
serializer.read(light.m_fog_height);
|
|
|
|
serializer.read(light.m_entity);
|
|
|
|
serializer.read(light.m_cascades);
|
2016-02-10 12:09:09 +01:00
|
|
|
light.m_specular_intensity = 1;
|
2016-01-28 21:44:35 +01:00
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
m_universe.addComponent(light.m_entity, GLOBAL_LIGHT_HASH, this, light.m_uid);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
serializer.read(m_global_light_last_uid);
|
|
|
|
serializer.read(m_active_global_light_uid);
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-03-25 19:53:41 +01:00
|
|
|
void deserializeTerrains(InputBlob& serializer, RenderSceneVersion version)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
int32 size = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
2015-09-26 13:51:55 +02:00
|
|
|
int old_size = m_terrains.size();
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = size; i < m_terrains.size(); ++i)
|
|
|
|
{
|
2015-11-11 23:25:44 +01:00
|
|
|
LUMIX_DELETE(m_allocator, m_terrains[i]);
|
2015-07-25 19:33:19 +02:00
|
|
|
m_terrains[i] = nullptr;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
m_terrains.resize(size);
|
2015-09-26 13:51:55 +02:00
|
|
|
for (int i = old_size; i < size; ++i)
|
|
|
|
{
|
|
|
|
m_terrains[i] = nullptr;
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
bool exists;
|
|
|
|
serializer.read(exists);
|
|
|
|
if (exists)
|
|
|
|
{
|
2015-09-26 13:51:55 +02:00
|
|
|
if (!m_terrains[i])
|
|
|
|
{
|
2015-11-11 23:25:44 +01:00
|
|
|
m_terrains[i] = LUMIX_NEW(m_allocator, Terrain)(
|
2015-09-26 13:51:55 +02:00
|
|
|
m_renderer, INVALID_ENTITY, *this, m_allocator);
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
Terrain* terrain = m_terrains[i];
|
2016-03-25 19:53:41 +01:00
|
|
|
terrain->deserialize(serializer, m_universe, *this, i, (int)version);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-07-25 19:33:19 +02:00
|
|
|
m_terrains[i] = nullptr;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-07 21:34:38 +01:00
|
|
|
|
|
|
|
int getVersion() const override
|
|
|
|
{
|
|
|
|
return (int)RenderSceneVersion::LATEST;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void deserialize(InputBlob& serializer, int version) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
deserializeCameras(serializer, (RenderSceneVersion)version);
|
2016-01-22 01:11:04 +01:00
|
|
|
deserializeRenderables(serializer, (RenderSceneVersion)version);
|
2015-11-08 11:44:20 +01:00
|
|
|
deserializeLights(serializer, (RenderSceneVersion)version);
|
2016-03-25 19:53:41 +01:00
|
|
|
deserializeTerrains(serializer, (RenderSceneVersion)version);
|
2015-12-12 00:46:27 +01:00
|
|
|
if (version >= 0) deserializeParticleEmitters(serializer, version);
|
2016-02-26 13:49:42 +01:00
|
|
|
if (version >= (int)RenderSceneVersion::RENDER_PARAMS &&
|
|
|
|
version < (int)RenderSceneVersion::RENDER_PARAMS_REMOVED)
|
|
|
|
{
|
|
|
|
deserializeRenderParams(serializer);
|
|
|
|
}
|
2016-05-02 21:41:18 +02:00
|
|
|
deserializeBoneAttachments(serializer, version);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyBoneAttachment(ComponentIndex component)
|
|
|
|
{
|
|
|
|
int idx = getBoneAttachmentIdx(component);
|
|
|
|
Entity entity = m_bone_attachments[idx].entity;
|
|
|
|
m_bone_attachments.eraseFast(idx);
|
|
|
|
m_universe.destroyComponent(entity, BONE_ATTACHMENT_HASH, this, component);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2014-08-17 17:55:34 +02:00
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
void destroyRenderable(ComponentIndex component)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 22:38:11 +02:00
|
|
|
m_renderable_destroyed.invoke(component);
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < m_light_influenced_geometry.size(); ++i)
|
|
|
|
{
|
|
|
|
Array<int>& influenced_geometry = m_light_influenced_geometry[i];
|
|
|
|
for (int j = 0; j < influenced_geometry.size(); ++j)
|
2014-11-16 22:13:33 +01:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
if (influenced_geometry[j] == component)
|
2015-07-15 20:31:40 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
influenced_geometry.erase(j);
|
2016-02-14 11:32:56 +01:00
|
|
|
break;
|
2014-11-16 22:13:33 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-11-16 22:13:33 +01:00
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
setModel(component, nullptr);
|
2015-12-10 20:27:51 +01:00
|
|
|
Entity entity = m_renderables[component].entity;
|
|
|
|
LUMIX_DELETE(m_allocator, m_renderables[component].pose);
|
2016-02-07 12:31:28 +01:00
|
|
|
m_renderables[component].pose = nullptr;
|
2015-12-10 20:27:51 +01:00
|
|
|
m_renderables[component].entity = INVALID_ENTITY;
|
2015-07-24 22:38:11 +02:00
|
|
|
m_universe.destroyComponent(entity, RENDERABLE_HASH, this, component);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-17 17:55:34 +02:00
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
|
|
|
|
void destroyGlobalLight(ComponentIndex component)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
Entity entity = m_global_lights[getGlobalLightIndex(component)].m_entity;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
m_universe.destroyComponent(entity, GLOBAL_LIGHT_HASH, this, component);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
if (component == m_active_global_light_uid)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
m_active_global_light_uid = -1;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-12-08 22:35:41 +01:00
|
|
|
m_global_lights.eraseFast(getGlobalLightIndex(component));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyPointLight(ComponentIndex component)
|
|
|
|
{
|
|
|
|
int index = getPointLightIndex(component);
|
|
|
|
Entity entity = m_point_lights[getPointLightIndex(component)].m_entity;
|
|
|
|
m_point_lights.eraseFast(index);
|
2016-01-26 10:27:31 +01:00
|
|
|
m_point_lights_map.erase(component);
|
2015-12-08 22:35:41 +01:00
|
|
|
m_light_influenced_geometry.eraseFast(index);
|
|
|
|
m_universe.destroyComponent(entity, POINT_LIGHT_HASH, this, component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyCamera(ComponentIndex component)
|
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
Entity entity = m_cameras[component].entity;
|
|
|
|
m_cameras[component].is_free = true;
|
2015-12-08 22:35:41 +01:00
|
|
|
m_universe.destroyComponent(entity, CAMERA_HASH, this, component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyTerrain(ComponentIndex component)
|
|
|
|
{
|
|
|
|
Entity entity = m_terrains[component]->getEntity();
|
|
|
|
LUMIX_DELETE(m_allocator, m_terrains[component]);
|
|
|
|
m_terrains[component] = nullptr;
|
|
|
|
m_universe.destroyComponent(entity, TERRAIN_HASH, this, component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyParticleEmitter(ComponentIndex component)
|
|
|
|
{
|
|
|
|
Entity entity = m_particle_emitters[component]->m_entity;
|
|
|
|
LUMIX_DELETE(m_allocator, m_particle_emitters[component]);
|
|
|
|
m_particle_emitters[component] = nullptr;
|
|
|
|
m_universe.destroyComponent(entity, PARTICLE_EMITTER_HASH, this, component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyParticleEmitterFade(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for (auto* module : emitter->m_modules)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
if (module->getType() == ParticleEmitter::AlphaModule::s_type)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_FADE_HASH, this, component);
|
|
|
|
break;
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-12 01:35:22 +01:00
|
|
|
void destroyParticleEmitterForce(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
2015-12-17 13:58:40 +01:00
|
|
|
for(auto* module : emitter->m_modules)
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
2015-12-17 13:58:40 +01:00
|
|
|
if(module->getType() == ParticleEmitter::ForceModule::s_type)
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_FORCE_HASH, this, component);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-17 13:58:40 +01:00
|
|
|
void destroyParticleEmitterAttractor(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for(auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if(module->getType() == ParticleEmitter::AttractorModule::s_type)
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_ATTRACTOR_HASH, this, component);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
void destroyParticleEmitterSize(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for (auto* module : emitter->m_modules)
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
if (module->getType() == ParticleEmitter::SizeModule::s_type)
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_SIZE_HASH, this, component);
|
|
|
|
break;
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-17 00:00:50 +01:00
|
|
|
float getParticleEmitterPlaneBounce(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[cmp];
|
2015-12-17 13:58:40 +01:00
|
|
|
for(auto* module : emitter->m_modules)
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
2015-12-17 13:58:40 +01:00
|
|
|
if(module->getType() == ParticleEmitter::PlaneModule::s_type)
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
|
|
|
return static_cast<ParticleEmitter::PlaneModule*>(module)->m_bounce;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterPlaneBounce(ComponentIndex cmp, float value) override
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[cmp];
|
2015-12-17 13:58:40 +01:00
|
|
|
for(auto* module : emitter->m_modules)
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
2015-12-17 13:58:40 +01:00
|
|
|
if(module->getType() == ParticleEmitter::PlaneModule::s_type)
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
|
|
|
static_cast<ParticleEmitter::PlaneModule*>(module)->m_bounce = value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-17 13:58:40 +01:00
|
|
|
float getParticleEmitterAttractorForce(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[cmp];
|
|
|
|
for(auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if(module->getType() == ParticleEmitter::AttractorModule::s_type)
|
|
|
|
{
|
|
|
|
return static_cast<ParticleEmitter::AttractorModule*>(module)->m_force;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterAttractorForce(ComponentIndex cmp, float value) override
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[cmp];
|
|
|
|
for(auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if(module->getType() == ParticleEmitter::AttractorModule::s_type)
|
|
|
|
{
|
|
|
|
static_cast<ParticleEmitter::AttractorModule*>(module)->m_force = value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-16 21:26:19 +01:00
|
|
|
void destroyParticleEmitterPlane(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for (auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if (module->getType() == ParticleEmitter::PlaneModule::s_type)
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_PLANE_HASH, this, component);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
void destroyParticleEmitterLinearMovement(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for (auto* module : emitter->m_modules)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
if (module->getType() == ParticleEmitter::LinearMovementModule::s_type)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH, this, component);
|
|
|
|
break;
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-18 21:23:51 +01:00
|
|
|
void destroyParticleEmitterSpawnShape(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for (auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if (module->getType() == ParticleEmitter::SpawnShapeModule::s_type)
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_SPAWN_SHAPE_HASH, this, component);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
void destroyParticleEmitterRandomRotation(ComponentIndex component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[component];
|
|
|
|
for (auto* module : emitter->m_modules)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
if (module->getType() == ParticleEmitter::RandomRotationModule::s_type)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2015-12-08 22:35:41 +01:00
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(
|
|
|
|
emitter->m_entity, PARTICLE_EMITTER_RANDOM_ROTATION_HASH, this, component);
|
|
|
|
break;
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-17 17:55:34 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
void destroyComponent(ComponentIndex component, uint32 type) override;
|
|
|
|
|
|
|
|
|
2015-12-07 14:50:31 +01:00
|
|
|
void setParticleEmitterAlpha(ComponentIndex cmp, const Vec2* values, int count) override
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-07 14:50:31 +01:00
|
|
|
ASSERT(count > 0);
|
2015-12-07 21:49:27 +01:00
|
|
|
ASSERT(values[1].x < 0.001f);
|
|
|
|
ASSERT(values[count - 2].x > 0.999f);
|
2015-12-07 14:50:31 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* alpha_module = getEmitterModule<ParticleEmitter::AlphaModule>(cmp);
|
|
|
|
if (!alpha_module) return;
|
2016-02-10 12:09:09 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
alpha_module->m_values.resize(count);
|
|
|
|
for (int i = 0; i < count; ++i)
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
alpha_module->m_values[i] = values[i];
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
alpha_module->sample();
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-12 01:35:22 +01:00
|
|
|
void setParticleEmitterAcceleration(ComponentIndex cmp, const Vec3& value) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::ForceModule>(cmp);
|
|
|
|
if (module) module->m_acceleration = value;
|
2015-12-12 01:35:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec3 getParticleEmitterAcceleration(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::ForceModule>(cmp);
|
|
|
|
return module ? module->m_acceleration : Vec3();
|
2015-12-12 01:35:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-07 00:55:32 +01:00
|
|
|
int getParticleEmitterSizeCount(ComponentIndex cmp) override
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SizeModule>(cmp);
|
|
|
|
return module ? module->m_values.size() : 0;
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-07 00:55:32 +01:00
|
|
|
const Vec2* getParticleEmitterSize(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SizeModule>(cmp);
|
|
|
|
return module ? &module->m_values[0] : nullptr;
|
2015-12-07 00:55:32 +01:00
|
|
|
}
|
2015-11-18 20:18:48 +01:00
|
|
|
|
|
|
|
|
2015-12-07 00:55:32 +01:00
|
|
|
void setParticleEmitterSize(ComponentIndex cmp, const Vec2* values, int count) override
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-07 00:55:32 +01:00
|
|
|
ASSERT(count > 0);
|
|
|
|
ASSERT(values[0].x < 0.001f);
|
|
|
|
ASSERT(values[count-1].x > 0.999f);
|
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SizeModule>(cmp);
|
|
|
|
if (!module) return;
|
|
|
|
|
|
|
|
auto size_module = static_cast<ParticleEmitter::SizeModule*>(module);
|
|
|
|
size_module->m_values.resize(count);
|
|
|
|
for (int i = 0; i < count; ++i)
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
size_module->m_values[i] = values[i];
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
size_module->sample();
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
template <typename T>
|
|
|
|
T* getEmitterModule(ComponentIndex cmp) const
|
2015-12-07 14:50:31 +01:00
|
|
|
{
|
|
|
|
auto& modules = m_particle_emitters[cmp]->m_modules;
|
2015-12-17 21:38:23 +01:00
|
|
|
for (auto* module : modules)
|
2015-12-07 14:50:31 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
if (module->getType() == T::s_type)
|
2015-12-07 14:50:31 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
return static_cast<T*>(module);
|
2015-12-07 14:50:31 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int getParticleEmitterAlphaCount(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AlphaModule>(cmp);
|
|
|
|
return module ? module->m_values.size() : 0;
|
2015-12-07 14:50:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const Vec2* getParticleEmitterAlpha(ComponentIndex cmp) override
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AlphaModule>(cmp);
|
|
|
|
return module ? &module->m_values[0] : 0;
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec2 getParticleEmitterLinearMovementX(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::LinearMovementModule>(cmp);
|
|
|
|
return module ? Vec2(module->m_x.from, module->m_x.to) : Vec2(0, 0);
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterLinearMovementX(ComponentIndex cmp, const Vec2& value) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::LinearMovementModule>(cmp);
|
2016-01-12 22:59:11 +01:00
|
|
|
if (module)
|
|
|
|
{
|
|
|
|
module->m_x = value;
|
|
|
|
module->m_x.check();
|
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec2 getParticleEmitterLinearMovementY(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::LinearMovementModule>(cmp);
|
|
|
|
return module ? Vec2(module->m_y.from, module->m_y.to) : Vec2(0, 0);
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterLinearMovementY(ComponentIndex cmp, const Vec2& value) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::LinearMovementModule>(cmp);
|
2016-01-12 22:59:11 +01:00
|
|
|
if (module)
|
|
|
|
{
|
|
|
|
module->m_y = value;
|
|
|
|
module->m_y.check();
|
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec2 getParticleEmitterLinearMovementZ(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::LinearMovementModule>(cmp);
|
|
|
|
return module ? Vec2(module->m_z.from, module->m_z.to) : Vec2(0, 0);
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterLinearMovementZ(ComponentIndex cmp, const Vec2& value) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::LinearMovementModule>(cmp);
|
2016-01-12 22:59:11 +01:00
|
|
|
if (module)
|
|
|
|
{
|
|
|
|
module->m_z = value;
|
|
|
|
module->m_z.check();
|
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec2 getParticleEmitterInitialLife(ComponentIndex cmp) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
|
|
|
return m_particle_emitters[cmp]->m_initial_life;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec2 getParticleEmitterSpawnPeriod(ComponentIndex cmp) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
|
|
|
return m_particle_emitters[cmp]->m_spawn_period;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setParticleEmitterInitialLife(ComponentIndex cmp, const Vec2& value) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
|
|
|
m_particle_emitters[cmp]->m_initial_life = value;
|
2016-01-12 22:59:11 +01:00
|
|
|
m_particle_emitters[cmp]->m_initial_life.checkZero();
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setParticleEmitterInitialSize(ComponentIndex cmp, const Vec2& value) override
|
2015-11-01 20:56:29 +01:00
|
|
|
{
|
|
|
|
m_particle_emitters[cmp]->m_initial_size = value;
|
2016-01-12 22:59:11 +01:00
|
|
|
m_particle_emitters[cmp]->m_initial_size.checkZero();
|
2015-11-01 20:56:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec2 getParticleEmitterInitialSize(ComponentIndex cmp) override
|
2015-11-01 20:56:29 +01:00
|
|
|
{
|
|
|
|
return m_particle_emitters[cmp]->m_initial_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setParticleEmitterSpawnPeriod(ComponentIndex cmp, const Vec2& value) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
|
|
|
m_particle_emitters[cmp]->m_spawn_period = value;
|
2015-11-04 22:43:54 +01:00
|
|
|
m_particle_emitters[cmp]->m_spawn_period.from =
|
2016-03-06 12:54:29 +01:00
|
|
|
Math::maximum(0.01f, m_particle_emitters[cmp]->m_spawn_period.from);
|
2016-01-12 22:59:11 +01:00
|
|
|
m_particle_emitters[cmp]->m_spawn_period.checkZero();
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
ComponentIndex createCamera(Entity entity)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
Camera& camera = m_cameras.emplace();
|
2016-04-17 21:47:54 +02:00
|
|
|
camera.is_free = false;
|
|
|
|
camera.is_ortho = false;
|
|
|
|
camera.ortho_size = 10;
|
|
|
|
camera.entity = entity;
|
|
|
|
camera.fov = 60;
|
|
|
|
camera.screen_width = 800;
|
|
|
|
camera.screen_height = 600;
|
|
|
|
camera.aspect = 800.0f / 600.0f;
|
|
|
|
camera.near = 0.1f;
|
|
|
|
camera.far = 10000.0f;
|
|
|
|
camera.slot[0] = '\0';
|
2015-12-08 22:35:41 +01:00
|
|
|
m_universe.addComponent(entity, CAMERA_HASH, this, m_cameras.size() - 1);
|
|
|
|
return m_cameras.size() - 1;
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
ComponentIndex createTerrain(Entity entity)
|
|
|
|
{
|
|
|
|
Terrain* terrain = LUMIX_NEW(m_allocator, Terrain)(
|
|
|
|
m_renderer, entity, *this, m_allocator);
|
|
|
|
m_terrains.push(terrain);
|
|
|
|
m_universe.addComponent(entity, TERRAIN_HASH, this, m_terrains.size() - 1);
|
|
|
|
return m_terrains.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ComponentIndex createComponent(uint32 type, Entity entity) override;
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex createParticleEmitterRandomRotation(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::RandomRotationModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_RANDOM_ROTATION_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-16 21:26:19 +01:00
|
|
|
ComponentIndex createParticleEmitterPlane(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::PlaneModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_PLANE_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex createParticleEmitterLinearMovement(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::LinearMovementModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-18 21:23:51 +01:00
|
|
|
ComponentIndex createParticleEmitterSpawnShape(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::SpawnShapeModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SPAWN_SHAPE_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex createParticleEmitterFade(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::AlphaModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_FADE_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
2015-07-24 22:38:11 +02:00
|
|
|
return INVALID_COMPONENT;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2014-10-31 22:53:37 +01:00
|
|
|
|
2015-12-12 01:35:22 +01:00
|
|
|
ComponentIndex createParticleEmitterForce(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::ForceModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_FORCE_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-17 13:58:40 +01:00
|
|
|
ComponentIndex createParticleEmitterAttractor(Entity entity)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if(emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::AttractorModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_ATTRACTOR_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-11-18 20:18:48 +01:00
|
|
|
ComponentIndex createParticleEmitterSize(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_particle_emitters.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[i];
|
|
|
|
if (emitter->m_entity == entity)
|
|
|
|
{
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::SizeModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SIZE_HASH, this, i);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-30 21:11:11 +01:00
|
|
|
ComponentIndex createParticleEmitter(Entity entity)
|
|
|
|
{
|
|
|
|
int index = -1;
|
|
|
|
for (int i = 0, c = m_particle_emitters.size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
if (!m_particle_emitters[i])
|
|
|
|
{
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == -1)
|
|
|
|
{
|
|
|
|
index = m_particle_emitters.size();
|
|
|
|
m_particle_emitters.push(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_particle_emitters[index] =
|
|
|
|
LUMIX_NEW(m_allocator, ParticleEmitter)(entity, m_universe, m_allocator);
|
|
|
|
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_HASH, this, index);
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Renderable* getRenderables() override
|
|
|
|
{
|
|
|
|
return &m_renderables[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Renderable* getRenderable(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return &m_renderables[cmp];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex getRenderableComponent(Entity entity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
ComponentIndex cmp = (ComponentIndex)entity;
|
2016-01-15 23:21:37 +01:00
|
|
|
if (cmp >= m_renderables.size()) return INVALID_COMPONENT;
|
|
|
|
if (m_renderables[cmp].entity == INVALID_ENTITY) return INVALID_COMPONENT;
|
2015-12-10 17:09:52 +01:00
|
|
|
return cmp;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-31 22:53:37 +01:00
|
|
|
|
|
|
|
|
2015-08-27 23:59:36 +02:00
|
|
|
Frustum getPointLightFrustum(ComponentIndex index) const
|
|
|
|
{
|
|
|
|
const PointLight& light = m_point_lights[index];
|
|
|
|
Frustum frustum;
|
|
|
|
frustum.computeOrtho(m_universe.getPosition(light.m_entity),
|
2016-04-17 21:47:54 +02:00
|
|
|
Vec3(1, 0, 0),
|
|
|
|
Vec3(0, 1, 0),
|
|
|
|
light.m_range,
|
|
|
|
light.m_range,
|
|
|
|
-light.m_range,
|
|
|
|
light.m_range);
|
2015-08-27 23:59:36 +02:00
|
|
|
|
|
|
|
return frustum;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
void onEntityDestroyed(Entity entity)
|
|
|
|
{
|
|
|
|
for (auto& i : m_bone_attachments)
|
|
|
|
{
|
|
|
|
if (i.parent_entity == entity)
|
|
|
|
{
|
|
|
|
i.parent_entity = INVALID_ENTITY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
void onEntityMoved(Entity entity)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
ComponentIndex cmp = (ComponentIndex)entity;
|
|
|
|
|
2015-12-10 22:01:05 +01:00
|
|
|
if (cmp < m_renderables.size() && m_renderables[cmp].entity != INVALID_ENTITY &&
|
|
|
|
m_renderables[cmp].model && m_renderables[cmp].model->isReady())
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
Renderable& r = m_renderables[cmp];
|
2015-12-10 20:27:51 +01:00
|
|
|
r.matrix = m_universe.getMatrix(entity);
|
2015-12-10 17:09:52 +01:00
|
|
|
m_culling_system->updateBoundingPosition(m_universe.getPosition(entity), cmp);
|
2016-01-25 21:52:08 +01:00
|
|
|
if (r.model && r.model->isReady())
|
|
|
|
{
|
|
|
|
float radius = m_universe.getScale(entity) * r.model->getBoundingRadius();
|
|
|
|
m_culling_system->updateBoundingRadius(radius, cmp);
|
|
|
|
}
|
2015-12-10 17:09:52 +01:00
|
|
|
|
|
|
|
if(m_is_forward_rendered)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 23:33:21 +01:00
|
|
|
float bounding_radius = r.model ? r.model->getBoundingRadius() : 1;
|
|
|
|
for (int light_idx = 0, c = m_point_lights.size(); light_idx < c; ++light_idx)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
for (int j = 0, c2 = m_light_influenced_geometry[light_idx].size(); j < c2; ++j)
|
|
|
|
{
|
|
|
|
if(m_light_influenced_geometry[light_idx][j] == cmp)
|
|
|
|
{
|
|
|
|
m_light_influenced_geometry[light_idx].eraseFast(j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Vec3 pos = m_universe.getPosition(r.entity);
|
2015-12-10 17:09:52 +01:00
|
|
|
Frustum frustum = getPointLightFrustum(light_idx);
|
|
|
|
if(frustum.isSphereInside(pos, bounding_radius))
|
|
|
|
{
|
|
|
|
m_light_influenced_geometry[light_idx].push(cmp);
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0, c = m_point_lights.size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
if (m_point_lights[i].m_entity == entity)
|
2014-07-20 00:45:57 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
detectLightInfluencedGeometry(i);
|
|
|
|
break;
|
2014-07-20 00:45:57 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-05-02 21:41:18 +02:00
|
|
|
|
|
|
|
bool was_updating = m_is_updating_attachments;
|
|
|
|
m_is_updating_attachments = true;
|
|
|
|
for (auto& attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
if (attachment.parent_entity == entity)
|
|
|
|
{
|
|
|
|
updateBoneAttachment(attachment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_is_updating_attachments = was_updating;
|
|
|
|
|
|
|
|
if (m_is_updating_attachments || m_is_game_running) return;
|
|
|
|
for (auto& attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
if (attachment.entity == entity)
|
|
|
|
{
|
|
|
|
updateRelativeMatrix(attachment);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-07-20 00:45:57 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Engine& getEngine() const override { return m_engine; }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
|
|
|
|
2016-03-11 23:26:38 +01:00
|
|
|
Entity getTerrainEntity(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return m_terrains[cmp]->getEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec2 getTerrainResolution(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return Vec2((float)m_terrains[cmp]->getWidth(), (float)m_terrains[cmp]->getHeight());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ComponentIndex getFirstTerrain() override
|
|
|
|
{
|
|
|
|
if (m_terrains.empty()) return INVALID_COMPONENT;
|
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_terrains[i]) return i;
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ComponentIndex getNextTerrain(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
for (int i = cmp + 1; i < m_terrains.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_terrains[i]) return i;
|
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex getTerrainComponent(Entity entity) override
|
2015-09-12 12:44:04 +02:00
|
|
|
{
|
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
|
|
|
auto* terrain = m_terrains[i];
|
|
|
|
if (terrain && terrain->getEntity() == entity)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-03 12:50:58 +02:00
|
|
|
Vec3 getTerrainNormalAt(ComponentIndex cmp, float x, float z) override
|
2015-10-21 21:36:01 +02:00
|
|
|
{
|
2015-10-21 22:22:47 +02:00
|
|
|
return m_terrains[cmp]->getNormal(x, z);
|
2015-10-21 21:36:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getTerrainHeightAt(ComponentIndex cmp, float x, float z) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_terrains[cmp]->getHeight(x, z);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-06 22:21:09 +02:00
|
|
|
|
2014-09-30 22:37:49 +02:00
|
|
|
|
2016-03-13 01:27:25 +01:00
|
|
|
AABB getTerrainAABB(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-03-13 01:27:25 +01:00
|
|
|
return m_terrains[cmp]->getAABB();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec2 getTerrainSize(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return m_terrains[cmp]->getSize();
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-30 22:37:49 +02:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
void setTerrainMaterialPath(ComponentIndex cmp, const Path& path) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-12 23:49:56 +01:00
|
|
|
if (path.isValid())
|
|
|
|
{
|
|
|
|
Material* material = static_cast<Material*>(
|
|
|
|
m_engine.getResourceManager().get(ResourceManager::MATERIAL)->load(path));
|
|
|
|
m_terrains[cmp]->setMaterial(material);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_terrains[cmp]->setMaterial(nullptr);
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Material* getTerrainMaterial(ComponentIndex cmp) override
|
2015-07-31 00:28:06 +02:00
|
|
|
{
|
|
|
|
return m_terrains[cmp]->getMaterial();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
Path getTerrainMaterialPath(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
if (m_terrains[cmp]->getMaterial())
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-06 14:18:59 +01:00
|
|
|
return m_terrains[cmp]->getMaterial()->getPath();
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-01-06 14:18:59 +01:00
|
|
|
return Path("");
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setTerrainXZScale(ComponentIndex cmp, float scale) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_terrains[cmp]->setXZScale(scale);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
float getTerrainXZScale(ComponentIndex cmp) override { return m_terrains[cmp]->getXZScale(); }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-07-09 21:33:35 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setTerrainYScale(ComponentIndex cmp, float scale) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_terrains[cmp]->setYScale(scale);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-07-09 21:33:35 +02:00
|
|
|
|
2016-05-03 12:50:58 +02:00
|
|
|
float getTerrainYScale(ComponentIndex cmp) override { return m_terrains[cmp]->getYScale(); }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Pose* getPose(ComponentIndex cmp) override { return m_renderables[cmp].pose; }
|
2014-10-29 20:08:31 +01:00
|
|
|
|
2014-06-20 22:54:32 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Entity getRenderableEntity(ComponentIndex cmp) override { return m_renderables[cmp].entity; }
|
2015-07-24 22:38:11 +02:00
|
|
|
|
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Model* getRenderableModel(ComponentIndex cmp) override { return m_renderables[cmp].model; }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-10-31 21:25:03 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void showRenderable(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 21:56:17 +01:00
|
|
|
if (!m_renderables[cmp].model || !m_renderables[cmp].model->isReady()) return;
|
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Sphere sphere(m_universe.getPosition(m_renderables[cmp].entity),
|
2015-12-10 21:56:17 +01:00
|
|
|
m_renderables[cmp].model->getBoundingRadius());
|
2015-12-10 17:09:52 +01:00
|
|
|
m_culling_system->addStatic(cmp, sphere);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-31 21:25:03 +01:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void hideRenderable(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
m_culling_system->removeStatic(cmp);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
Path getRenderablePath(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-06 14:18:59 +01:00
|
|
|
return m_renderables[cmp].model ? m_renderables[cmp].model->getPath() : Path("");
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
void setRenderableLayer(ComponentIndex cmp, const int32& layer) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
m_culling_system->setLayerMask(cmp, (int64)1 << (int64)layer);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2016-01-22 01:11:04 +01:00
|
|
|
int getRenderableMaterialsCount(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return m_renderables[cmp].model ? m_renderables[cmp].mesh_count : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
void setRenderablePath(ComponentIndex cmp, const Path& path) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
Renderable& r = m_renderables[cmp];
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
auto* manager = m_engine.getResourceManager().get(ResourceManager::MODEL);
|
2016-02-12 23:49:56 +01:00
|
|
|
if (path.isValid())
|
|
|
|
{
|
|
|
|
Model* model = static_cast<Model*>(manager->load(path));
|
|
|
|
setModel(cmp, model);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setModel(cmp, nullptr);
|
|
|
|
}
|
2015-12-10 20:27:51 +01:00
|
|
|
r.matrix = m_universe.getMatrix(r.entity);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-07-08 22:31:01 +02:00
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
void forceGrassUpdate(ComponentIndex cmp) override { m_terrains[cmp]->forceGrassUpdate(); }
|
2015-10-22 20:06:12 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void getTerrainInfos(Array<const TerrainInfo*>& infos,
|
2016-02-23 19:46:43 +01:00
|
|
|
const Vec3& camera_pos,
|
|
|
|
LIFOAllocator& frame_allocator) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
infos.reserve(m_terrains.size());
|
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
2016-02-16 10:17:37 +01:00
|
|
|
if (m_terrains[i])
|
2014-08-09 14:37:23 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
m_terrains[i]->getInfos(infos, camera_pos, frame_allocator);
|
2014-08-09 14:37:23 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-09 14:37:23 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void getGrassInfos(const Frustum& frustum,
|
2016-02-23 19:46:43 +01:00
|
|
|
Array<GrassInfo>& infos,
|
|
|
|
ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-10-12 09:56:46 +02:00
|
|
|
|
|
|
|
if (!m_is_grass_enabled) return;
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
2016-02-16 10:17:37 +01:00
|
|
|
if (m_terrains[i])
|
2014-09-05 21:58:21 +02:00
|
|
|
{
|
2015-10-22 23:07:56 +02:00
|
|
|
m_terrains[i]->getGrassInfos(frustum, infos, camera);
|
2014-09-05 21:58:21 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-09-05 21:58:21 +02:00
|
|
|
|
|
|
|
|
2016-03-13 01:27:25 +01:00
|
|
|
static int LUA_castCameraRay(lua_State* L)
|
|
|
|
{
|
|
|
|
auto* scene = LuaWrapper::checkArg<RenderSceneImpl*>(L, 1);
|
|
|
|
const char* slot = LuaWrapper::checkArg<const char*>(L, 2);
|
|
|
|
|
|
|
|
ComponentIndex camera_cmp = scene->getCameraInSlot(slot);
|
2016-04-17 21:47:54 +02:00
|
|
|
Vec3 origin = scene->m_universe.getPosition(scene->m_cameras[camera_cmp].entity);
|
|
|
|
Quat rot = scene->m_universe.getRotation(scene->m_cameras[camera_cmp].entity);
|
2016-03-13 01:27:25 +01:00
|
|
|
|
|
|
|
RayCastModelHit hit = scene->castRay(origin, rot * Vec3(0, 0, -1), INVALID_COMPONENT);
|
|
|
|
LuaWrapper::pushLua(L, hit.m_is_hit);
|
|
|
|
LuaWrapper::pushLua(L, hit.m_is_hit ? hit.m_origin + hit.m_dir * hit.m_t : Vec3(0, 0, 0));
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-04 22:49:53 +01:00
|
|
|
static Texture* LUA_getMaterialTexture(Material* material, int texture_index)
|
|
|
|
{
|
|
|
|
if (!material) return nullptr;
|
|
|
|
return material->getTexture(texture_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void LUA_setRenderablePath(IScene* scene, int component, const char* path)
|
|
|
|
{
|
|
|
|
RenderScene* render_scene = (RenderScene*)scene;
|
|
|
|
render_scene->setRenderablePath(component, Path(path));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-31 16:58:42 +02:00
|
|
|
static unsigned int LUA_compareTGA(RenderSceneImpl* scene, const char* path, const char* path_preimage, int min_diff)
|
|
|
|
{
|
|
|
|
auto& fs = scene->m_engine.getFileSystem();
|
|
|
|
auto file1 = fs.open(fs.getDefaultDevice(), Lumix::Path(path), Lumix::FS::Mode::OPEN_AND_READ);
|
|
|
|
auto file2 = fs.open(fs.getDefaultDevice(), Lumix::Path(path_preimage), Lumix::FS::Mode::OPEN_AND_READ);
|
|
|
|
if (!file1)
|
|
|
|
{
|
|
|
|
if (file2) fs.close(*file2);
|
|
|
|
Lumix::g_log_error.log("render_test") << "Failed to open " << path;
|
|
|
|
return 0xffffFFFF;
|
|
|
|
}
|
|
|
|
else if (!file2)
|
|
|
|
{
|
|
|
|
fs.close(*file1);
|
|
|
|
Lumix::g_log_error.log("render_test") << "Failed to open " << path_preimage;
|
|
|
|
return 0xffffFFFF;
|
|
|
|
}
|
|
|
|
return Lumix::Texture::compareTGA(scene->m_allocator, file1, file2, min_diff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void LUA_makeScreenshot(RenderSceneImpl* scene, const char* path)
|
|
|
|
{
|
|
|
|
scene->m_renderer.makeScreenshot(Path(path));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-04 22:49:53 +01:00
|
|
|
static void LUA_setRenderableMaterial(RenderScene* scene,
|
|
|
|
ComponentIndex cmp,
|
|
|
|
int index,
|
|
|
|
const char* path)
|
|
|
|
{
|
|
|
|
scene->setRenderableMaterial(cmp, index, Path(path));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
bool isGrassEnabled() const override
|
2015-10-12 09:56:46 +02:00
|
|
|
{
|
|
|
|
return m_is_grass_enabled;
|
|
|
|
}
|
2016-02-24 20:46:14 +01:00
|
|
|
|
2015-10-18 22:27:54 +02:00
|
|
|
|
2016-03-25 19:53:41 +01:00
|
|
|
float getGrassDistance(ComponentIndex cmp, int index) override
|
2015-10-18 22:27:54 +02:00
|
|
|
{
|
2016-03-25 19:53:41 +01:00
|
|
|
return m_terrains[cmp]->getGrassTypeDistance(index);
|
2015-10-18 22:27:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-25 19:53:41 +01:00
|
|
|
void setGrassDistance(ComponentIndex cmp, int index, float value) override
|
2015-10-18 22:27:54 +02:00
|
|
|
{
|
2016-03-25 19:53:41 +01:00
|
|
|
m_terrains[cmp]->setGrassTypeDistance(index, value);
|
2015-10-18 22:27:54 +02:00
|
|
|
}
|
|
|
|
|
2016-02-24 20:46:14 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void enableGrass(bool enabled) override
|
2015-10-12 09:56:46 +02:00
|
|
|
{
|
|
|
|
m_is_grass_enabled = enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void
|
2015-07-24 08:42:35 +02:00
|
|
|
setGrassDensity(ComponentIndex cmp, int index, int density) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_terrains[cmp]->setGrassTypeDensity(index, density);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-05 21:58:21 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
int getGrassDensity(ComponentIndex cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_terrains[cmp]->getGrassTypeDensity(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-05 21:58:21 +02:00
|
|
|
|
2014-09-05 21:12:20 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void
|
2015-07-24 08:42:35 +02:00
|
|
|
setGrassGround(ComponentIndex cmp, int index, int ground) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_terrains[cmp]->setGrassTypeGround(index, ground);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-05 21:12:20 +02:00
|
|
|
|
2014-08-10 13:10:56 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
int getGrassGround(ComponentIndex cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_terrains[cmp]->getGrassTypeGround(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-10 13:10:56 +02:00
|
|
|
|
2014-09-05 21:12:20 +02:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
void setGrassPath(ComponentIndex cmp, int index, const Path& path) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-06 14:18:59 +01:00
|
|
|
m_terrains[cmp]->setGrassTypePath(index, path);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-05 21:12:20 +02:00
|
|
|
|
2014-08-10 13:10:56 +02:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
Path getGrassPath(ComponentIndex cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-06 14:18:59 +01:00
|
|
|
return m_terrains[cmp]->getGrassTypePath(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-10 13:10:56 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
int getGrassCount(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_terrains[cmp]->getGrassTypeCount();
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-10 13:10:56 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addGrass(ComponentIndex cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_terrains[cmp]->addGrassType(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-15 22:16:03 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void removeGrass(ComponentIndex cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_terrains[cmp]->removeGrassType(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex getFirstRenderable() override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
return getNextRenderable(-1);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-28 23:17:18 +01:00
|
|
|
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex getNextRenderable(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
for(int i = cmp + 1; i < m_renderables.size(); ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
if(m_renderables[i].entity != INVALID_ENTITY) return i;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-24 22:38:11 +02:00
|
|
|
return INVALID_COMPONENT;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-20 22:45:47 +02:00
|
|
|
|
|
|
|
|
2016-02-16 10:32:31 +01:00
|
|
|
const CullingSystem::Results* cull(const Frustum& frustum)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-12-10 17:09:52 +01:00
|
|
|
if (m_renderables.empty()) return nullptr;
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2016-02-16 10:32:31 +01:00
|
|
|
m_culling_system->cullToFrustumAsync(frustum, ~0UL);
|
2015-07-21 20:10:50 +02:00
|
|
|
return &m_culling_system->getResult();
|
|
|
|
}
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2016-02-16 10:17:37 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void runJobs(Array<MTJD::Job*>& jobs, MTJD::Group& sync_point)
|
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
for (int i = 0; i < jobs.size(); ++i)
|
|
|
|
{
|
|
|
|
m_engine.getMTJDManager().schedule(jobs[i]);
|
|
|
|
}
|
|
|
|
if (!jobs.empty())
|
|
|
|
{
|
|
|
|
sync_point.sync();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-04 00:39:17 +01:00
|
|
|
void fillTemporaryInfos(const CullingSystem::Results& results,
|
|
|
|
const Frustum& frustum,
|
|
|
|
const Vec3& lod_ref_point)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
m_jobs.clear();
|
|
|
|
|
|
|
|
while (m_temporary_infos.size() < results.size())
|
|
|
|
{
|
|
|
|
m_temporary_infos.emplace(m_allocator);
|
|
|
|
}
|
|
|
|
while (m_temporary_infos.size() > results.size())
|
|
|
|
{
|
|
|
|
m_temporary_infos.pop();
|
|
|
|
}
|
2015-10-01 02:07:22 +02:00
|
|
|
for (int subresult_index = 0; subresult_index < results.size(); ++subresult_index)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
Array<RenderableMesh>& subinfos = m_temporary_infos[subresult_index];
|
2015-07-21 20:10:50 +02:00
|
|
|
subinfos.clear();
|
2015-12-10 21:56:17 +01:00
|
|
|
if (results[subresult_index].empty()) continue;
|
|
|
|
|
2015-10-01 02:07:22 +02:00
|
|
|
MTJD::Job* job = MTJD::makeJob(m_engine.getMTJDManager(),
|
2016-03-04 00:39:17 +01:00
|
|
|
[&subinfos, this, &results, subresult_index, &frustum, lod_ref_point]()
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-11-27 21:03:22 +01:00
|
|
|
PROFILE_BLOCK("Temporary Info Job");
|
2015-12-14 01:39:37 +01:00
|
|
|
PROFILE_INT("Renderable count", results[subresult_index].size());
|
2016-03-04 00:39:17 +01:00
|
|
|
Vec3 ref_point = lod_ref_point;
|
2015-12-10 21:56:17 +01:00
|
|
|
const int* LUMIX_RESTRICT raw_subresults = &results[subresult_index][0];
|
|
|
|
Renderable* LUMIX_RESTRICT renderables = &m_renderables[0];
|
|
|
|
for (int i = 0, c = results[subresult_index].size(); i < c; ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 21:56:17 +01:00
|
|
|
Renderable* LUMIX_RESTRICT renderable = &renderables[raw_subresults[i]];
|
|
|
|
Model* LUMIX_RESTRICT model = renderable->model;
|
2015-07-21 20:10:50 +02:00
|
|
|
float squared_distance =
|
2016-03-04 00:39:17 +01:00
|
|
|
(renderable->matrix.getTranslation() - ref_point).squaredLength();
|
2015-12-10 21:56:17 +01:00
|
|
|
|
|
|
|
LODMeshIndices lod = model->getLODMeshIndices(squared_distance);
|
2016-01-29 01:18:41 +01:00
|
|
|
for (int j = lod.from, c = lod.to; j <= c; ++j)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
auto& info = subinfos.emplace();
|
2015-12-10 21:56:17 +01:00
|
|
|
info.renderable = raw_subresults[i];
|
2016-01-22 01:11:04 +01:00
|
|
|
info.mesh = &renderable->meshes[j];
|
2014-12-08 01:06:51 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
m_allocator);
|
|
|
|
job->addDependency(&m_sync_point);
|
|
|
|
m_jobs.push(job);
|
|
|
|
}
|
|
|
|
runJobs(m_jobs, m_sync_point);
|
|
|
|
}
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
int getClosestPointLights(const Vec3& reference_pos,
|
2015-09-02 11:14:42 +02:00
|
|
|
ComponentIndex* lights,
|
|
|
|
int max_lights) override
|
|
|
|
{
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
float dists[16];
|
|
|
|
ASSERT(max_lights <= lengthOf(dists));
|
|
|
|
ASSERT(max_lights > 0);
|
|
|
|
if (m_point_lights.empty()) return 0;
|
|
|
|
|
|
|
|
int light_count = 0;
|
2015-09-02 11:14:42 +02:00
|
|
|
for (auto light : m_point_lights)
|
|
|
|
{
|
|
|
|
Vec3 light_pos = m_universe.getPosition(light.m_entity);
|
|
|
|
float dist_squared = (reference_pos - light_pos).squaredLength();
|
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
dists[light_count] = dist_squared;
|
|
|
|
lights[light_count] = light.m_uid;
|
|
|
|
|
|
|
|
for (int i = light_count; i > 0 && dists[i - 1] > dists[i]; --i)
|
|
|
|
{
|
|
|
|
float tmp = dists[i];
|
|
|
|
dists[i] = dists[i - 1];
|
|
|
|
dists[i - 1] = tmp;
|
|
|
|
|
|
|
|
ComponentIndex tmp2 = lights[i];
|
|
|
|
lights[i] = lights[i - 1];
|
|
|
|
lights[i - 1] = tmp2;
|
|
|
|
}
|
|
|
|
++light_count;
|
|
|
|
if (light_count == max_lights)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
for (int i = max_lights; i < m_point_lights.size(); ++i)
|
|
|
|
{
|
|
|
|
PointLight& light = m_point_lights[i];
|
|
|
|
Vec3 light_pos = m_universe.getPosition(light.m_entity);
|
|
|
|
float dist_squared = (reference_pos - light_pos).squaredLength();
|
|
|
|
|
|
|
|
if (dist_squared < dists[max_lights - 1])
|
|
|
|
{
|
|
|
|
dists[max_lights - 1] = dist_squared;
|
|
|
|
lights[max_lights - 1] = light.m_uid;
|
|
|
|
|
|
|
|
for (int i = max_lights - 1; i > 0 && dists[i - 1] > dists[i];
|
|
|
|
--i)
|
|
|
|
{
|
|
|
|
float tmp = dists[i];
|
|
|
|
dists[i] = dists[i - 1];
|
|
|
|
dists[i - 1] = tmp;
|
|
|
|
|
|
|
|
ComponentIndex tmp2 = lights[i];
|
|
|
|
lights[i] = lights[i - 1];
|
|
|
|
lights[i - 1] = tmp2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return light_count;
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void getPointLights(const Frustum& frustum,
|
2015-07-24 08:42:35 +02:00
|
|
|
Array<ComponentIndex>& lights) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
for (int i = 0, ci = m_point_lights.size(); i < ci; ++i)
|
|
|
|
{
|
|
|
|
PointLight& light = m_point_lights[i];
|
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
if (frustum.isSphereInside(m_universe.getPosition(light.m_entity),
|
|
|
|
light.m_range))
|
2015-02-14 00:13:34 +01:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
lights.push(light.m_uid);
|
2015-02-14 00:13:34 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Entity getCameraEntity(ComponentIndex camera) const override
|
2015-07-24 08:42:35 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].entity;
|
2015-07-24 08:42:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setLightCastShadows(ComponentIndex cmp,
|
2015-09-02 11:14:42 +02:00
|
|
|
bool cast_shadows) override
|
|
|
|
{
|
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_cast_shadows = cast_shadows;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
bool getLightCastShadows(ComponentIndex cmp) override
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_cast_shadows;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
void getPointLightInfluencedGeometry(ComponentIndex light_cmp,
|
|
|
|
const Frustum& frustum,
|
2016-02-16 10:32:31 +01:00
|
|
|
Array<RenderableMesh>& infos) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
int light_index = getPointLightIndex(light_cmp);
|
2015-12-10 17:09:52 +01:00
|
|
|
for (int j = 0, cj = m_light_influenced_geometry[light_index].size(); j < cj; ++j)
|
|
|
|
{
|
|
|
|
ComponentIndex renderable_cmp = m_light_influenced_geometry[light_index][j];
|
|
|
|
Renderable& renderable = m_renderables[renderable_cmp];
|
|
|
|
const Sphere& sphere = m_culling_system->getSphere(renderable_cmp);
|
2016-02-16 10:32:31 +01:00
|
|
|
if (frustum.isSphereInside(sphere.m_position, sphere.m_radius))
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
for (int k = 0, kc = renderable.model->getMeshCount(); k < kc; ++k)
|
2015-02-14 00:13:34 +01:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
auto& info = infos.emplace();
|
2015-12-10 20:27:51 +01:00
|
|
|
info.mesh = &renderable.model->getMesh(k);
|
|
|
|
info.renderable = renderable_cmp;
|
2015-02-14 00:13:34 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-11-14 00:25:08 +01:00
|
|
|
void getPointLightInfluencedGeometry(ComponentIndex light_cmp,
|
2016-02-16 10:32:31 +01:00
|
|
|
Array<RenderableMesh>& infos) override
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
|
|
|
int light_index = getPointLightIndex(light_cmp);
|
|
|
|
auto& geoms = m_light_influenced_geometry[light_index];
|
|
|
|
for (int j = 0, cj = geoms.size(); j < cj; ++j)
|
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
const Renderable& renderable = m_renderables[geoms[j]];
|
2015-12-10 20:27:51 +01:00
|
|
|
for (int k = 0, kc = renderable.model->getMeshCount(); k < kc; ++k)
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
auto& info = infos.emplace();
|
2015-12-10 20:27:51 +01:00
|
|
|
info.mesh = &renderable.model->getMesh(k);
|
|
|
|
info.renderable = geoms[j];
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-16 10:32:31 +01:00
|
|
|
void getRenderableEntities(const Frustum& frustum, Array<Entity>& entities) override
|
2015-10-18 14:49:46 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
2016-02-16 10:32:31 +01:00
|
|
|
const CullingSystem::Results* results = cull(frustum);
|
2015-10-18 14:49:46 +02:00
|
|
|
if (!results) return;
|
|
|
|
|
|
|
|
for (auto& subresults : *results)
|
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
for (ComponentIndex renderable_cmp : subresults)
|
2015-10-18 14:49:46 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
entities.push(m_renderables[renderable_cmp].entity);
|
2015-10-18 14:49:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-04 00:39:17 +01:00
|
|
|
Array<Array<RenderableMesh>>& getRenderableInfos(const Frustum& frustum,
|
|
|
|
const Vec3& lod_ref_point) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2016-02-16 11:55:55 +01:00
|
|
|
for(auto& i : m_temporary_infos) i.clear();
|
2016-02-16 10:17:37 +01:00
|
|
|
const CullingSystem::Results* results = cull(frustum);
|
|
|
|
if (!results) return m_temporary_infos;
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2016-03-04 00:39:17 +01:00
|
|
|
fillTemporaryInfos(*results, frustum, lod_ref_point);
|
2016-02-16 10:17:37 +01:00
|
|
|
return m_temporary_infos;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setCameraSlot(ComponentIndex camera, const char* slot) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
copyString(m_cameras[camera].slot, lengthOf(m_cameras[camera].slot), slot);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-02-26 11:03:08 +01:00
|
|
|
|
|
|
|
ComponentIndex getCameraComponent(Entity entity)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_cameras.size(); ++i)
|
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
if (m_cameras[i].entity == entity) return i;
|
2016-02-26 11:03:08 +01:00
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
const char* getCameraSlot(ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].slot;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getCameraFOV(ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].fov;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setCameraFOV(ComponentIndex camera, float fov) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
m_cameras[camera].fov = fov;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setCameraNearPlane(ComponentIndex camera,
|
2015-07-23 23:17:51 +02:00
|
|
|
float near_plane) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
m_cameras[camera].near = near_plane;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getCameraNearPlane(ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].near;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setCameraFarPlane(ComponentIndex camera,
|
2015-07-23 23:17:51 +02:00
|
|
|
float far_plane) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
m_cameras[camera].far = far_plane;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getCameraFarPlane(ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].far;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
float getCameraScreenWidth(ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].screen_width;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-11-30 15:10:13 +01:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
float getCameraScreenHeight(ComponentIndex camera) override
|
|
|
|
{
|
|
|
|
return m_cameras[camera].screen_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Matrix getCameraProjection(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
Camera& camera = m_cameras[cmp];
|
|
|
|
Matrix mtx;
|
|
|
|
float ratio = camera.screen_height > 0 ? camera.screen_width / camera.screen_height : 1;
|
|
|
|
if (camera.is_ortho)
|
|
|
|
{
|
|
|
|
mtx.setOrtho(-camera.ortho_size * ratio,
|
|
|
|
camera.ortho_size * ratio,
|
|
|
|
camera.ortho_size,
|
|
|
|
-camera.ortho_size,
|
|
|
|
camera.near,
|
|
|
|
camera.far);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mtx.setPerspective(Math::degreesToRadians(camera.fov), ratio, camera.near, camera.far);
|
|
|
|
}
|
|
|
|
return mtx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setCameraScreenSize(ComponentIndex camera, int w, int h) override
|
|
|
|
{
|
|
|
|
m_cameras[camera].screen_width = (float)w;
|
|
|
|
m_cameras[camera].screen_height = (float)h;
|
|
|
|
m_cameras[camera].aspect = w / (float)h;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float getCameraOrthoSize(ComponentIndex camera) override { return m_cameras[camera].ortho_size; }
|
|
|
|
void setCameraOrthoSize(ComponentIndex camera, float value) override { m_cameras[camera].ortho_size = value; }
|
|
|
|
|
|
|
|
|
|
|
|
bool isCameraOrtho(ComponentIndex camera) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
return m_cameras[camera].is_ortho;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-11-30 15:10:13 +01:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-04-17 21:47:54 +02:00
|
|
|
void setCameraOrtho(ComponentIndex camera, bool is_ortho) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
m_cameras[camera].is_ortho = is_ortho;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-11-30 15:10:13 +01:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-03-10 19:32:48 +01:00
|
|
|
const Array<DebugTriangle>& getDebugTriangles() const override
|
|
|
|
{
|
|
|
|
return m_debug_triangles;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
const Array<DebugLine>& getDebugLines() const override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
return m_debug_lines;
|
|
|
|
}
|
2014-11-30 15:10:13 +01:00
|
|
|
|
2014-12-14 22:14:21 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
const Array<DebugPoint>& getDebugPoints() const override
|
2015-08-28 21:55:53 +02:00
|
|
|
{
|
|
|
|
return m_debug_points;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugSphere(const Vec3& center,
|
2015-10-10 23:47:16 +02:00
|
|
|
float radius,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-10-10 23:47:16 +02:00
|
|
|
float life) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
static const int COLS = 36;
|
|
|
|
static const int ROWS = COLS >> 1;
|
|
|
|
static const float STEP = (Math::PI / 180.0f) * 360.0f / COLS;
|
|
|
|
int p2 = COLS >> 1;
|
|
|
|
int r2 = ROWS >> 1;
|
|
|
|
float prev_ci = 1;
|
|
|
|
float prev_si = 0;
|
|
|
|
for (int y = -r2; y < r2; ++y)
|
|
|
|
{
|
|
|
|
float cy = cos(y * STEP);
|
|
|
|
float cy1 = cos((y + 1) * STEP);
|
|
|
|
float sy = sin(y * STEP);
|
|
|
|
float sy1 = sin((y + 1) * STEP);
|
|
|
|
|
|
|
|
for (int i = -p2; i < p2; ++i)
|
|
|
|
{
|
|
|
|
float ci = cos(i * STEP);
|
|
|
|
float si = sin(i * STEP);
|
|
|
|
addDebugLine(Vec3(center.x + radius * ci * cy,
|
|
|
|
center.y + radius * sy,
|
|
|
|
center.z + radius * si * cy),
|
|
|
|
Vec3(center.x + radius * ci * cy1,
|
|
|
|
center.y + radius * sy1,
|
|
|
|
center.z + radius * si * cy1),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(Vec3(center.x + radius * ci * cy,
|
|
|
|
center.y + radius * sy,
|
|
|
|
center.z + radius * si * cy),
|
|
|
|
Vec3(center.x + radius * prev_ci * cy,
|
|
|
|
center.y + radius * sy,
|
|
|
|
center.z + radius * prev_si * cy),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(Vec3(center.x + radius * prev_ci * cy1,
|
|
|
|
center.y + radius * sy1,
|
|
|
|
center.z + radius * prev_si * cy1),
|
|
|
|
Vec3(center.x + radius * ci * cy1,
|
|
|
|
center.y + radius * sy1,
|
|
|
|
center.z + radius * si * cy1),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
prev_ci = ci;
|
|
|
|
prev_si = si;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-14 22:14:21 +01:00
|
|
|
|
2014-12-14 21:57:08 +01:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
void addDebugHalfSphere(const Vec3& center, float radius, bool top, uint32 color, float life)
|
2015-10-10 23:47:16 +02:00
|
|
|
{
|
|
|
|
static const int COLS = 36;
|
|
|
|
static const int ROWS = COLS >> 1;
|
|
|
|
static const float STEP = (Math::PI / 180.0f) * 360.0f / COLS;
|
|
|
|
int p2 = COLS >> 1;
|
|
|
|
int yfrom = top ? 0 : -(ROWS >> 1);
|
|
|
|
int yto = top ? ROWS >> 1 : 0;
|
|
|
|
for (int y = yfrom; y < yto; ++y)
|
|
|
|
{
|
|
|
|
float cy = cos(y * STEP);
|
|
|
|
float cy1 = cos((y + 1) * STEP);
|
|
|
|
float sy = sin(y * STEP);
|
|
|
|
float sy1 = sin((y + 1) * STEP);
|
|
|
|
float prev_ci = cos((-p2 - 1) * STEP);
|
|
|
|
float prev_si = sin((-p2 - 1) * STEP);
|
|
|
|
|
|
|
|
for (int i = -p2; i < p2; ++i)
|
|
|
|
{
|
|
|
|
float ci = cos(i * STEP);
|
|
|
|
float si = sin(i * STEP);
|
|
|
|
addDebugLine(Vec3(center.x + radius * ci * cy,
|
|
|
|
center.y + radius * sy,
|
|
|
|
center.z + radius * si * cy),
|
|
|
|
Vec3(center.x + radius * ci * cy1,
|
|
|
|
center.y + radius * sy1,
|
|
|
|
center.z + radius * si * cy1),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(Vec3(center.x + radius * ci * cy,
|
|
|
|
center.y + radius * sy,
|
|
|
|
center.z + radius * si * cy),
|
|
|
|
Vec3(center.x + radius * prev_ci * cy,
|
|
|
|
center.y + radius * sy,
|
|
|
|
center.z + radius * prev_si * cy),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(Vec3(center.x + radius * prev_ci * cy1,
|
|
|
|
center.y + radius * sy1,
|
|
|
|
center.z + radius * prev_si * cy1),
|
|
|
|
Vec3(center.x + radius * ci * cy1,
|
|
|
|
center.y + radius * sy1,
|
|
|
|
center.z + radius * si * cy1),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
prev_ci = ci;
|
|
|
|
prev_si = si;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-10 19:32:48 +01:00
|
|
|
void addDebugTriangle(const Vec3& p0,
|
|
|
|
const Vec3& p1,
|
|
|
|
const Vec3& p2,
|
|
|
|
uint32 color,
|
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
DebugTriangle& tri = m_debug_triangles.emplace();
|
|
|
|
tri.p0 = p0;
|
|
|
|
tri.p1 = p1;
|
|
|
|
tri.p2 = p2;
|
|
|
|
tri.color = ARGBToABGR(color);
|
|
|
|
tri.life = life;
|
|
|
|
}
|
|
|
|
|
2015-10-10 23:47:16 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugCapsule(const Vec3& position,
|
2015-10-10 23:47:16 +02:00
|
|
|
float height,
|
|
|
|
float radius,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-10-10 23:47:16 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
addDebugHalfSphere(position + Vec3(0, radius, 0), radius, false, color, life);
|
|
|
|
addDebugHalfSphere(position + Vec3(0, radius + height, 0), radius, true, color, life);
|
|
|
|
|
|
|
|
Vec3 z_vec(0, 0, 1.0f);
|
|
|
|
Vec3 x_vec(1.0f, 0, 0);
|
|
|
|
z_vec.normalize();
|
|
|
|
x_vec.normalize();
|
|
|
|
Vec3 bottom = position + Vec3(0, radius, 0);
|
|
|
|
Vec3 top = bottom + Vec3(0, height, 0);
|
|
|
|
for (int i = 1; i <= 32; ++i)
|
|
|
|
{
|
|
|
|
float a = i / 32.0f * 2 * Math::PI;
|
|
|
|
float x = cosf(a) * radius;
|
|
|
|
float z = sinf(a) * radius;
|
|
|
|
addDebugLine(bottom + x_vec * x + z_vec * z,
|
|
|
|
top + x_vec * x + z_vec * z,
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugCylinder(const Vec3& position,
|
2015-07-21 20:10:50 +02:00
|
|
|
const Vec3& up,
|
|
|
|
float radius,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-07-21 20:10:50 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
Vec3 z_vec(-up.y, up.x, 0);
|
|
|
|
Vec3 x_vec = crossProduct(up, z_vec);
|
|
|
|
float prevx = radius;
|
|
|
|
float prevz = 0;
|
|
|
|
z_vec.normalize();
|
|
|
|
x_vec.normalize();
|
|
|
|
Vec3 top = position + up;
|
|
|
|
for (int i = 1; i <= 32; ++i)
|
|
|
|
{
|
|
|
|
float a = i / 32.0f * 2 * Math::PI;
|
|
|
|
float x = cosf(a) * radius;
|
|
|
|
float z = sinf(a) * radius;
|
|
|
|
addDebugLine(position + x_vec * x + z_vec * z,
|
|
|
|
position + x_vec * prevx + z_vec * prevz,
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(top + x_vec * x + z_vec * z,
|
|
|
|
top + x_vec * prevx + z_vec * prevz,
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(position + x_vec * x + z_vec * z,
|
|
|
|
top + x_vec * x + z_vec * z,
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
prevx = x;
|
|
|
|
prevz = z;
|
|
|
|
}
|
|
|
|
}
|
2014-12-14 21:57:08 +01:00
|
|
|
|
2014-07-05 17:24:12 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugCube(const Vec3& pos,
|
2015-10-24 12:25:06 +02:00
|
|
|
const Vec3& dir,
|
|
|
|
const Vec3& up,
|
|
|
|
const Vec3& right,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-10-24 12:25:06 +02:00
|
|
|
float life) override
|
2015-08-26 22:06:42 +02:00
|
|
|
{
|
|
|
|
addDebugLine(pos + dir + up + right, pos + dir + up - right, color, life);
|
|
|
|
addDebugLine(pos - dir + up + right, pos - dir + up - right, color, life);
|
|
|
|
addDebugLine(pos + dir + up + right, pos - dir + up + right, color, life);
|
|
|
|
addDebugLine(pos + dir + up - right, pos - dir + up - right, color, life);
|
|
|
|
|
|
|
|
addDebugLine(pos + dir - up + right, pos + dir - up - right, color, life);
|
|
|
|
addDebugLine(pos - dir - up + right, pos - dir - up - right, color, life);
|
|
|
|
addDebugLine(pos + dir - up + right, pos - dir - up + right, color, life);
|
|
|
|
addDebugLine(pos + dir - up - right, pos - dir - up - right, color, life);
|
|
|
|
|
|
|
|
addDebugLine(pos + dir + up + right, pos + dir - up + right, color, life);
|
|
|
|
addDebugLine(pos + dir + up - right, pos + dir - up - right, color, life);
|
|
|
|
addDebugLine(pos - dir + up + right, pos - dir - up + right, color, life);
|
|
|
|
addDebugLine(pos - dir + up - right, pos - dir - up - right, color, life);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-11 17:25:14 +01:00
|
|
|
void addDebugCubeSolid(const Vec3& min,
|
|
|
|
const Vec3& max,
|
|
|
|
uint32 color,
|
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
Vec3 a = min;
|
|
|
|
Vec3 b = min;
|
|
|
|
Vec3 c = max;
|
|
|
|
|
|
|
|
b.x = max.x;
|
|
|
|
c.z = min.z;
|
|
|
|
addDebugTriangle(a, c, b, color, life);
|
|
|
|
b.x = min.x;
|
|
|
|
b.y = max.y;
|
|
|
|
addDebugTriangle(a, b, c, color, life);
|
|
|
|
|
|
|
|
b = max;
|
|
|
|
c = max;
|
|
|
|
a.z = max.z;
|
|
|
|
b.y = min.y;
|
|
|
|
addDebugTriangle(a, b, c, color, life);
|
|
|
|
b.x = min.x;
|
|
|
|
b.y = max.y;
|
|
|
|
addDebugTriangle(a, c, b, color, life);
|
|
|
|
|
|
|
|
a = min;
|
|
|
|
b = min;
|
|
|
|
c = max;
|
|
|
|
|
|
|
|
b.x = max.x;
|
|
|
|
c.y = min.y;
|
|
|
|
addDebugTriangle(a, c, b, color, life);
|
|
|
|
b.x = min.x;
|
|
|
|
b.z = max.z;
|
|
|
|
addDebugTriangle(a, b, c, color, life);
|
|
|
|
|
|
|
|
b = max;
|
|
|
|
c = max;
|
|
|
|
a.y = max.y;
|
|
|
|
b.z = min.z;
|
|
|
|
addDebugTriangle(a, c, b, color, life);
|
|
|
|
b.x = min.x;
|
|
|
|
b.z = max.z;
|
|
|
|
addDebugTriangle(a, b, c, color, life);
|
|
|
|
|
|
|
|
a = min;
|
|
|
|
b = min;
|
|
|
|
c = max;
|
|
|
|
|
|
|
|
b.y = max.y;
|
|
|
|
c.x = min.x;
|
|
|
|
addDebugTriangle(a, c, b, color, life);
|
|
|
|
b.y = min.y;
|
|
|
|
b.z = max.z;
|
|
|
|
addDebugTriangle(a, b, c, color, life);
|
|
|
|
|
|
|
|
b = max;
|
|
|
|
c = max;
|
|
|
|
a.x = max.x;
|
|
|
|
b.z = min.z;
|
|
|
|
addDebugTriangle(a, b, c, color, life);
|
|
|
|
b.y = min.y;
|
|
|
|
b.z = max.z;
|
|
|
|
addDebugTriangle(a, c, b, color, life);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugCube(const Vec3& min,
|
2015-07-21 20:10:50 +02:00
|
|
|
const Vec3& max,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-07-21 20:10:50 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
Vec3 a = min;
|
|
|
|
Vec3 b = min;
|
|
|
|
b.x = max.x;
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.set(b.x, b.y, max.z);
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
b.set(min.x, a.y, a.z);
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.set(b.x, b.y, min.z);
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
|
|
|
|
a = min;
|
|
|
|
a.y = max.y;
|
|
|
|
b = a;
|
|
|
|
b.x = max.x;
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.set(b.x, b.y, max.z);
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
b.set(min.x, a.y, a.z);
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.set(b.x, b.y, min.z);
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
|
|
|
|
a = min;
|
|
|
|
b = a;
|
|
|
|
b.y = max.y;
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.x = max.x;
|
|
|
|
b.x = max.x;
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.z = max.z;
|
|
|
|
b.z = max.z;
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
a.x = min.x;
|
|
|
|
b.x = min.x;
|
|
|
|
addDebugLine(a, b, color, life);
|
|
|
|
}
|
2014-12-17 21:33:27 +01:00
|
|
|
|
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
void addDebugFrustum(const Frustum& frustum, uint32 color, float life) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-03-11 17:25:14 +01:00
|
|
|
addDebugFrustum(frustum.position,
|
|
|
|
frustum.direction,
|
|
|
|
frustum.up,
|
|
|
|
frustum.fov,
|
|
|
|
frustum.ratio,
|
|
|
|
frustum.near_distance,
|
|
|
|
frustum.far_distance,
|
2015-07-21 20:10:50 +02:00
|
|
|
color,
|
|
|
|
life);
|
|
|
|
}
|
2014-12-17 21:33:27 +01:00
|
|
|
|
2014-12-14 21:42:30 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugFrustum(const Vec3& position,
|
2015-07-21 20:10:50 +02:00
|
|
|
const Vec3& direction,
|
|
|
|
const Vec3& up,
|
|
|
|
float fov,
|
|
|
|
float ratio,
|
|
|
|
float near_distance,
|
|
|
|
float far_distance,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-07-21 20:10:50 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
Vec3 points[8];
|
|
|
|
Vec3 near_center = position + direction * near_distance;
|
|
|
|
Vec3 far_center = position + direction * far_distance;
|
|
|
|
Vec3 right = crossProduct(direction, up);
|
2015-08-27 12:14:35 +02:00
|
|
|
float scale = (float)tan(Math::degreesToRadians(fov * 0.5f));
|
|
|
|
Vec3 up_near = up * near_distance * scale;
|
|
|
|
Vec3 right_near = right * (near_distance * scale * ratio);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
points[0] = near_center + up_near + right_near;
|
|
|
|
points[1] = near_center + up_near - right_near;
|
|
|
|
points[2] = near_center - up_near - right_near;
|
|
|
|
points[3] = near_center - up_near + right_near;
|
|
|
|
|
2015-08-27 12:14:35 +02:00
|
|
|
Vec3 up_far = up * far_distance * scale;
|
|
|
|
Vec3 right_far = right * (far_distance * scale * ratio);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
points[4] = far_center + up_far + right_far;
|
|
|
|
points[5] = far_center + up_far - right_far;
|
|
|
|
points[6] = far_center - up_far - right_far;
|
|
|
|
points[7] = far_center - up_far + right_far;
|
|
|
|
|
|
|
|
addDebugLine(points[0], points[1], color, life);
|
|
|
|
addDebugLine(points[1], points[2], color, life);
|
|
|
|
addDebugLine(points[2], points[3], color, life);
|
|
|
|
addDebugLine(points[3], points[0], color, life);
|
|
|
|
|
|
|
|
addDebugLine(points[4], points[5], color, life);
|
|
|
|
addDebugLine(points[5], points[6], color, life);
|
|
|
|
addDebugLine(points[6], points[7], color, life);
|
|
|
|
addDebugLine(points[7], points[4], color, life);
|
|
|
|
|
|
|
|
addDebugLine(points[0], points[4], color, life);
|
|
|
|
addDebugLine(points[1], points[5], color, life);
|
|
|
|
addDebugLine(points[2], points[6], color, life);
|
|
|
|
addDebugLine(points[3], points[7], color, life);
|
|
|
|
}
|
2014-12-14 21:42:30 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugCircle(const Vec3& center,
|
2015-10-24 12:25:06 +02:00
|
|
|
const Vec3& up,
|
|
|
|
float radius,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-10-24 12:25:06 +02:00
|
|
|
float life) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
Vec3 z_vec(-up.y, up.x, 0);
|
|
|
|
Vec3 x_vec = crossProduct(up, z_vec);
|
|
|
|
float prevx = radius;
|
|
|
|
float prevz = 0;
|
|
|
|
z_vec.normalize();
|
|
|
|
x_vec.normalize();
|
|
|
|
for (int i = 1; i <= 64; ++i)
|
|
|
|
{
|
|
|
|
float a = i / 64.0f * 2 * Math::PI;
|
|
|
|
float x = cosf(a) * radius;
|
|
|
|
float z = sinf(a) * radius;
|
|
|
|
addDebugLine(center + x_vec * x + z_vec * z,
|
2015-10-24 12:25:06 +02:00
|
|
|
center + x_vec * prevx + z_vec * prevz,
|
|
|
|
color,
|
|
|
|
life);
|
2015-07-21 20:10:50 +02:00
|
|
|
prevx = x;
|
|
|
|
prevz = z;
|
|
|
|
}
|
|
|
|
}
|
2014-07-07 23:37:40 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugCross(const Vec3& center,
|
2015-07-21 20:10:50 +02:00
|
|
|
float size,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 color,
|
2015-07-21 20:10:50 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
addDebugLine(
|
|
|
|
center, Vec3(center.x - size, center.y, center.z), color, life);
|
|
|
|
addDebugLine(
|
|
|
|
center, Vec3(center.x + size, center.y, center.z), color, life);
|
|
|
|
addDebugLine(
|
|
|
|
center, Vec3(center.x, center.y - size, center.z), color, life);
|
|
|
|
addDebugLine(
|
|
|
|
center, Vec3(center.x, center.y + size, center.z), color, life);
|
|
|
|
addDebugLine(
|
|
|
|
center, Vec3(center.x, center.y, center.z - size), color, life);
|
|
|
|
addDebugLine(
|
|
|
|
center, Vec3(center.x, center.y, center.z + size), color, life);
|
|
|
|
}
|
2014-07-20 18:14:37 +02:00
|
|
|
|
2014-10-12 22:38:17 +02:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
void addDebugPoint(const Vec3& pos, uint32 color, float life) override
|
2015-08-28 21:55:53 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
DebugPoint& point = m_debug_points.emplace();
|
2016-03-10 19:32:48 +01:00
|
|
|
point.pos = pos;
|
|
|
|
point.color = ARGBToABGR(color);
|
|
|
|
point.life = life;
|
2015-08-28 21:55:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
static uint32 ARGBToABGR(uint32 color)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-10-24 12:25:06 +02:00
|
|
|
return ((color & 0xff) << 16) | (color & 0xff00) | ((color & 0xff0000) >> 16) |
|
|
|
|
(color & 0xff000000);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2014-10-12 22:38:17 +02:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
void addDebugLine(const Vec3& from, const Vec3& to, uint32 color, float life) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
DebugLine& line = m_debug_lines.emplace();
|
2016-03-10 19:32:48 +01:00
|
|
|
line.from = from;
|
|
|
|
line.to = to;
|
|
|
|
line.color = ARGBToABGR(color);
|
|
|
|
line.life = life;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-04 11:36:33 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
RayCastModelHit castRayTerrain(ComponentIndex terrain,
|
2015-10-24 12:25:06 +02:00
|
|
|
const Vec3& origin,
|
|
|
|
const Vec3& dir) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
RayCastModelHit hit;
|
|
|
|
hit.m_is_hit = false;
|
2015-07-23 23:17:51 +02:00
|
|
|
if (m_terrains[terrain])
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
hit = m_terrains[terrain]->castRay(origin, dir);
|
2015-07-25 00:09:11 +02:00
|
|
|
hit.m_component = terrain;
|
|
|
|
hit.m_component_type = TERRAIN_HASH;
|
|
|
|
hit.m_entity = m_terrains[terrain]->getEntity();
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
return hit;
|
|
|
|
}
|
2014-10-12 22:38:17 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
RayCastModelHit castRay(const Vec3& origin,
|
2015-12-10 17:09:52 +01:00
|
|
|
const Vec3& dir,
|
|
|
|
ComponentIndex ignored_renderable) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-26 01:18:05 +01:00
|
|
|
PROFILE_FUNCTION();
|
2015-07-21 20:10:50 +02:00
|
|
|
RayCastModelHit hit;
|
|
|
|
hit.m_is_hit = false;
|
2015-08-02 10:39:50 +02:00
|
|
|
Universe& universe = getUniverse();
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < m_renderables.size(); ++i)
|
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
auto& r = m_renderables[i];
|
2015-12-10 20:27:51 +01:00
|
|
|
if (ignored_renderable != i && r.model)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
const Vec3& pos = r.matrix.getTranslation();
|
|
|
|
float radius = r.model->getBoundingRadius();
|
|
|
|
float scale = universe.getScale(r.entity);
|
2015-07-21 20:10:50 +02:00
|
|
|
Vec3 intersection;
|
|
|
|
if (dotProduct(pos - origin, pos - origin) < radius * radius ||
|
2015-12-10 17:09:52 +01:00
|
|
|
Math::getRaySphereIntersection(origin, dir, pos, radius * scale, intersection))
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
RayCastModelHit new_hit = r.model->castRay(origin, dir, r.matrix);
|
2015-12-10 17:09:52 +01:00
|
|
|
if (new_hit.m_is_hit && (!hit.m_is_hit || new_hit.m_t < hit.m_t))
|
2014-07-20 18:14:37 +02:00
|
|
|
{
|
2015-07-25 00:09:11 +02:00
|
|
|
new_hit.m_component = i;
|
2015-12-10 20:27:51 +01:00
|
|
|
new_hit.m_entity = r.entity;
|
2015-07-25 00:09:11 +02:00
|
|
|
new_hit.m_component_type = RENDERABLE_HASH;
|
2015-07-21 20:10:50 +02:00
|
|
|
hit = new_hit;
|
|
|
|
hit.m_is_hit = true;
|
2014-07-20 18:14:37 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
for (int i = 0; i < m_terrains.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_terrains[i])
|
2015-02-18 00:34:22 +01:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
RayCastModelHit terrain_hit = m_terrains[i]->castRay(origin, dir);
|
|
|
|
if (terrain_hit.m_is_hit && (!hit.m_is_hit || terrain_hit.m_t < hit.m_t))
|
2015-02-18 00:34:22 +01:00
|
|
|
{
|
2015-07-25 00:09:11 +02:00
|
|
|
terrain_hit.m_component = i;
|
|
|
|
terrain_hit.m_component_type = TERRAIN_HASH;
|
|
|
|
terrain_hit.m_entity = m_terrains[i]->getEntity();
|
2015-07-21 20:10:50 +02:00
|
|
|
hit = terrain_hit;
|
2015-02-18 00:34:22 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
return hit;
|
|
|
|
}
|
2015-02-18 00:34:22 +01:00
|
|
|
|
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
int getPointLightIndex(ComponentIndex cmp) const
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-26 10:27:31 +01:00
|
|
|
return m_point_lights_map[cmp];
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-18 00:34:22 +01:00
|
|
|
|
2015-08-11 23:23:19 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec4 getShadowmapCascades(ComponentIndex cmp) override
|
2015-09-10 22:14:54 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_cascades;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setShadowmapCascades(ComponentIndex cmp,
|
2015-09-10 22:14:54 +02:00
|
|
|
const Vec4& value) override
|
|
|
|
{
|
|
|
|
Vec4 valid_value = value;
|
2016-03-06 12:54:29 +01:00
|
|
|
valid_value.x = Math::maximum(valid_value.x, 0.02f);
|
|
|
|
valid_value.y = Math::maximum(valid_value.x + 0.01f, valid_value.y);
|
|
|
|
valid_value.z = Math::maximum(valid_value.y + 0.01f, valid_value.z);
|
|
|
|
valid_value.w = Math::maximum(valid_value.z + 0.01f, valid_value.w);
|
2015-09-10 22:14:54 +02:00
|
|
|
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_cascades = valid_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
int getGlobalLightIndex(int uid) const
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_global_lights.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_global_lights[i].m_uid == uid)
|
2015-02-18 00:34:22 +01:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
return i;
|
2015-02-18 00:34:22 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2015-02-18 00:34:22 +01:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setFogDensity(ComponentIndex cmp, float density) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_fog_density = density;
|
|
|
|
}
|
2014-09-25 22:39:33 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setFogColor(ComponentIndex cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_fog_color = color;
|
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getFogDensity(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_fog_density;
|
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getFogBottom(ComponentIndex cmp) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_fog_bottom;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setFogBottom(ComponentIndex cmp, float bottom) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_fog_bottom = bottom;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getFogHeight(ComponentIndex cmp) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_fog_height;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setFogHeight(ComponentIndex cmp, float height) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_fog_height = height;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec3 getFogColor(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_fog_color;
|
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getLightAttenuation(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-09-09 02:18:09 +02:00
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_attenuation_param;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setLightAttenuation(ComponentIndex cmp,
|
2015-09-09 02:18:09 +02:00
|
|
|
float attenuation) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
int index = getPointLightIndex(cmp);
|
2015-09-09 02:18:09 +02:00
|
|
|
m_point_lights[index].m_attenuation_param = attenuation;
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getLightRange(ComponentIndex cmp) override
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_range;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setLightRange(ComponentIndex cmp, float value) override
|
2015-09-09 02:18:09 +02:00
|
|
|
{
|
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_range = value;
|
|
|
|
}
|
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
void setPointLightIntensity(ComponentIndex cmp, float intensity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_diffuse_intensity = intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
void setGlobalLightIntensity(ComponentIndex cmp, float intensity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_diffuse_intensity = intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
void setPointLightColor(ComponentIndex cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-09-02 11:14:42 +02:00
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_diffuse_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-10 08:12:12 +02:00
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
void setGlobalLightColor(ComponentIndex cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_diffuse_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-10 08:12:12 +02:00
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
void setGlobalLightSpecular(ComponentIndex cmp, const Vec3& color) override
|
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_specular = color;
|
|
|
|
}
|
|
|
|
|
2016-02-10 12:09:09 +01:00
|
|
|
void setGlobalLightSpecularIntensity(ComponentIndex cmp, float intensity) override
|
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_specular_intensity = intensity;
|
|
|
|
}
|
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
void setLightAmbientIntensity(ComponentIndex cmp, float intensity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_ambient_intensity = intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-02-10 12:09:09 +01:00
|
|
|
void setLightAmbientColor(ComponentIndex cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
m_global_lights[getGlobalLightIndex(cmp)].m_ambient_color = color;
|
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getPointLightIntensity(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_diffuse_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getGlobalLightIntensity(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_diffuse_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec3 getPointLightColor(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-09-02 11:14:42 +02:00
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_diffuse_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-02-10 12:09:09 +01:00
|
|
|
void setPointLightSpecularColor(ComponentIndex cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_specular_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec3 getPointLightSpecularColor(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_specular_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-21 19:26:27 +02:00
|
|
|
|
2016-02-10 12:09:09 +01:00
|
|
|
void setPointLightSpecularIntensity(ComponentIndex cmp, float intensity) override
|
|
|
|
{
|
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_specular_intensity = intensity;
|
|
|
|
}
|
|
|
|
|
|
|
|
float getPointLightSpecularIntensity(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_specular_intensity;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec3 getGlobalLightColor(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_diffuse_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-07-05 17:24:12 +02:00
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
Vec3 getGlobalLightSpecular(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_specular;
|
|
|
|
}
|
|
|
|
|
2016-02-10 12:09:09 +01:00
|
|
|
float getGlobalLightSpecularIntensity(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_specular_intensity;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getLightAmbientIntensity(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_ambient_intensity;
|
|
|
|
}
|
2014-11-16 21:25:11 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Vec3 getLightAmbientColor(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_ambient_color;
|
|
|
|
}
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setActiveGlobalLight(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
m_active_global_light_uid = cmp;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-06 20:56:28 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex getActiveGlobalLight() override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_active_global_light_uid;
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
2014-10-30 00:16:32 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Entity getPointLightEntity(ComponentIndex cmp) const override
|
2015-07-24 08:42:35 +02:00
|
|
|
{
|
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_entity;
|
|
|
|
}
|
2016-01-24 17:20:03 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
Entity getGlobalLightEntity(ComponentIndex cmp) const override
|
2015-07-24 08:42:35 +02:00
|
|
|
{
|
|
|
|
return m_global_lights[getGlobalLightIndex(cmp)].m_entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
ComponentIndex getCameraInSlot(const char* slot) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
for (int i = 0, c = m_cameras.size(); i < c; ++i)
|
|
|
|
{
|
2016-04-17 21:47:54 +02:00
|
|
|
if (!m_cameras[i].is_free && compareString(m_cameras[i].slot, slot) == 0)
|
2014-08-20 22:45:47 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return i;
|
2014-08-20 22:45:47 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-24 22:38:11 +02:00
|
|
|
return INVALID_COMPONENT;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getTime() const override { return m_time; }
|
2014-10-30 00:16:32 +01:00
|
|
|
|
|
|
|
|
2016-01-10 13:41:12 +01:00
|
|
|
void modelUnloaded(Model*, ComponentIndex component)
|
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
auto& r = m_renderables[component];
|
|
|
|
if (!r.custom_meshes)
|
|
|
|
{
|
|
|
|
r.meshes = nullptr;
|
|
|
|
r.mesh_count = 0;
|
|
|
|
}
|
2016-02-06 15:20:34 +01:00
|
|
|
LUMIX_DELETE(m_allocator, r.pose);
|
|
|
|
r.pose = nullptr;
|
2016-02-06 00:44:43 +01:00
|
|
|
|
2016-02-27 22:38:35 +01:00
|
|
|
for (int i = 0; i < m_point_lights.size(); ++i)
|
|
|
|
{
|
|
|
|
m_light_influenced_geometry[i].eraseItemFast(component);
|
|
|
|
}
|
2016-01-10 13:41:12 +01:00
|
|
|
m_culling_system->removeStatic(component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-06 00:44:43 +01:00
|
|
|
void freeCustomMeshes(Renderable& r, MaterialManager* manager)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
if (!r.custom_meshes) return;
|
2016-01-22 01:11:04 +01:00
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
|
|
|
{
|
2016-01-22 18:02:07 +01:00
|
|
|
manager->unload(*r.meshes[i].material);
|
2016-01-22 01:11:04 +01:00
|
|
|
r.meshes[i].~Mesh();
|
|
|
|
}
|
|
|
|
m_allocator.deallocate(r.meshes);
|
|
|
|
r.meshes = nullptr;
|
2016-02-06 00:44:43 +01:00
|
|
|
r.custom_meshes = false;
|
|
|
|
r.mesh_count = 0;
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
void modelLoaded(Model* model, ComponentIndex component)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
auto& rm = m_engine.getResourceManager();
|
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(ResourceManager::MATERIAL));
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
auto& r = m_renderables[component];
|
2015-12-10 20:27:51 +01:00
|
|
|
float bounding_radius = r.model->getBoundingRadius();
|
|
|
|
float scale = m_universe.getScale(r.entity);
|
2015-12-10 21:56:17 +01:00
|
|
|
Sphere sphere(r.matrix.getTranslation(), bounding_radius * scale);
|
|
|
|
m_culling_system->addStatic(component, sphere);
|
|
|
|
m_culling_system->setLayerMask(component, r.layer_mask);
|
2016-02-06 11:20:21 +01:00
|
|
|
ASSERT(!r.pose);
|
2015-12-10 20:27:51 +01:00
|
|
|
if (model->getBoneCount() > 0)
|
|
|
|
{
|
|
|
|
r.pose = LUMIX_NEW(m_allocator, Pose)(m_allocator);
|
|
|
|
r.pose->resize(model->getBoneCount());
|
|
|
|
model->getPose(*r.pose);
|
2016-04-26 19:26:39 +02:00
|
|
|
int skinned_define_idx = m_renderer.getShaderDefineIdx("SKINNED");
|
|
|
|
for (int i = 0; i < model->getMeshCount(); ++i)
|
|
|
|
{
|
|
|
|
model->getMesh(i).material->setDefine(skinned_define_idx, true);
|
|
|
|
}
|
2015-12-10 20:27:51 +01:00
|
|
|
}
|
2016-01-20 22:13:07 +01:00
|
|
|
r.matrix = m_universe.getMatrix(r.entity);
|
2016-04-19 10:25:24 +02:00
|
|
|
ASSERT(!r.meshes || r.custom_meshes);
|
2016-01-22 01:11:04 +01:00
|
|
|
if (r.meshes)
|
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
allocateCustomMeshes(r, model->getMeshCount());
|
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
auto& src = model->getMesh(i);
|
|
|
|
if (!r.meshes[i].material)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
material_manager->load(*src.material);
|
|
|
|
r.meshes[i].material = src.material;
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
r.meshes[i].set(
|
2016-05-01 15:25:54 +02:00
|
|
|
src.attribute_array_offset, src.attribute_array_size, src.indices_offset, src.indices_count);
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
else
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
|
|
|
r.meshes = &r.model->getMesh(0);
|
|
|
|
r.mesh_count = r.model->getMeshCount();
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < m_point_lights.size(); ++i)
|
|
|
|
{
|
|
|
|
PointLight& light = m_point_lights[i];
|
2015-12-10 20:27:51 +01:00
|
|
|
Vec3 t = r.matrix.getTranslation();
|
|
|
|
float radius = r.model->getBoundingRadius();
|
2015-07-24 08:42:35 +02:00
|
|
|
if ((t - m_universe.getPosition(light.m_entity)).squaredLength() <
|
2015-12-10 17:09:52 +01:00
|
|
|
(radius + light.m_range) * (radius + light.m_range))
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
m_light_influenced_geometry[i].push(component);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-10-30 00:16:32 +01:00
|
|
|
|
2016-01-10 13:41:12 +01:00
|
|
|
|
2016-02-06 00:44:43 +01:00
|
|
|
void modelUnloaded(Model* model)
|
2016-01-10 13:41:12 +01:00
|
|
|
{
|
|
|
|
for (int i = 0, c = m_renderables.size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
if (m_renderables[i].entity != INVALID_ENTITY && m_renderables[i].model == model)
|
|
|
|
{
|
|
|
|
modelUnloaded(model, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void modelLoaded(Model* model)
|
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
for (int i = 0, c = m_renderables.size(); i < c; ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
if (m_renderables[i].entity != INVALID_ENTITY && m_renderables[i].model == model)
|
2014-11-08 02:54:55 +01:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
modelLoaded(model, i);
|
2014-11-08 02:54:55 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-05-02 21:41:18 +02:00
|
|
|
|
|
|
|
for (auto& attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
if (m_renderables[attachment.parent_entity].entity != INVALID_ENTITY &&
|
|
|
|
m_renderables[attachment.parent_entity].model == model)
|
|
|
|
{
|
|
|
|
updateRelativeMatrix(attachment);
|
|
|
|
}
|
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-11-08 02:54:55 +01:00
|
|
|
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
ModelLoadedCallback* getModelLoadedCallback(Model* model)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_model_loaded_callbacks.size(); ++i)
|
|
|
|
{
|
|
|
|
if (m_model_loaded_callbacks[i]->m_model == model)
|
2015-02-14 00:13:34 +01:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
return m_model_loaded_callbacks[i];
|
2015-02-14 00:13:34 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
ModelLoadedCallback* new_callback =
|
2015-11-11 23:25:44 +01:00
|
|
|
LUMIX_NEW(m_allocator, ModelLoadedCallback)(*this, model);
|
2015-07-21 20:10:50 +02:00
|
|
|
m_model_loaded_callbacks.push(new_callback);
|
|
|
|
return new_callback;
|
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
|
|
|
|
2016-02-06 00:44:43 +01:00
|
|
|
void allocateCustomMeshes(Renderable& r, int count)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
if (r.custom_meshes && r.mesh_count == count) return;
|
2016-01-22 01:11:04 +01:00
|
|
|
|
|
|
|
auto& rm = r.model->getResourceManager();
|
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(ResourceManager::MATERIAL));
|
2016-02-06 00:44:43 +01:00
|
|
|
|
|
|
|
auto* new_meshes = (Mesh*)m_allocator.allocate(count * sizeof(Mesh));
|
|
|
|
if (r.meshes)
|
2016-01-22 01:37:13 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
new (NewPlaceholder(), new_meshes + i) Mesh(r.meshes[i]);
|
2016-01-22 01:37:13 +01:00
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
|
|
|
|
if (r.custom_meshes)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
for (int i = count; i < r.mesh_count; ++i)
|
|
|
|
{
|
|
|
|
material_manager->unload(*r.meshes[i].material);
|
|
|
|
}
|
|
|
|
m_allocator.deallocate(r.meshes);
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
|
|
|
{
|
|
|
|
material_manager->load(*r.meshes[i].material);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = r.mesh_count; i < count; ++i)
|
|
|
|
{
|
2016-05-01 15:25:54 +02:00
|
|
|
new (NewPlaceholder(), new_meshes + i) Mesh(nullptr, 0, 0, 0, 0, "", m_allocator);
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
r.meshes = new_meshes;
|
|
|
|
r.mesh_count = count;
|
|
|
|
r.custom_meshes = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setRenderableMaterial(ComponentIndex cmp, int index, const Path& path) override
|
|
|
|
{
|
|
|
|
auto& r = m_renderables[cmp];
|
|
|
|
if (r.meshes && r.mesh_count > index && path == r.meshes[index].material->getPath()) return;
|
|
|
|
|
|
|
|
auto& rm = r.model->getResourceManager();
|
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(ResourceManager::MATERIAL));
|
2016-02-10 12:09:09 +01:00
|
|
|
|
2016-03-06 12:54:29 +01:00
|
|
|
int new_count = Math::maximum(int8(index + 1), r.mesh_count);
|
2016-02-06 00:44:43 +01:00
|
|
|
allocateCustomMeshes(r, new_count);
|
2016-01-22 01:11:04 +01:00
|
|
|
|
2016-01-22 18:02:07 +01:00
|
|
|
if (r.meshes[index].material) material_manager->unload(*r.meshes[index].material);
|
2016-01-22 01:11:04 +01:00
|
|
|
auto* new_material = static_cast<Material*>(material_manager->load(path));
|
2016-01-22 18:02:07 +01:00
|
|
|
r.meshes[index].material = new_material;
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
2016-02-10 12:09:09 +01:00
|
|
|
|
|
|
|
|
2016-01-22 01:11:04 +01:00
|
|
|
Path getRenderableMaterial(ComponentIndex cmp, int index) override
|
|
|
|
{
|
|
|
|
auto& r = m_renderables[cmp];
|
|
|
|
if (!r.meshes) return Path("");
|
|
|
|
|
2016-01-22 18:02:07 +01:00
|
|
|
return r.meshes[index].material->getPath();
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
void setModel(ComponentIndex component, Model* model)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
ASSERT(m_renderables[component].entity != INVALID_ENTITY);
|
2015-12-10 17:09:52 +01:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Model* old_model = m_renderables[component].model;
|
2015-12-10 21:56:17 +01:00
|
|
|
bool no_change = model == old_model && old_model;
|
|
|
|
if (no_change)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-09-26 15:12:28 +02:00
|
|
|
old_model->getResourceManager().get(ResourceManager::MODEL)->unload(*old_model);
|
2015-07-21 20:10:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (old_model)
|
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
auto& rm = old_model->getResourceManager();
|
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(ResourceManager::MATERIAL));
|
2016-02-06 00:44:43 +01:00
|
|
|
freeCustomMeshes(m_renderables[component], material_manager);
|
2015-07-21 20:10:50 +02:00
|
|
|
ModelLoadedCallback* callback = getModelLoadedCallback(old_model);
|
|
|
|
--callback->m_ref_count;
|
2015-12-10 23:33:21 +01:00
|
|
|
if (old_model->isReady())
|
|
|
|
{
|
|
|
|
m_culling_system->removeStatic(component);
|
|
|
|
}
|
2015-09-26 15:12:28 +02:00
|
|
|
old_model->getResourceManager().get(ResourceManager::MODEL)->unload(*old_model);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-12-10 20:27:51 +01:00
|
|
|
m_renderables[component].model = model;
|
2016-01-22 01:11:04 +01:00
|
|
|
m_renderables[component].meshes = nullptr;
|
|
|
|
m_renderables[component].mesh_count = 0;
|
2016-02-07 12:31:28 +01:00
|
|
|
LUMIX_DELETE(m_allocator, m_renderables[component].pose);
|
|
|
|
m_renderables[component].pose = nullptr;
|
2015-07-21 20:10:50 +02:00
|
|
|
if (model)
|
|
|
|
{
|
|
|
|
ModelLoadedCallback* callback = getModelLoadedCallback(model);
|
|
|
|
++callback->m_ref_count;
|
|
|
|
|
|
|
|
if (model->isReady())
|
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
modelLoaded(model, component);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-08 00:32:36 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
IAllocator& getAllocator() override { return m_allocator; }
|
2015-04-08 00:32:36 +02:00
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void detectLightInfluencedGeometry(int light_index)
|
|
|
|
{
|
2015-08-27 23:59:36 +02:00
|
|
|
if (!m_is_forward_rendered) return;
|
2016-01-26 15:21:38 +01:00
|
|
|
|
2015-08-27 23:59:36 +02:00
|
|
|
Frustum frustum = getPointLightFrustum(light_index);
|
|
|
|
m_culling_system->cullToFrustum(frustum, 0xffffFFFF);
|
|
|
|
const CullingSystem::Results& results =
|
|
|
|
m_culling_system->getResult();
|
|
|
|
Array<int>& influenced_geometry =
|
|
|
|
m_light_influenced_geometry[light_index];
|
|
|
|
influenced_geometry.clear();
|
|
|
|
for (int i = 0; i < results.size(); ++i)
|
|
|
|
{
|
|
|
|
const CullingSystem::Subresults& subresult = results[i];
|
|
|
|
influenced_geometry.reserve(influenced_geometry.size() +
|
|
|
|
subresult.size());
|
|
|
|
for (int j = 0, c = subresult.size(); j < c; ++j)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-08-27 23:59:36 +02:00
|
|
|
influenced_geometry.push(subresult[j]);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-10 08:12:12 +02:00
|
|
|
|
|
|
|
|
2015-12-17 13:58:40 +01:00
|
|
|
int getParticleEmitterAttractorCount(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AttractorModule>(cmp);
|
|
|
|
return module ? module->m_count : 0;
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addParticleEmitterAttractor(ComponentIndex cmp, int index) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AttractorModule>(cmp);
|
|
|
|
if (!module) return;
|
2015-12-17 13:58:40 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* plane_module = static_cast<ParticleEmitter::AttractorModule*>(module);
|
|
|
|
if (plane_module->m_count == lengthOf(plane_module->m_entities)) return;
|
2015-12-17 13:58:40 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
if (index < 0)
|
|
|
|
{
|
|
|
|
plane_module->m_entities[plane_module->m_count] = INVALID_ENTITY;
|
|
|
|
++plane_module->m_count;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = plane_module->m_count - 1; i > index; --i)
|
|
|
|
{
|
|
|
|
plane_module->m_entities[i] = plane_module->m_entities[i - 1];
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
plane_module->m_entities[index] = INVALID_ENTITY;
|
|
|
|
++plane_module->m_count;
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void removeParticleEmitterAttractor(ComponentIndex cmp, int index) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AttractorModule>(cmp);
|
|
|
|
if (!module) return;
|
2015-12-17 13:58:40 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
for (int i = index; i < module->m_count - 1; ++i)
|
|
|
|
{
|
|
|
|
module->m_entities[i] = module->m_entities[i + 1];
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
--module->m_count;
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Entity getParticleEmitterAttractorEntity(ComponentIndex cmp, int index) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AttractorModule>(cmp);
|
|
|
|
return module ? module->m_entities[index] : INVALID_ENTITY;
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterAttractorEntity(ComponentIndex cmp, int index, Entity entity) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AttractorModule>(cmp);
|
|
|
|
if(module) module->m_entities[index] = entity;
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-18 21:23:51 +01:00
|
|
|
float getParticleEmitterShapeRadius(ComponentIndex cmp) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SpawnShapeModule>(cmp);
|
|
|
|
return module ? module->m_radius : 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterShapeRadius(ComponentIndex cmp, float value) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SpawnShapeModule>(cmp);
|
|
|
|
if (module) module->m_radius = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-16 21:26:19 +01:00
|
|
|
int getParticleEmitterPlaneCount(ComponentIndex cmp) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::PlaneModule>(cmp);
|
|
|
|
return module ? module->m_count : 0;
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addParticleEmitterPlane(ComponentIndex cmp, int index) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* plane_module = getEmitterModule<ParticleEmitter::PlaneModule>(cmp);
|
|
|
|
if (!plane_module) return;
|
|
|
|
|
|
|
|
if (plane_module->m_count == lengthOf(plane_module->m_entities)) return;
|
|
|
|
|
|
|
|
if (index < 0)
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
plane_module->m_entities[plane_module->m_count] = INVALID_ENTITY;
|
|
|
|
++plane_module->m_count;
|
|
|
|
return;
|
|
|
|
}
|
2015-12-16 21:26:19 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
for (int i = plane_module->m_count - 1; i > index; --i)
|
|
|
|
{
|
|
|
|
plane_module->m_entities[i] = plane_module->m_entities[i - 1];
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
plane_module->m_entities[index] = INVALID_ENTITY;
|
|
|
|
++plane_module->m_count;
|
|
|
|
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void removeParticleEmitterPlane(ComponentIndex cmp, int index) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* plane_module = getEmitterModule<ParticleEmitter::PlaneModule>(cmp);
|
|
|
|
if (!plane_module) return;
|
2015-12-16 21:26:19 +01:00
|
|
|
|
2015-12-17 21:38:23 +01:00
|
|
|
for (int i = index; i < plane_module->m_count - 1; ++i)
|
|
|
|
{
|
|
|
|
plane_module->m_entities[i] = plane_module->m_entities[i + 1];
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
2015-12-17 21:38:23 +01:00
|
|
|
--plane_module->m_count;
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Entity getParticleEmitterPlaneEntity(ComponentIndex cmp, int index) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::PlaneModule>(cmp);
|
|
|
|
return module ? module->m_entities[index] : INVALID_ENTITY;
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterPlaneEntity(ComponentIndex cmp, int index, Entity entity) override
|
|
|
|
{
|
2015-12-17 21:38:23 +01:00
|
|
|
auto* module = getEmitterModule<ParticleEmitter::PlaneModule>(cmp);
|
|
|
|
if (module) module->m_entities[index] = entity;
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
DelegateList<void(ComponentIndex)>& renderableCreated() override
|
2015-07-24 22:38:11 +02:00
|
|
|
{
|
|
|
|
return m_renderable_created;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
DelegateList<void(ComponentIndex)>& renderableDestroyed() override
|
2015-07-24 22:38:11 +02:00
|
|
|
{
|
|
|
|
return m_renderable_destroyed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
float getLightFOV(ComponentIndex cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
return m_point_lights[getPointLightIndex(cmp)].m_fov;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-10 08:12:12 +02:00
|
|
|
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void setLightFOV(ComponentIndex cmp, float fov) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2015-07-24 08:42:35 +02:00
|
|
|
m_point_lights[getPointLightIndex(cmp)].m_fov = fov;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
ComponentIndex createGlobalLight(Entity entity)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
GlobalLight& light = m_global_lights.emplace();
|
2015-07-21 20:10:50 +02:00
|
|
|
light.m_entity = entity;
|
2016-02-10 12:09:09 +01:00
|
|
|
light.m_diffuse_color.set(1, 1, 1);
|
|
|
|
light.m_diffuse_intensity = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
light.m_ambient_color.set(1, 1, 1);
|
|
|
|
light.m_ambient_intensity = 1;
|
|
|
|
light.m_fog_color.set(1, 1, 1);
|
|
|
|
light.m_fog_density = 0;
|
|
|
|
light.m_uid = ++m_global_light_last_uid;
|
2015-09-10 22:14:54 +02:00
|
|
|
light.m_cascades.set(3, 8, 100, 300);
|
2015-10-17 00:18:47 +02:00
|
|
|
light.m_fog_bottom = 0.0f;
|
|
|
|
light.m_fog_height = 10.0f;
|
2016-01-28 21:44:35 +01:00
|
|
|
light.m_specular.set(0, 0, 0);
|
2016-02-10 12:09:09 +01:00
|
|
|
light.m_specular_intensity = 1;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
if (m_global_lights.size() == 1)
|
|
|
|
{
|
|
|
|
m_active_global_light_uid = light.m_uid;
|
|
|
|
}
|
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
m_universe.addComponent(entity, GLOBAL_LIGHT_HASH, this, light.m_uid);
|
|
|
|
return light.m_uid;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
ComponentIndex createPointLight(Entity entity)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
PointLight& light = m_point_lights.emplace();
|
2015-10-30 17:17:29 +01:00
|
|
|
m_light_influenced_geometry.push(Array<int>(m_allocator));
|
2015-07-21 20:10:50 +02:00
|
|
|
light.m_entity = entity;
|
2015-09-02 11:14:42 +02:00
|
|
|
light.m_diffuse_color.set(1, 1, 1);
|
2016-02-10 12:09:09 +01:00
|
|
|
light.m_diffuse_intensity = 1;
|
2015-07-21 20:10:50 +02:00
|
|
|
light.m_uid = ++m_point_light_last_uid;
|
|
|
|
light.m_fov = 999;
|
|
|
|
light.m_specular_color.set(1, 1, 1);
|
2016-02-10 12:09:09 +01:00
|
|
|
light.m_specular_intensity = 1;
|
2015-09-02 11:14:42 +02:00
|
|
|
light.m_cast_shadows = false;
|
2015-09-09 02:18:09 +02:00
|
|
|
light.m_attenuation_param = 2;
|
2015-09-09 21:34:16 +02:00
|
|
|
light.m_range = 10;
|
2016-01-26 10:27:31 +01:00
|
|
|
m_point_lights_map.insert(light.m_uid, m_point_lights.size() - 1);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
m_universe.addComponent(entity, POINT_LIGHT_HASH, this, light.m_uid);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
detectLightInfluencedGeometry(m_point_lights.size() - 1);
|
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
return light.m_uid;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
ComponentIndex createBoneAttachment(Entity entity)
|
|
|
|
{
|
|
|
|
BoneAttachment& attachment = m_bone_attachments.emplace();
|
|
|
|
attachment.entity = entity;
|
|
|
|
attachment.parent_entity = INVALID_ENTITY;
|
|
|
|
attachment.bone_index = -1;
|
|
|
|
|
|
|
|
m_universe.addComponent(entity, BONE_ATTACHMENT_HASH, this, entity);
|
|
|
|
return entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-25 00:09:11 +02:00
|
|
|
ComponentIndex createRenderable(Entity entity)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-12-10 17:09:52 +01:00
|
|
|
while(entity >= m_renderables.size())
|
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
auto& r = m_renderables.emplace();
|
|
|
|
r.entity = INVALID_ENTITY;
|
|
|
|
r.model = nullptr;
|
|
|
|
r.pose = nullptr;
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
|
|
|
auto& r = m_renderables[entity];
|
2015-12-10 20:27:51 +01:00
|
|
|
r.entity = entity;
|
|
|
|
r.model = nullptr;
|
2016-01-09 18:44:25 +01:00
|
|
|
r.layer_mask = 1;
|
2016-01-22 01:11:04 +01:00
|
|
|
r.meshes = nullptr;
|
2015-12-10 20:27:51 +01:00
|
|
|
r.pose = nullptr;
|
2016-02-06 00:44:43 +01:00
|
|
|
r.custom_meshes = false;
|
2016-01-22 01:11:04 +01:00
|
|
|
r.mesh_count = 0;
|
2015-12-10 20:27:51 +01:00
|
|
|
r.matrix = m_universe.getMatrix(entity);
|
2015-12-10 21:56:17 +01:00
|
|
|
m_universe.addComponent(entity, RENDERABLE_HASH, this, entity);
|
2015-12-10 17:09:52 +01:00
|
|
|
m_renderable_created.invoke(m_renderables.size() - 1);
|
2015-12-10 21:56:17 +01:00
|
|
|
return entity;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
2015-11-04 22:43:54 +01:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
void setParticleEmitterMaterialPath(ComponentIndex cmp, const Path& path) override
|
2015-11-04 22:43:54 +01:00
|
|
|
{
|
|
|
|
if (!m_particle_emitters[cmp]) return;
|
|
|
|
|
|
|
|
auto* manager = m_engine.getResourceManager().get(ResourceManager::MATERIAL);
|
2016-01-06 14:18:59 +01:00
|
|
|
Material* material = static_cast<Material*>(manager->load(path));
|
2015-11-04 22:43:54 +01:00
|
|
|
m_particle_emitters[cmp]->setMaterial(material);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
Path getParticleEmitterMaterialPath(ComponentIndex cmp) override
|
2015-11-04 22:43:54 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[cmp];
|
2016-01-06 14:18:59 +01:00
|
|
|
if (!emitter) return Path("");
|
|
|
|
if (!emitter->getMaterial()) return Path("");
|
2015-11-04 22:43:54 +01:00
|
|
|
|
2016-01-06 14:18:59 +01:00
|
|
|
return emitter->getMaterial()->getPath();
|
2015-11-04 22:43:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const Array<ParticleEmitter*>& getParticleEmitters() const override
|
|
|
|
{
|
|
|
|
return m_particle_emitters;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
private:
|
|
|
|
IAllocator& m_allocator;
|
|
|
|
Array<ModelLoadedCallback*> m_model_loaded_callbacks;
|
|
|
|
|
2015-12-10 17:09:52 +01:00
|
|
|
Array<Renderable> m_renderables;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
int m_point_light_last_uid;
|
|
|
|
Array<PointLight> m_point_lights;
|
2016-03-06 12:54:29 +01:00
|
|
|
HashMap<ComponentIndex, int> m_point_lights_map;
|
2015-12-10 17:09:52 +01:00
|
|
|
Array<Array<ComponentIndex>> m_light_influenced_geometry;
|
2015-07-21 20:10:50 +02:00
|
|
|
int m_active_global_light_uid;
|
|
|
|
int m_global_light_last_uid;
|
|
|
|
Array<GlobalLight> m_global_lights;
|
|
|
|
Array<Camera> m_cameras;
|
2016-05-02 21:41:18 +02:00
|
|
|
Array<BoneAttachment> m_bone_attachments;
|
2015-07-21 20:10:50 +02:00
|
|
|
Array<Terrain*> m_terrains;
|
|
|
|
Universe& m_universe;
|
|
|
|
Renderer& m_renderer;
|
|
|
|
Engine& m_engine;
|
2016-03-10 19:32:48 +01:00
|
|
|
Array<DebugTriangle> m_debug_triangles;
|
2015-07-21 20:10:50 +02:00
|
|
|
Array<DebugLine> m_debug_lines;
|
2015-08-28 21:55:53 +02:00
|
|
|
Array<DebugPoint> m_debug_points;
|
2015-07-21 20:10:50 +02:00
|
|
|
CullingSystem* m_culling_system;
|
2015-10-30 21:11:11 +01:00
|
|
|
Array<ParticleEmitter*> m_particle_emitters;
|
2015-12-10 20:27:51 +01:00
|
|
|
Array<Array<RenderableMesh>> m_temporary_infos;
|
2015-07-21 20:10:50 +02:00
|
|
|
MTJD::Group m_sync_point;
|
|
|
|
Array<MTJD::Job*> m_jobs;
|
|
|
|
float m_time;
|
2016-05-02 21:41:18 +02:00
|
|
|
bool m_is_updating_attachments;
|
2015-07-21 20:10:50 +02:00
|
|
|
bool m_is_forward_rendered;
|
2015-10-12 09:56:46 +02:00
|
|
|
bool m_is_grass_enabled;
|
2015-12-12 00:46:27 +01:00
|
|
|
bool m_is_game_running;
|
2015-07-24 22:38:11 +02:00
|
|
|
DelegateList<void(ComponentIndex)> m_renderable_created;
|
|
|
|
DelegateList<void(ComponentIndex)> m_renderable_destroyed;
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
|
|
|
|
static struct
|
|
|
|
{
|
|
|
|
uint32 type;
|
|
|
|
ComponentIndex(RenderSceneImpl::*creator)(Entity);
|
|
|
|
void (RenderSceneImpl::*destroyer)(ComponentIndex);
|
2016-05-02 21:41:18 +02:00
|
|
|
} COMPONENT_INFOS[] = {{RENDERABLE_HASH, &RenderSceneImpl::createRenderable, &RenderSceneImpl::destroyRenderable},
|
2015-12-08 22:35:41 +01:00
|
|
|
{GLOBAL_LIGHT_HASH, &RenderSceneImpl::createGlobalLight, &RenderSceneImpl::destroyGlobalLight},
|
|
|
|
{POINT_LIGHT_HASH, &RenderSceneImpl::createPointLight, &RenderSceneImpl::destroyPointLight},
|
|
|
|
{CAMERA_HASH, &RenderSceneImpl::createCamera, &RenderSceneImpl::destroyCamera},
|
|
|
|
{TERRAIN_HASH, &RenderSceneImpl::createTerrain, &RenderSceneImpl::destroyTerrain},
|
2016-05-02 21:41:18 +02:00
|
|
|
{PARTICLE_EMITTER_HASH, &RenderSceneImpl::createParticleEmitter, &RenderSceneImpl::destroyParticleEmitter},
|
2015-12-08 22:35:41 +01:00
|
|
|
{PARTICLE_EMITTER_FADE_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterFade,
|
|
|
|
&RenderSceneImpl::destroyParticleEmitterFade},
|
2016-05-02 21:41:18 +02:00
|
|
|
{PARTICLE_EMITTER_FORCE_HASH,
|
2015-12-12 01:35:22 +01:00
|
|
|
&RenderSceneImpl::createParticleEmitterForce,
|
|
|
|
&RenderSceneImpl::destroyParticleEmitterForce},
|
2015-12-17 13:58:40 +01:00
|
|
|
{PARTICLE_EMITTER_ATTRACTOR_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterAttractor,
|
|
|
|
&RenderSceneImpl::destroyParticleEmitterAttractor},
|
2015-12-08 22:35:41 +01:00
|
|
|
{PARTICLE_EMITTER_SIZE_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterSize,
|
|
|
|
&RenderSceneImpl::destroyParticleEmitterSize},
|
|
|
|
{PARTICLE_EMITTER_LINEAR_MOVEMENT_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterLinearMovement,
|
|
|
|
&RenderSceneImpl::destroyParticleEmitterLinearMovement},
|
2015-12-18 21:23:51 +01:00
|
|
|
{PARTICLE_EMITTER_SPAWN_SHAPE_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterSpawnShape,
|
2016-05-02 21:41:18 +02:00
|
|
|
&RenderSceneImpl::destroyParticleEmitterSpawnShape},
|
2015-12-08 22:35:41 +01:00
|
|
|
{PARTICLE_EMITTER_RANDOM_ROTATION_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterRandomRotation,
|
2015-12-16 21:26:19 +01:00
|
|
|
&RenderSceneImpl::destroyParticleEmitterRandomRotation},
|
|
|
|
{PARTICLE_EMITTER_PLANE_HASH,
|
|
|
|
&RenderSceneImpl::createParticleEmitterPlane,
|
|
|
|
&RenderSceneImpl::destroyParticleEmitterPlane},
|
2016-05-02 21:41:18 +02:00
|
|
|
{BONE_ATTACHMENT_HASH, &RenderSceneImpl::createBoneAttachment, &RenderSceneImpl::destroyBoneAttachment}
|
2015-12-08 22:35:41 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
ComponentIndex RenderSceneImpl::createComponent(uint32 type, Entity entity)
|
|
|
|
{
|
|
|
|
for (auto& i : COMPONENT_INFOS)
|
|
|
|
{
|
|
|
|
if (i.type == type)
|
|
|
|
{
|
|
|
|
return (this->*i.creator)(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RenderSceneImpl::destroyComponent(ComponentIndex component, uint32 type)
|
|
|
|
{
|
|
|
|
for (auto& i : COMPONENT_INFOS)
|
|
|
|
{
|
|
|
|
if (i.type == type)
|
|
|
|
{
|
|
|
|
(this->*i.destroyer)(component);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ASSERT(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
RenderScene* RenderScene::createInstance(Renderer& renderer,
|
|
|
|
Engine& engine,
|
|
|
|
Universe& universe,
|
|
|
|
bool is_forward_rendered,
|
|
|
|
IAllocator& allocator)
|
|
|
|
{
|
2015-11-11 23:25:44 +01:00
|
|
|
return LUMIX_NEW(allocator, RenderSceneImpl)(
|
2015-07-21 20:10:50 +02:00
|
|
|
renderer, engine, universe, is_forward_rendered, allocator);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RenderScene::destroyInstance(RenderScene* scene)
|
|
|
|
{
|
2015-11-11 23:25:44 +01:00
|
|
|
LUMIX_DELETE(scene->getAllocator(), static_cast<RenderSceneImpl*>(scene));
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-04-02 15:35:08 +02:00
|
|
|
|
|
|
|
|
|
|
|
void RenderScene::registerLuaAPI(lua_State* L)
|
|
|
|
{
|
|
|
|
Pipeline::registerLuaAPI(L);
|
2016-05-07 11:49:39 +02:00
|
|
|
Model::registerLuaAPI(L);
|
2016-04-02 15:35:08 +02:00
|
|
|
|
|
|
|
#define REGISTER_FUNCTION(F)\
|
|
|
|
do { \
|
|
|
|
auto f = &LuaWrapper::wrapMethod<RenderSceneImpl, decltype(&RenderSceneImpl::F), &RenderSceneImpl::F>; \
|
|
|
|
LuaWrapper::createSystemFunction(L, "Renderer", #F, f); \
|
|
|
|
} while(false) \
|
|
|
|
|
|
|
|
REGISTER_FUNCTION(getCameraSlot);
|
|
|
|
REGISTER_FUNCTION(getCameraComponent);
|
|
|
|
REGISTER_FUNCTION(getRenderableComponent);
|
2016-05-07 11:49:39 +02:00
|
|
|
REGISTER_FUNCTION(getRenderableModel);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(addDebugCross);
|
2016-05-07 11:49:39 +02:00
|
|
|
REGISTER_FUNCTION(addDebugLine);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(getTerrainMaterial);
|
|
|
|
|
|
|
|
#undef REGISTER_FUNCTION
|
|
|
|
|
|
|
|
#define REGISTER_FUNCTION(F)\
|
|
|
|
do { \
|
|
|
|
auto f = &LuaWrapper::wrap<decltype(&RenderSceneImpl::LUA_##F), &RenderSceneImpl::LUA_##F>; \
|
|
|
|
LuaWrapper::createSystemFunction(L, "Renderer", #F, f); \
|
|
|
|
} while(false) \
|
|
|
|
|
|
|
|
REGISTER_FUNCTION(getMaterialTexture);
|
|
|
|
REGISTER_FUNCTION(setRenderableMaterial);
|
|
|
|
REGISTER_FUNCTION(setRenderablePath);
|
|
|
|
REGISTER_FUNCTION(makeScreenshot);
|
|
|
|
REGISTER_FUNCTION(compareTGA);
|
|
|
|
|
|
|
|
LuaWrapper::createSystemFunction(L, "Renderer", "castCameraRay", &RenderSceneImpl::LUA_castCameraRay);
|
|
|
|
|
|
|
|
#undef REGISTER_FUNCTION
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Lumix
|