383 lines
12 KiB
C++
Executable File
383 lines
12 KiB
C++
Executable File
#include "logging.hpp"
|
|
#include "physics.hpp"
|
|
#include "ref_scope.hpp"
|
|
#include "renderer/model3d.hpp"
|
|
#include <Jolt/Physics/Body/MotionType.h>
|
|
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
|
#include <Jolt/Physics/Collision/Shape/ConvexShape.h>
|
|
#include <pch.hpp>
|
|
|
|
#include <renderer/renderer3d.hpp>
|
|
#include <scene/components.hpp>
|
|
#include <open_engine/scene/native_scriptable_entity.hpp>
|
|
#include <scene/entity.hpp>
|
|
#include <scene/scene.hpp>
|
|
#include <core/time.hpp>
|
|
|
|
#include <Jolt/Physics/Collision/Shape/Shape.h>
|
|
#include <Jolt/Physics/Collision/Shape/PlaneShape.h>
|
|
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
|
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
|
#include <Jolt/Physics/EActivation.h>
|
|
#include <Jolt/Math/Real.h>
|
|
#include <Jolt/Math/Quat.h>
|
|
#include <cstdint>
|
|
#include <entt/entity/fwd.hpp>
|
|
|
|
namespace OpenEngine {
|
|
|
|
static Ref<ShapeSettings> CreateShape(entt::registry& reg, entt::entity e)
|
|
{
|
|
if (reg.any_of<BoxShapeComponent>(e)) {
|
|
auto& c = reg.get<BoxShapeComponent>(e);
|
|
return CreateRef<BoxShapeSettings>(ToJolt(c.size * 0.5f));
|
|
}
|
|
if (reg.any_of<SphereShapeComponent>(e)) {
|
|
auto& c = reg.get<SphereShapeComponent>(e);
|
|
return CreateRef<SphereShapeSettings>(c.radius);
|
|
}
|
|
if (reg.any_of<PlaneShapeComponent>(e)) {
|
|
auto& c = reg.get<PlaneShapeComponent>(e);
|
|
const Plane plane({ 0.0f, 1.0f, 0.0f }, 0);
|
|
return CreateRef<PlaneShapeSettings>(plane, nullptr, c.extent);
|
|
}
|
|
|
|
OE_CORE_ERROR("Entity {} has no shape component!", reg.get<TagComponent>(e).tag);
|
|
return nullptr;
|
|
};
|
|
|
|
void Scene::OnRuntimeStart()
|
|
{
|
|
body_interface = &physics_engine.GetBodyInterface();
|
|
// TODO: Cleanup components aquisition
|
|
auto view = registry.view<TransformComponent, PhysicsBodyComponent>();
|
|
for (auto e : view) {
|
|
Entity entity = { e, this };
|
|
|
|
auto shape_settings = CreateShape(registry, e);
|
|
if (!shape_settings)
|
|
shape_settings = CreateRef<BoxShapeSettings>(Vec3(0.5f, 0.5f, 0.5f));
|
|
|
|
auto shape_result = shape_settings->Create();
|
|
if (shape_result.HasError()) {
|
|
OE_CORE_ERROR("Shape creation failed: {}", shape_result.GetError().c_str());
|
|
continue;
|
|
}
|
|
ShapeRefC shape = shape_result.Get();
|
|
|
|
auto& pbc = entity.GetComponents<PhysicsBodyComponent>();
|
|
auto& tc = entity.GetComponents<TransformComponent>();
|
|
|
|
glm::vec3& pos = tc.translation;
|
|
glm::vec3& scale = tc.scale;
|
|
glm::vec3& rot = tc.rotation;
|
|
|
|
Quat quat = Quat::sEulerAngles(Vec3(rot.x, rot.y, rot.z));
|
|
BodyCreationSettings settings(
|
|
shape,
|
|
//new BoxShape(Vec3(scale.x * 0.5, scale.y * 0.5f, scale.z * 0.5f)),
|
|
Vec3(pos.x, pos.y, pos.z),
|
|
quat,
|
|
(EMotionType)pbc.type,
|
|
pbc.layer);
|
|
|
|
settings.mLinearDamping = pbc.linear_damping;
|
|
settings.mAngularDamping = pbc.angular_damping;
|
|
settings.mGravityFactor = pbc.gravity_factor;
|
|
settings.mRestitution = pbc.restitution;
|
|
settings.mFriction = pbc.friction;
|
|
settings.mObjectLayer = (ObjectLayer)pbc.layer;
|
|
|
|
pbc.body = body_interface->CreateAndAddBody(settings, (EActivation)pbc.initial_activation_state);
|
|
}
|
|
}
|
|
|
|
void Scene::OnRuntimeStop()
|
|
{
|
|
auto view = registry.view<PhysicsBodyComponent>();
|
|
for (auto e : view) {
|
|
Entity entity = { e, this };
|
|
|
|
auto& pbc = entity.GetComponents<PhysicsBodyComponent>();
|
|
|
|
body_interface->RemoveBody(pbc.body);
|
|
body_interface->DestroyBody(pbc.body);
|
|
}
|
|
}
|
|
|
|
Entity Scene::CreateEntity(const std::string& name)
|
|
{
|
|
return CreateEntityWithUUID(UUID(), name);
|
|
}
|
|
|
|
Entity Scene::CreateEntityWithUUID(UUID uuid, const std::string& name)
|
|
{
|
|
Entity entity = { registry.create(), this };
|
|
|
|
entity.AddComponent<IDComponent>(uuid);
|
|
auto& tag = entity.AddComponent<TagComponent>();
|
|
tag.tag = name.empty() ? "Entity" : name;
|
|
|
|
return entity;
|
|
}
|
|
|
|
void Scene::DeleteEntity(entt::entity entity)
|
|
{
|
|
registry.destroy(entity);
|
|
}
|
|
|
|
void Scene::MarkEntityForDeletion(Entity entity)
|
|
{
|
|
pending_deletion.emplace_back(entity);
|
|
}
|
|
|
|
void Scene::UpdateEntities()
|
|
{
|
|
for (auto& entity : pending_deletion)
|
|
DeleteEntity(entity);
|
|
|
|
pending_deletion.clear();
|
|
}
|
|
|
|
void Scene::OnUpdatePhysics()
|
|
{
|
|
static int step = 0;
|
|
static float accumulator = 0.0f;
|
|
static const float fixedDT = 1.0f / 60.0f;
|
|
|
|
float real_delta_time = Time::DeltaTime(); // e.g. from a timer
|
|
accumulator += real_delta_time;
|
|
|
|
if (accumulator >= fixedDT) {
|
|
step++;
|
|
physics_engine.Update(fixedDT, 1);
|
|
accumulator -= fixedDT;
|
|
}
|
|
}
|
|
|
|
void Scene::OnUpdateRuntime()
|
|
{
|
|
{
|
|
OE_PROFILE_SCOPE("Updating Sripts");
|
|
|
|
registry.view<NativeScriptComponent>().each([=, this](auto entity, auto& nsc)
|
|
{
|
|
if (!nsc.instance) {
|
|
nsc.instance = nsc.InstanciateScript();
|
|
nsc.instance->entity = Entity{ entity, this };
|
|
nsc.instance->OnCreate();
|
|
}
|
|
|
|
nsc.instance->OnUpdate();
|
|
});
|
|
}
|
|
|
|
auto view = registry.view<TransformComponent, PhysicsBodyComponent>();
|
|
for (auto e : view) {
|
|
Entity entity = { e, this };
|
|
|
|
auto& pos = entity.GetComponents<TransformComponent>().translation;
|
|
auto& body = entity.GetComponents<PhysicsBodyComponent>();
|
|
|
|
body_interface->SetPosition(body.body, { pos.x, pos.y, pos.z }, EActivation::Activate);
|
|
|
|
body_interface->SetRestitution(body.body, body.restitution);
|
|
body_interface->SetFriction(body.body, body.friction);
|
|
}
|
|
|
|
OnUpdatePhysics();
|
|
|
|
for (auto e : view) {
|
|
Entity entity = { e, this };
|
|
|
|
auto& transform = entity.GetComponents<TransformComponent>();
|
|
auto& body = entity.GetComponents<PhysicsBodyComponent>();
|
|
|
|
auto position = body_interface->GetPosition(body.body);
|
|
auto rotation = body_interface->GetRotation(body.body).GetEulerAngles();
|
|
transform.translation.x = position.GetX();
|
|
transform.translation.y = position.GetY();
|
|
transform.translation.z = position.GetZ();
|
|
|
|
transform.rotation.x = rotation.GetX();
|
|
transform.rotation.y = rotation.GetY();
|
|
transform.rotation.z = rotation.GetZ();
|
|
|
|
body_interface->SetGravityFactor(body.body, body.gravity_factor);
|
|
}
|
|
|
|
SceneCamera* main_camera = nullptr;
|
|
glm::mat4 main_transform{ 1.0f };
|
|
{
|
|
auto camera_view = registry.view<CameraComponent, TransformComponent>();
|
|
for (auto entity : camera_view) {
|
|
auto [camera_component, transform] = camera_view.get<CameraComponent, TransformComponent>(entity);
|
|
|
|
if (camera_component.primary) {
|
|
main_camera = &camera_component.camera;
|
|
main_transform = GetTransformFromComp(transform);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (main_camera) {
|
|
Renderer3D::BeginScene(*main_camera, main_transform);
|
|
|
|
auto view = registry.view<TransformComponent, MeshComponent>();
|
|
|
|
for (const auto& e : view) {
|
|
auto [transform, mesh] = view.get<TransformComponent, MeshComponent>(e);
|
|
Entity entity(e, this);
|
|
|
|
Material material;
|
|
if (entity.HasComponent<MaterialComponent>())
|
|
material = entity.GetComponents<MaterialComponent>().material;
|
|
|
|
Renderer3D::DrawMesh(mesh.mesh, material, GetTransformFromComp(transform));
|
|
/*
|
|
if (sprite.texture)
|
|
Renderer2D::DrawQuad(GetTransformFromComp(transform),
|
|
sprite.texture, sprite.color, (int)entity, sprite.tiling_factor);
|
|
else
|
|
Renderer2D::DrawQuad(GetTransformFromComp(transform),
|
|
sprite.color, (int)entity);
|
|
*/
|
|
}
|
|
|
|
Renderer3D::EndScene();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Scene::OnUpdateEditor(EditorCamera& camera)
|
|
{
|
|
Renderer3D::BeginScene(camera);
|
|
|
|
auto view = registry.view<TransformComponent, MeshComponent>();
|
|
|
|
for (const auto& entity : view) {
|
|
auto [transform, mesh] = view.get<TransformComponent, MeshComponent>(entity);
|
|
|
|
Material material;
|
|
|
|
Entity _entity(entity, this);
|
|
if (_entity.HasComponent<MaterialComponent>())
|
|
material = _entity.GetComponents<MaterialComponent>().material;
|
|
|
|
if (mesh.mesh)
|
|
Renderer3D::DrawMesh(mesh.mesh, material, GetTransformFromComp(transform), (uint32_t)_entity);
|
|
}
|
|
|
|
auto model_view = registry.view<TransformComponent, ModelComponent>();
|
|
|
|
for (const auto& entity : model_view) {
|
|
auto [transform, model_comp] = model_view.get<TransformComponent, ModelComponent>(entity);
|
|
|
|
Entity _entity(entity, this);
|
|
|
|
Renderer3D::DrawModel(model_comp.model, GetTransformFromComp(transform), (uint32_t)_entity);
|
|
}
|
|
|
|
Renderer3D::EndScene();
|
|
}
|
|
|
|
void Scene::OnViewportResize(uint32_t width, uint32_t height)
|
|
{
|
|
viewport_width = width;
|
|
viewport_height = height;
|
|
|
|
auto view = registry.view<CameraComponent>();
|
|
for (auto entity : view) {
|
|
auto& camera_comp = view.get<CameraComponent>(entity);
|
|
if (!camera_comp.fixed_aspect_ratio)
|
|
camera_comp.camera.SetViewportSize(width, height);
|
|
}
|
|
}
|
|
|
|
Entity Scene::GetPrimaryCamera()
|
|
{
|
|
auto view = registry.view<CameraComponent>();
|
|
|
|
for (auto entity : view) {
|
|
const auto& camera = view.get<CameraComponent>(entity);
|
|
if (camera.primary)
|
|
return Entity { entity, this };
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
template<typename T>
|
|
void Scene::OnComponentAdded(Entity entity, T& component)
|
|
{
|
|
static_assert(false);
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<TransformComponent>(Entity entity, TransformComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<CameraComponent>(Entity entity, CameraComponent& component)
|
|
{
|
|
if (viewport_width > 0 && viewport_height > 0)
|
|
component.camera.SetViewportSize(viewport_width, viewport_height);
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<SpriteRendererComponent>(Entity entity, SpriteRendererComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<TagComponent>(Entity entity, TagComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<NativeScriptComponent>(Entity entity, NativeScriptComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<MeshComponent>(Entity entity, MeshComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<MaterialComponent>(Entity entity, MaterialComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<PhysicsBodyComponent>(Entity entity, PhysicsBodyComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<SphereShapeComponent>(Entity entity, SphereShapeComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<BoxShapeComponent>(Entity entity, BoxShapeComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<IDComponent>(Entity entity, IDComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<PlaneShapeComponent>(Entity entity, PlaneShapeComponent& component)
|
|
{
|
|
}
|
|
|
|
template<>
|
|
void Scene::OnComponentAdded<ModelComponent>(Entity entity, ModelComponent& component)
|
|
{
|
|
}
|
|
}
|