Files
FlaxEngine/Source/Engine/Level/Actors/Decal.cpp

146 lines
3.5 KiB
C++

// Copyright (c) 2012-2021 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)
{
_world = Matrix::Scaling(_size);
_bounds.Extents = Vector3::Half;
_bounds.Transformation = _world;
_bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere);
}
void Decal::SetSize(const Vector3& value)
{
const auto v = value.GetAbsolute();
if (v != _size)
{
_size = v;
Transform t = _transform;
t.Scale *= _size;
t.GetWorld(_world);
_bounds.Extents = Vector3::Half;
_bounds.Transformation = _world;
_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();
}
#endif
void Decal::Draw(RenderContext& renderContext)
{
if ((renderContext.View.Flags & ViewFlags::Decals) != 0 &&
Material &&
Material->IsLoaded() &&
Material->IsDecal())
{
const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center, _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);
}
bool Decal::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
{
return _bounds.Intersects(ray, distance, normal);
}
void Decal::OnEnable()
{
GetSceneRendering()->AddCommon(this);
#if USE_EDITOR
GetSceneRendering()->AddViewportIcon(this);
#endif
// Base
Actor::OnEnable();
}
void Decal::OnDisable()
{
#if USE_EDITOR
GetSceneRendering()->RemoveViewportIcon(this);
#endif
GetSceneRendering()->RemoveCommon(this);
// Base
Actor::OnDisable();
}
void Decal::OnTransformChanged()
{
// Base
Actor::OnTransformChanged();
Transform t = _transform;
t.Scale *= _size;
t.GetWorld(_world);
_bounds.Extents = Vector3::Half;
_bounds.Transformation = _world;
_bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere);
}