154 lines
3.9 KiB
C++
154 lines
3.9 KiB
C++
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
#include "Decal.h"
|
|
#include "Engine/Content/Assets/MaterialInstance.h"
|
|
#include "Engine/Serialization/Serialization.h"
|
|
#include "Engine/Renderer/RenderList.h"
|
|
#include "Engine/Level/Scene/SceneRendering.h"
|
|
#include "Engine/Graphics/RenderView.h"
|
|
#include "Engine/Graphics/RenderTask.h"
|
|
#include "Engine/Graphics/RenderTools.h"
|
|
|
|
Decal::Decal(const SpawnParams& params)
|
|
: Actor(params)
|
|
, _size(100.0f)
|
|
{
|
|
_drawCategory = SceneRendering::PreRender;
|
|
_bounds.Extents = _size * 0.5f;
|
|
_bounds.Transformation = _transform;
|
|
_bounds.GetBoundingBox(_box);
|
|
BoundingSphere::FromBox(_box, _sphere);
|
|
}
|
|
|
|
void Decal::SetSize(const Vector3& value)
|
|
{
|
|
const auto v = value.GetAbsolute();
|
|
if (v != _size)
|
|
{
|
|
_size = v;
|
|
_bounds.Extents = v * 0.5f;
|
|
_bounds.GetBoundingBox(_box);
|
|
BoundingSphere::FromBox(_box, _sphere);
|
|
}
|
|
}
|
|
|
|
MaterialInstance* Decal::CreateAndSetVirtualMaterialInstance()
|
|
{
|
|
auto material = Material.Get();
|
|
CHECK_RETURN(material && !material->WaitForLoaded(), nullptr);
|
|
const auto result = material->CreateVirtualInstance();
|
|
Material = result;
|
|
return result;
|
|
}
|
|
|
|
#if USE_EDITOR
|
|
|
|
#include "Engine/Debug/DebugDraw.h"
|
|
|
|
void Decal::OnDebugDrawSelected()
|
|
{
|
|
DEBUG_DRAW_WIRE_BOX(_bounds, Color::BlueViolet, 0, true);
|
|
|
|
// Base
|
|
Actor::OnDebugDrawSelected();
|
|
}
|
|
|
|
BoundingBox Decal::GetEditorBox() const
|
|
{
|
|
const Vector3 size(10.0f);
|
|
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
|
}
|
|
|
|
#endif
|
|
|
|
void Decal::OnLayerChanged()
|
|
{
|
|
if (_sceneRenderingKey != -1)
|
|
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
|
|
}
|
|
|
|
void Decal::Draw(RenderContext& renderContext)
|
|
{
|
|
if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Decals) &&
|
|
EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer) &&
|
|
Material &&
|
|
Material->IsLoaded() &&
|
|
Material->IsDecal())
|
|
{
|
|
const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
|
|
const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt;
|
|
|
|
// Check if decal is being culled
|
|
if (Math::Square(DrawMinScreenSize * 0.5f) > screenRadiusSquared)
|
|
return;
|
|
|
|
renderContext.List->Decals.Add(this);
|
|
}
|
|
}
|
|
|
|
void Decal::Serialize(SerializeStream& stream, const void* otherObj)
|
|
{
|
|
// Base
|
|
Actor::Serialize(stream, otherObj);
|
|
|
|
SERIALIZE_GET_OTHER_OBJ(Decal);
|
|
|
|
SERIALIZE(Material);
|
|
SERIALIZE_MEMBER(Size, _size);
|
|
SERIALIZE(SortOrder);
|
|
SERIALIZE(DrawMinScreenSize);
|
|
}
|
|
|
|
void Decal::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
|
{
|
|
// Base
|
|
Actor::Deserialize(stream, modifier);
|
|
|
|
DESERIALIZE(Material);
|
|
DESERIALIZE_MEMBER(Size, _size);
|
|
DESERIALIZE(SortOrder);
|
|
DESERIALIZE(DrawMinScreenSize);
|
|
|
|
_bounds.Extents = _size * 0.5f;
|
|
}
|
|
|
|
bool Decal::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal)
|
|
{
|
|
return _bounds.Intersects(ray, distance, normal);
|
|
}
|
|
|
|
void Decal::OnEnable()
|
|
{
|
|
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
|
|
#if USE_EDITOR
|
|
GetSceneRendering()->AddViewportIcon(this);
|
|
#endif
|
|
|
|
// Base
|
|
Actor::OnEnable();
|
|
}
|
|
|
|
void Decal::OnDisable()
|
|
{
|
|
#if USE_EDITOR
|
|
GetSceneRendering()->RemoveViewportIcon(this);
|
|
#endif
|
|
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
|
|
|
|
// Base
|
|
Actor::OnDisable();
|
|
}
|
|
|
|
void Decal::OnTransformChanged()
|
|
{
|
|
// Base
|
|
Actor::OnTransformChanged();
|
|
|
|
_bounds.Transformation = _transform;
|
|
_bounds.GetBoundingBox(_box);
|
|
BoundingSphere::FromBox(_box, _sphere);
|
|
|
|
if (_sceneRenderingKey != -1)
|
|
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
|
|
}
|