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"
|
2016-10-03 17:07:32 +02:00
|
|
|
#include "engine/crc32.h"
|
2017-02-24 15:20:58 +01:00
|
|
|
#include "engine/engine.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/fs/file_system.h"
|
|
|
|
#include "engine/geometry.h"
|
2017-09-16 14:04:24 +02:00
|
|
|
#include "engine/job_system.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/json_serializer.h"
|
|
|
|
#include "engine/lifo_allocator.h"
|
|
|
|
#include "engine/log.h"
|
|
|
|
#include "engine/lua_wrapper.h"
|
|
|
|
#include "engine/math_utils.h"
|
2016-06-12 15:26:41 +02:00
|
|
|
#include "engine/path_utils.h"
|
2016-10-17 00:19:02 +02:00
|
|
|
#include "engine/plugin_manager.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/profiler.h"
|
2017-10-18 23:43:02 +02:00
|
|
|
#include "engine/properties.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/resource_manager.h"
|
|
|
|
#include "engine/resource_manager_base.h"
|
2016-12-11 21:44:47 +01:00
|
|
|
#include "engine/serializer.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/timer.h"
|
2017-02-24 15:20:58 +01:00
|
|
|
#include "engine/universe/universe.h"
|
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"
|
2016-10-17 10:21:25 +02:00
|
|
|
#include "renderer/frame_buffer.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#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"
|
2016-06-12 15:26:41 +02:00
|
|
|
#include "renderer/texture_manager.h"
|
2016-11-09 10:09:33 +01:00
|
|
|
#include <cfloat>
|
2017-02-24 15:20:58 +01:00
|
|
|
#include <cmath>
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
|
|
|
namespace Lumix
|
|
|
|
{
|
|
|
|
|
2015-07-24 22:38:11 +02:00
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
enum class RenderSceneVersion : int
|
|
|
|
{
|
|
|
|
GRASS_ROTATION_MODE,
|
2017-02-09 14:22:41 +01:00
|
|
|
GLOBAL_LIGHT_REFACTOR,
|
2017-02-21 16:37:07 +01:00
|
|
|
EMITTER_MATERIAL,
|
2017-02-27 20:13:50 +01:00
|
|
|
BONE_ATTACHMENT_TRANSFORM,
|
2017-04-13 17:05:07 +02:00
|
|
|
MODEL_INSTNACE_FLAGS,
|
2017-04-21 23:26:44 +02:00
|
|
|
INDIRECT_INTENSITY,
|
2017-01-24 16:56:42 +01:00
|
|
|
|
|
|
|
LATEST
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-10-18 23:43:02 +02:00
|
|
|
static const ComponentType MODEL_INSTANCE_TYPE = Properties::getComponentType("renderable");
|
|
|
|
static const ComponentType DECAL_TYPE = Properties::getComponentType("decal");
|
|
|
|
static const ComponentType POINT_LIGHT_TYPE = Properties::getComponentType("point_light");
|
|
|
|
static const ComponentType PARTICLE_EMITTER_TYPE = Properties::getComponentType("particle_emitter");
|
|
|
|
static const ComponentType PARTICLE_EMITTER_ALPHA_TYPE = Properties::getComponentType("particle_emitter_alpha");
|
|
|
|
static const ComponentType PARTICLE_EMITTER_FORCE_HASH = Properties::getComponentType("particle_emitter_force");
|
2016-12-10 15:16:01 +01:00
|
|
|
static const ComponentType PARTICLE_EMITTER_ATTRACTOR_TYPE =
|
2017-10-18 23:43:02 +02:00
|
|
|
Properties::getComponentType("particle_emitter_attractor");
|
2016-12-10 15:16:01 +01:00
|
|
|
static const ComponentType PARTICLE_EMITTER_SUBIMAGE_TYPE =
|
2017-10-18 23:43:02 +02:00
|
|
|
Properties::getComponentType("particle_emitter_subimage");
|
2016-12-10 15:16:01 +01:00
|
|
|
static const ComponentType PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE =
|
2017-10-18 23:43:02 +02:00
|
|
|
Properties::getComponentType("particle_emitter_linear_movement");
|
2016-12-10 15:16:01 +01:00
|
|
|
static const ComponentType PARTICLE_EMITTER_SPAWN_SHAPE_TYPE =
|
2017-10-18 23:43:02 +02:00
|
|
|
Properties::getComponentType("particle_emitter_spawn_shape");
|
|
|
|
static const ComponentType PARTICLE_EMITTER_PLANE_TYPE = Properties::getComponentType("particle_emitter_plane");
|
2016-12-10 15:16:01 +01:00
|
|
|
static const ComponentType PARTICLE_EMITTER_RANDOM_ROTATION_TYPE =
|
2017-10-18 23:43:02 +02:00
|
|
|
Properties::getComponentType("particle_emitter_random_rotation");
|
|
|
|
static const ComponentType PARTICLE_EMITTER_SIZE_TYPE = Properties::getComponentType("particle_emitter_size");
|
|
|
|
static const ComponentType GLOBAL_LIGHT_TYPE = Properties::getComponentType("global_light");
|
|
|
|
static const ComponentType CAMERA_TYPE = Properties::getComponentType("camera");
|
|
|
|
static const ComponentType TERRAIN_TYPE = Properties::getComponentType("terrain");
|
|
|
|
static const ComponentType BONE_ATTACHMENT_TYPE = Properties::getComponentType("bone_attachment");
|
|
|
|
static const ComponentType ENVIRONMENT_PROBE_TYPE = Properties::getComponentType("environment_probe");
|
2016-06-22 00:46:48 +02:00
|
|
|
|
2016-07-24 22:21:43 +02:00
|
|
|
static const ResourceType MATERIAL_TYPE("material");
|
|
|
|
static const ResourceType TEXTURE_TYPE("texture");
|
|
|
|
static const ResourceType MODEL_TYPE("model");
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
struct Decal : public DecalInfo
|
|
|
|
{
|
|
|
|
Entity entity;
|
|
|
|
Vec3 scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
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;
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle m_component;
|
2015-07-21 20:10:50 +02:00
|
|
|
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
|
|
|
|
{
|
2016-02-10 12:09:09 +01:00
|
|
|
Vec3 m_diffuse_color;
|
|
|
|
float m_diffuse_intensity;
|
2017-04-21 23:26:44 +02:00
|
|
|
float m_indirect_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
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_ortho;
|
|
|
|
char slot[MAX_SLOT_LENGTH + 1];
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-06-12 15:26:41 +02:00
|
|
|
struct EnvironmentProbe
|
|
|
|
{
|
|
|
|
Texture* texture;
|
2016-11-29 20:00:36 +01:00
|
|
|
Texture* irradiance;
|
|
|
|
Texture* radiance;
|
2017-01-03 17:04:09 +01:00
|
|
|
u64 guid;
|
2016-06-12 15:26:41 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
struct BoneAttachment
|
|
|
|
{
|
|
|
|
Entity entity;
|
|
|
|
Entity parent_entity;
|
|
|
|
int bone_index;
|
2017-08-18 13:54:56 +02:00
|
|
|
RigidTransform relative_transform;
|
2016-05-02 21:41:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-10-07 12:57:30 +02:00
|
|
|
class RenderSceneImpl LUMIX_FINAL : public RenderScene
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
private:
|
2016-07-25 02:00:22 +02:00
|
|
|
struct ModelLoadedCallback
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2015-07-21 20:10:50 +02:00
|
|
|
ModelLoadedCallback(RenderSceneImpl& scene, Model* model)
|
|
|
|
: m_scene(scene)
|
|
|
|
, m_ref_count(0)
|
|
|
|
, m_model(model)
|
|
|
|
{
|
2016-07-25 02:00:22 +02:00
|
|
|
m_model->getObserverCb().bind<RenderSceneImpl, &RenderSceneImpl::modelStateChanged>(&scene);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
~ModelLoadedCallback()
|
|
|
|
{
|
2016-07-25 02:00:22 +02:00
|
|
|
m_model->getObserverCb().unbind<RenderSceneImpl, &RenderSceneImpl::modelStateChanged>(&m_scene);
|
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,
|
2016-07-21 14:23:46 +02:00
|
|
|
IAllocator& allocator);
|
2014-10-30 00:16:32 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
~RenderSceneImpl()
|
|
|
|
{
|
2016-05-02 21:41:18 +02:00
|
|
|
m_universe.entityTransformed().unbind<RenderSceneImpl, &RenderSceneImpl::onEntityMoved>(this);
|
|
|
|
m_universe.entityDestroyed().unbind<RenderSceneImpl, &RenderSceneImpl::onEntityDestroyed>(this);
|
2016-07-24 15:44:37 +02:00
|
|
|
CullingSystem::destroy(*m_culling_system);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-25 02:00:22 +02:00
|
|
|
void modelStateChanged(Resource::State old_state, Resource::State new_state, Resource& resource)
|
|
|
|
{
|
|
|
|
Model* model = static_cast<Model*>(&resource);
|
|
|
|
if (new_state == Resource::State::READY)
|
|
|
|
{
|
|
|
|
modelLoaded(model);
|
|
|
|
}
|
|
|
|
else if (old_state == Resource::State::READY && new_state != Resource::State::READY)
|
|
|
|
{
|
|
|
|
modelUnloaded(model);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-24 15:44:37 +02:00
|
|
|
void clear() override
|
|
|
|
{
|
|
|
|
auto& rm = m_engine.getResourceManager();
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(MATERIAL_TYPE));
|
2014-10-30 00:16:32 +01:00
|
|
|
|
2016-07-24 15:44:37 +02:00
|
|
|
m_model_loaded_callbacks.clear();
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
for (Decal& decal : m_decals)
|
|
|
|
{
|
2016-07-24 15:44:37 +02:00
|
|
|
if (decal.material) material_manager->unload(*decal.material);
|
2016-07-22 13:57:52 +02:00
|
|
|
}
|
2016-07-24 15:44:37 +02:00
|
|
|
m_decals.clear();
|
2016-07-22 13:57:52 +02:00
|
|
|
|
2016-08-02 21:34:22 +02:00
|
|
|
m_cameras.clear();
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
for (auto* terrain : m_terrains)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
LUMIX_DELETE(m_allocator, terrain);
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
2016-07-24 15:44:37 +02:00
|
|
|
m_terrains.clear();
|
2015-10-30 21:11:11 +01:00
|
|
|
|
2016-07-09 00:54:39 +02:00
|
|
|
for (auto* emitter : m_particle_emitters)
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
2016-07-09 00:54:39 +02:00
|
|
|
LUMIX_DELETE(m_allocator, emitter);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-07-24 15:44:37 +02:00
|
|
|
m_particle_emitters.clear();
|
2015-01-04 15:05:20 +01:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
for (auto& i : m_model_instances)
|
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
|
|
|
{
|
2016-02-06 10:58:50 +01:00
|
|
|
freeCustomMeshes(i, material_manager);
|
2016-07-25 01:02:36 +02:00
|
|
|
i.model->getResourceManager().unload(*i.model);
|
2015-12-10 20:27:51 +01:00
|
|
|
LUMIX_DELETE(m_allocator, i.pose);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2016-09-29 22:24:53 +02:00
|
|
|
m_model_instances.clear();
|
2016-07-24 15:44:37 +02:00
|
|
|
m_culling_system->clear();
|
2014-10-15 20:46:01 +02:00
|
|
|
|
2016-07-09 00:54:39 +02:00
|
|
|
for (auto& probe : m_environment_probes)
|
2016-06-12 15:26:41 +02:00
|
|
|
{
|
2016-07-25 01:02:36 +02:00
|
|
|
if (probe.texture) probe.texture->getResourceManager().unload(*probe.texture);
|
2017-02-28 21:18:37 +01:00
|
|
|
if (probe.radiance) probe.radiance->getResourceManager().unload(*probe.radiance);
|
|
|
|
if (probe.irradiance) probe.irradiance->getResourceManager().unload(*probe.irradiance);
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
2016-07-24 15:44:37 +02:00
|
|
|
m_environment_probes.clear();
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-15 20:46:01 +02:00
|
|
|
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void resetParticleEmitter(ComponentHandle cmp) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters[{cmp.index}]->reset();
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
2016-02-26 13:49:42 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ParticleEmitter* getParticleEmitter(ComponentHandle cmp) override
|
2015-12-16 23:42:23 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
return m_particle_emitters[{cmp.index}];
|
2015-12-16 23:42:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void updateEmitter(ComponentHandle cmp, float time_delta) override
|
2015-12-12 00:46:27 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters[{cmp.index}]->update(time_delta);
|
2015-12-12 00:46:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getComponent(Entity entity, ComponentType type) override
|
2015-12-13 11:45:31 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
if (type == MODEL_INSTANCE_TYPE)
|
2015-12-13 11:45:31 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
if (entity.index >= m_model_instances.size()) return INVALID_COMPONENT;
|
2017-01-11 17:01:53 +01:00
|
|
|
ComponentHandle cmp = {entity.index};
|
2017-05-23 14:01:09 +02:00
|
|
|
return m_model_instances[entity.index].entity.isValid() ? cmp : INVALID_COMPONENT;
|
2015-12-13 11:45:31 +01:00
|
|
|
}
|
2016-07-22 13:57:52 +02:00
|
|
|
if (type == ENVIRONMENT_PROBE_TYPE)
|
|
|
|
{
|
|
|
|
int index = m_environment_probes.find(entity);
|
|
|
|
if (index < 0) return INVALID_COMPONENT;
|
|
|
|
return {entity.index};
|
|
|
|
}
|
|
|
|
if (type == DECAL_TYPE)
|
|
|
|
{
|
|
|
|
int index = m_decals.find(entity);
|
|
|
|
if (index < 0) return INVALID_COMPONENT;
|
|
|
|
return {entity.index};
|
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
if (type == POINT_LIGHT_TYPE)
|
2015-12-13 11:45:31 +01:00
|
|
|
{
|
|
|
|
for (auto& i : m_point_lights)
|
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
if (i.m_entity == entity) return i.m_component;
|
2015-12-13 11:45:31 +01:00
|
|
|
}
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
if (type == GLOBAL_LIGHT_TYPE)
|
2015-12-13 11:45:31 +01:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
auto iter = m_global_lights.find(entity);
|
|
|
|
if (iter.isValid()) return {entity.index};
|
2015-12-13 11:45:31 +01:00
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
if (type == CAMERA_TYPE)
|
2015-12-13 11:45:31 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_cameras.find(entity);
|
|
|
|
ComponentHandle cmp = {entity.index};
|
|
|
|
return iter.isValid() ? cmp : INVALID_COMPONENT;
|
2015-12-13 11:45:31 +01:00
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
if (type == TERRAIN_TYPE)
|
2015-12-13 11:45:31 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_terrains.find(entity);
|
2017-01-11 17:01:53 +01:00
|
|
|
if (!iter.isValid()) return INVALID_COMPONENT;
|
2016-07-08 15:42:47 +02:00
|
|
|
return {entity.index};
|
2015-12-13 11:45:31 +01:00
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
if (type == PARTICLE_EMITTER_TYPE)
|
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = m_particle_emitters.find(entity);
|
|
|
|
if (index < 0) return INVALID_COMPONENT;
|
2017-01-11 17:01:53 +01:00
|
|
|
if (m_particle_emitters.at(index)->m_is_valid) return {entity.index};
|
2016-08-28 01:07:51 +02:00
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
if (type == BONE_ATTACHMENT_TYPE)
|
|
|
|
{
|
|
|
|
for (auto& attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
if (attachment.entity == entity)
|
|
|
|
{
|
|
|
|
return {entity.index};
|
|
|
|
}
|
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
2016-06-23 22:42:00 +02:00
|
|
|
static const ComponentType EMITTER_MODULES[] = {ParticleEmitter::AttractorModule::s_type,
|
|
|
|
ParticleEmitter::AlphaModule::s_type,
|
|
|
|
ParticleEmitter::ForceModule::s_type,
|
|
|
|
ParticleEmitter::LinearMovementModule::s_type,
|
|
|
|
ParticleEmitter::PlaneModule::s_type,
|
|
|
|
ParticleEmitter::RandomRotationModule::s_type,
|
|
|
|
ParticleEmitter::SizeModule::s_type,
|
2016-10-02 22:56:47 +02:00
|
|
|
ParticleEmitter::SubimageModule::s_type,
|
2016-06-23 22:42:00 +02:00
|
|
|
ParticleEmitter::SpawnShapeModule::s_type};
|
2016-06-22 00:46:48 +02:00
|
|
|
|
|
|
|
for (auto& module : EMITTER_MODULES)
|
|
|
|
{
|
2016-06-23 22:42:00 +02:00
|
|
|
if (module == type)
|
2016-06-22 00:46:48 +02:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = m_particle_emitters.find(entity);
|
|
|
|
if (index < 0) return INVALID_COMPONENT;
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
|
|
|
|
if (emitter->getModule(type)) return {entity.index};
|
2016-06-22 00:46:48 +02:00
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
}
|
2015-12-13 11:45:31 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Int2 getParticleEmitterSpawnCount(ComponentHandle cmp) override
|
2015-12-12 00:46:27 +01:00
|
|
|
{
|
|
|
|
Int2 ret;
|
2016-06-29 11:10:35 +02:00
|
|
|
ret.x = m_particle_emitters[{cmp.index}]->m_spawn_count.from;
|
|
|
|
ret.y = m_particle_emitters[{cmp.index}]->m_spawn_count.to;
|
2015-12-12 00:46:27 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterSpawnCount(ComponentHandle cmp, const Int2& value) override
|
2015-12-12 00:46:27 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters[{cmp.index}]->m_spawn_count.from = value.x;
|
|
|
|
m_particle_emitters[{cmp.index}]->m_spawn_count.to = Math::maximum(value.x, value.y);
|
2015-12-12 00:46:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void getRay(ComponentHandle camera_index,
|
2017-10-04 10:47:31 +02:00
|
|
|
const Vec2& screen_pos,
|
2015-08-27 23:59:36 +02:00
|
|
|
Vec3& origin,
|
|
|
|
Vec3& dir) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Camera& camera = m_cameras[{camera_index.index}];
|
2016-04-17 21:47:54 +02:00
|
|
|
origin = m_universe.getPosition(camera.entity);
|
|
|
|
|
|
|
|
float width = camera.screen_width;
|
|
|
|
float height = camera.screen_height;
|
|
|
|
if (width <= 0 || height <= 0)
|
|
|
|
{
|
2016-07-01 22:19:34 +02:00
|
|
|
dir = m_universe.getRotation(camera.entity).rotate(Vec3(0, 0, 1));
|
2016-04-17 21:47:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-04 10:47:31 +02:00
|
|
|
float nx = 2 * (screen_pos.x / width) - 1;
|
|
|
|
float ny = 2 * ((height - screen_pos.y) / height) - 1;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
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-06-22 15:05:19 +02:00
|
|
|
Frustum getCameraFrustum(ComponentHandle cmp) const override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
const Camera& camera = m_cameras[{cmp.index}];
|
2016-04-17 21:47:54 +02:00
|
|
|
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-07-26 21:03:47 +02:00
|
|
|
-mtx.getZVector(),
|
2016-04-17 21:47:54 +02:00
|
|
|
mtx.getYVector(),
|
2016-06-25 10:20:29 +02:00
|
|
|
camera.fov,
|
2016-04-17 21:47:54 +02:00
|
|
|
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
|
|
|
|
2017-10-10 16:53:23 +02:00
|
|
|
Frustum getCameraFrustum(ComponentHandle cmp, const Vec2& viewport_min_px, const Vec2& viewport_max_px) const override
|
2017-10-09 13:33:24 +02:00
|
|
|
{
|
|
|
|
const Camera& camera = m_cameras[{cmp.index}];
|
|
|
|
Matrix mtx = m_universe.getMatrix(camera.entity);
|
|
|
|
Frustum ret;
|
|
|
|
float ratio = camera.screen_height > 0 ? camera.screen_width / camera.screen_height : 1;
|
2017-10-10 16:53:23 +02:00
|
|
|
Vec2 viewport_min = { viewport_min_px.x / camera.screen_width * 2 - 1, (1 - viewport_max_px.y / camera.screen_height) * 2 - 1 };
|
|
|
|
Vec2 viewport_max = { viewport_max_px.x / camera.screen_width * 2 - 1, (1 - viewport_min_px.y / camera.screen_height) * 2 - 1 };
|
2017-10-09 13:33:24 +02:00
|
|
|
if (camera.is_ortho)
|
|
|
|
{
|
|
|
|
ret.computeOrtho(mtx.getTranslation(),
|
|
|
|
mtx.getZVector(),
|
|
|
|
mtx.getYVector(),
|
|
|
|
camera.ortho_size * ratio,
|
|
|
|
camera.ortho_size,
|
|
|
|
camera.near,
|
2017-10-10 17:29:40 +02:00
|
|
|
camera.far,
|
|
|
|
viewport_min,
|
|
|
|
viewport_max);
|
2017-10-09 13:33:24 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
ret.computePerspective(mtx.getTranslation(),
|
|
|
|
-mtx.getZVector(),
|
|
|
|
mtx.getYVector(),
|
|
|
|
camera.fov,
|
|
|
|
ratio,
|
|
|
|
camera.near,
|
2017-10-10 16:53:23 +02:00
|
|
|
camera.far,
|
|
|
|
viewport_min,
|
|
|
|
viewport_max);
|
2017-10-09 13:33:24 +02:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
void updateBoneAttachment(const BoneAttachment& bone_attachment)
|
|
|
|
{
|
2017-05-23 14:01:09 +02:00
|
|
|
if (!bone_attachment.parent_entity.isValid()) return;
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle model_instance = getModelInstanceComponent(bone_attachment.parent_entity);
|
|
|
|
if (model_instance == INVALID_COMPONENT) return;
|
2017-08-28 00:42:15 +02:00
|
|
|
const Pose* parent_pose = lockPose(model_instance);
|
2016-05-02 21:41:18 +02:00
|
|
|
if (!parent_pose) return;
|
|
|
|
|
2016-07-01 22:19:34 +02:00
|
|
|
Transform parent_entity_transform = m_universe.getTransform(bone_attachment.parent_entity);
|
2016-05-02 21:41:18 +02:00
|
|
|
int idx = bone_attachment.bone_index;
|
2017-08-28 00:42:15 +02:00
|
|
|
if (idx < 0 || idx > parent_pose->count)
|
|
|
|
{
|
|
|
|
unlockPose(model_instance, false);
|
|
|
|
return;
|
|
|
|
}
|
2017-08-27 23:25:45 +02:00
|
|
|
float original_scale = m_universe.getScale(bone_attachment.entity);
|
2017-08-18 13:54:56 +02:00
|
|
|
Transform bone_transform = {parent_pose->positions[idx], parent_pose->rotations[idx], 1.0f};
|
|
|
|
Transform relative_transform = { bone_attachment.relative_transform.pos, bone_attachment.relative_transform.rot, 1.0f};
|
2017-08-27 23:25:45 +02:00
|
|
|
Transform result = parent_entity_transform * bone_transform * relative_transform;
|
|
|
|
result.scale = original_scale;
|
|
|
|
m_universe.setTransform(bone_attachment.entity, result);
|
2017-08-28 00:42:15 +02:00
|
|
|
unlockPose(model_instance, false);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity getBoneAttachmentParent(ComponentHandle cmp) override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
return m_bone_attachments[{cmp.index}].parent_entity;
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void updateRelativeMatrix(BoneAttachment& attachment)
|
|
|
|
{
|
|
|
|
if (attachment.parent_entity == INVALID_ENTITY) return;
|
|
|
|
if (attachment.bone_index < 0) return;
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle model_instance = getModelInstanceComponent(attachment.parent_entity);
|
|
|
|
if (model_instance == INVALID_COMPONENT) return;
|
2017-08-28 00:42:15 +02:00
|
|
|
const Pose* pose = lockPose(model_instance);
|
2016-05-02 21:41:18 +02:00
|
|
|
if (!pose) return;
|
|
|
|
ASSERT(pose->is_absolute);
|
2017-08-28 00:42:15 +02:00
|
|
|
if (attachment.bone_index >= pose->count)
|
|
|
|
{
|
|
|
|
unlockPose(model_instance, false);
|
|
|
|
return;
|
|
|
|
}
|
2017-08-18 13:54:56 +02:00
|
|
|
Transform bone_transform = {pose->positions[attachment.bone_index], pose->rotations[attachment.bone_index], 1.0f};
|
2016-05-02 21:41:18 +02:00
|
|
|
|
2016-07-01 22:19:34 +02:00
|
|
|
Transform inv_parent_transform = m_universe.getTransform(attachment.parent_entity) * bone_transform;
|
|
|
|
inv_parent_transform = inv_parent_transform.inverted();
|
|
|
|
Transform child_transform = m_universe.getTransform(attachment.entity);
|
2017-08-18 13:54:56 +02:00
|
|
|
Transform res = inv_parent_transform * child_transform;
|
|
|
|
attachment.relative_transform = {res.pos, res.rot};
|
2017-08-28 00:42:15 +02:00
|
|
|
unlockPose(model_instance, false);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getBoneAttachmentPosition(ComponentHandle cmp) override
|
2016-05-06 12:14:53 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
return m_bone_attachments[{cmp.index}].relative_transform.pos;
|
2016-05-06 12:14:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setBoneAttachmentPosition(ComponentHandle cmp, const Vec3& pos) override
|
2016-05-06 12:14:53 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& attachment = m_bone_attachments[{cmp.index}];
|
2016-08-28 16:27:46 +02:00
|
|
|
attachment.relative_transform.pos = pos;
|
|
|
|
m_is_updating_attachments = true;
|
|
|
|
updateBoneAttachment(attachment);
|
|
|
|
m_is_updating_attachments = false;
|
2016-05-06 12:14:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-28 16:56:38 +02:00
|
|
|
Vec3 getBoneAttachmentRotation(ComponentHandle cmp) override
|
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
return m_bone_attachments[{cmp.index}].relative_transform.rot.toEuler();
|
2016-08-28 16:56:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setBoneAttachmentRotation(ComponentHandle cmp, const Vec3& rot) override
|
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& attachment = m_bone_attachments[{cmp.index}];
|
2016-08-28 16:56:38 +02:00
|
|
|
Vec3 euler = rot;
|
|
|
|
euler.x = Math::clamp(euler.x, -Math::PI * 0.5f, Math::PI * 0.5f);
|
|
|
|
attachment.relative_transform.rot.fromEuler(euler);
|
|
|
|
m_is_updating_attachments = true;
|
|
|
|
updateBoneAttachment(attachment);
|
|
|
|
m_is_updating_attachments = false;
|
|
|
|
}
|
|
|
|
|
2017-02-18 12:12:35 +01:00
|
|
|
|
2017-10-29 14:48:13 +01:00
|
|
|
void setBoneAttachmentRotationQuat(ComponentHandle cmp, const Quat& rot) override
|
|
|
|
{
|
|
|
|
BoneAttachment& attachment = m_bone_attachments[{cmp.index}];
|
|
|
|
attachment.relative_transform.rot = rot;
|
|
|
|
m_is_updating_attachments = true;
|
|
|
|
updateBoneAttachment(attachment);
|
|
|
|
m_is_updating_attachments = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getBoneAttachmentBone(ComponentHandle cmp) override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
return m_bone_attachments[{cmp.index}].bone_index;
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setBoneAttachmentBone(ComponentHandle cmp, int value) override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& ba = m_bone_attachments[{cmp.index}];
|
|
|
|
ba.bone_index = value;
|
|
|
|
updateRelativeMatrix(ba);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setBoneAttachmentParent(ComponentHandle cmp, Entity entity) override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& ba = m_bone_attachments[{cmp.index}];
|
|
|
|
ba.parent_entity = entity;
|
|
|
|
if (entity.isValid() && entity.index < m_model_instances.size())
|
|
|
|
{
|
|
|
|
ModelInstance& mi = m_model_instances[entity.index];
|
|
|
|
mi.flags = mi.flags | ModelInstance::IS_BONE_ATTACHMENT_PARENT;
|
|
|
|
}
|
|
|
|
updateRelativeMatrix(ba);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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
|
|
|
{
|
2016-07-09 00:54:39 +02:00
|
|
|
for (auto* emitter : m_particle_emitters)
|
2015-12-12 00:46:27 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
if (emitter->m_is_valid) emitter->update(dt);
|
2015-12-12 00:46:27 +01:00
|
|
|
}
|
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
|
|
|
|
2016-12-10 15:16:01 +01:00
|
|
|
void serializeModelInstance(ISerializer& serialize, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ModelInstance& r = m_model_instances[{cmp.index}];
|
|
|
|
ASSERT(r.entity != INVALID_ENTITY);
|
|
|
|
|
|
|
|
serialize.write("source", r.model ? r.model->getPath().c_str() : "");
|
2017-08-28 22:58:04 +02:00
|
|
|
serialize.write("flags", u8(r.flags & ModelInstance::PERSISTENT_FLAGS));
|
2016-12-10 15:16:01 +01:00
|
|
|
bool has_changed_materials = r.model && r.model->isReady() && r.meshes != &r.model->getMesh(0);
|
|
|
|
serialize.write("custom_materials", has_changed_materials ? r.mesh_count : 0);
|
|
|
|
if (has_changed_materials)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
|
|
|
{
|
|
|
|
serialize.write("", r.meshes[i].material->getPath().c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-13 17:05:07 +02:00
|
|
|
|
|
|
|
static bool keepSkin(ModelInstance& r)
|
|
|
|
{
|
|
|
|
return (r.flags & (u8)ModelInstance::KEEP_SKIN) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool hasCustomMeshes(ModelInstance& r)
|
|
|
|
{
|
|
|
|
return (r.flags & (u8)ModelInstance::CUSTOM_MESHES) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void deserializeModelInstance(IDeserializer& serializer, Entity entity, int scene_version)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
while (entity.index >= m_model_instances.size())
|
|
|
|
{
|
|
|
|
auto& r = m_model_instances.emplace();
|
|
|
|
r.entity = INVALID_ENTITY;
|
|
|
|
r.pose = nullptr;
|
|
|
|
r.model = nullptr;
|
|
|
|
r.meshes = nullptr;
|
|
|
|
r.mesh_count = 0;
|
|
|
|
}
|
|
|
|
auto& r = m_model_instances[entity.index];
|
|
|
|
r.entity = entity;
|
|
|
|
r.model = nullptr;
|
|
|
|
r.pose = nullptr;
|
2017-04-13 17:05:07 +02:00
|
|
|
r.flags = 0;
|
2016-12-10 15:16:01 +01:00
|
|
|
r.meshes = nullptr;
|
|
|
|
r.mesh_count = 0;
|
|
|
|
|
|
|
|
r.matrix = m_universe.getMatrix(r.entity);
|
|
|
|
|
|
|
|
char path[MAX_PATH_LENGTH];
|
|
|
|
serializer.read(path, lengthOf(path));
|
2017-04-13 17:05:07 +02:00
|
|
|
if (scene_version > (int)RenderSceneVersion::MODEL_INSTNACE_FLAGS)
|
|
|
|
{
|
|
|
|
serializer.read(&r.flags);
|
2017-08-28 22:58:04 +02:00
|
|
|
r.flags &= ModelInstance::PERSISTENT_FLAGS;
|
2017-04-13 17:05:07 +02:00
|
|
|
}
|
2016-12-10 15:16:01 +01:00
|
|
|
|
|
|
|
ComponentHandle cmp = {r.entity.index};
|
|
|
|
if (path[0] != 0)
|
|
|
|
{
|
|
|
|
auto* model = static_cast<Model*>(m_engine.getResourceManager().get(MODEL_TYPE)->load(Path(path)));
|
|
|
|
setModel(cmp, model);
|
|
|
|
}
|
|
|
|
|
|
|
|
int material_count;
|
|
|
|
serializer.read(&material_count);
|
|
|
|
if (material_count > 0)
|
|
|
|
{
|
|
|
|
allocateCustomMeshes(r, material_count);
|
|
|
|
for (int j = 0; j < material_count; ++j)
|
|
|
|
{
|
|
|
|
char path[MAX_PATH_LENGTH];
|
|
|
|
serializer.read(path, lengthOf(path));
|
|
|
|
setModelInstanceMaterial(cmp, j, Path(path));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_universe.addComponent(r.entity, MODEL_INSTANCE_TYPE, this, cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeGlobalLight(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
GlobalLight& light = m_global_lights[{cmp.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.write("cascades", light.m_cascades);
|
|
|
|
serializer.write("diffuse_color", light.m_diffuse_color);
|
|
|
|
serializer.write("diffuse_intensity", light.m_diffuse_intensity);
|
2017-04-21 23:26:44 +02:00
|
|
|
serializer.write("indirect_intensity", light.m_indirect_intensity);
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.write("fog_bottom", light.m_fog_bottom);
|
|
|
|
serializer.write("fog_color", light.m_fog_color);
|
|
|
|
serializer.write("fog_density", light.m_fog_density);
|
|
|
|
serializer.write("fog_height", light.m_fog_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-09 14:22:41 +01:00
|
|
|
void deserializeGlobalLight(IDeserializer& serializer, Entity entity, int scene_version)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
GlobalLight light;
|
2016-12-10 15:16:01 +01:00
|
|
|
light.m_entity = entity;
|
|
|
|
serializer.read(&light.m_cascades);
|
2017-02-21 16:37:07 +01:00
|
|
|
if (scene_version <= (int)RenderSceneVersion::GLOBAL_LIGHT_REFACTOR)
|
2017-02-09 14:22:41 +01:00
|
|
|
{
|
|
|
|
ComponentHandle dummy;
|
|
|
|
serializer.read(&dummy);
|
|
|
|
}
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.read(&light.m_diffuse_color);
|
|
|
|
serializer.read(&light.m_diffuse_intensity);
|
2017-04-21 23:26:44 +02:00
|
|
|
if (scene_version > (int)RenderSceneVersion::INDIRECT_INTENSITY)
|
|
|
|
{
|
|
|
|
serializer.read(&light.m_indirect_intensity);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
light.m_indirect_intensity = 1;
|
|
|
|
}
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.read(&light.m_fog_bottom);
|
|
|
|
serializer.read(&light.m_fog_color);
|
|
|
|
serializer.read(&light.m_fog_density);
|
|
|
|
serializer.read(&light.m_fog_height);
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights.insert(entity, light);
|
|
|
|
ComponentHandle cmp = {entity.index};
|
|
|
|
m_universe.addComponent(light.m_entity, GLOBAL_LIGHT_TYPE, this, cmp);
|
|
|
|
m_active_global_light_cmp = cmp;
|
2016-12-10 15:16:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializePointLight(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
PointLight& light = m_point_lights[m_point_lights_map[cmp]];
|
|
|
|
serializer.write("attenuation", light.m_attenuation_param);
|
|
|
|
serializer.write("cast_shadow", light.m_cast_shadows);
|
|
|
|
serializer.write("component", light.m_component);
|
|
|
|
serializer.write("diffuse_color", light.m_diffuse_color);
|
|
|
|
serializer.write("diffuse_intensity", light.m_diffuse_intensity);
|
|
|
|
serializer.write("fov", light.m_fov);
|
|
|
|
serializer.write("range", light.m_range);
|
|
|
|
serializer.write("specular_color", light.m_specular_color);
|
|
|
|
serializer.write("specular_intensity", light.m_specular_intensity);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializePointLight(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
2016-12-14 16:54:33 +01:00
|
|
|
m_light_influenced_geometry.emplace(m_allocator);
|
2016-12-10 15:16:01 +01:00
|
|
|
PointLight& light = m_point_lights.emplace();
|
|
|
|
light.m_entity = entity;
|
|
|
|
serializer.read(&light.m_attenuation_param);
|
|
|
|
serializer.read(&light.m_cast_shadows);
|
|
|
|
serializer.read(&light.m_component);
|
|
|
|
serializer.read(&light.m_diffuse_color);
|
|
|
|
serializer.read(&light.m_diffuse_intensity);
|
|
|
|
serializer.read(&light.m_fov);
|
|
|
|
serializer.read(&light.m_range);
|
|
|
|
serializer.read(&light.m_specular_color);
|
|
|
|
serializer.read(&light.m_specular_intensity);
|
|
|
|
m_point_lights_map.insert(light.m_component, m_point_lights.size() - 1);
|
|
|
|
|
|
|
|
m_universe.addComponent(light.m_entity, POINT_LIGHT_TYPE, this, light.m_component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeDecal(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
2017-05-18 10:51:28 +02:00
|
|
|
const Decal& decal = m_decals[{cmp.index}];
|
|
|
|
serializer.write("scale", decal.scale);
|
|
|
|
serializer.write("material", decal.material ? decal.material->getPath().c_str() : "");
|
2016-12-10 15:16:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeDecal(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ResourceManagerBase* material_manager = m_engine.getResourceManager().get(MATERIAL_TYPE);
|
|
|
|
Decal& decal = m_decals.insert(entity);
|
|
|
|
char tmp[MAX_PATH_LENGTH];
|
|
|
|
decal.entity = entity;
|
|
|
|
serializer.read(&decal.scale);
|
|
|
|
serializer.read(tmp, lengthOf(tmp));
|
|
|
|
decal.material = tmp[0] == '\0' ? nullptr : static_cast<Material*>(material_manager->load(Path(tmp)));
|
|
|
|
updateDecalInfo(decal);
|
|
|
|
m_universe.addComponent(decal.entity, DECAL_TYPE, this, {decal.entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeCamera(ISerializer& serialize, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
Camera& camera = m_cameras[{cmp.index}];
|
|
|
|
serialize.write("far", camera.far);
|
|
|
|
serialize.write("fov", camera.fov);
|
|
|
|
serialize.write("is_ortho", camera.is_ortho);
|
|
|
|
serialize.write("ortho_size", camera.ortho_size);
|
|
|
|
serialize.write("near", camera.near);
|
|
|
|
serialize.write("slot", camera.slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeCamera(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
Camera camera;
|
|
|
|
camera.entity = entity;
|
|
|
|
serializer.read(&camera.far);
|
|
|
|
serializer.read(&camera.fov);
|
|
|
|
serializer.read(&camera.is_ortho);
|
|
|
|
serializer.read(&camera.ortho_size);
|
|
|
|
serializer.read(&camera.near);
|
|
|
|
serializer.read(camera.slot, lengthOf(camera.slot));
|
|
|
|
m_cameras.insert(camera.entity, camera);
|
|
|
|
m_universe.addComponent(camera.entity, CAMERA_TYPE, this, {camera.entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeBoneAttachment(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& attachment = m_bone_attachments[{cmp.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.write("bone_index", attachment.bone_index);
|
|
|
|
serializer.write("parent", attachment.parent_entity);
|
|
|
|
serializer.write("relative_transform", attachment.relative_transform);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeBoneAttachment(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& bone_attachment = m_bone_attachments.emplace(entity);
|
2016-12-10 15:16:01 +01:00
|
|
|
bone_attachment.entity = entity;
|
|
|
|
serializer.read(&bone_attachment.bone_index);
|
|
|
|
serializer.read(&bone_attachment.parent_entity);
|
|
|
|
serializer.read(&bone_attachment.relative_transform);
|
|
|
|
ComponentHandle cmp = {bone_attachment.entity.index};
|
|
|
|
m_universe.addComponent(bone_attachment.entity, BONE_ATTACHMENT_TYPE, this, cmp);
|
2017-08-28 00:42:15 +02:00
|
|
|
Entity parent_entity = bone_attachment.parent_entity;
|
|
|
|
if (parent_entity.isValid() && parent_entity.index < m_model_instances.size())
|
|
|
|
{
|
|
|
|
ModelInstance& mi = m_model_instances[parent_entity.index];
|
|
|
|
mi.flags = mi.flags | ModelInstance::IS_BONE_ATTACHMENT_PARENT;
|
|
|
|
}
|
2016-12-10 15:16:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeTerrain(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
Terrain* terrain = m_terrains[{cmp.index}];
|
|
|
|
serializer.write("layer_mask", terrain->m_layer_mask);
|
|
|
|
serializer.write("scale", terrain->m_scale);
|
|
|
|
serializer.write("material", terrain->m_material ? terrain->m_material->getPath().c_str() : "");
|
|
|
|
serializer.write("grass_count", terrain->m_grass_types.size());
|
|
|
|
for (Terrain::GrassType& type : terrain->m_grass_types)
|
|
|
|
{
|
|
|
|
serializer.write("density", type.m_density);
|
|
|
|
serializer.write("distance", type.m_distance);
|
2017-01-24 16:56:42 +01:00
|
|
|
serializer.write("rotation_mode", (int)type.m_rotation_mode);
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.write("model", type.m_grass_model ? type.m_grass_model->getPath().c_str() : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeTerrain(IDeserializer& serializer, Entity entity, int version)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
Terrain* terrain = LUMIX_NEW(m_allocator, Terrain)(m_renderer, entity, *this, m_allocator);
|
|
|
|
m_terrains.insert(entity, terrain);
|
|
|
|
terrain->m_entity = entity;
|
|
|
|
serializer.read(&terrain->m_layer_mask);
|
|
|
|
serializer.read(&terrain->m_scale);
|
|
|
|
char tmp[MAX_PATH_LENGTH];
|
|
|
|
serializer.read(tmp, lengthOf(tmp));
|
|
|
|
auto* material = tmp[0] ? m_engine.getResourceManager().get(MATERIAL_TYPE)->load(Path(tmp)) : nullptr;
|
|
|
|
terrain->setMaterial((Material*)material);
|
|
|
|
|
|
|
|
int count;
|
|
|
|
serializer.read(&count);
|
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
Terrain::GrassType type(*terrain);
|
|
|
|
serializer.read(&type.m_density);
|
|
|
|
serializer.read(&type.m_distance);
|
2017-01-24 16:56:42 +01:00
|
|
|
if (version >= (int)RenderSceneVersion::GRASS_ROTATION_MODE)
|
|
|
|
{
|
|
|
|
serializer.read((int*)&type.m_rotation_mode);
|
|
|
|
}
|
2016-12-12 22:46:07 +01:00
|
|
|
type.m_idx = i;
|
2016-12-10 15:16:01 +01:00
|
|
|
serializer.read(tmp, lengthOf(tmp));
|
|
|
|
terrain->m_grass_types.push(type);
|
|
|
|
terrain->setGrassTypePath(terrain->m_grass_types.size() - 1, Path(tmp));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_universe.addComponent(entity, TERRAIN_TYPE, this, { entity.index });
|
|
|
|
}
|
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void serializeEnvironmentProbe(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
serializer.write("guid", m_environment_probes[{cmp.index}].guid);
|
|
|
|
}
|
2016-12-10 15:16:01 +01:00
|
|
|
|
|
|
|
|
2017-02-09 19:46:18 +01:00
|
|
|
int getVersion() const override { return (int)RenderSceneVersion::LATEST; }
|
2017-01-24 16:56:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
void deserializeEnvironmentProbe(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
auto* texture_manager = m_engine.getResourceManager().get(TEXTURE_TYPE);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> probe_dir("universes/", m_universe.getName(), "/probes/");
|
2016-12-10 15:16:01 +01:00
|
|
|
EnvironmentProbe& probe = m_environment_probes.insert(entity);
|
2017-01-03 17:04:09 +01:00
|
|
|
serializer.read(&probe.guid);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> path_str(probe_dir, probe.guid, ".dds");
|
2016-12-10 15:16:01 +01:00
|
|
|
probe.texture = static_cast<Texture*>(texture_manager->load(Path(path_str)));
|
|
|
|
probe.texture->setFlag(BGFX_TEXTURE_SRGB, true);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> irr_path_str(probe_dir, probe.guid, "_irradiance.dds");
|
2016-12-10 15:16:01 +01:00
|
|
|
probe.irradiance = static_cast<Texture*>(texture_manager->load(Path(irr_path_str)));
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true);
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> r_path_str(probe_dir, probe.guid, "_radiance.dds");
|
2016-12-10 15:16:01 +01:00
|
|
|
probe.radiance = static_cast<Texture*>(texture_manager->load(Path(r_path_str)));
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true);
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);
|
|
|
|
|
|
|
|
m_universe.addComponent(entity, ENVIRONMENT_PROBE_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitter(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
serializer.write("autoemit", emitter->m_autoemit);
|
|
|
|
serializer.write("local_space", emitter->m_local_space);
|
|
|
|
serializer.write("spawn_period_from", emitter->m_spawn_period.from);
|
|
|
|
serializer.write("spawn_period_to", emitter->m_spawn_period.to);
|
|
|
|
serializer.write("initial_life_from", emitter->m_initial_life.from);
|
|
|
|
serializer.write("initial_life_to", emitter->m_initial_life.to);
|
|
|
|
serializer.write("initial_size_from", emitter->m_initial_size.from);
|
|
|
|
serializer.write("initial_size_to", emitter->m_initial_size.to);
|
|
|
|
serializer.write("spawn_count_from", emitter->m_spawn_count.from);
|
|
|
|
serializer.write("spawn_count_to", emitter->m_spawn_count.to);
|
2017-02-22 15:12:36 +01:00
|
|
|
const Material* material = emitter->getMaterial();
|
2017-02-21 16:37:07 +01:00
|
|
|
serializer.write("material", material ? material->getPath().c_str() : "");
|
2016-12-10 15:16:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-21 16:37:07 +01:00
|
|
|
void deserializeParticleEmitter(IDeserializer& serializer, Entity entity, int scene_version)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = LUMIX_NEW(m_allocator, ParticleEmitter)(entity, m_universe, m_allocator);
|
|
|
|
emitter->m_entity = entity;
|
|
|
|
serializer.read(&emitter->m_autoemit);
|
|
|
|
serializer.read(&emitter->m_local_space);
|
|
|
|
serializer.read(&emitter->m_spawn_period.from);
|
|
|
|
serializer.read(&emitter->m_spawn_period.to);
|
|
|
|
serializer.read(&emitter->m_initial_life.from);
|
|
|
|
serializer.read(&emitter->m_initial_life.to);
|
|
|
|
serializer.read(&emitter->m_initial_size.from);
|
|
|
|
serializer.read(&emitter->m_initial_size.to);
|
|
|
|
serializer.read(&emitter->m_spawn_count.from);
|
|
|
|
serializer.read(&emitter->m_spawn_count.to);
|
2017-02-21 16:37:07 +01:00
|
|
|
if (scene_version > (int)RenderSceneVersion::EMITTER_MATERIAL)
|
|
|
|
{
|
|
|
|
char tmp[MAX_PATH_LENGTH];
|
|
|
|
serializer.read(tmp, lengthOf(tmp));
|
|
|
|
ResourceManagerBase* material_manager = m_engine.getResourceManager().get(MATERIAL_TYPE);
|
|
|
|
Material* material = (Material*)material_manager->load(Path(tmp));
|
|
|
|
emitter->setMaterial(material);
|
|
|
|
}
|
|
|
|
|
2016-12-10 15:16:01 +01:00
|
|
|
m_particle_emitters.insert(entity, emitter);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
void serializeParticleEmitterAlpha(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::AlphaModule*)emitter->getModule(PARTICLE_EMITTER_ALPHA_TYPE);
|
|
|
|
serializer.write("count", module->m_values.size());
|
|
|
|
for (Vec2 v : module->m_values)
|
|
|
|
{
|
|
|
|
serializer.write("", v.x);
|
|
|
|
serializer.write("", v.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterAlpha(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::AlphaModule)(*emitter);
|
|
|
|
int count;
|
|
|
|
serializer.read(&count);
|
|
|
|
module->m_values.clear();
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
Vec2& v = module->m_values.emplace();
|
|
|
|
serializer.read(&v.x);
|
|
|
|
serializer.read(&v.y);
|
|
|
|
}
|
|
|
|
module->sample();
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_ALPHA_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitterAttractor(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::AttractorModule*)emitter->getModule(PARTICLE_EMITTER_ATTRACTOR_TYPE);
|
|
|
|
serializer.write("force", module->m_force);
|
|
|
|
serializer.write("count", module->m_count);
|
|
|
|
for (int i = 0; i < module->m_count; ++i)
|
|
|
|
{
|
|
|
|
serializer.write("", module->m_entities[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterAttractor(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::AttractorModule)(*emitter);
|
|
|
|
serializer.read(&module->m_force);
|
|
|
|
serializer.read(&module->m_count);
|
|
|
|
for (int i = 0; i < module->m_count; ++i)
|
|
|
|
{
|
|
|
|
serializer.read(&module->m_entities[i]);
|
|
|
|
}
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_ATTRACTOR_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
void serializeParticleEmitterForce(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::ForceModule*)emitter->getModule(PARTICLE_EMITTER_FORCE_HASH);
|
|
|
|
serializer.write("acceleration", module->m_acceleration);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterForce(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::ForceModule)(*emitter);
|
|
|
|
serializer.read(&module->m_acceleration);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_FORCE_HASH, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitterLinearMovement(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::LinearMovementModule*)emitter->getModule(PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE);
|
|
|
|
serializer.write("x_from", module->m_x.from);
|
|
|
|
serializer.write("x_to", module->m_x.to);
|
|
|
|
serializer.write("y_from", module->m_y.from);
|
|
|
|
serializer.write("y_to", module->m_y.to);
|
|
|
|
serializer.write("z_from", module->m_z.from);
|
|
|
|
serializer.write("z_to", module->m_z.to);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterLinearMovement(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::LinearMovementModule)(*emitter);
|
|
|
|
serializer.read(&module->m_x.from);
|
|
|
|
serializer.read(&module->m_x.to);
|
|
|
|
serializer.read(&module->m_y.from);
|
|
|
|
serializer.read(&module->m_y.to);
|
|
|
|
serializer.read(&module->m_z.from);
|
|
|
|
serializer.read(&module->m_z.to);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitterPlane(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::PlaneModule*)emitter->getModule(PARTICLE_EMITTER_PLANE_TYPE);
|
|
|
|
serializer.write("bounce", module->m_bounce);
|
|
|
|
serializer.write("entities_count", module->m_count);
|
|
|
|
for (int i = 0; i < module->m_count; ++i)
|
|
|
|
{
|
|
|
|
serializer.write("", module->m_entities[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterPlane(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::PlaneModule)(*emitter);
|
|
|
|
serializer.read(&module->m_bounce);
|
|
|
|
serializer.read(&module->m_count);
|
|
|
|
for (int i = 0; i < module->m_count; ++i)
|
|
|
|
{
|
|
|
|
serializer.read(&module->m_entities[i]);
|
|
|
|
}
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_PLANE_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
void serializeParticleEmitterSpawnShape(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::SpawnShapeModule*)emitter->getModule(PARTICLE_EMITTER_SPAWN_SHAPE_TYPE);
|
|
|
|
serializer.write("shape", (u8)module->m_shape);
|
|
|
|
serializer.write("radius", module->m_radius);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterSpawnShape(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::SpawnShapeModule)(*emitter);
|
|
|
|
serializer.read((u8*)&module->m_shape);
|
|
|
|
serializer.read(&module->m_radius);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SPAWN_SHAPE_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
void serializeParticleEmitterSize(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::SizeModule*)emitter->getModule(PARTICLE_EMITTER_SIZE_TYPE);
|
|
|
|
serializer.write("count", module->m_values.size());
|
|
|
|
for (Vec2 v : module->m_values)
|
|
|
|
{
|
|
|
|
serializer.write("", v.x);
|
|
|
|
serializer.write("", v.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterSize(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::SizeModule)(*emitter);
|
|
|
|
int count;
|
|
|
|
serializer.read(&count);
|
|
|
|
module->m_values.clear();
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
Vec2& v = module->m_values.emplace();
|
|
|
|
serializer.read(&v.x);
|
|
|
|
serializer.read(&v.y);
|
|
|
|
}
|
|
|
|
module->sample();
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SIZE_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitterRandomRotation(ISerializer& serialize, ComponentHandle cmp) {}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterRandomRotation(IDeserializer& serialize, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::RandomRotationModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_RANDOM_ROTATION_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitterSubimage(ISerializer& serializer, ComponentHandle cmp)
|
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
|
|
|
auto* module = (ParticleEmitter::SubimageModule*)emitter->getModule(PARTICLE_EMITTER_SUBIMAGE_TYPE);
|
|
|
|
serializer.write("rows", module->rows);
|
|
|
|
serializer.write("cols", module->cols);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-24 16:56:42 +01:00
|
|
|
void deserializeParticleEmitterSubimage(IDeserializer& serializer, Entity entity, int /*scene_version*/)
|
2016-12-10 15:16:01 +01:00
|
|
|
{
|
|
|
|
ParticleEmitter* emitter = m_particle_emitters[entity];
|
|
|
|
auto* module = LUMIX_NEW(m_allocator, ParticleEmitter::SubimageModule)(*emitter);
|
|
|
|
serializer.read(&module->rows);
|
|
|
|
serializer.read(&module->cols);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SUBIMAGE_TYPE, this, {entity.index});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
void serializeBoneAttachments(OutputBlob& serializer)
|
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
serializer.write((i32)m_bone_attachments.size());
|
2016-05-02 21:41:18 +02:00
|
|
|
for (auto& attachment : m_bone_attachments)
|
|
|
|
{
|
|
|
|
serializer.write(attachment.bone_index);
|
|
|
|
serializer.write(attachment.entity);
|
|
|
|
serializer.write(attachment.parent_entity);
|
2017-02-27 20:13:50 +01:00
|
|
|
serializer.write(attachment.relative_transform);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void serializeCameras(OutputBlob& serializer)
|
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
serializer.write((i32)m_cameras.size());
|
2016-07-08 15:42:47 +02:00
|
|
|
for (auto& camera : m_cameras)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
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.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)
|
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
serializer.write((i32)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
|
|
|
}
|
2016-06-22 15:05:19 +02:00
|
|
|
serializer.write(m_point_light_last_cmp);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
serializer.write((i32)m_global_lights.size());
|
2017-02-09 14:22:41 +01:00
|
|
|
for (const GlobalLight& light : m_global_lights)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
serializer.write(light);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-06-22 15:05:19 +02:00
|
|
|
serializer.write(m_active_global_light_cmp);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void serializeModelInstances(OutputBlob& serializer)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
serializer.write((i32)m_model_instances.size());
|
2016-09-29 22:24:53 +02:00
|
|
|
for (auto& r : m_model_instances)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
serializer.write(r.entity);
|
2017-08-28 22:58:04 +02:00
|
|
|
serializer.write(u8(r.flags & ModelInstance::PERSISTENT_FLAGS));
|
2016-01-22 01:11:04 +01:00
|
|
|
if(r.entity != INVALID_ENTITY)
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
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)
|
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
serializer.write((i32)m_terrains.size());
|
2016-07-08 15:42:47 +02:00
|
|
|
for (auto* terrain : m_terrains)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
terrain->serialize(serializer);
|
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-07-22 13:57:52 +02:00
|
|
|
void deserializeDecals(InputBlob& serializer)
|
|
|
|
{
|
2016-07-24 22:21:43 +02:00
|
|
|
ResourceManagerBase* material_manager = m_engine.getResourceManager().get(MATERIAL_TYPE);
|
2016-07-22 13:57:52 +02:00
|
|
|
int count;
|
|
|
|
serializer.read(count);
|
|
|
|
m_decals.reserve(count);
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
char tmp[MAX_PATH_LENGTH];
|
|
|
|
Decal decal;
|
|
|
|
serializer.read(decal.entity);
|
|
|
|
serializer.read(decal.scale);
|
|
|
|
serializer.readString(tmp, lengthOf(tmp));
|
|
|
|
decal.material = tmp[0] == '\0' ? nullptr : static_cast<Material*>(material_manager->load(Path(tmp)));
|
|
|
|
updateDecalInfo(decal);
|
|
|
|
m_decals.insert(decal.entity, decal);
|
|
|
|
m_universe.addComponent(decal.entity, DECAL_TYPE, this, {decal.entity.index});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeDecals(OutputBlob& serializer)
|
|
|
|
{
|
|
|
|
serializer.write(m_decals.size());
|
|
|
|
for (auto& decal : m_decals)
|
|
|
|
{
|
|
|
|
serializer.write(decal.entity);
|
|
|
|
serializer.write(decal.scale);
|
|
|
|
serializer.writeString(decal.material ? decal.material->getPath().c_str() : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-12 15:26:41 +02:00
|
|
|
void serializeEnvironmentProbes(OutputBlob& serializer)
|
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 count = m_environment_probes.size();
|
2016-06-12 15:26:41 +02:00
|
|
|
serializer.write(count);
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
Entity entity = m_environment_probes.getKey(i);
|
|
|
|
serializer.write(entity);
|
2017-01-03 17:04:09 +01:00
|
|
|
serializer.write(m_environment_probes.at(i).guid);
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void deserializeEnvironmentProbes(InputBlob& serializer)
|
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 count;
|
2016-06-12 15:26:41 +02:00
|
|
|
serializer.read(count);
|
|
|
|
m_environment_probes.reserve(count);
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* texture_manager = m_engine.getResourceManager().get(TEXTURE_TYPE);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> probe_dir("universes/", m_universe.getName(), "/probes/");
|
2016-06-12 15:26:41 +02:00
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
Entity entity;
|
|
|
|
serializer.read(entity);
|
2016-07-24 17:29:17 +02:00
|
|
|
EnvironmentProbe& probe = m_environment_probes.insert(entity);
|
2017-01-03 17:04:09 +01:00
|
|
|
serializer.read(probe.guid);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> path_str(probe_dir, probe.guid, ".dds");
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.texture = static_cast<Texture*>(texture_manager->load(Path(path_str)));
|
|
|
|
probe.texture->setFlag(BGFX_TEXTURE_SRGB, true);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> irr_path_str(probe_dir, probe.guid, "_irradiance.dds");
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.irradiance = static_cast<Texture*>(texture_manager->load(Path(irr_path_str)));
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
2016-11-30 22:33:33 +01:00
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true);
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> r_path_str(probe_dir, probe.guid, "_radiance.dds");
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.radiance = static_cast<Texture*>(texture_manager->load(Path(r_path_str)));
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
2016-11-30 22:33:33 +01:00
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true);
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);
|
2016-11-29 20:00:36 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = {entity.index};
|
|
|
|
m_universe.addComponent(entity, ENVIRONMENT_PROBE_TYPE, this, cmp);
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserializeBoneAttachments(InputBlob& serializer)
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 count;
|
2016-05-02 21:41:18 +02:00
|
|
|
serializer.read(count);
|
2017-08-28 00:42:15 +02:00
|
|
|
m_bone_attachments.clear();
|
|
|
|
m_bone_attachments.reserve(count);
|
2016-05-02 21:41:18 +02:00
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment bone_attachment;
|
2016-06-22 15:05:19 +02:00
|
|
|
serializer.read(bone_attachment.bone_index);
|
|
|
|
serializer.read(bone_attachment.entity);
|
|
|
|
serializer.read(bone_attachment.parent_entity);
|
2017-02-27 20:13:50 +01:00
|
|
|
serializer.read(bone_attachment.relative_transform);
|
2017-08-28 00:42:15 +02:00
|
|
|
m_bone_attachments.insert(bone_attachment.entity, bone_attachment);
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = {bone_attachment.entity.index};
|
|
|
|
m_universe.addComponent(bone_attachment.entity, BONE_ATTACHMENT_TYPE, this, cmp);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserializeParticleEmitters(InputBlob& serializer)
|
2015-11-07 21:34:38 +01:00
|
|
|
{
|
|
|
|
int count;
|
|
|
|
serializer.read(count);
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters.reserve(count);
|
2015-11-07 21:34:38 +01:00
|
|
|
for(int i = 0; i < count; ++i)
|
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
ParticleEmitter* emitter = LUMIX_NEW(m_allocator, ParticleEmitter)(INVALID_ENTITY, m_universe, m_allocator);
|
|
|
|
serializer.read(emitter->m_is_valid);
|
2017-01-03 17:04:09 +01:00
|
|
|
if (emitter->m_is_valid)
|
2015-11-07 21:34:38 +01:00
|
|
|
{
|
2017-01-03 17:04:09 +01:00
|
|
|
emitter->deserialize(serializer, m_engine.getResourceManager());
|
2016-06-29 11:10:35 +02:00
|
|
|
ComponentHandle cmp = {emitter->m_entity.index};
|
|
|
|
if (emitter->m_is_valid) m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_TYPE, this, cmp);
|
2015-11-08 11:44:20 +01:00
|
|
|
for (auto* module : emitter->m_modules)
|
|
|
|
{
|
|
|
|
if (module->getType() == ParticleEmitter::AlphaModule::s_type)
|
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_ALPHA_TYPE, this, cmp);
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2015-12-18 21:23:51 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::ForceModule::s_type)
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_FORCE_HASH, this, cmp);
|
2015-12-12 01:35:22 +01:00
|
|
|
}
|
2016-10-02 22:56:47 +02:00
|
|
|
else if (module->getType() == ParticleEmitter::SubimageModule::s_type)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_SUBIMAGE_TYPE, this, cmp);
|
2016-10-02 22:56:47 +02:00
|
|
|
}
|
2015-12-18 21:23:51 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::SpawnShapeModule::s_type)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_SPAWN_SHAPE_TYPE, this, cmp);
|
2015-12-18 21:23:51 +01:00
|
|
|
}
|
|
|
|
else if (module->getType() == ParticleEmitter::AttractorModule::s_type)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_ATTRACTOR_TYPE, this, cmp);
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::LinearMovementModule::s_type)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE, this, cmp);
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2015-12-16 21:26:19 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::PlaneModule::s_type)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_PLANE_TYPE, this, cmp);
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::RandomRotationModule::s_type)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_RANDOM_ROTATION_TYPE, this, cmp);
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2015-11-18 20:18:48 +01:00
|
|
|
else if (module->getType() == ParticleEmitter::SizeModule::s_type)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(emitter->m_entity, PARTICLE_EMITTER_SIZE_TYPE, this, cmp);
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2015-11-07 21:34:38 +01:00
|
|
|
}
|
2016-06-29 11:10:35 +02:00
|
|
|
if (!emitter->m_is_valid && emitter->m_modules.empty())
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, emitter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_particle_emitters.insert(emitter->m_entity, emitter);
|
|
|
|
}
|
2015-11-07 21:34:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void serializeParticleEmitters(OutputBlob& serializer)
|
|
|
|
{
|
|
|
|
serializer.write(m_particle_emitters.size());
|
2016-07-09 00:54:39 +02:00
|
|
|
for (auto* emitter : m_particle_emitters)
|
2015-11-07 21:34:38 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
serializer.write(emitter->m_is_valid);
|
|
|
|
emitter->serialize(serializer);
|
2015-11-07 21:34:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void serialize(OutputBlob& serializer) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
serializeCameras(serializer);
|
2016-09-29 22:24:53 +02:00
|
|
|
serializeModelInstances(serializer);
|
2015-07-21 20:10:50 +02:00
|
|
|
serializeLights(serializer);
|
|
|
|
serializeTerrains(serializer);
|
2015-11-07 21:34:38 +01:00
|
|
|
serializeParticleEmitters(serializer);
|
2016-05-02 21:41:18 +02:00
|
|
|
serializeBoneAttachments(serializer);
|
2016-06-12 15:26:41 +02:00
|
|
|
serializeEnvironmentProbes(serializer);
|
2016-07-22 13:57:52 +02:00
|
|
|
serializeDecals(serializer);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-07 21:34:38 +01:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserializeCameras(InputBlob& serializer)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 size;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
2016-07-08 15:42:47 +02:00
|
|
|
m_cameras.rehash(size);
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Camera camera;
|
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);
|
2017-01-03 17:04:09 +01:00
|
|
|
serializer.read(camera.ortho_size);
|
2016-04-17 21:47:54 +02:00
|
|
|
serializer.read(camera.near);
|
2016-07-08 15:42:47 +02:00
|
|
|
serializer.readString(camera.slot, lengthOf(camera.slot));
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
m_cameras.insert(camera.entity, camera);
|
|
|
|
m_universe.addComponent(camera.entity, CAMERA_TYPE, this, {camera.entity.index});
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserializeModelInstances(InputBlob& serializer)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 size = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
2016-09-29 22:24:53 +02:00
|
|
|
m_model_instances.reserve(size);
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances.emplace();
|
2015-12-10 20:27:51 +01:00
|
|
|
serializer.read(r.entity);
|
2017-04-13 17:05:07 +02:00
|
|
|
serializer.read(r.flags);
|
2017-08-28 22:58:04 +02:00
|
|
|
r.flags &= ModelInstance::PERSISTENT_FLAGS;
|
2017-05-23 14:01:09 +02:00
|
|
|
ASSERT(r.entity.index == i || !r.entity.isValid());
|
2015-12-10 20:27:51 +01:00
|
|
|
r.model = nullptr;
|
|
|
|
r.pose = nullptr;
|
2016-02-06 00:44:43 +01:00
|
|
|
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 20:27:51 +01:00
|
|
|
r.matrix = m_universe.getMatrix(r.entity);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 path;
|
2015-12-10 17:09:52 +01:00
|
|
|
serializer.read(path);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = { r.entity.index };
|
2016-02-09 20:40:04 +01:00
|
|
|
if (path != 0)
|
|
|
|
{
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* model = static_cast<Model*>(m_engine.getResourceManager().get(MODEL_TYPE)->load(Path(path)));
|
2016-06-22 15:05:19 +02:00
|
|
|
setModel(cmp, model);
|
2016-02-09 20:40:04 +01:00
|
|
|
}
|
2016-01-22 01:11:04 +01:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
int material_count;
|
|
|
|
serializer.read(material_count);
|
|
|
|
if (material_count > 0)
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2017-01-03 17:04:09 +01:00
|
|
|
allocateCustomMeshes(r, material_count);
|
|
|
|
for (int j = 0; j < material_count; ++j)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2017-01-03 17:04:09 +01:00
|
|
|
char path[MAX_PATH_LENGTH];
|
|
|
|
serializer.readString(path, lengthOf(path));
|
|
|
|
setModelInstanceMaterial(cmp, j, Path(path));
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2016-01-22 01:11:04 +01:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
m_universe.addComponent(r.entity, MODEL_INSTANCE_TYPE, this, cmp);
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserializeLights(InputBlob& serializer)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 size = 0;
|
2015-07-21 20:10:50 +02:00
|
|
|
serializer.read(size);
|
|
|
|
m_point_lights.resize(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
2016-12-14 16:54:33 +01:00
|
|
|
m_light_influenced_geometry.emplace(m_allocator);
|
2015-07-21 20:10:50 +02:00
|
|
|
PointLight& light = m_point_lights[i];
|
2017-01-03 17:04:09 +01:00
|
|
|
serializer.read(light);
|
2016-06-22 15:05:19 +02:00
|
|
|
m_point_lights_map.insert(light.m_component, i);
|
2015-11-08 11:44:20 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
m_universe.addComponent(light.m_entity, POINT_LIGHT_TYPE, this, light.m_component);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-06-22 15:05:19 +02:00
|
|
|
serializer.read(m_point_light_last_cmp);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
serializer.read(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
GlobalLight light;
|
2017-01-03 17:04:09 +01:00
|
|
|
serializer.read(light);
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights.insert(light.m_entity, light);
|
|
|
|
m_universe.addComponent(light.m_entity, GLOBAL_LIGHT_TYPE, this, {light.m_entity.index});
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-06-22 15:05:19 +02:00
|
|
|
serializer.read(m_active_global_light_cmp);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserializeTerrains(InputBlob& serializer)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-20 17:27:41 +01:00
|
|
|
i32 size = 0;
|
2016-07-08 15:42:47 +02:00
|
|
|
serializer.read(size);
|
2015-07-21 20:10:50 +02:00
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
{
|
2017-01-03 17:04:09 +01:00
|
|
|
auto* terrain = LUMIX_NEW(m_allocator, Terrain)(m_renderer, INVALID_ENTITY, *this, m_allocator);
|
|
|
|
terrain->deserialize(serializer, m_universe, *this);
|
|
|
|
m_terrains.insert(terrain->getEntity(), terrain);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-11-07 21:34:38 +01:00
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
void deserialize(InputBlob& serializer) override
|
2015-11-07 21:34:38 +01:00
|
|
|
{
|
2017-01-03 17:04:09 +01:00
|
|
|
deserializeCameras(serializer);
|
|
|
|
deserializeModelInstances(serializer);
|
|
|
|
deserializeLights(serializer);
|
|
|
|
deserializeTerrains(serializer);
|
|
|
|
deserializeParticleEmitters(serializer);
|
|
|
|
deserializeBoneAttachments(serializer);
|
|
|
|
deserializeEnvironmentProbes(serializer);
|
|
|
|
deserializeDecals(serializer);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyBoneAttachment(ComponentHandle component)
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
Entity entity = {component.index};
|
|
|
|
const BoneAttachment& bone_attachment = m_bone_attachments[entity];
|
|
|
|
Entity parent_entity = bone_attachment.parent_entity;
|
|
|
|
if (parent_entity.isValid() && parent_entity.index < m_model_instances.size())
|
|
|
|
{
|
|
|
|
ModelInstance& mi = m_model_instances[bone_attachment.parent_entity.index];
|
|
|
|
mi.flags = mi.flags & ~ModelInstance::IS_BONE_ATTACHMENT_PARENT;
|
|
|
|
}
|
|
|
|
m_bone_attachments.erase(entity);
|
2016-06-22 00:46:48 +02:00
|
|
|
m_universe.destroyComponent(entity, BONE_ATTACHMENT_TYPE, 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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyEnvironmentProbe(ComponentHandle component)
|
2016-06-12 15:26:41 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity entity = {component.index};
|
2016-06-12 15:26:41 +02:00
|
|
|
auto& probe = m_environment_probes[entity];
|
2016-07-25 01:02:36 +02:00
|
|
|
if (probe.texture) probe.texture->getResourceManager().unload(*probe.texture);
|
2016-06-12 15:26:41 +02:00
|
|
|
m_environment_probes.erase(entity);
|
2016-06-22 00:46:48 +02:00
|
|
|
m_universe.destroyComponent(entity, ENVIRONMENT_PROBE_TYPE, this, component);
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void destroyModelInstance(ComponentHandle component)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
for (int i = 0; i < m_light_influenced_geometry.size(); ++i)
|
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
Array<ComponentHandle>& influenced_geometry = m_light_influenced_geometry[i];
|
2015-07-21 20:10:50 +02:00
|
|
|
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);
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& model_instance = m_model_instances[component.index];
|
|
|
|
Entity entity = model_instance.entity;
|
|
|
|
LUMIX_DELETE(m_allocator, model_instance.pose);
|
|
|
|
model_instance.pose = nullptr;
|
|
|
|
model_instance.entity = INVALID_ENTITY;
|
|
|
|
m_universe.destroyComponent(entity, MODEL_INSTANCE_TYPE, 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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyGlobalLight(ComponentHandle component)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
Entity entity = {component.index};
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-06-22 00:46:48 +02:00
|
|
|
m_universe.destroyComponent(entity, GLOBAL_LIGHT_TYPE, this, component);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
if (component == m_active_global_light_cmp)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
m_active_global_light_cmp = INVALID_COMPONENT;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights.erase(entity);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
void destroyDecal(ComponentHandle component)
|
|
|
|
{
|
|
|
|
Entity entity = {component.index};
|
|
|
|
m_decals.erase(entity);
|
|
|
|
m_universe.destroyComponent(entity, DECAL_TYPE, this, component);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyPointLight(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
int index = m_point_lights_map[component];
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity entity = m_point_lights[index].m_entity;
|
2015-12-08 22:35:41 +01:00
|
|
|
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);
|
2016-06-22 15:05:19 +02:00
|
|
|
if (index < m_point_lights.size())
|
|
|
|
{
|
|
|
|
m_point_lights_map[m_point_lights[index].m_component] = index;
|
|
|
|
}
|
2016-06-22 00:46:48 +02:00
|
|
|
m_universe.destroyComponent(entity, POINT_LIGHT_TYPE, this, component);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyCamera(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Entity entity = {component.index};
|
|
|
|
m_cameras.erase(entity);
|
2016-06-22 00:46:48 +02:00
|
|
|
m_universe.destroyComponent(entity, CAMERA_TYPE, this, component);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyTerrain(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Entity entity = {component.index};
|
|
|
|
LUMIX_DELETE(m_allocator, m_terrains[entity]);
|
|
|
|
m_terrains.erase(entity);
|
2016-06-22 00:46:48 +02:00
|
|
|
m_universe.destroyComponent(entity, TERRAIN_TYPE, this, component);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitter(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
|
|
|
emitter->reset();
|
|
|
|
emitter->m_is_valid = false;
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_TYPE, this, component);
|
|
|
|
cleanup(emitter);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void cleanup(ParticleEmitter* emitter)
|
|
|
|
{
|
|
|
|
if (emitter->m_is_valid) return;
|
|
|
|
if (!emitter->m_modules.empty()) return;
|
|
|
|
|
|
|
|
m_particle_emitters.erase(emitter->m_entity);
|
2016-06-22 15:05:19 +02:00
|
|
|
LUMIX_DELETE(m_allocator, emitter);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterAlpha(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_ALPHA_TYPE);
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_ALPHA_TYPE, this, component);
|
|
|
|
cleanup(emitter);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterForce(ComponentHandle component)
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_FORCE_HASH);
|
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_FORCE_HASH, this, component);
|
|
|
|
cleanup(emitter);
|
2015-12-12 01:35:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-02 22:56:47 +02:00
|
|
|
void destroyParticleEmitterSubimage(ComponentHandle component)
|
|
|
|
{
|
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_SUBIMAGE_TYPE);
|
2016-10-02 22:56:47 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
|
|
|
emitter->m_subimage_module = nullptr;
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_SUBIMAGE_TYPE, this, component);
|
2016-10-02 22:56:47 +02:00
|
|
|
cleanup(emitter);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterAttractor(ComponentHandle component)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_ATTRACTOR_TYPE);
|
2016-06-29 11:10:35 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_ATTRACTOR_TYPE, this, component);
|
2016-06-29 11:10:35 +02:00
|
|
|
cleanup(emitter);
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterSize(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_SIZE_TYPE);
|
2016-06-29 11:10:35 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_SIZE_TYPE, this, component);
|
2016-06-29 11:10:35 +02:00
|
|
|
cleanup(emitter);
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getParticleEmitterPlaneBounce(ComponentHandle cmp) override
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{cmp.index}];
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterPlaneBounce(ComponentHandle cmp, float value) override
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{cmp.index}];
|
2016-06-22 15:05:19 +02:00
|
|
|
for (auto* module : emitter->m_modules)
|
2015-12-17 00:00:50 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02: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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getParticleEmitterAttractorForce(ComponentHandle cmp) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{cmp.index}];
|
2016-06-22 15:05:19 +02:00
|
|
|
for (auto* module : emitter->m_modules)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
if (module->getType() == ParticleEmitter::AttractorModule::s_type)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
|
|
|
return static_cast<ParticleEmitter::AttractorModule*>(module)->m_force;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterAttractorForce(ComponentHandle cmp, float value) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{cmp.index}];
|
2016-06-22 15:05:19 +02:00
|
|
|
for (auto* module : emitter->m_modules)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
if (module->getType() == ParticleEmitter::AttractorModule::s_type)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
|
|
|
static_cast<ParticleEmitter::AttractorModule*>(module)->m_force = value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterPlane(ComponentHandle component)
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_PLANE_TYPE);
|
2016-06-29 11:10:35 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_PLANE_TYPE, this, component);
|
2016-06-29 11:10:35 +02:00
|
|
|
cleanup(emitter);
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterLinearMovement(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE);
|
2016-06-29 11:10:35 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE, this, component);
|
2016-06-29 11:10:35 +02:00
|
|
|
cleanup(emitter);
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterSpawnShape(ComponentHandle component)
|
2015-12-18 21:23:51 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_SPAWN_SHAPE_TYPE);
|
2016-06-29 11:10:35 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_SPAWN_SHAPE_TYPE, this, component);
|
2016-06-29 11:10:35 +02:00
|
|
|
cleanup(emitter);
|
|
|
|
|
2015-12-18 21:23:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyParticleEmitterRandomRotation(ComponentHandle component)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{component.index}];
|
2016-12-10 15:16:01 +01:00
|
|
|
auto* module = emitter->getModule(PARTICLE_EMITTER_RANDOM_ROTATION_TYPE);
|
2016-06-29 11:10:35 +02:00
|
|
|
|
|
|
|
ASSERT(module);
|
|
|
|
|
|
|
|
LUMIX_DELETE(m_allocator, module);
|
|
|
|
emitter->m_modules.eraseItem(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.destroyComponent(emitter->m_entity, PARTICLE_EMITTER_RANDOM_ROTATION_TYPE, this, component);
|
2016-06-29 11:10:35 +02:00
|
|
|
cleanup(emitter);
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-17 17:55:34 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void destroyComponent(ComponentHandle component, ComponentType type) override;
|
2015-12-08 22:35:41 +01:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterAlpha(ComponentHandle 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-02 22:56:47 +02:00
|
|
|
void setParticleEmitterSubimageRows(ComponentHandle cmp, const int& value) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SubimageModule>(cmp);
|
|
|
|
if (module) module->rows = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParticleEmitterSubimageCols(ComponentHandle cmp, const int& value) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SubimageModule>(cmp);
|
|
|
|
if (module) module->cols = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int getParticleEmitterSubimageRows(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SubimageModule>(cmp);
|
|
|
|
return module ? module->rows : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int getParticleEmitterSubimageCols(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SubimageModule>(cmp);
|
|
|
|
return module ? module->cols : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterAcceleration(ComponentHandle cmp, const Vec3& value) override
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-04 17:41:16 +02:00
|
|
|
void setParticleEmitterAutoemit(ComponentHandle cmp, bool autoemit) override
|
|
|
|
{
|
|
|
|
m_particle_emitters[{cmp.index}]->m_autoemit = autoemit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool getParticleEmitterAutoemit(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
return m_particle_emitters[{cmp.index}]->m_autoemit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-04 21:12:33 +02:00
|
|
|
void setParticleEmitterLocalSpace(ComponentHandle cmp, bool local_space) override
|
|
|
|
{
|
|
|
|
m_particle_emitters[{cmp.index}]->m_local_space = local_space;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool getParticleEmitterLocalSpace(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
return m_particle_emitters[{cmp.index}]->m_local_space;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getParticleEmitterAcceleration(ComponentHandle cmp) override
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getParticleEmitterSizeCount(ComponentHandle 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
const Vec2* getParticleEmitterSize(ComponentHandle cmp) override
|
2015-12-07 00:55:32 +01:00
|
|
|
{
|
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
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterSize(ComponentHandle 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>
|
2016-06-22 15:05:19 +02:00
|
|
|
T* getEmitterModule(ComponentHandle cmp) const
|
2015-12-07 14:50:31 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto& modules = m_particle_emitters[{cmp.index}]->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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getParticleEmitterAlphaCount(ComponentHandle cmp) override
|
2015-12-17 21:38:23 +01:00
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::AlphaModule>(cmp);
|
|
|
|
return module ? module->m_values.size() : 0;
|
2015-12-07 14:50:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
const Vec2* getParticleEmitterAlpha(ComponentHandle 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getParticleEmitterLinearMovementX(ComponentHandle cmp) override
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterLinearMovementX(ComponentHandle cmp, const Vec2& value) override
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getParticleEmitterLinearMovementY(ComponentHandle cmp) override
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterLinearMovementY(ComponentHandle cmp, const Vec2& value) override
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getParticleEmitterLinearMovementZ(ComponentHandle cmp) override
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterLinearMovementZ(ComponentHandle cmp, const Vec2& value) override
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getParticleEmitterInitialLife(ComponentHandle cmp) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
return m_particle_emitters[{cmp.index}]->m_initial_life;
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getParticleEmitterSpawnPeriod(ComponentHandle cmp) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
return m_particle_emitters[{cmp.index}]->m_spawn_period;
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterInitialLife(ComponentHandle cmp, const Vec2& value) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters[{cmp.index}]->m_initial_life = value;
|
|
|
|
m_particle_emitters[{cmp.index}]->m_initial_life.checkZero();
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterInitialSize(ComponentHandle cmp, const Vec2& value) override
|
2015-11-01 20:56:29 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters[{cmp.index}]->m_initial_size = value;
|
|
|
|
m_particle_emitters[{cmp.index}]->m_initial_size.checkZero();
|
2015-11-01 20:56:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getParticleEmitterInitialSize(ComponentHandle cmp) override
|
2015-11-01 20:56:29 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
return m_particle_emitters[{cmp.index}]->m_initial_size;
|
2015-11-01 20:56:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterSpawnPeriod(ComponentHandle cmp, const Vec2& value) override
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
auto* emitter = m_particle_emitters[{cmp.index}];
|
2016-06-22 15:05:19 +02:00
|
|
|
emitter->m_spawn_period = value;
|
|
|
|
emitter->m_spawn_period.from = Math::maximum(0.01f, emitter->m_spawn_period.from);
|
|
|
|
emitter->m_spawn_period.checkZero();
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createCamera(Entity entity)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Camera camera;
|
2016-04-17 21:47:54 +02:00
|
|
|
camera.is_ortho = false;
|
|
|
|
camera.ortho_size = 10;
|
|
|
|
camera.entity = entity;
|
2016-06-25 10:20:29 +02:00
|
|
|
camera.fov = Math::degreesToRadians(60);
|
2016-04-17 21:47:54 +02:00
|
|
|
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';
|
2017-05-23 14:01:09 +02:00
|
|
|
if (!getCameraInSlot("main").isValid()) copyString(camera.slot, "main");
|
2016-07-08 15:42:47 +02:00
|
|
|
m_cameras.insert(entity, camera);
|
|
|
|
m_universe.addComponent(entity, CAMERA_TYPE, this, {entity.index});
|
|
|
|
return {entity.index};
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createTerrain(Entity entity)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
Terrain* terrain = LUMIX_NEW(m_allocator, Terrain)(m_renderer, entity, *this, m_allocator);
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains.insert(entity, terrain);
|
|
|
|
m_universe.addComponent(entity, TERRAIN_TYPE, this, {entity.index});
|
|
|
|
return {entity.index};
|
2015-12-08 22:35:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createComponent(ComponentType type, Entity entity) override;
|
2015-12-08 22:35:41 +01:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterRandomRotation(Entity entity)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::RandomRotationModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_RANDOM_ROTATION_TYPE, this, {entity.index});
|
2016-06-29 11:10:35 +02:00
|
|
|
return {entity.index};
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterPlane(Entity entity)
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::PlaneModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_PLANE_TYPE, this, {entity.index});
|
2016-06-29 11:10:35 +02:00
|
|
|
return {entity.index};
|
2015-12-16 21:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterLinearMovement(Entity entity)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::LinearMovementModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE, this, {entity.index});
|
2016-06-29 11:10:35 +02:00
|
|
|
return {entity.index};
|
2015-11-08 11:44:20 +01:00
|
|
|
}
|
2016-06-29 11:10:35 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterSpawnShape(Entity entity)
|
2015-12-18 21:23:51 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::SpawnShapeModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SPAWN_SHAPE_TYPE, this, {entity.index});
|
2016-06-29 11:10:35 +02:00
|
|
|
return {entity.index};
|
2015-12-18 21:23:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterAlpha(Entity entity)
|
2015-11-08 11:44:20 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::AlphaModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_ALPHA_TYPE, this, {entity.index});
|
|
|
|
return {entity.index};
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2014-10-31 22:53:37 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterForce(Entity entity)
|
2015-12-12 01:35:22 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::ForceModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-10-02 22:56:47 +02:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_FORCE_HASH, this, {entity.index});
|
|
|
|
return {entity.index};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ComponentHandle createParticleEmitterSubimage(Entity entity)
|
|
|
|
{
|
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::SubimageModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SUBIMAGE_TYPE, this, {entity.index});
|
2016-10-02 22:56:47 +02:00
|
|
|
return {entity.index};
|
2015-12-12 01:35:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterAttractor(Entity entity)
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::AttractorModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_ATTRACTOR_TYPE, this, { entity.index });
|
2016-06-29 11:10:35 +02:00
|
|
|
return{ entity.index };
|
2015-12-17 13:58:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitterSize(Entity entity)
|
2015-11-18 20:18:48 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
auto* emitter = m_particle_emitters.at(index);
|
|
|
|
auto module = LUMIX_NEW(m_allocator, ParticleEmitter::SizeModule)(*emitter);
|
|
|
|
emitter->addModule(module);
|
2016-12-10 15:16:01 +01:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_SIZE_TYPE, this, { entity.index });
|
2016-06-29 11:10:35 +02:00
|
|
|
return{ entity.index };
|
2015-11-18 20:18:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createParticleEmitter(Entity entity)
|
2015-10-30 21:11:11 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
int index = allocateParticleEmitter(entity);
|
|
|
|
m_particle_emitters.at(index)->init();
|
2015-10-30 21:11:11 +01:00
|
|
|
|
2016-06-29 11:10:35 +02:00
|
|
|
m_universe.addComponent(entity, PARTICLE_EMITTER_TYPE, this, {entity.index});
|
2015-10-30 21:11:11 +01:00
|
|
|
|
2016-06-29 11:10:35 +02:00
|
|
|
return {entity.index};
|
|
|
|
}
|
2015-10-30 21:11:11 +01:00
|
|
|
|
|
|
|
|
2016-06-29 11:10:35 +02:00
|
|
|
int allocateParticleEmitter(Entity entity)
|
|
|
|
{
|
|
|
|
int index = m_particle_emitters.find(entity);
|
|
|
|
if (index >= 0) return index;
|
|
|
|
return m_particle_emitters.insert(entity, LUMIX_NEW(m_allocator, ParticleEmitter)(entity, m_universe, m_allocator));
|
2015-10-30 21:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
ModelInstance* getModelInstances() override
|
2015-12-10 20:27:51 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
return &m_model_instances[0];
|
2015-12-10 20:27:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
ModelInstance* getModelInstance(ComponentHandle cmp) override
|
2015-12-10 20:27:51 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
return &m_model_instances[cmp.index];
|
2015-12-10 20:27:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle getModelInstanceComponent(Entity entity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = {entity.index};
|
2016-09-29 22:24:53 +02:00
|
|
|
if (cmp.index >= m_model_instances.size()) return INVALID_COMPONENT;
|
2017-05-23 14:01:09 +02:00
|
|
|
if (!m_model_instances[cmp.index].entity.isValid()) 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
|
|
|
|
|
|
|
|
2017-07-03 14:11:11 +02:00
|
|
|
Vec3 getPoseBonePosition(ComponentHandle model_instance, int bone_index)
|
|
|
|
{
|
|
|
|
Pose* pose = m_model_instances[model_instance.index].pose;
|
|
|
|
return pose->positions[bone_index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Frustum getPointLightFrustum(ComponentHandle cmp) const
|
2015-08-27 23:59:36 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
const PointLight& light = m_point_lights[m_point_lights_map[cmp]];
|
2015-08-27 23:59:36 +02:00
|
|
|
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
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
int index = entity.index;
|
|
|
|
ComponentHandle cmp = {index};
|
2015-12-10 17:09:52 +01:00
|
|
|
|
2017-05-23 14:01:09 +02:00
|
|
|
if (index < m_model_instances.size() && m_model_instances[index].entity.isValid() &&
|
2016-09-29 22:24:53 +02:00
|
|
|
m_model_instances[index].model && m_model_instances[index].model->isReady())
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
ModelInstance& r = m_model_instances[index];
|
2015-12-10 20:27:51 +01:00
|
|
|
r.matrix = m_universe.getMatrix(entity);
|
2016-01-25 21:52:08 +01:00
|
|
|
if (r.model && r.model->isReady())
|
|
|
|
{
|
2016-07-07 10:27:53 +02:00
|
|
|
float radius = m_universe.getScale(entity) * r.model->getBoundingRadius();
|
|
|
|
Vec3 position = m_universe.getPosition(entity);
|
|
|
|
m_culling_system->updateBoundingSphere({position, radius}, cmp);
|
2016-01-25 21:52:08 +01:00
|
|
|
}
|
2015-12-10 17:09:52 +01:00
|
|
|
|
2016-11-02 18:29:44 +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
|
|
|
{
|
2016-11-02 18:29:44 +01:00
|
|
|
for (int j = 0, c2 = m_light_influenced_geometry[light_idx].size(); j < c2; ++j)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-02 18:29:44 +01:00
|
|
|
if(m_light_influenced_geometry[light_idx][j] == cmp)
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2016-11-02 18:29:44 +01:00
|
|
|
m_light_influenced_geometry[light_idx].eraseFast(j);
|
|
|
|
break;
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2016-11-02 18:29:44 +01:00
|
|
|
}
|
2015-12-10 17:09:52 +01:00
|
|
|
|
2016-11-02 18:29:44 +01:00
|
|
|
Vec3 pos = m_universe.getPosition(r.entity);
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
int decal_idx = m_decals.find(entity);
|
|
|
|
if (decal_idx >= 0)
|
|
|
|
{
|
|
|
|
updateDecalInfo(m_decals.at(decal_idx));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
detectLightInfluencedGeometry(m_point_lights[i].m_component);
|
2015-07-21 20:10:50 +02:00
|
|
|
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-06-22 15:05:19 +02:00
|
|
|
Entity getTerrainEntity(ComponentHandle cmp) override
|
2016-03-11 23:26:38 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return {cmp.index};
|
2016-03-11 23:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getTerrainResolution(ComponentHandle cmp) override
|
2016-03-11 23:26:38 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto* terrain = m_terrains[{cmp.index}];
|
2016-06-22 15:05:19 +02:00
|
|
|
return Vec2((float)terrain->getWidth(), (float)terrain->getHeight());
|
2016-03-11 23:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getFirstTerrain() override
|
2016-03-11 23:26:38 +01:00
|
|
|
{
|
|
|
|
if (m_terrains.empty()) return INVALID_COMPONENT;
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_terrains.begin();
|
|
|
|
return {iter.value()->getEntity().index};
|
2016-03-11 23:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getNextTerrain(ComponentHandle cmp) override
|
2016-03-11 23:26:38 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_terrains.find({cmp.index});
|
|
|
|
++iter;
|
|
|
|
if (!iter.isValid()) return INVALID_COMPONENT;
|
|
|
|
return {iter.value()->getEntity().index};
|
2016-03-11 23:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getTerrainComponent(Entity entity) override
|
2015-09-12 12:44:04 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_terrains.find(entity);
|
|
|
|
if (!iter.isValid()) return INVALID_COMPONENT;
|
|
|
|
return {iter.value()->getEntity().index};
|
2015-09-12 12:44:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getTerrainNormalAt(ComponentHandle cmp, float x, float z) override
|
2015-10-21 21:36:01 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->getNormal(x, z);
|
2015-10-21 21:36:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getTerrainHeightAt(ComponentHandle cmp, float x, float z) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->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-06-22 15:05:19 +02:00
|
|
|
AABB getTerrainAABB(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->getAABB();
|
2016-03-13 01:27:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getTerrainSize(ComponentHandle cmp) override
|
2016-03-13 01:27:25 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->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-06-22 15:05:19 +02:00
|
|
|
void setTerrainMaterialPath(ComponentHandle cmp, const Path& path) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-02-12 23:49:56 +01:00
|
|
|
if (path.isValid())
|
|
|
|
{
|
2016-07-24 22:21:43 +02:00
|
|
|
Material* material = static_cast<Material*>(m_engine.getResourceManager().get(MATERIAL_TYPE)->load(path));
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->setMaterial(material);
|
2016-02-12 23:49:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->setMaterial(nullptr);
|
2016-02-12 23:49:56 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
Material* getTerrainMaterial(ComponentHandle cmp) override { return m_terrains[{cmp.index}]->getMaterial(); }
|
2015-07-31 00:28:06 +02:00
|
|
|
|
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
void setDecalScale(ComponentHandle cmp, const Vec3& value) override
|
|
|
|
{
|
|
|
|
Decal& decal = m_decals[{cmp.index}];
|
|
|
|
decal.scale = value;
|
|
|
|
updateDecalInfo(decal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vec3 getDecalScale(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
return m_decals[{cmp.index}].scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void getDecals(const Frustum& frustum, Array<DecalInfo>& decals) override
|
|
|
|
{
|
|
|
|
decals.reserve(m_decals.size());
|
|
|
|
for (const Decal& decal : m_decals)
|
|
|
|
{
|
|
|
|
if (!decal.material || !decal.material->isReady()) continue;
|
|
|
|
if (frustum.isSphereInside(decal.position, decal.radius)) decals.push(decal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setDecalMaterialPath(ComponentHandle cmp, const Path& path) override
|
|
|
|
{
|
2016-07-24 22:21:43 +02:00
|
|
|
ResourceManagerBase* material_manager = m_engine.getResourceManager().get(MATERIAL_TYPE);
|
2016-07-22 13:57:52 +02:00
|
|
|
Decal& decal = m_decals[{cmp.index}];
|
|
|
|
if (decal.material)
|
|
|
|
{
|
|
|
|
material_manager->unload(*decal.material);
|
|
|
|
}
|
|
|
|
if (path.isValid())
|
|
|
|
{
|
|
|
|
decal.material = static_cast<Material*>(material_manager->load(path));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
decal.material = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Path getDecalMaterialPath(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
Decal& decal = m_decals[{cmp.index}];
|
|
|
|
return decal.material ? decal.material->getPath() : Path("");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Path getTerrainMaterialPath(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Terrain* terrain = m_terrains[{cmp.index}];
|
|
|
|
if (terrain->getMaterial())
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return terrain->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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setTerrainXZScale(ComponentHandle cmp, float scale) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->setXZScale(scale);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
float getTerrainXZScale(ComponentHandle cmp) override { return m_terrains[{cmp.index}]->getXZScale(); }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-07-09 21:33:35 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setTerrainYScale(ComponentHandle cmp, float scale) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->setYScale(scale);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-07-09 21:33:35 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
float getTerrainYScale(ComponentHandle cmp) override { return m_terrains[{cmp.index}]->getYScale(); }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2017-08-28 00:42:15 +02:00
|
|
|
Pose* lockPose(ComponentHandle cmp) override { return m_model_instances[cmp.index].pose; }
|
|
|
|
void unlockPose(ComponentHandle cmp, bool changed) override
|
|
|
|
{
|
|
|
|
if (!changed) return;
|
|
|
|
if (cmp.index < m_model_instances.size()
|
|
|
|
&& (m_model_instances[cmp.index].flags & ModelInstance::IS_BONE_ATTACHMENT_PARENT) == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Entity parent = {cmp.index};
|
|
|
|
for (BoneAttachment& ba : m_bone_attachments)
|
|
|
|
{
|
|
|
|
if (ba.parent_entity != parent) continue;
|
|
|
|
m_is_updating_attachments = true;
|
|
|
|
updateBoneAttachment(ba);
|
|
|
|
m_is_updating_attachments = false;
|
|
|
|
}
|
|
|
|
}
|
2014-10-29 20:08:31 +01:00
|
|
|
|
2014-06-20 22:54:32 +02:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
Entity getModelInstanceEntity(ComponentHandle cmp) override { return m_model_instances[cmp.index].entity; }
|
2015-07-24 22:38:11 +02:00
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
Model* getModelInstanceModel(ComponentHandle cmp) override { return m_model_instances[cmp.index].model; }
|
2014-08-18 22:33:31 +02:00
|
|
|
|
2014-10-31 21:25:03 +01:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
static u64 getLayerMask(ModelInstance& model_instance)
|
2016-10-22 18:08:53 +02:00
|
|
|
{
|
|
|
|
Model* model = model_instance.model;
|
|
|
|
if (!model->isReady()) return 1;
|
2016-11-20 17:27:41 +01:00
|
|
|
u64 layer_mask = 0;
|
2016-10-22 18:08:53 +02:00
|
|
|
for(int i = 0; i < model->getMeshCount(); ++i)
|
|
|
|
{
|
|
|
|
layer_mask |= model->getMesh(i).material->getRenderLayerMask();
|
|
|
|
}
|
|
|
|
return layer_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void showModelInstance(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& model_instance = m_model_instances[cmp.index];
|
|
|
|
if (!model_instance.model || !model_instance.model->isReady()) return;
|
2015-12-10 21:56:17 +01:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
Sphere sphere(m_universe.getPosition(model_instance.entity), model_instance.model->getBoundingRadius());
|
2016-11-20 17:27:41 +01:00
|
|
|
u64 layer_mask = getLayerMask(model_instance);
|
2016-10-22 18:08:53 +02:00
|
|
|
if(!m_culling_system->isAdded(cmp)) m_culling_system->addStatic(cmp, sphere, layer_mask);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-31 21:25:03 +01:00
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void hideModelInstance(ComponentHandle 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-09-29 22:24:53 +02:00
|
|
|
Path getModelInstancePath(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
return m_model_instances[cmp.index].model ? m_model_instances[cmp.index].model->getPath() : Path("");
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
int getModelInstanceMaterialsCount(ComponentHandle cmp) override
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
return m_model_instances[cmp.index].model ? m_model_instances[cmp.index].mesh_count : 0;
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void setModelInstancePath(ComponentHandle cmp, const Path& path) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
ModelInstance& r = m_model_instances[cmp.index];
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* manager = m_engine.getResourceManager().get(MODEL_TYPE);
|
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
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
void forceGrassUpdate(ComponentHandle cmp) override { m_terrains[{cmp.index}]->forceGrassUpdate(); }
|
2015-10-22 20:06:12 +02:00
|
|
|
|
|
|
|
|
2017-10-02 13:28:20 +02:00
|
|
|
void getTerrainInfos(const Frustum& frustum, const Vec3& lod_ref_point, Array<TerrainInfo>& infos) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
infos.reserve(m_terrains.size());
|
2016-07-08 15:42:47 +02:00
|
|
|
for (auto* terrain : m_terrains)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-09-25 17:33:29 +02:00
|
|
|
terrain->getInfos(infos, frustum, lod_ref_point);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-09 14:37:23 +02:00
|
|
|
|
|
|
|
|
2017-10-02 13:28:20 +02:00
|
|
|
void getGrassInfos(const Frustum& frustum, ComponentHandle camera, Array<GrassInfo>& infos) 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;
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
for (auto* terrain : m_terrains)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
terrain->getGrassInfos(frustum, infos, camera);
|
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);
|
2016-11-11 15:09:52 +01:00
|
|
|
float x, y;
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle camera_cmp = scene->getCameraInSlot(slot);
|
2017-05-23 14:01:09 +02:00
|
|
|
if (!camera_cmp.isValid()) return 0;
|
2016-11-11 15:09:52 +01:00
|
|
|
if (lua_gettop(L) > 3)
|
|
|
|
{
|
|
|
|
x = LuaWrapper::checkArg<float>(L, 3);
|
|
|
|
y = LuaWrapper::checkArg<float>(L, 4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = scene->getCameraScreenWidth(camera_cmp) * 0.5f;
|
|
|
|
y = scene->getCameraScreenHeight(camera_cmp) * 0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vec3 origin, dir;
|
2017-10-04 10:47:31 +02:00
|
|
|
scene->getRay(camera_cmp, {x, y}, origin, dir);
|
2016-03-13 01:27:25 +01:00
|
|
|
|
2016-11-11 15:09:52 +01:00
|
|
|
RayCastModelHit hit = scene->castRay(origin, dir, INVALID_COMPONENT);
|
2016-09-15 22:37:37 +02:00
|
|
|
LuaWrapper::push(L, hit.m_is_hit);
|
|
|
|
LuaWrapper::push(L, hit.m_is_hit ? hit.m_origin + hit.m_dir * hit.m_t : Vec3(0, 0, 0));
|
2016-03-13 01:27:25 +01:00
|
|
|
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2016-10-31 16:19:27 +01:00
|
|
|
|
|
|
|
static bgfx::TextureHandle* LUA_getTextureHandle(RenderScene* scene, int resource_idx)
|
|
|
|
{
|
|
|
|
Resource* res = scene->getEngine().getLuaResource(resource_idx);
|
|
|
|
if (!res) return nullptr;
|
|
|
|
return &static_cast<Texture*>(res)->handle;
|
|
|
|
}
|
|
|
|
|
2016-09-14 13:19:51 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
static void LUA_setTexturePixel(Texture* texture, int x, int y, u32 value)
|
2016-09-14 13:19:51 +02:00
|
|
|
{
|
|
|
|
if (!texture) return;
|
|
|
|
if (!texture->isReady()) return;
|
|
|
|
if (texture->data.empty()) return;
|
|
|
|
if (texture->bytes_per_pixel != 4) return;
|
|
|
|
|
|
|
|
x = Math::clamp(x, 0, texture->width - 1);
|
|
|
|
y = Math::clamp(y, 0, texture->height - 1);
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
((u32*)&texture->data[0])[x + y * texture->width] = value;
|
2016-09-14 13:19:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void LUA_updateTextureData(Texture* texture, int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
if (!texture) return;
|
|
|
|
if (!texture->isReady()) return;
|
|
|
|
if (texture->data.empty()) return;
|
|
|
|
|
|
|
|
texture->onDataUpdated(x, y, w, h);
|
|
|
|
}
|
|
|
|
|
2016-11-29 20:00:36 +01:00
|
|
|
|
2016-09-14 13:19:51 +02:00
|
|
|
static int LUA_getTextureWidth(Texture* texture)
|
|
|
|
{
|
|
|
|
if (!texture) return 0;
|
|
|
|
if (!texture->isReady()) return 0;
|
|
|
|
|
|
|
|
return texture->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int LUA_getTextureHeight(Texture* texture)
|
|
|
|
{
|
|
|
|
if (!texture) return 0;
|
|
|
|
if (!texture->isReady()) return 0;
|
|
|
|
|
|
|
|
return texture->height;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-14 14:15:27 +02:00
|
|
|
static float LUA_getTerrainHeightAt(RenderSceneImpl* render_scene, ComponentHandle cmp, int x, int z)
|
|
|
|
{
|
|
|
|
return render_scene->m_terrains[{cmp.index}]->getHeight(x, z);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-04 17:41:16 +02:00
|
|
|
static void LUA_emitParticle(RenderSceneImpl* render_scene, ComponentHandle emitter)
|
|
|
|
{
|
|
|
|
int idx = render_scene->m_particle_emitters.find({ emitter.index });
|
|
|
|
if (idx < 0) return;
|
|
|
|
return render_scene->m_particle_emitters.at(idx)->emit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-14 14:15:27 +02:00
|
|
|
void setTerrainHeightAt(ComponentHandle cmp, int x, int z, float height)
|
|
|
|
{
|
|
|
|
m_terrains[{cmp.index}]->setHeight(x, z, height);
|
|
|
|
}
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
static u32 LUA_getTexturePixel(Texture* texture, int x, int y)
|
2016-09-14 13:19:51 +02:00
|
|
|
{
|
|
|
|
if (!texture) return 0;
|
|
|
|
if (!texture->isReady()) return 0;
|
|
|
|
if (texture->data.empty()) return 0;
|
|
|
|
if (texture->bytes_per_pixel != 4) return 0;
|
|
|
|
|
|
|
|
x = Math::clamp(x, 0, texture->width - 1);
|
|
|
|
y = Math::clamp(y, 0, texture->height - 1);
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
return ((u32*)&texture->data[0])[x + y * texture->width];
|
2016-09-14 13:19:51 +02:00
|
|
|
}
|
|
|
|
|
2016-03-13 01:27:25 +01:00
|
|
|
|
2016-10-17 00:19:02 +02:00
|
|
|
static Pipeline* LUA_createPipeline(Engine* engine, const char* path)
|
|
|
|
{
|
|
|
|
Renderer& renderer = *static_cast<Renderer*>(engine->getPluginManager().getPlugin("renderer"));
|
2017-10-03 22:08:41 +02:00
|
|
|
Pipeline* pipeline = Pipeline::create(renderer, Path(path), "", renderer.getEngine().getAllocator());
|
2016-10-17 00:19:02 +02:00
|
|
|
pipeline->load();
|
|
|
|
return pipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void LUA_destroyPipeline(Pipeline* pipeline)
|
|
|
|
{
|
|
|
|
Pipeline::destroy(pipeline);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void LUA_setPipelineScene(Pipeline* pipeline, RenderScene* scene)
|
|
|
|
{
|
|
|
|
pipeline->setScene(scene);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-28 23:16:28 +02:00
|
|
|
static RenderScene* LUA_getPipelineScene(Pipeline* pipeline)
|
|
|
|
{
|
|
|
|
return pipeline->getScene();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-17 10:21:25 +02:00
|
|
|
static void LUA_pipelineRender(Pipeline* pipeline, int w, int h)
|
2016-10-17 00:19:02 +02:00
|
|
|
{
|
2017-10-06 17:52:00 +02:00
|
|
|
pipeline->resize(w, h);
|
2016-10-17 00:19:02 +02:00
|
|
|
pipeline->render();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-17 10:21:25 +02:00
|
|
|
static bgfx::TextureHandle* LUA_getRenderBuffer(Pipeline* pipeline,
|
|
|
|
const char* framebuffer_name,
|
|
|
|
int renderbuffer_idx)
|
|
|
|
{
|
2017-10-06 17:52:00 +02:00
|
|
|
bgfx::TextureHandle& handle = pipeline->getRenderbuffer(framebuffer_name, renderbuffer_idx);
|
|
|
|
return &handle;
|
2016-10-17 10:21:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
static void LUA_setModelInstancePath(IScene* scene, int component, const char* path)
|
2016-03-04 22:49:53 +01:00
|
|
|
{
|
|
|
|
RenderScene* render_scene = (RenderScene*)scene;
|
2016-09-29 22:24:53 +02:00
|
|
|
render_scene->setModelInstancePath({component}, Path(path));
|
2016-03-04 22:49:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-03 17:07:32 +02:00
|
|
|
static int LUA_getModelBoneIndex(Model* model, const char* bone)
|
|
|
|
{
|
|
|
|
if (!model) return 0;
|
|
|
|
return model->getBoneIndex(crc32(bone)).value();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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();
|
2017-05-23 19:57:11 +02:00
|
|
|
auto file1 = fs.open(fs.getDefaultDevice(), Path(path), FS::Mode::OPEN_AND_READ);
|
|
|
|
auto file2 = fs.open(fs.getDefaultDevice(), Path(path_preimage), FS::Mode::OPEN_AND_READ);
|
2016-03-31 16:58:42 +02:00
|
|
|
if (!file1)
|
|
|
|
{
|
|
|
|
if (file2) fs.close(*file2);
|
2017-05-23 19:57:11 +02:00
|
|
|
g_log_error.log("render_test") << "Failed to open " << path;
|
2016-03-31 16:58:42 +02:00
|
|
|
return 0xffffFFFF;
|
|
|
|
}
|
|
|
|
else if (!file2)
|
|
|
|
{
|
|
|
|
fs.close(*file1);
|
2017-05-23 19:57:11 +02:00
|
|
|
g_log_error.log("render_test") << "Failed to open " << path_preimage;
|
2016-03-31 16:58:42 +02:00
|
|
|
return 0xffffFFFF;
|
|
|
|
}
|
2017-05-23 19:57:11 +02:00
|
|
|
unsigned int result = Texture::compareTGA(file1, file2, min_diff, scene->m_allocator);
|
2016-08-17 11:12:10 +02:00
|
|
|
fs.close(*file1);
|
|
|
|
fs.close(*file2);
|
|
|
|
return result;
|
2016-03-31 16:58:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void LUA_makeScreenshot(RenderSceneImpl* scene, const char* path)
|
|
|
|
{
|
|
|
|
scene->m_renderer.makeScreenshot(Path(path));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
static void LUA_setModelInstanceMaterial(RenderScene* scene,
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp,
|
2016-03-04 22:49:53 +01:00
|
|
|
int index,
|
|
|
|
const char* path)
|
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
scene->setModelInstanceMaterial(cmp, index, Path(path));
|
2016-03-04 22:49:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
|
2017-01-26 09:28:23 +01:00
|
|
|
int getGrassRotationMode(ComponentHandle cmp, int index) override
|
|
|
|
{
|
|
|
|
return (int)m_terrains[{cmp.index}]->getGrassTypeRotationMode(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setGrassRotationMode(ComponentHandle cmp, int index, int value) override
|
|
|
|
{
|
|
|
|
m_terrains[{cmp.index}]->setGrassTypeRotationMode(index, (Terrain::GrassType::RotationMode)value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getGrassDistance(ComponentHandle cmp, int index) override
|
2015-10-18 22:27:54 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->getGrassTypeDistance(index);
|
2015-10-18 22:27:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setGrassDistance(ComponentHandle cmp, int index, float value) override
|
2015-10-18 22:27:54 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->setGrassTypeDistance(index, value);
|
2015-10-18 22:27:54 +02:00
|
|
|
}
|
|
|
|
|
2016-02-24 20:46:14 +01:00
|
|
|
|
2016-08-02 21:02:47 +02:00
|
|
|
void enableGrass(bool enabled) override { m_is_grass_enabled = enabled; }
|
2015-10-12 09:56:46 +02:00
|
|
|
|
|
|
|
|
2016-08-02 21:02:47 +02:00
|
|
|
void setGrassDensity(ComponentHandle cmp, int index, int density) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->setGrassTypeDensity(index, density);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-05 21:58:21 +02:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getGrassDensity(ComponentHandle cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setGrassPath(ComponentHandle cmp, int index, const Path& path) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->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-06-22 15:05:19 +02:00
|
|
|
Path getGrassPath(ComponentHandle cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->getGrassTypePath(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-08-10 13:10:56 +02:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getGrassCount(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_terrains[{cmp.index}]->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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void addGrass(ComponentHandle cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->addGrassType(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-15 22:16:03 +02:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void removeGrass(ComponentHandle cmp, int index) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_terrains[{cmp.index}]->removeGrassType(index);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle getFirstModelInstance() override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
return getNextModelInstance(INVALID_COMPONENT);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-28 23:17:18 +01:00
|
|
|
|
2014-08-20 22:45:47 +02:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle getNextModelInstance(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
for(int i = cmp.index + 1; i < m_model_instances.size(); ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
if (m_model_instances[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
|
|
|
|
2017-10-02 16:24:04 +02:00
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
int getClosestPointLights(const Vec3& reference_pos,
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle* lights,
|
2015-09-02 11:14:42 +02:00
|
|
|
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;
|
2016-06-22 15:05:19 +02:00
|
|
|
lights[light_count] = light.m_component;
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle tmp2 = lights[i];
|
2015-09-04 14:00:28 +02:00
|
|
|
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;
|
2016-06-22 15:05:19 +02:00
|
|
|
lights[max_lights - 1] = light.m_component;
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle tmp2 = lights[i];
|
2015-09-04 14:00:28 +02:00
|
|
|
lights[i] = lights[i - 1];
|
|
|
|
lights[i - 1] = tmp2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return light_count;
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void getPointLights(const Frustum& frustum, Array<ComponentHandle>& 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];
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
if (frustum.isSphereInside(m_universe.getPosition(light.m_entity), light.m_range))
|
2015-02-14 00:13:34 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
lights.push(light.m_component);
|
2015-02-14 00:13:34 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
Entity getCameraEntity(ComponentHandle camera) const override { return {camera.index}; }
|
2015-07-24 08:42:35 +02:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setLightCastShadows(ComponentHandle cmp, bool cast_shadows) override
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[cmp]].m_cast_shadows = cast_shadows;
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
bool getLightCastShadows(ComponentHandle cmp) override
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_cast_shadows;
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void getPointLightInfluencedGeometry(ComponentHandle light_cmp,
|
2015-12-10 17:09:52 +01:00
|
|
|
const Frustum& frustum,
|
2016-09-29 22:24:53 +02:00
|
|
|
Array<ModelInstanceMesh>& infos) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
int light_index = m_point_lights_map[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)
|
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle model_instance_cmp = m_light_influenced_geometry[light_index][j];
|
|
|
|
ModelInstance& model_instance = m_model_instances[model_instance_cmp.index];
|
|
|
|
const Sphere& sphere = m_culling_system->getSphere(model_instance_cmp);
|
2016-07-22 13:57:52 +02:00
|
|
|
if (frustum.isSphereInside(sphere.position, sphere.radius))
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
for (int k = 0, kc = model_instance.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();
|
2016-09-29 22:24:53 +02:00
|
|
|
info.mesh = &model_instance.model->getMesh(k);
|
|
|
|
info.model_instance = model_instance_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
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void getPointLightInfluencedGeometry(ComponentHandle light_cmp, Array<ModelInstanceMesh>& infos) override
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
int light_index = m_point_lights_map[light_cmp];
|
2015-09-02 11:14:42 +02:00
|
|
|
auto& geoms = m_light_influenced_geometry[light_index];
|
|
|
|
for (int j = 0, cj = geoms.size(); j < cj; ++j)
|
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
const ModelInstance& model_instance = m_model_instances[geoms[j].index];
|
|
|
|
for (int k = 0, kc = model_instance.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();
|
2016-09-29 22:24:53 +02:00
|
|
|
info.mesh = &model_instance.model->getMesh(k);
|
|
|
|
info.model_instance = geoms[j];
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void getModelInstanceEntities(const Frustum& frustum, Array<Entity>& entities) override
|
2015-10-18 14:49:46 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
2017-10-02 16:24:04 +02:00
|
|
|
auto& results = m_culling_system->cull(frustum, ~0ULL);
|
2015-10-18 14:49:46 +02:00
|
|
|
|
2017-10-02 16:24:04 +02:00
|
|
|
for (auto& subresults : results)
|
2015-10-18 14:49:46 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
for (ComponentHandle model_instance_cmp : subresults)
|
2015-10-18 14:49:46 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
entities.push(m_model_instances[model_instance_cmp.index].entity);
|
2015-10-18 14:49:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
float getCameraLODMultiplier(ComponentHandle camera)
|
|
|
|
{
|
|
|
|
float lod_multiplier;
|
|
|
|
if (isCameraOrtho(camera))
|
|
|
|
{
|
|
|
|
lod_multiplier = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lod_multiplier = getCameraFOV(camera) / Math::degreesToRadians(60);
|
|
|
|
lod_multiplier *= lod_multiplier;
|
|
|
|
}
|
|
|
|
return lod_multiplier;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-22 18:08:53 +02:00
|
|
|
Array<Array<ModelInstanceMesh>>& getModelInstanceInfos(const Frustum& frustum,
|
|
|
|
const Vec3& lod_ref_point,
|
2017-10-10 13:21:45 +02:00
|
|
|
ComponentHandle camera,
|
2016-11-20 17:27:41 +01:00
|
|
|
u64 layer_mask) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-10-02 16:24:04 +02:00
|
|
|
for (auto& i : m_temporary_infos) i.clear();
|
|
|
|
const CullingSystem::Results& results = m_culling_system->cull(frustum, layer_mask);
|
|
|
|
|
|
|
|
while (m_temporary_infos.size() < results.size())
|
|
|
|
{
|
|
|
|
m_temporary_infos.emplace(m_allocator);
|
|
|
|
}
|
|
|
|
while (m_temporary_infos.size() > results.size())
|
|
|
|
{
|
|
|
|
m_temporary_infos.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
JobSystem::JobDecl jobs[64];
|
|
|
|
JobSystem::LambdaJob job_storage[64];
|
|
|
|
ASSERT(results.size() <= lengthOf(jobs));
|
|
|
|
|
|
|
|
volatile int counter = 0;
|
|
|
|
for (int subresult_index = 0; subresult_index < results.size(); ++subresult_index)
|
|
|
|
{
|
|
|
|
Array<ModelInstanceMesh>& subinfos = m_temporary_infos[subresult_index];
|
|
|
|
subinfos.clear();
|
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
JobSystem::fromLambda([&subinfos, this, &results, subresult_index, &frustum, lod_ref_point, camera]() {
|
2017-10-02 16:24:04 +02:00
|
|
|
PROFILE_BLOCK("Temporary Info Job");
|
|
|
|
PROFILE_INT("ModelInstance count", results[subresult_index].size());
|
|
|
|
if (results[subresult_index].empty()) return;
|
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
float lod_multiplier = getCameraLODMultiplier(camera);
|
2017-10-02 16:24:04 +02:00
|
|
|
Vec3 ref_point = lod_ref_point;
|
2017-10-10 13:21:45 +02:00
|
|
|
float final_lod_multiplier = m_lod_multiplier * lod_multiplier;
|
2017-10-02 16:24:04 +02:00
|
|
|
const ComponentHandle* LUMIX_RESTRICT raw_subresults = &results[subresult_index][0];
|
|
|
|
ModelInstance* LUMIX_RESTRICT model_instances = &m_model_instances[0];
|
|
|
|
for (int i = 0, c = results[subresult_index].size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
const ModelInstance* LUMIX_RESTRICT model_instance = &model_instances[raw_subresults[i].index];
|
|
|
|
float squared_distance = (model_instance->matrix.getTranslation() - ref_point).squaredLength();
|
2017-10-10 13:21:45 +02:00
|
|
|
squared_distance *= final_lod_multiplier;
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2017-10-02 16:24:04 +02:00
|
|
|
const Model* LUMIX_RESTRICT model = model_instance->model;
|
|
|
|
LODMeshIndices lod = model->getLODMeshIndices(squared_distance);
|
|
|
|
for (int j = lod.from, c = lod.to; j <= c; ++j)
|
|
|
|
{
|
|
|
|
auto& info = subinfos.emplace();
|
|
|
|
info.model_instance = raw_subresults[i];
|
|
|
|
info.mesh = &model_instance->meshes[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, &job_storage[subresult_index], &jobs[subresult_index], nullptr);
|
|
|
|
}
|
|
|
|
JobSystem::runJobs(jobs, results.size(), &counter);
|
|
|
|
JobSystem::wait(&counter);
|
2014-11-16 19:31:51 +01:00
|
|
|
|
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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setCameraSlot(ComponentHandle cmp, const char* slot) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto& camera = m_cameras[{cmp.index}];
|
2016-06-22 15:05:19 +02:00
|
|
|
copyString(camera.slot, lengthOf(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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getCameraComponent(Entity entity)
|
2016-02-26 11:03:08 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_cameras.find(entity);
|
|
|
|
if (!iter.isValid()) return INVALID_COMPONENT;
|
|
|
|
return {entity.index};
|
2016-02-26 11:03:08 +01:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
const char* getCameraSlot(ComponentHandle camera) override { return m_cameras[{camera.index}].slot; }
|
|
|
|
float getCameraFOV(ComponentHandle camera) override { return m_cameras[{camera.index}].fov; }
|
|
|
|
void setCameraFOV(ComponentHandle camera, float fov) override { m_cameras[{camera.index}].fov = fov; }
|
2017-02-18 01:37:02 +01:00
|
|
|
void setCameraNearPlane(ComponentHandle camera, float near_plane) override { m_cameras[{camera.index}].near = Math::maximum(near_plane, 0.00001f); }
|
2016-07-08 15:42:47 +02:00
|
|
|
float getCameraNearPlane(ComponentHandle camera) override { return m_cameras[{camera.index}].near; }
|
|
|
|
void setCameraFarPlane(ComponentHandle camera, float far_plane) override { m_cameras[{camera.index}].far = far_plane; }
|
|
|
|
float getCameraFarPlane(ComponentHandle camera) override { return m_cameras[{camera.index}].far; }
|
|
|
|
float getCameraScreenWidth(ComponentHandle camera) override { return m_cameras[{camera.index}].screen_width; }
|
|
|
|
float getCameraScreenHeight(ComponentHandle camera) override { return m_cameras[{camera.index}].screen_height; }
|
2016-04-17 21:47:54 +02:00
|
|
|
|
|
|
|
|
2016-09-17 01:00:38 +02:00
|
|
|
void setGlobalLODMultiplier(float multiplier) { m_lod_multiplier = multiplier; }
|
|
|
|
float getGlobalLODMultiplier() const { return m_lod_multiplier; }
|
|
|
|
|
|
|
|
|
2016-08-04 10:24:43 +02:00
|
|
|
Matrix getCameraViewProjection(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
Matrix view = m_universe.getMatrix({cmp.index});
|
|
|
|
view.fastInverse();
|
|
|
|
return getCameraProjection(cmp) * view;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Matrix getCameraProjection(ComponentHandle cmp) override
|
2016-04-17 21:47:54 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
Camera& camera = m_cameras[{cmp.index}];
|
2016-04-17 21:47:54 +02:00
|
|
|
Matrix mtx;
|
|
|
|
float ratio = camera.screen_height > 0 ? camera.screen_width / camera.screen_height : 1;
|
2017-10-11 17:13:47 +02:00
|
|
|
bool is_homogenous_depth = bgfx::getCaps()->homogeneousDepth;
|
2016-04-17 21:47:54 +02:00
|
|
|
if (camera.is_ortho)
|
|
|
|
{
|
|
|
|
mtx.setOrtho(-camera.ortho_size * ratio,
|
|
|
|
camera.ortho_size * ratio,
|
|
|
|
-camera.ortho_size,
|
2016-06-03 02:17:47 +02:00
|
|
|
camera.ortho_size,
|
2016-04-17 21:47:54 +02:00
|
|
|
camera.near,
|
2016-06-03 02:17:47 +02:00
|
|
|
camera.far,
|
2017-10-11 17:13:47 +02:00
|
|
|
is_homogenous_depth);
|
2016-04-17 21:47:54 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-11 17:13:47 +02:00
|
|
|
mtx.setPerspective(camera.fov, ratio, camera.near, camera.far, is_homogenous_depth);
|
2016-04-17 21:47:54 +02:00
|
|
|
}
|
|
|
|
return mtx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setCameraScreenSize(ComponentHandle camera, int w, int h) override
|
2016-04-17 21:47:54 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto& cam = m_cameras[{camera.index}];
|
|
|
|
cam.screen_width = (float)w;
|
|
|
|
cam.screen_height = (float)h;
|
|
|
|
cam.aspect = w / (float)h;
|
2016-04-17 21:47:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec2 getCameraScreenSize(ComponentHandle camera) override
|
2016-05-10 09:43:39 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
auto& cam = m_cameras[{camera.index}];
|
|
|
|
return Vec2(cam.screen_width, cam.screen_height);
|
2016-05-10 09:43:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
float getCameraOrthoSize(ComponentHandle camera) override { return m_cameras[{camera.index}].ortho_size; }
|
|
|
|
void setCameraOrthoSize(ComponentHandle camera, float value) override { m_cameras[{camera.index}].ortho_size = value; }
|
|
|
|
bool isCameraOrtho(ComponentHandle camera) override { return m_cameras[{camera.index}].is_ortho; }
|
|
|
|
void setCameraOrtho(ComponentHandle camera, bool is_ortho) override { m_cameras[{camera.index}].is_ortho = is_ortho; }
|
2016-04-17 21:47:54 +02:00
|
|
|
|
|
|
|
|
2016-06-03 02:17:47 +02:00
|
|
|
const Array<DebugTriangle>& getDebugTriangles() const override { return m_debug_triangles; }
|
|
|
|
const Array<DebugLine>& getDebugLines() const override { return m_debug_lines; }
|
|
|
|
const Array<DebugPoint>& getDebugPoints() const override { return m_debug_points; }
|
2015-08-28 21:55:53 +02:00
|
|
|
|
|
|
|
|
2015-11-08 11:44:20 +01:00
|
|
|
void addDebugSphere(const Vec3& center,
|
2015-10-10 23:47:16 +02:00
|
|
|
float radius,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 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
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugHalfSphere(const Matrix& transform, float radius, bool top, u32 color, float life)
|
2016-06-28 19:48:50 +02:00
|
|
|
{
|
|
|
|
Vec3 center = transform.getTranslation();
|
|
|
|
Vec3 x_vec = transform.getXVector();
|
|
|
|
Vec3 y_vec = transform.getYVector();
|
|
|
|
if (!top) y_vec *= -1;
|
|
|
|
Vec3 z_vec = transform.getZVector();
|
|
|
|
static const int COLS = 36;
|
|
|
|
static const int ROWS = COLS >> 1;
|
|
|
|
static const float STEP = Math::degreesToRadians(360.0f) / COLS;
|
|
|
|
int p2 = COLS >> 1;
|
|
|
|
for (int y = 0; y < ROWS >> 1; ++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(-STEP);
|
|
|
|
float prev_si = sin(-STEP);
|
|
|
|
|
|
|
|
Vec3 y_offset = y_vec * sy;
|
|
|
|
Vec3 y_offset1 = y_vec * sy1;
|
|
|
|
|
|
|
|
for (int i = 0; i < COLS; ++i)
|
|
|
|
{
|
|
|
|
float ci = cos(i * STEP);
|
|
|
|
float si = sin(i * STEP);
|
|
|
|
|
|
|
|
addDebugLine(
|
|
|
|
center + radius * (x_vec * ci * cy + z_vec * si * cy + y_offset),
|
|
|
|
center + radius * (x_vec * prev_ci * cy + z_vec * prev_si * cy + y_offset),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
addDebugLine(
|
|
|
|
center + radius * (x_vec * ci * cy + z_vec * si * cy + y_offset),
|
|
|
|
center + radius * (x_vec * ci * cy1 + z_vec * si * cy1 + y_offset1),
|
|
|
|
color,
|
|
|
|
life);
|
|
|
|
prev_ci = ci;
|
|
|
|
prev_si = si;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugHalfSphere(const Vec3& center, float radius, bool top, u32 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,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 color,
|
2016-03-10 19:32:48 +01:00
|
|
|
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,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-28 19:48:50 +02:00
|
|
|
void addDebugCapsule(const Matrix& transform,
|
|
|
|
float height,
|
|
|
|
float radius,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 color,
|
2016-06-28 19:48:50 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
Vec3 x_vec = transform.getXVector();
|
|
|
|
Vec3 y_vec = transform.getYVector();
|
|
|
|
Vec3 z_vec = transform.getZVector();
|
|
|
|
Vec3 position = transform.getTranslation();
|
|
|
|
|
|
|
|
Matrix tmp = transform;
|
|
|
|
tmp.setTranslation(transform.getTranslation() + y_vec * radius);
|
|
|
|
addDebugHalfSphere(tmp, radius, false, color, life);
|
|
|
|
tmp.setTranslation(transform.getTranslation() + y_vec * (radius + height));
|
|
|
|
addDebugHalfSphere(tmp, radius, true, color, life);
|
|
|
|
|
|
|
|
Vec3 bottom = position + y_vec * radius;
|
|
|
|
Vec3 top = bottom + y_vec * height;
|
|
|
|
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,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 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,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 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,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 color,
|
2016-03-11 17:25:14 +01:00
|
|
|
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;
|
2017-04-18 15:33:44 +02:00
|
|
|
addDebugTriangle(a, b, c, color, life);
|
2016-03-11 17:25:14 +01:00
|
|
|
b.x = min.x;
|
|
|
|
b.z = max.z;
|
2017-04-18 15:33:44 +02:00
|
|
|
addDebugTriangle(a, c, b, color, life);
|
2016-03-11 17:25:14 +01:00
|
|
|
|
|
|
|
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,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 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
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugFrustum(const Frustum& frustum, u32 color, float life) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-10-10 13:21:45 +02:00
|
|
|
addDebugLine(frustum.points[0], frustum.points[1], color, life);
|
|
|
|
addDebugLine(frustum.points[1], frustum.points[2], color, life);
|
|
|
|
addDebugLine(frustum.points[2], frustum.points[3], color, life);
|
|
|
|
addDebugLine(frustum.points[3], frustum.points[0], color, life);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
addDebugLine(frustum.points[4], frustum.points[5], color, life);
|
|
|
|
addDebugLine(frustum.points[5], frustum.points[6], color, life);
|
|
|
|
addDebugLine(frustum.points[6], frustum.points[7], color, life);
|
|
|
|
addDebugLine(frustum.points[7], frustum.points[4], color, life);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
addDebugLine(frustum.points[0], frustum.points[4], color, life);
|
|
|
|
addDebugLine(frustum.points[1], frustum.points[5], color, life);
|
|
|
|
addDebugLine(frustum.points[2], frustum.points[6], color, life);
|
|
|
|
addDebugLine(frustum.points[3], frustum.points[7], color, life);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-12-14 21:42:30 +01:00
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugCircle(const Vec3& center, const Vec3& up, float radius, u32 color, 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;
|
2016-06-16 19:24:15 +02:00
|
|
|
addDebugLine(center + x_vec * x + z_vec * z, 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
|
|
|
|
2017-10-10 13:21:45 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugCross(const Vec3& center, float size, u32 color, float life) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-16 19:24:15 +02:00
|
|
|
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);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-07-20 18:14:37 +02:00
|
|
|
|
2014-10-12 22:38:17 +02:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugPoint(const Vec3& pos, u32 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-27 00:57:29 +02:00
|
|
|
void addDebugCone(const Vec3& vertex,
|
|
|
|
const Vec3& dir,
|
|
|
|
const Vec3& axis0,
|
|
|
|
const Vec3& axis1,
|
2016-11-20 17:27:41 +01:00
|
|
|
u32 color,
|
2016-06-27 00:57:29 +02:00
|
|
|
float life) override
|
|
|
|
{
|
|
|
|
Vec3 base_center = vertex + dir;
|
|
|
|
Vec3 prev_p = base_center + axis0;
|
|
|
|
for (int i = 1; i <= 32; ++i)
|
|
|
|
{
|
|
|
|
float angle = i / 32.0f * 2 * Math::PI;
|
|
|
|
Vec3 x = cosf(angle) * axis0;
|
|
|
|
Vec3 z = sinf(angle) * axis1;
|
|
|
|
Vec3 p = base_center + x + z;
|
|
|
|
addDebugLine(p, prev_p, color, life);
|
2016-06-27 14:35:05 +02:00
|
|
|
addDebugLine(vertex, p, color, life);
|
2016-06-27 00:57:29 +02:00
|
|
|
prev_p = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
static u32 ARGBToABGR(u32 color)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-16 19:24:15 +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
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
void addDebugLine(const Vec3& from, const Vec3& to, u32 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
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
RayCastModelHit castRayTerrain(ComponentHandle cmp, const Vec3& origin, const Vec3& dir) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
|
|
|
RayCastModelHit hit;
|
|
|
|
hit.m_is_hit = false;
|
2016-07-08 15:42:47 +02:00
|
|
|
auto iter = m_terrains.find({cmp.index});
|
|
|
|
if (!iter.isValid()) return hit;
|
|
|
|
|
|
|
|
auto* terrain = iter.value();
|
|
|
|
hit = terrain->castRay(origin, dir);
|
|
|
|
hit.m_component = cmp;
|
|
|
|
hit.m_component_type = TERRAIN_TYPE;
|
|
|
|
hit.m_entity = terrain->getEntity();
|
2015-07-21 20:10:50 +02:00
|
|
|
return hit;
|
|
|
|
}
|
2014-10-12 22:38:17 +02:00
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
RayCastModelHit castRay(const Vec3& origin, const Vec3& dir, ComponentHandle ignored_model_instance) 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;
|
2017-07-13 00:21:10 +02:00
|
|
|
hit.m_origin = origin;
|
|
|
|
hit.m_dir = dir;
|
2016-11-09 10:09:33 +01:00
|
|
|
float cur_dist = FLT_MAX;
|
2015-08-02 10:39:50 +02:00
|
|
|
Universe& universe = getUniverse();
|
2016-09-29 22:24:53 +02:00
|
|
|
for (int i = 0; i < m_model_instances.size(); ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances[i];
|
2016-11-09 10:09:33 +01:00
|
|
|
if (ignored_model_instance.index == i || !r.model) continue;
|
|
|
|
|
|
|
|
const Vec3& pos = r.matrix.getTranslation();
|
|
|
|
float scale = universe.getScale(r.entity);
|
2017-08-18 21:43:16 +02:00
|
|
|
float radius = r.model->getBoundingRadius() * scale;
|
2016-11-09 10:09:33 +01:00
|
|
|
float dist = (pos - origin).length();
|
2017-08-18 21:43:16 +02:00
|
|
|
if (dist - radius > cur_dist) continue;
|
2016-11-09 10:09:33 +01:00
|
|
|
|
|
|
|
Vec3 intersection;
|
2017-08-18 21:43:16 +02:00
|
|
|
if (Math::getRaySphereIntersection(origin, dir, pos, radius, intersection))
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-04-13 17:05:07 +02:00
|
|
|
RayCastModelHit new_hit = r.model->castRay(origin, dir, r.matrix, r.pose);
|
2016-11-09 10:09:33 +01:00
|
|
|
if (new_hit.m_is_hit && (!hit.m_is_hit || new_hit.m_t < hit.m_t))
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-09 10:09:33 +01:00
|
|
|
new_hit.m_component = {i};
|
|
|
|
new_hit.m_entity = r.entity;
|
|
|
|
new_hit.m_component_type = MODEL_INSTANCE_TYPE;
|
|
|
|
hit = new_hit;
|
|
|
|
hit.m_is_hit = true;
|
|
|
|
cur_dist = dir.length() * hit.m_t;
|
2014-07-20 18:14:37 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-11-09 10:09:33 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
for (auto* terrain : m_terrains)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
RayCastModelHit terrain_hit = terrain->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
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
terrain_hit.m_component = {terrain->getEntity().index};
|
|
|
|
terrain_hit.m_component_type = TERRAIN_TYPE;
|
|
|
|
terrain_hit.m_entity = terrain->getEntity();
|
|
|
|
hit = terrain_hit;
|
2015-02-18 00:34:22 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-11-09 10:09:33 +01:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
return hit;
|
|
|
|
}
|
2015-02-18 00:34:22 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec4 getShadowmapCascades(ComponentHandle cmp) override
|
2015-09-10 22:14:54 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_cascades;
|
2015-09-10 22:14:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setShadowmapCascades(ComponentHandle cmp, const Vec4& value) override
|
2015-09-10 22:14:54 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_cascades = valid_value;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-18 00:34:22 +01:00
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setFogDensity(ComponentHandle cmp, float density) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_fog_density = density;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 22:39:33 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setFogColor(ComponentHandle cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_fog_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getFogDensity(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_fog_density;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getFogBottom(ComponentHandle cmp) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_fog_bottom;
|
2015-10-17 00:18:47 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setFogBottom(ComponentHandle cmp, float bottom) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_fog_bottom = bottom;
|
2015-10-17 00:18:47 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getFogHeight(ComponentHandle cmp) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_fog_height;
|
2015-10-17 00:18:47 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setFogHeight(ComponentHandle cmp, float height) override
|
2015-10-17 00:18:47 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_fog_height = height;
|
2015-10-17 00:18:47 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getFogColor(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_fog_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getLightAttenuation(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_attenuation_param;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
|
|
|
void setLightAttenuation(ComponentHandle cmp, float attenuation) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
int index = m_point_lights_map[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
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getLightRange(ComponentHandle cmp) override
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_range;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setLightRange(ComponentHandle cmp, float value) override
|
2015-09-09 02:18:09 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[cmp]].m_range = value;
|
2015-09-09 02:18:09 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setPointLightIntensity(ComponentHandle cmp, float intensity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[cmp]].m_diffuse_intensity = intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setGlobalLightIntensity(ComponentHandle cmp, float intensity) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_diffuse_intensity = intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2017-04-21 23:26:44 +02:00
|
|
|
void setGlobalLightIndirectIntensity(ComponentHandle cmp, float intensity) override
|
|
|
|
{
|
|
|
|
m_global_lights[{cmp.index}].m_indirect_intensity = intensity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setPointLightColor(ComponentHandle cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[cmp]].m_diffuse_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-10 08:12:12 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setGlobalLightColor(ComponentHandle cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights[{cmp.index}].m_diffuse_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-07-10 08:12:12 +02:00
|
|
|
|
2016-12-02 15:46:09 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getPointLightIntensity(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_diffuse_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-05 22:57:55 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getGlobalLightIntensity(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_diffuse_intensity;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-09-25 21:30:57 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2017-04-21 23:26:44 +02:00
|
|
|
float getGlobalLightIndirectIntensity(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
return m_global_lights[{cmp.index}].m_indirect_intensity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getPointLightColor(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_diffuse_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setPointLightSpecularColor(ComponentHandle cmp, const Vec3& color) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[cmp]].m_specular_color = color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getPointLightSpecularColor(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_specular_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-21 19:26:27 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setPointLightSpecularIntensity(ComponentHandle cmp, float intensity) override
|
2016-02-10 12:09:09 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[cmp]].m_specular_intensity = intensity;
|
2016-02-10 12:09:09 +01:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getPointLightSpecularIntensity(ComponentHandle cmp) override
|
2016-02-10 12:09:09 +01:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_specular_intensity;
|
2016-02-10 12:09:09 +01:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Vec3 getGlobalLightColor(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_diffuse_color;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-07-05 17:24:12 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setActiveGlobalLight(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
m_active_global_light_cmp = cmp;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-10-06 20:56:28 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getActiveGlobalLight() override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
return m_active_global_light_cmp;
|
2016-07-08 15:42:47 +02:00
|
|
|
}
|
|
|
|
|
2014-10-30 00:16:32 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity getPointLightEntity(ComponentHandle cmp) const override
|
2015-07-24 08:42:35 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[cmp]].m_entity;
|
2015-07-24 08:42:35 +02:00
|
|
|
}
|
2016-01-24 17:20:03 +01:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity getGlobalLightEntity(ComponentHandle cmp) const override
|
2015-07-24 08:42:35 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
return m_global_lights[{cmp.index}].m_entity;
|
2015-07-24 08:42:35 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void reloadEnvironmentProbe(ComponentHandle cmp) override
|
2016-06-12 15:26:41 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity entity = {cmp.index};
|
|
|
|
auto& probe = m_environment_probes[entity];
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* texture_manager = m_engine.getResourceManager().get(TEXTURE_TYPE);
|
2016-06-12 15:26:41 +02:00
|
|
|
if (probe.texture) texture_manager->unload(*probe.texture);
|
2017-05-23 19:57:11 +02:00
|
|
|
StaticString<MAX_PATH_LENGTH> path("universes/", m_universe.getName(), "/probes/", probe.guid, ".dds");
|
2016-06-12 15:26:41 +02:00
|
|
|
probe.texture = static_cast<Texture*>(texture_manager->load(Path(path)));
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.texture->setFlag(BGFX_TEXTURE_SRGB, true);
|
|
|
|
path = "universes/";
|
2017-01-05 15:40:59 +01:00
|
|
|
path << m_universe.getName() << "/probes/" << probe.guid << "_irradiance.dds";
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.irradiance = static_cast<Texture*>(texture_manager->load(Path(path)));
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
2016-11-30 22:33:33 +01:00
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true);
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);
|
2016-11-29 20:00:36 +01:00
|
|
|
path = "universes/";
|
2017-01-05 15:40:59 +01:00
|
|
|
path << m_universe.getName() << "/probes/" << probe.guid << "_radiance.dds";
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.radiance = static_cast<Texture*>(texture_manager->load(Path(path)));
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
2016-11-30 22:33:33 +01:00
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_MIN_ANISOTROPIC, true);
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_MAG_ANISOTROPIC, true);
|
2016-11-29 20:00:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ComponentHandle getNearestEnvironmentProbe(const Vec3& pos) const override
|
|
|
|
{
|
|
|
|
float nearest_dist_squared = FLT_MAX;
|
|
|
|
Entity nearest = INVALID_ENTITY;
|
|
|
|
for (int i = 0, c = m_environment_probes.size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
Entity probe_entity = m_environment_probes.getKey(i);
|
|
|
|
Vec3 probe_pos = m_universe.getPosition(probe_entity);
|
|
|
|
float dist_squared = (pos - probe_pos).squaredLength();
|
|
|
|
if (dist_squared < nearest_dist_squared)
|
|
|
|
{
|
|
|
|
nearest = probe_entity;
|
|
|
|
nearest_dist_squared = dist_squared;
|
|
|
|
}
|
|
|
|
}
|
2017-05-23 14:01:09 +02:00
|
|
|
if (!nearest.isValid()) return INVALID_COMPONENT;
|
2016-11-29 20:00:36 +01:00
|
|
|
return {nearest.index};
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-11-29 20:00:36 +01:00
|
|
|
Texture* getEnvironmentProbeTexture(ComponentHandle cmp) const override
|
2016-06-12 15:26:41 +02:00
|
|
|
{
|
2016-11-29 20:00:36 +01:00
|
|
|
Entity entity = {cmp.index};
|
2016-06-22 15:05:19 +02:00
|
|
|
return m_environment_probes[entity].texture;
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-11-29 20:00:36 +01:00
|
|
|
Texture* getEnvironmentProbeIrradiance(ComponentHandle cmp) const override
|
|
|
|
{
|
|
|
|
Entity entity = {cmp.index};
|
|
|
|
return m_environment_probes[entity].irradiance;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Texture* getEnvironmentProbeRadiance(ComponentHandle cmp) const override
|
|
|
|
{
|
|
|
|
Entity entity = {cmp.index};
|
|
|
|
return m_environment_probes[entity].radiance;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-01-03 17:04:09 +01:00
|
|
|
u64 getEnvironmentProbeGUID(ComponentHandle cmp) const override
|
|
|
|
{
|
|
|
|
Entity entity = { cmp.index };
|
|
|
|
return m_environment_probes[entity].guid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle getCameraInSlot(const char* slot) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
for (const auto& camera : m_cameras)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
if (equalStrings(camera.slot, slot))
|
2014-08-20 22:45:47 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return {camera.entity.index};
|
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
|
|
|
|
2016-07-08 15:42: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-06-22 15:05:19 +02:00
|
|
|
void modelUnloaded(Model*, ComponentHandle component)
|
2016-01-10 13:41:12 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances[component.index];
|
2017-04-13 17:05:07 +02:00
|
|
|
if (!hasCustomMeshes(r))
|
2016-02-06 00:44:43 +01:00
|
|
|
{
|
|
|
|
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-09-29 22:24:53 +02:00
|
|
|
void freeCustomMeshes(ModelInstance& r, MaterialManager* manager)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2017-04-13 17:05:07 +02:00
|
|
|
if (!hasCustomMeshes(r)) 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;
|
2017-04-13 17:05:07 +02:00
|
|
|
r.flags = r.flags & ~(u8)ModelInstance::CUSTOM_MESHES;
|
2016-02-06 00:44:43 +01:00
|
|
|
r.mesh_count = 0;
|
2016-01-22 01:11:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void modelLoaded(Model* model, ComponentHandle component)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-01-22 01:11:04 +01:00
|
|
|
auto& rm = m_engine.getResourceManager();
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.get(MATERIAL_TYPE));
|
2016-01-22 01:11:04 +01:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances[component.index];
|
2016-10-28 01:49:36 +02:00
|
|
|
|
2017-02-20 16:06:33 +01:00
|
|
|
if (model->getMesh(0).material->getLayersCount() > 0)
|
|
|
|
{
|
|
|
|
if (model->getBoneCount() > 0)
|
|
|
|
{
|
|
|
|
r.type = ModelInstance::MULTILAYER_SKINNED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r.type = ModelInstance::MULTILAYER_RIGID;
|
|
|
|
}
|
|
|
|
}
|
2016-10-28 01:49:36 +02:00
|
|
|
else if (model->getBoneCount() > 0) r.type = ModelInstance::SKINNED;
|
|
|
|
else r.type = ModelInstance::RIGID;
|
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);
|
2016-10-22 18:08:53 +02:00
|
|
|
m_culling_system->addStatic(component, sphere, getLayerMask(r));
|
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);
|
2017-04-13 17:05:07 +02:00
|
|
|
ASSERT(!r.meshes || hasCustomMeshes(r));
|
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
|
|
|
|
2017-08-28 00:42:15 +02:00
|
|
|
if ((r.flags & ModelInstance::IS_BONE_ATTACHMENT_PARENT) != 0)
|
|
|
|
{
|
|
|
|
updateBoneAttachment(m_bone_attachments[r.entity]);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
for (int i = 0, c = m_model_instances.size(); i < c; ++i)
|
2016-01-10 13:41:12 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
if (m_model_instances[i].entity != INVALID_ENTITY && m_model_instances[i].model == model)
|
2016-01-10 13:41:12 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
modelUnloaded(model, {i});
|
2016-01-10 13:41:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
void modelLoaded(Model* model)
|
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
for (int i = 0, c = m_model_instances.size(); i < c; ++i)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
if (m_model_instances[i].entity != INVALID_ENTITY && m_model_instances[i].model == model)
|
2014-11-08 02:54:55 +01:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
modelLoaded(model, {i});
|
2014-11-08 02:54:55 +01:00
|
|
|
}
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-08 02:54:55 +01:00
|
|
|
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2016-07-25 02:00:22 +02:00
|
|
|
ModelLoadedCallback& getModelLoadedCallback(Model* model)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-25 02:00:22 +02:00
|
|
|
int idx = m_model_loaded_callbacks.find(model);
|
|
|
|
if (idx >= 0) return m_model_loaded_callbacks.at(idx);
|
|
|
|
return m_model_loaded_callbacks.emplace(model, *this, model);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void allocateCustomMeshes(ModelInstance& r, int count)
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2017-04-13 17:05:07 +02:00
|
|
|
if (hasCustomMeshes(r) && r.mesh_count == count) return;
|
2016-01-22 01:11:04 +01:00
|
|
|
|
2016-06-15 15:28:07 +02:00
|
|
|
ASSERT(r.model);
|
2016-01-22 01:11:04 +01:00
|
|
|
auto& rm = r.model->getResourceManager();
|
2016-07-25 01:02:36 +02:00
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.getOwner().get(MATERIAL_TYPE));
|
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
|
|
|
|
2017-04-13 17:05:07 +02:00
|
|
|
if (hasCustomMeshes(r))
|
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);
|
|
|
|
}
|
2016-07-24 15:13:52 +02:00
|
|
|
for (int i = 0; i < r.mesh_count; ++i)
|
|
|
|
{
|
|
|
|
r.meshes[i].~Mesh();
|
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
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;
|
2017-04-13 17:05:07 +02:00
|
|
|
r.flags |= (u8)ModelInstance::CUSTOM_MESHES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool getModelInstanceKeepSkin(ComponentHandle cmp) override
|
|
|
|
{
|
|
|
|
auto& r = m_model_instances[cmp.index];
|
|
|
|
return keepSkin(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setModelInstanceKeepSkin(ComponentHandle cmp, bool keep) override
|
|
|
|
{
|
|
|
|
auto& r = m_model_instances[cmp.index];
|
|
|
|
if (keep)
|
|
|
|
{
|
|
|
|
r.flags |= (u8)ModelInstance::KEEP_SKIN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r.flags &= ~(u8)ModelInstance::KEEP_SKIN;
|
|
|
|
}
|
2016-02-06 00:44:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
void setModelInstanceMaterial(ComponentHandle cmp, int index, const Path& path) override
|
2016-02-06 00:44:43 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances[cmp.index];
|
|
|
|
if (r.meshes && r.mesh_count > index && r.meshes[index].material && path == r.meshes[index].material->getPath()) return;
|
2016-02-06 00:44:43 +01:00
|
|
|
|
|
|
|
auto& rm = r.model->getResourceManager();
|
2016-07-25 01:02:36 +02:00
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.getOwner().get(MATERIAL_TYPE));
|
2016-02-10 12:09:09 +01:00
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
int new_count = Math::maximum(i8(index + 1), r.mesh_count);
|
2016-02-06 00:44:43 +01:00
|
|
|
allocateCustomMeshes(r, new_count);
|
2016-06-15 15:28:07 +02:00
|
|
|
ASSERT(r.meshes);
|
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-09-29 22:24:53 +02:00
|
|
|
Path getModelInstanceMaterial(ComponentHandle cmp, int index) override
|
2016-01-22 01:11:04 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances[cmp.index];
|
2016-01-22 01:11:04 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setModel(ComponentHandle component, Model* model)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& model_instance = m_model_instances[component.index];
|
2017-05-23 14:01:09 +02:00
|
|
|
ASSERT(model_instance.entity.isValid());
|
2016-09-29 22:24:53 +02:00
|
|
|
Model* old_model = model_instance.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
|
|
|
{
|
2016-07-25 01:02:36 +02:00
|
|
|
old_model->getResourceManager().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();
|
2016-07-25 01:02:36 +02:00
|
|
|
auto* material_manager = static_cast<MaterialManager*>(rm.getOwner().get(MATERIAL_TYPE));
|
2016-09-29 22:24:53 +02:00
|
|
|
freeCustomMeshes(model_instance, material_manager);
|
2016-07-25 02:00:22 +02:00
|
|
|
ModelLoadedCallback& callback = getModelLoadedCallback(old_model);
|
|
|
|
--callback.m_ref_count;
|
|
|
|
if (callback.m_ref_count == 0)
|
2016-05-12 07:48:51 +02:00
|
|
|
{
|
2016-07-25 02:00:22 +02:00
|
|
|
m_model_loaded_callbacks.erase(old_model);
|
2016-05-12 07:48:51 +02:00
|
|
|
}
|
|
|
|
|
2015-12-10 23:33:21 +01:00
|
|
|
if (old_model->isReady())
|
|
|
|
{
|
|
|
|
m_culling_system->removeStatic(component);
|
|
|
|
}
|
2016-07-25 01:02:36 +02:00
|
|
|
old_model->getResourceManager().unload(*old_model);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2016-09-29 22:24:53 +02:00
|
|
|
model_instance.model = model;
|
|
|
|
model_instance.meshes = nullptr;
|
|
|
|
model_instance.mesh_count = 0;
|
|
|
|
LUMIX_DELETE(m_allocator, model_instance.pose);
|
|
|
|
model_instance.pose = nullptr;
|
2015-07-21 20:10:50 +02:00
|
|
|
if (model)
|
|
|
|
{
|
2017-04-13 17:05:07 +02:00
|
|
|
if (keepSkin(model_instance)) model->setKeepSkin();
|
2016-07-25 02:00:22 +02:00
|
|
|
ModelLoadedCallback& callback = getModelLoadedCallback(model);
|
|
|
|
++callback.m_ref_count;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void detectLightInfluencedGeometry(ComponentHandle cmp)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-06-22 15:05:19 +02:00
|
|
|
Frustum frustum = getPointLightFrustum(cmp);
|
2017-10-02 16:24:04 +02:00
|
|
|
const CullingSystem::Results& results = m_culling_system->cull(frustum, ~0ULL);
|
2016-12-14 16:54:33 +01:00
|
|
|
auto& influenced_geometry = m_light_influenced_geometry[m_point_lights_map[cmp]];
|
2015-08-27 23:59:36 +02:00
|
|
|
influenced_geometry.clear();
|
|
|
|
for (int i = 0; i < results.size(); ++i)
|
|
|
|
{
|
|
|
|
const CullingSystem::Subresults& subresult = results[i];
|
2016-06-22 15:05:19 +02:00
|
|
|
influenced_geometry.reserve(influenced_geometry.size() + subresult.size());
|
2015-08-27 23:59:36 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getParticleEmitterAttractorCount(ComponentHandle cmp) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void addParticleEmitterAttractor(ComponentHandle cmp, int index) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void removeParticleEmitterAttractor(ComponentHandle cmp, int index) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity getParticleEmitterAttractorEntity(ComponentHandle cmp, int index) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterAttractorEntity(ComponentHandle cmp, int index, Entity entity) override
|
2015-12-17 13:58:40 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getParticleEmitterShapeRadius(ComponentHandle cmp) override
|
2015-12-18 21:23:51 +01:00
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SpawnShapeModule>(cmp);
|
|
|
|
return module ? module->m_radius : 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterShapeRadius(ComponentHandle cmp, float value) override
|
2015-12-18 21:23:51 +01:00
|
|
|
{
|
|
|
|
auto* module = getEmitterModule<ParticleEmitter::SpawnShapeModule>(cmp);
|
|
|
|
if (module) module->m_radius = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
int getParticleEmitterPlaneCount(ComponentHandle cmp) override
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void addParticleEmitterPlane(ComponentHandle cmp, int index) override
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void removeParticleEmitterPlane(ComponentHandle cmp, int index) override
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Entity getParticleEmitterPlaneEntity(ComponentHandle cmp, int index) override
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterPlaneEntity(ComponentHandle cmp, int index, Entity entity) override
|
2015-12-16 21:26:19 +01:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
float getLightFOV(ComponentHandle cmp) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
return m_point_lights[m_point_lights_map[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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setLightFOV(ComponentHandle cmp, float fov) override
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-07-08 15:42:47 +02:00
|
|
|
m_point_lights[m_point_lights_map[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
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createGlobalLight(Entity entity)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2017-02-09 14:22:41 +01:00
|
|
|
GlobalLight light;
|
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;
|
2017-04-21 23:26:44 +02:00
|
|
|
light.m_indirect_intensity = 1;
|
2015-07-21 20:10:50 +02:00
|
|
|
light.m_fog_color.set(1, 1, 1);
|
|
|
|
light.m_fog_density = 0;
|
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;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2017-02-09 14:22:41 +01:00
|
|
|
ComponentHandle cmp = {entity.index};
|
|
|
|
if (m_global_lights.empty()) m_active_global_light_cmp = cmp;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2017-02-09 14:22:41 +01:00
|
|
|
m_global_lights.insert(entity, light);
|
|
|
|
m_universe.addComponent(entity, GLOBAL_LIGHT_TYPE, this, cmp);
|
|
|
|
return cmp;
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle 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();
|
2016-06-22 15:05:19 +02:00
|
|
|
m_light_influenced_geometry.emplace(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;
|
2016-06-22 15:05:19 +02:00
|
|
|
++m_point_light_last_cmp.index;
|
2016-06-22 22:16:20 +02:00
|
|
|
light.m_component = m_point_light_last_cmp;
|
2016-06-25 10:20:29 +02:00
|
|
|
light.m_fov = Math::degreesToRadians(360);
|
2015-07-21 20:10:50 +02:00
|
|
|
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-06-22 15:05:19 +02:00
|
|
|
m_point_lights_map.insert(light.m_component, m_point_lights.size() - 1);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
m_universe.addComponent(entity, POINT_LIGHT_TYPE, this, light.m_component);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
detectLightInfluencedGeometry(light.m_component);
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
return light.m_component;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
void updateDecalInfo(Decal& decal) const
|
|
|
|
{
|
|
|
|
decal.position = m_universe.getPosition(decal.entity);
|
|
|
|
decal.radius = decal.scale.length();
|
|
|
|
decal.mtx = m_universe.getMatrix(decal.entity);
|
|
|
|
decal.mtx.setXVector(decal.mtx.getXVector() * decal.scale.x);
|
|
|
|
decal.mtx.setYVector(decal.mtx.getYVector() * decal.scale.y);
|
|
|
|
decal.mtx.setZVector(decal.mtx.getZVector() * decal.scale.z);
|
|
|
|
decal.inv_mtx = decal.mtx;
|
|
|
|
decal.inv_mtx.inverse();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ComponentHandle createDecal(Entity entity)
|
|
|
|
{
|
2016-07-24 17:29:17 +02:00
|
|
|
Decal& decal = m_decals.insert(entity);
|
2016-07-22 13:57:52 +02:00
|
|
|
decal.material = nullptr;
|
|
|
|
decal.entity = entity;
|
|
|
|
decal.scale.set(1, 1, 1);
|
|
|
|
updateDecalInfo(decal);
|
|
|
|
|
|
|
|
ComponentHandle cmp = {entity.index};
|
|
|
|
m_universe.addComponent(entity, DECAL_TYPE, this, cmp);
|
|
|
|
return cmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createEnvironmentProbe(Entity entity)
|
2016-06-12 15:26:41 +02:00
|
|
|
{
|
2016-07-24 17:29:17 +02:00
|
|
|
EnvironmentProbe& probe = m_environment_probes.insert(entity);
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* texture_manager = m_engine.getResourceManager().get(TEXTURE_TYPE);
|
2016-11-29 20:00:36 +01:00
|
|
|
probe.texture = static_cast<Texture*>(texture_manager->load(Path("pipelines/pbr/default_probe.dds")));
|
|
|
|
probe.texture->setFlag(BGFX_TEXTURE_SRGB, true);
|
|
|
|
probe.irradiance = static_cast<Texture*>(texture_manager->load(Path("pipelines/pbr/default_probe.dds")));
|
|
|
|
probe.irradiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
|
|
|
probe.radiance = static_cast<Texture*>(texture_manager->load(Path("pipelines/pbr/default_probe.dds")));
|
|
|
|
probe.radiance->setFlag(BGFX_TEXTURE_SRGB, true);
|
2017-01-03 17:04:09 +01:00
|
|
|
probe.guid = Math::randGUID();
|
2016-06-12 15:26:41 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = {entity.index};
|
|
|
|
m_universe.addComponent(entity, ENVIRONMENT_PROBE_TYPE, this, cmp);
|
|
|
|
return cmp;
|
2016-06-12 15:26:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle createBoneAttachment(Entity entity)
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-08-28 00:42:15 +02:00
|
|
|
BoneAttachment& attachment = m_bone_attachments.emplace(entity);
|
2016-05-02 21:41:18 +02:00
|
|
|
attachment.entity = entity;
|
|
|
|
attachment.parent_entity = INVALID_ENTITY;
|
|
|
|
attachment.bone_index = -1;
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = { entity.index };
|
|
|
|
m_universe.addComponent(entity, BONE_ATTACHMENT_TYPE, this, cmp);
|
|
|
|
return cmp;
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
ComponentHandle createModelInstance(Entity entity)
|
2014-06-16 21:18:15 +02:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
while(entity.index >= m_model_instances.size())
|
2015-12-10 17:09:52 +01:00
|
|
|
{
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances.emplace();
|
2015-12-10 20:27:51 +01:00
|
|
|
r.entity = INVALID_ENTITY;
|
|
|
|
r.model = nullptr;
|
|
|
|
r.pose = nullptr;
|
2015-12-10 17:09:52 +01:00
|
|
|
}
|
2016-09-29 22:24:53 +02:00
|
|
|
auto& r = m_model_instances[entity.index];
|
2015-12-10 20:27:51 +01:00
|
|
|
r.entity = entity;
|
|
|
|
r.model = nullptr;
|
2016-01-22 01:11:04 +01:00
|
|
|
r.meshes = nullptr;
|
2015-12-10 20:27:51 +01:00
|
|
|
r.pose = nullptr;
|
2017-04-13 17:05:07 +02:00
|
|
|
r.flags = 0;
|
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);
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle cmp = {entity.index};
|
2016-09-29 22:24:53 +02:00
|
|
|
m_universe.addComponent(entity, MODEL_INSTANCE_TYPE, this, cmp);
|
2016-06-22 15:05:19 +02:00
|
|
|
return cmp;
|
2014-06-16 21:18:15 +02:00
|
|
|
}
|
|
|
|
|
2015-11-04 22:43:54 +01:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void setParticleEmitterMaterialPath(ComponentHandle cmp, const Path& path) override
|
2015-11-04 22:43:54 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
if (!m_particle_emitters[{cmp.index}]) return;
|
2015-11-04 22:43:54 +01:00
|
|
|
|
2016-07-24 22:21:43 +02:00
|
|
|
auto* manager = m_engine.getResourceManager().get(MATERIAL_TYPE);
|
2016-01-06 14:18:59 +01:00
|
|
|
Material* material = static_cast<Material*>(manager->load(path));
|
2016-06-29 11:10:35 +02:00
|
|
|
m_particle_emitters[{cmp.index}]->setMaterial(material);
|
2015-11-04 22:43:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
Path getParticleEmitterMaterialPath(ComponentHandle cmp) override
|
2015-11-04 22:43:54 +01:00
|
|
|
{
|
2016-06-29 11:10:35 +02:00
|
|
|
ParticleEmitter* emitter = m_particle_emitters[{cmp.index}];
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-29 11:10:35 +02:00
|
|
|
const AssociativeArray<Entity, ParticleEmitter*>& getParticleEmitters() const override
|
2015-11-04 22:43:54 +01:00
|
|
|
{
|
|
|
|
return m_particle_emitters;
|
|
|
|
}
|
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
private:
|
|
|
|
IAllocator& m_allocator;
|
2016-07-08 15:42:47 +02:00
|
|
|
Universe& m_universe;
|
|
|
|
Renderer& m_renderer;
|
|
|
|
Engine& m_engine;
|
|
|
|
CullingSystem* m_culling_system;
|
2015-07-21 20:10:50 +02:00
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle m_point_light_last_cmp;
|
|
|
|
Array<Array<ComponentHandle>> m_light_influenced_geometry;
|
|
|
|
ComponentHandle m_active_global_light_cmp;
|
2016-07-08 15:42:47 +02:00
|
|
|
HashMap<ComponentHandle, int> m_point_lights_map;
|
|
|
|
|
2016-07-22 13:57:52 +02:00
|
|
|
AssociativeArray<Entity, Decal> m_decals;
|
2016-09-29 22:24:53 +02:00
|
|
|
Array<ModelInstance> m_model_instances;
|
2017-02-09 14:22:41 +01:00
|
|
|
HashMap<Entity, GlobalLight> m_global_lights;
|
2016-07-08 15:42:47 +02:00
|
|
|
Array<PointLight> m_point_lights;
|
|
|
|
HashMap<Entity, Camera> m_cameras;
|
2017-08-28 00:42:15 +02:00
|
|
|
AssociativeArray<Entity, BoneAttachment> m_bone_attachments;
|
2016-06-12 15:26:41 +02:00
|
|
|
AssociativeArray<Entity, EnvironmentProbe> m_environment_probes;
|
2016-07-08 15:42:47 +02:00
|
|
|
HashMap<Entity, Terrain*> m_terrains;
|
|
|
|
AssociativeArray<Entity, ParticleEmitter*> m_particle_emitters;
|
|
|
|
|
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;
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-09-29 22:24:53 +02:00
|
|
|
Array<Array<ModelInstanceMesh>> m_temporary_infos;
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2015-07-21 20:10:50 +02:00
|
|
|
float m_time;
|
2016-09-17 01:00:38 +02:00
|
|
|
float m_lod_multiplier;
|
2016-05-02 21:41:18 +02:00
|
|
|
bool m_is_updating_attachments;
|
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;
|
2016-07-08 15:42:47 +02:00
|
|
|
|
2016-07-25 02:00:22 +02:00
|
|
|
AssociativeArray<Model*, ModelLoadedCallback> m_model_loaded_callbacks;
|
2015-07-21 20:10:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
|
2016-12-10 15:16:01 +01:00
|
|
|
#define COMPONENT_TYPE(type, name) \
|
|
|
|
{ \
|
|
|
|
type \
|
|
|
|
, static_cast<Universe::Serialize>(&RenderSceneImpl::serialize##name) \
|
|
|
|
, static_cast<Universe::Deserialize>(&RenderSceneImpl::deserialize##name) \
|
|
|
|
, &RenderSceneImpl::create##name \
|
|
|
|
, &RenderSceneImpl::destroy##name \
|
|
|
|
}
|
|
|
|
|
2015-12-08 22:35:41 +01:00
|
|
|
static struct
|
|
|
|
{
|
2016-06-22 00:46:48 +02:00
|
|
|
ComponentType type;
|
2016-12-10 15:16:01 +01:00
|
|
|
Universe::Serialize serialize;
|
|
|
|
Universe::Deserialize deserialize;
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle(RenderSceneImpl::*creator)(Entity);
|
|
|
|
void (RenderSceneImpl::*destroyer)(ComponentHandle);
|
2016-10-02 22:56:47 +02:00
|
|
|
} COMPONENT_INFOS[] = {
|
2016-12-10 15:16:01 +01:00
|
|
|
COMPONENT_TYPE(MODEL_INSTANCE_TYPE, ModelInstance),
|
|
|
|
COMPONENT_TYPE(GLOBAL_LIGHT_TYPE, GlobalLight),
|
|
|
|
COMPONENT_TYPE(POINT_LIGHT_TYPE, PointLight),
|
|
|
|
COMPONENT_TYPE(DECAL_TYPE, Decal),
|
|
|
|
COMPONENT_TYPE(CAMERA_TYPE, Camera),
|
|
|
|
COMPONENT_TYPE(TERRAIN_TYPE, Terrain),
|
|
|
|
COMPONENT_TYPE(BONE_ATTACHMENT_TYPE, BoneAttachment),
|
|
|
|
COMPONENT_TYPE(ENVIRONMENT_PROBE_TYPE, EnvironmentProbe),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_TYPE, ParticleEmitter),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_ALPHA_TYPE, ParticleEmitterAlpha),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_ATTRACTOR_TYPE, ParticleEmitterAttractor),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_FORCE_HASH, ParticleEmitterForce),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_LINEAR_MOVEMENT_TYPE, ParticleEmitterLinearMovement),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_PLANE_TYPE, ParticleEmitterPlane),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_RANDOM_ROTATION_TYPE, ParticleEmitterRandomRotation),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_SIZE_TYPE, ParticleEmitterSize),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_SPAWN_SHAPE_TYPE, ParticleEmitterSpawnShape),
|
|
|
|
COMPONENT_TYPE(PARTICLE_EMITTER_SUBIMAGE_TYPE, ParticleEmitterSubimage)
|
|
|
|
};
|
2015-12-08 22:35:41 +01:00
|
|
|
|
2016-12-10 15:16:01 +01:00
|
|
|
#undef COMPONENT_TYPE
|
2015-12-08 22:35:41 +01:00
|
|
|
|
2016-07-21 14:23:46 +02:00
|
|
|
RenderSceneImpl::RenderSceneImpl(Renderer& renderer,
|
|
|
|
Engine& engine,
|
|
|
|
Universe& universe,
|
|
|
|
IAllocator& allocator)
|
|
|
|
: m_engine(engine)
|
|
|
|
, m_universe(universe)
|
|
|
|
, m_renderer(renderer)
|
|
|
|
, m_allocator(allocator)
|
|
|
|
, m_model_loaded_callbacks(m_allocator)
|
2016-09-29 22:24:53 +02:00
|
|
|
, m_model_instances(m_allocator)
|
2016-07-21 14:23:46 +02:00
|
|
|
, 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-07-22 13:57:52 +02:00
|
|
|
, m_decals(m_allocator)
|
2016-07-21 14:23:46 +02:00
|
|
|
, m_debug_triangles(m_allocator)
|
|
|
|
, m_debug_lines(m_allocator)
|
|
|
|
, m_debug_points(m_allocator)
|
|
|
|
, m_temporary_infos(m_allocator)
|
|
|
|
, m_active_global_light_cmp(INVALID_COMPONENT)
|
|
|
|
, m_point_light_last_cmp(INVALID_COMPONENT)
|
|
|
|
, m_is_grass_enabled(true)
|
|
|
|
, m_is_game_running(false)
|
|
|
|
, m_particle_emitters(m_allocator)
|
|
|
|
, m_point_lights_map(m_allocator)
|
|
|
|
, m_bone_attachments(m_allocator)
|
|
|
|
, m_environment_probes(m_allocator)
|
2016-09-17 01:00:38 +02:00
|
|
|
, m_lod_multiplier(1.0f)
|
|
|
|
, m_time(0)
|
|
|
|
, m_is_updating_attachments(false)
|
2016-06-22 00:46:48 +02:00
|
|
|
{
|
2016-07-21 14:23:46 +02:00
|
|
|
m_universe.entityTransformed().bind<RenderSceneImpl, &RenderSceneImpl::onEntityMoved>(this);
|
|
|
|
m_universe.entityDestroyed().bind<RenderSceneImpl, &RenderSceneImpl::onEntityDestroyed>(this);
|
2017-09-16 14:04:24 +02:00
|
|
|
m_culling_system = CullingSystem::create(m_allocator);
|
2016-09-29 22:24:53 +02:00
|
|
|
m_model_instances.reserve(5000);
|
2016-07-21 14:23:46 +02:00
|
|
|
|
2016-06-22 00:46:48 +02:00
|
|
|
for (auto& i : COMPONENT_INFOS)
|
|
|
|
{
|
2016-12-10 15:16:01 +01:00
|
|
|
universe.registerComponentType(i.type, this, i.serialize, i.deserialize);
|
2016-06-22 00:46:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
ComponentHandle RenderSceneImpl::createComponent(ComponentType type, Entity entity)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
|
|
|
for (auto& i : COMPONENT_INFOS)
|
|
|
|
{
|
|
|
|
if (i.type == type)
|
|
|
|
{
|
|
|
|
return (this->*i.creator)(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return INVALID_COMPONENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-22 15:05:19 +02:00
|
|
|
void RenderSceneImpl::destroyComponent(ComponentHandle component, ComponentType type)
|
2015-12-08 22:35:41 +01:00
|
|
|
{
|
|
|
|
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,
|
2016-06-29 11:10:35 +02:00
|
|
|
Engine& engine,
|
|
|
|
Universe& universe,
|
|
|
|
IAllocator& allocator)
|
2015-07-21 20:10:50 +02:00
|
|
|
{
|
2016-11-02 18:29:44 +01:00
|
|
|
return LUMIX_NEW(allocator, RenderSceneImpl)(renderer, engine, universe, allocator);
|
2015-07-21 20:10:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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) \
|
|
|
|
|
2016-09-17 01:00:38 +02:00
|
|
|
REGISTER_FUNCTION(setGlobalLODMultiplier);
|
|
|
|
REGISTER_FUNCTION(getGlobalLODMultiplier);
|
2016-08-04 10:24:43 +02:00
|
|
|
REGISTER_FUNCTION(getCameraViewProjection);
|
2016-08-03 13:21:16 +02:00
|
|
|
REGISTER_FUNCTION(getGlobalLightEntity);
|
|
|
|
REGISTER_FUNCTION(getActiveGlobalLight);
|
2016-08-30 12:19:05 +02:00
|
|
|
REGISTER_FUNCTION(getCameraInSlot);
|
|
|
|
REGISTER_FUNCTION(getCameraEntity);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(getCameraSlot);
|
|
|
|
REGISTER_FUNCTION(getCameraComponent);
|
2016-09-29 22:24:53 +02:00
|
|
|
REGISTER_FUNCTION(getModelInstanceComponent);
|
|
|
|
REGISTER_FUNCTION(getModelInstanceModel);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(addDebugCross);
|
2016-05-07 11:49:39 +02:00
|
|
|
REGISTER_FUNCTION(addDebugLine);
|
2016-10-13 19:48:38 +02:00
|
|
|
REGISTER_FUNCTION(addDebugCircle);
|
|
|
|
REGISTER_FUNCTION(addDebugSphere);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(getTerrainMaterial);
|
2016-09-14 13:19:51 +02:00
|
|
|
REGISTER_FUNCTION(getTerrainNormalAt);
|
2016-09-14 14:15:27 +02:00
|
|
|
REGISTER_FUNCTION(setTerrainHeightAt);
|
2016-11-02 19:47:44 +01:00
|
|
|
REGISTER_FUNCTION(hideModelInstance);
|
|
|
|
REGISTER_FUNCTION(showModelInstance);
|
2017-07-03 14:11:11 +02:00
|
|
|
REGISTER_FUNCTION(getPoseBonePosition);
|
2016-04-02 15:35:08 +02:00
|
|
|
|
2017-01-09 16:34:26 +01:00
|
|
|
#undef REGISTER_FUNCTION
|
2016-04-02 15:35:08 +02:00
|
|
|
|
|
|
|
#define REGISTER_FUNCTION(F)\
|
|
|
|
do { \
|
|
|
|
auto f = &LuaWrapper::wrap<decltype(&RenderSceneImpl::LUA_##F), &RenderSceneImpl::LUA_##F>; \
|
|
|
|
LuaWrapper::createSystemFunction(L, "Renderer", #F, f); \
|
|
|
|
} while(false) \
|
|
|
|
|
2016-10-17 00:19:02 +02:00
|
|
|
REGISTER_FUNCTION(createPipeline);
|
|
|
|
REGISTER_FUNCTION(destroyPipeline);
|
|
|
|
REGISTER_FUNCTION(setPipelineScene);
|
2016-10-28 23:16:28 +02:00
|
|
|
REGISTER_FUNCTION(getPipelineScene);
|
2016-10-17 00:19:02 +02:00
|
|
|
REGISTER_FUNCTION(pipelineRender);
|
2016-10-17 10:21:25 +02:00
|
|
|
REGISTER_FUNCTION(getRenderBuffer);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(getMaterialTexture);
|
2016-09-14 13:19:51 +02:00
|
|
|
REGISTER_FUNCTION(getTextureWidth);
|
|
|
|
REGISTER_FUNCTION(getTextureHeight);
|
|
|
|
REGISTER_FUNCTION(getTexturePixel);
|
|
|
|
REGISTER_FUNCTION(setTexturePixel);
|
2016-10-31 16:19:27 +01:00
|
|
|
REGISTER_FUNCTION(getTextureHandle);
|
2016-09-14 13:19:51 +02:00
|
|
|
REGISTER_FUNCTION(updateTextureData);
|
2016-09-29 22:24:53 +02:00
|
|
|
REGISTER_FUNCTION(setModelInstanceMaterial);
|
|
|
|
REGISTER_FUNCTION(setModelInstancePath);
|
2016-10-03 17:07:32 +02:00
|
|
|
REGISTER_FUNCTION(getModelBoneIndex);
|
2016-04-02 15:35:08 +02:00
|
|
|
REGISTER_FUNCTION(makeScreenshot);
|
|
|
|
REGISTER_FUNCTION(compareTGA);
|
2016-09-14 14:15:27 +02:00
|
|
|
REGISTER_FUNCTION(getTerrainHeightAt);
|
2016-10-04 17:41:16 +02:00
|
|
|
REGISTER_FUNCTION(emitParticle);
|
2016-04-02 15:35:08 +02:00
|
|
|
|
|
|
|
LuaWrapper::createSystemFunction(L, "Renderer", "castCameraRay", &RenderSceneImpl::LUA_castCameraRay);
|
|
|
|
|
|
|
|
#undef REGISTER_FUNCTION
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Lumix
|