Files
OpenEngine/open_engine/src/open_engine/scene/scene.cpp
2026-03-06 18:07:51 +01:00

356 lines
11 KiB
C++
Executable File

#include "logging.hpp"
#include "physics.hpp"
#include "ref_scope.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/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);
}
OE_CORE_ERROR("Entity has no shape component!");
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));
}
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)
{
}
}