Merge more code together for meshes
This commit is contained in:
@@ -79,9 +79,9 @@ Model::Model(const SpawnParams& params, const AssetInfo* info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Model::~Model()
|
bool Model::HasAnyLODInitialized() const
|
||||||
{
|
{
|
||||||
ASSERT(_streamingTask == nullptr);
|
return LODs.HasItems() && LODs.Last().HasAnyMeshInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, Mesh** mesh, int32 lodIndex)
|
bool Model::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, Mesh** mesh, int32 lodIndex)
|
||||||
@@ -890,6 +890,12 @@ AssetChunksFlag Model::getChunksToPreload() const
|
|||||||
return GET_CHUNK_FLAG(0) | GET_CHUNK_FLAG(15);
|
return GET_CHUNK_FLAG(0) | GET_CHUNK_FLAG(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ModelLOD::HasAnyMeshInitialized() const
|
||||||
|
{
|
||||||
|
// Note: we initialize all meshes at once so the last one can be used to check it.
|
||||||
|
return Meshes.HasItems() && Meshes.Last().IsInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
bool ModelLOD::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, Mesh** mesh)
|
bool ModelLOD::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, Mesh** mesh)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|||||||
@@ -3,9 +3,156 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ModelBase.h"
|
#include "ModelBase.h"
|
||||||
#include "Engine/Graphics/Models/ModelLOD.h"
|
#include "Engine/Graphics/Models/Mesh.h"
|
||||||
|
|
||||||
class Mesh;
|
/// <summary>
|
||||||
|
/// Represents single Level Of Detail for the model. Contains a collection of the meshes.
|
||||||
|
/// </summary>
|
||||||
|
API_CLASS(NoSpawn) class FLAXENGINE_API ModelLOD : public ScriptingObject
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(ModelLOD, ScriptingObject);
|
||||||
|
friend Model;
|
||||||
|
friend Mesh;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Model* _model = nullptr;
|
||||||
|
int32 _lodIndex = 0;
|
||||||
|
uint32 _verticesCount = 0;
|
||||||
|
|
||||||
|
void Link(Model* model, int32 lodIndex)
|
||||||
|
{
|
||||||
|
_model = model;
|
||||||
|
_lodIndex = lodIndex;
|
||||||
|
_verticesCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() float ScreenSize = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The meshes array.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(ReadOnly) Array<Mesh> Meshes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether any mesh has been initialized.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if any mesh has been initialized, otherwise false.</returns>
|
||||||
|
bool HasAnyMeshInitialized() const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the model LOD index.
|
||||||
|
/// </summary>
|
||||||
|
API_PROPERTY() FORCE_INLINE int32 GetLODIndex() const
|
||||||
|
{
|
||||||
|
return _lodIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the vertex count for this model LOD level.
|
||||||
|
/// </summary>
|
||||||
|
API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
|
||||||
|
{
|
||||||
|
return _verticesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ray">The ray to test</param>
|
||||||
|
/// <param name="world">World to test</param>
|
||||||
|
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
||||||
|
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
||||||
|
/// <param name="mesh">Mesh, or null</param>
|
||||||
|
/// <returns>True whether the two objects intersected</returns>
|
||||||
|
bool Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, Mesh** mesh);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ray">The ray to test</param>
|
||||||
|
/// <param name="transform">The instance transformation.</param>
|
||||||
|
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
||||||
|
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
||||||
|
/// <param name="mesh">Mesh, or null</param>
|
||||||
|
/// <returns>True whether the two objects intersected</returns>
|
||||||
|
bool Intersects(const Ray& ray, const Transform& transform, Real& distance, Vector3& normal, Mesh** mesh);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get model bounding box in transformed world matrix.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">World matrix</param>
|
||||||
|
/// <returns>Bounding box</returns>
|
||||||
|
BoundingBox GetBox(const Matrix& world) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get model bounding box in transformed world.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="transform">The instance transformation.</param>
|
||||||
|
/// <param name="deformation">The meshes deformation container (optional).</param>
|
||||||
|
/// <returns>Bounding box</returns>
|
||||||
|
BoundingBox GetBox(const Transform& transform, const MeshDeformation* deformation = nullptr) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the bounding box combined for all meshes in this model LOD.
|
||||||
|
/// </summary>
|
||||||
|
API_PROPERTY() BoundingBox GetBox() const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the meshes. Binds vertex and index buffers and invokes the draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">The GPU context to draw with.</param>
|
||||||
|
FORCE_INLINE void Render(GPUContext* context)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
Meshes.Get()[i].Render(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the meshes from the model LOD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderContext">The rendering context.</param>
|
||||||
|
/// <param name="material">The material to use for rendering.</param>
|
||||||
|
/// <param name="world">The world transformation of the model.</param>
|
||||||
|
/// <param name="flags">The object static flags.</param>
|
||||||
|
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
|
||||||
|
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
|
||||||
|
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
|
||||||
|
/// <param name="sortOrder">Object sorting key.</param>
|
||||||
|
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
Meshes.Get()[i].Draw(renderContext, material, world, flags, receiveDecals, drawModes, perInstanceRandom, sortOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws all the meshes from the model LOD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderContext">The rendering context.</param>
|
||||||
|
/// <param name="info">The packed drawing info data.</param>
|
||||||
|
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
||||||
|
FORCE_INLINE void Draw(const RenderContext& renderContext, const Mesh::DrawInfo& info, float lodDitherFactor) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
Meshes.Get()[i].Draw(renderContext, info, lodDitherFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws all the meshes from the model LOD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderContextBatch">The rendering context batch.</param>
|
||||||
|
/// <param name="info">The packed drawing info data.</param>
|
||||||
|
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
||||||
|
FORCE_INLINE void Draw(const RenderContextBatch& renderContextBatch, const Mesh::DrawInfo& info, float lodDitherFactor) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
Meshes.Get()[i].Draw(renderContextBatch, info, lodDitherFactor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Model asset that contains model object made of meshes which can rendered on the GPU.
|
/// Model asset that contains model object made of meshes which can rendered on the GPU.
|
||||||
@@ -26,20 +173,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(ReadOnly) SDFData SDF;
|
API_FIELD(ReadOnly) SDFData SDF;
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
/// Finalizes an instance of the <see cref="Model"/> class.
|
|
||||||
/// </summary>
|
|
||||||
~Model();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether any LOD has been initialized.
|
/// Determines whether any LOD has been initialized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FORCE_INLINE bool HasAnyLODInitialized() const
|
bool HasAnyLODInitialized() const;
|
||||||
{
|
|
||||||
return LODs.HasItems() && LODs.Last().HasAnyMeshInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -163,12 +163,16 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ModelBase::~ModelBase()
|
||||||
|
{
|
||||||
|
ASSERT(_streamingTask == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void ModelBase::SetupMaterialSlots(int32 slotsCount)
|
void ModelBase::SetupMaterialSlots(int32 slotsCount)
|
||||||
{
|
{
|
||||||
CHECK(slotsCount >= 0 && slotsCount < 4096);
|
CHECK(slotsCount >= 0 && slotsCount < 4096);
|
||||||
if (!IsVirtual() && WaitForLoaded())
|
if (!IsVirtual() && WaitForLoaded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
|
||||||
const int32 prevCount = MaterialSlots.Count();
|
const int32 prevCount = MaterialSlots.Count();
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
~ModelBase();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The minimum screen size to draw this model (the bottom limit). Used to cull small models. Set to 0 to disable this feature.
|
/// The minimum screen size to draw this model (the bottom limit). Used to cull small models. Set to 0 to disable this feature.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ SkinnedModel::SkinnedModel(const SpawnParams& params, const AssetInfo* info)
|
|||||||
|
|
||||||
SkinnedModel::~SkinnedModel()
|
SkinnedModel::~SkinnedModel()
|
||||||
{
|
{
|
||||||
ASSERT(_streamingTask == nullptr);
|
|
||||||
ASSERT(_skeletonMappingCache.Count() == 0);
|
ASSERT(_skeletonMappingCache.Count() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,6 +1052,12 @@ AssetChunksFlag SkinnedModel::getChunksToPreload() const
|
|||||||
return GET_CHUNK_FLAG(0);
|
return GET_CHUNK_FLAG(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkinnedModelLOD::HasAnyMeshInitialized() const
|
||||||
|
{
|
||||||
|
// Note: we initialize all meshes at once so the last one can be used to check it.
|
||||||
|
return Meshes.HasItems() && Meshes.Last().IsInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
bool SkinnedModelLOD::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, SkinnedMesh** mesh)
|
bool SkinnedModelLOD::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, SkinnedMesh** mesh)
|
||||||
{
|
{
|
||||||
// Check all meshes
|
// Check all meshes
|
||||||
|
|||||||
@@ -4,9 +4,135 @@
|
|||||||
|
|
||||||
#include "ModelBase.h"
|
#include "ModelBase.h"
|
||||||
#include "Engine/Core/Collections/Dictionary.h"
|
#include "Engine/Core/Collections/Dictionary.h"
|
||||||
#include "Engine/Graphics/Models/Config.h"
|
#include "Engine/Graphics/Models/SkinnedMesh.h"
|
||||||
#include "Engine/Graphics/Models/SkeletonData.h"
|
#include "Engine/Graphics/Models/SkeletonData.h"
|
||||||
#include "Engine/Graphics/Models/SkinnedModelLOD.h"
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents single Level Of Detail for the skinned model. Contains a collection of the meshes.
|
||||||
|
/// </summary>
|
||||||
|
API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedModelLOD : public ScriptingObject
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedModelLOD, ScriptingObject);
|
||||||
|
friend SkinnedModel;
|
||||||
|
private:
|
||||||
|
SkinnedModel* _model = nullptr;
|
||||||
|
int32 _lodIndex = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() float ScreenSize = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The meshes array.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(ReadOnly) Array<SkinnedMesh> Meshes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the model LOD index.
|
||||||
|
/// </summary>
|
||||||
|
API_PROPERTY() FORCE_INLINE int32 GetLODIndex() const
|
||||||
|
{
|
||||||
|
return _lodIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether any mesh has been initialized.
|
||||||
|
/// </summary>
|
||||||
|
bool HasAnyMeshInitialized() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ray">The ray to test</param>
|
||||||
|
/// <param name="world">World to test</param>
|
||||||
|
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
||||||
|
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
||||||
|
/// <param name="mesh">Mesh, or null</param>
|
||||||
|
/// <returns>True whether the two objects intersected</returns>
|
||||||
|
bool Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, SkinnedMesh** mesh);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ray">The ray to test</param>
|
||||||
|
/// <param name="transform">Instance transformation</param>
|
||||||
|
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
||||||
|
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
||||||
|
/// <param name="mesh">Mesh, or null</param>
|
||||||
|
/// <returns>True whether the two objects intersected</returns>
|
||||||
|
bool Intersects(const Ray& ray, const Transform& transform, Real& distance, Vector3& normal, SkinnedMesh** mesh);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get model bounding box in transformed world for given instance buffer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">World matrix</param>
|
||||||
|
/// <returns>Bounding box</returns>
|
||||||
|
BoundingBox GetBox(const Matrix& world) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get model bounding box in transformed world.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="transform">The instance transformation.</param>
|
||||||
|
/// <param name="deformation">The meshes deformation container (optional).</param>
|
||||||
|
/// <returns>Bounding box</returns>
|
||||||
|
BoundingBox GetBox(const Transform& transform, const MeshDeformation* deformation = nullptr) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get model bounding box in transformed world for given instance buffer for only one mesh
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">World matrix</param>
|
||||||
|
/// <param name="meshIndex">esh index</param>
|
||||||
|
/// <returns>Bounding box</returns>
|
||||||
|
BoundingBox GetBox(const Matrix& world, int32 meshIndex) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the bounding box combined for all meshes in this model LOD.
|
||||||
|
/// </summary>
|
||||||
|
API_PROPERTY() BoundingBox GetBox() const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the meshes. Binds vertex and index buffers and invokes the draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">The GPU context to draw with.</param>
|
||||||
|
FORCE_INLINE void Render(GPUContext* context)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
{
|
||||||
|
Meshes.Get()[i].Render(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws all the meshes from the model LOD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderContext">The rendering context.</param>
|
||||||
|
/// <param name="info">The packed drawing info data.</param>
|
||||||
|
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
||||||
|
FORCE_INLINE void Draw(const RenderContext& renderContext, const SkinnedMesh::DrawInfo& info, float lodDitherFactor) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
{
|
||||||
|
Meshes.Get()[i].Draw(renderContext, info, lodDitherFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws all the meshes from the model LOD.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="renderContextBatch">The rendering context batch.</param>
|
||||||
|
/// <param name="info">The packed drawing info data.</param>
|
||||||
|
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
||||||
|
FORCE_INLINE void Draw(const RenderContextBatch& renderContextBatch, const SkinnedMesh::DrawInfo& info, float lodDitherFactor) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Meshes.Count(); i++)
|
||||||
|
{
|
||||||
|
Meshes.Get()[i].Draw(renderContextBatch, info, lodDitherFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Skinned model asset that contains model object made of meshes that can be rendered on the GPU using skeleton bones skinning.
|
/// Skinned model asset that contains model object made of meshes that can be rendered on the GPU using skeleton bones skinning.
|
||||||
|
|||||||
@@ -1,159 +0,0 @@
|
|||||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Mesh.h"
|
|
||||||
|
|
||||||
class MemoryReadStream;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents single Level Of Detail for the model. Contains a collection of the meshes.
|
|
||||||
/// </summary>
|
|
||||||
API_CLASS(NoSpawn) class FLAXENGINE_API ModelLOD : public ScriptingObject
|
|
||||||
{
|
|
||||||
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(ModelLOD, ScriptingObject);
|
|
||||||
friend Model;
|
|
||||||
friend Mesh;
|
|
||||||
private:
|
|
||||||
Model* _model = nullptr;
|
|
||||||
int32 _lodIndex = 0;
|
|
||||||
uint32 _verticesCount = 0;
|
|
||||||
|
|
||||||
void Link(Model* model, int32 lodIndex)
|
|
||||||
{
|
|
||||||
_model = model;
|
|
||||||
_lodIndex = lodIndex;
|
|
||||||
_verticesCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
/// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() float ScreenSize = 1.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The meshes array.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD(ReadOnly) Array<Mesh> Meshes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether any mesh has been initialized.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if any mesh has been initialized, otherwise false.</returns>
|
|
||||||
FORCE_INLINE bool HasAnyMeshInitialized() const
|
|
||||||
{
|
|
||||||
// Note: we initialize all meshes at once so the last one can be used to check it.
|
|
||||||
return Meshes.HasItems() && Meshes.Last().IsInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the model LOD index.
|
|
||||||
/// </summary>
|
|
||||||
API_PROPERTY() FORCE_INLINE int32 GetLODIndex() const
|
|
||||||
{
|
|
||||||
return _lodIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the vertex count for this model LOD level.
|
|
||||||
/// </summary>
|
|
||||||
API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
|
|
||||||
{
|
|
||||||
return _verticesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ray">The ray to test</param>
|
|
||||||
/// <param name="world">World to test</param>
|
|
||||||
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
|
||||||
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
|
||||||
/// <param name="mesh">Mesh, or null</param>
|
|
||||||
/// <returns>True whether the two objects intersected</returns>
|
|
||||||
bool Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, Mesh** mesh);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ray">The ray to test</param>
|
|
||||||
/// <param name="transform">The instance transformation.</param>
|
|
||||||
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
|
||||||
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
|
||||||
/// <param name="mesh">Mesh, or null</param>
|
|
||||||
/// <returns>True whether the two objects intersected</returns>
|
|
||||||
bool Intersects(const Ray& ray, const Transform& transform, Real& distance, Vector3& normal, Mesh** mesh);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get model bounding box in transformed world matrix.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="world">World matrix</param>
|
|
||||||
/// <returns>Bounding box</returns>
|
|
||||||
BoundingBox GetBox(const Matrix& world) const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get model bounding box in transformed world.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="transform">The instance transformation.</param>
|
|
||||||
/// <param name="deformation">The meshes deformation container (optional).</param>
|
|
||||||
/// <returns>Bounding box</returns>
|
|
||||||
BoundingBox GetBox(const Transform& transform, const MeshDeformation* deformation = nullptr) const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the bounding box combined for all meshes in this model LOD.
|
|
||||||
/// </summary>
|
|
||||||
API_PROPERTY() BoundingBox GetBox() const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws the meshes. Binds vertex and index buffers and invokes the draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">The GPU context to draw with.</param>
|
|
||||||
FORCE_INLINE void Render(GPUContext* context)
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
Meshes.Get()[i].Render(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws the meshes from the model LOD.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderContext">The rendering context.</param>
|
|
||||||
/// <param name="material">The material to use for rendering.</param>
|
|
||||||
/// <param name="world">The world transformation of the model.</param>
|
|
||||||
/// <param name="flags">The object static flags.</param>
|
|
||||||
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
|
|
||||||
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
|
|
||||||
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
|
|
||||||
/// <param name="sortOrder">Object sorting key.</param>
|
|
||||||
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int8 sortOrder = 0) const
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
Meshes.Get()[i].Draw(renderContext, material, world, flags, receiveDecals, drawModes, perInstanceRandom, sortOrder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws all the meshes from the model LOD.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderContext">The rendering context.</param>
|
|
||||||
/// <param name="info">The packed drawing info data.</param>
|
|
||||||
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
|
||||||
FORCE_INLINE void Draw(const RenderContext& renderContext, const Mesh::DrawInfo& info, float lodDitherFactor) const
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
Meshes.Get()[i].Draw(renderContext, info, lodDitherFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws all the meshes from the model LOD.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderContextBatch">The rendering context batch.</param>
|
|
||||||
/// <param name="info">The packed drawing info data.</param>
|
|
||||||
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
|
||||||
FORCE_INLINE void Draw(const RenderContextBatch& renderContextBatch, const Mesh::DrawInfo& info, float lodDitherFactor) const
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
Meshes.Get()[i].Draw(renderContextBatch, info, lodDitherFactor);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "SkinnedMesh.h"
|
|
||||||
|
|
||||||
class MemoryReadStream;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents single Level Of Detail for the skinned model. Contains a collection of the meshes.
|
|
||||||
/// </summary>
|
|
||||||
API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedModelLOD : public ScriptingObject
|
|
||||||
{
|
|
||||||
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedModelLOD, ScriptingObject);
|
|
||||||
friend SkinnedModel;
|
|
||||||
private:
|
|
||||||
SkinnedModel* _model = nullptr;
|
|
||||||
int32 _lodIndex = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
/// The screen size to switch LODs. Bottom limit of the model screen size to render this LOD.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() float ScreenSize = 1.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The meshes array.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD(ReadOnly) Array<SkinnedMesh> Meshes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the model LOD index.
|
|
||||||
/// </summary>
|
|
||||||
API_PROPERTY() FORCE_INLINE int32 GetLODIndex() const
|
|
||||||
{
|
|
||||||
return _lodIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether any mesh has been initialized.
|
|
||||||
/// </summary>
|
|
||||||
bool HasAnyMeshInitialized() const
|
|
||||||
{
|
|
||||||
// Note: we initialize all meshes at once so the last one can be used to check it.
|
|
||||||
return Meshes.HasItems() && Meshes.Last().IsInitialized();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ray">The ray to test</param>
|
|
||||||
/// <param name="world">World to test</param>
|
|
||||||
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
|
||||||
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
|
||||||
/// <param name="mesh">Mesh, or null</param>
|
|
||||||
/// <returns>True whether the two objects intersected</returns>
|
|
||||||
bool Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal, SkinnedMesh** mesh);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if there is an intersection between the Model and a Ray in given world using given instance
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ray">The ray to test</param>
|
|
||||||
/// <param name="transform">Instance transformation</param>
|
|
||||||
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
|
||||||
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
|
||||||
/// <param name="mesh">Mesh, or null</param>
|
|
||||||
/// <returns>True whether the two objects intersected</returns>
|
|
||||||
bool Intersects(const Ray& ray, const Transform& transform, Real& distance, Vector3& normal, SkinnedMesh** mesh);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get model bounding box in transformed world for given instance buffer
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="world">World matrix</param>
|
|
||||||
/// <returns>Bounding box</returns>
|
|
||||||
BoundingBox GetBox(const Matrix& world) const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get model bounding box in transformed world.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="transform">The instance transformation.</param>
|
|
||||||
/// <param name="deformation">The meshes deformation container (optional).</param>
|
|
||||||
/// <returns>Bounding box</returns>
|
|
||||||
BoundingBox GetBox(const Transform& transform, const MeshDeformation* deformation = nullptr) const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get model bounding box in transformed world for given instance buffer for only one mesh
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="world">World matrix</param>
|
|
||||||
/// <param name="meshIndex">esh index</param>
|
|
||||||
/// <returns>Bounding box</returns>
|
|
||||||
BoundingBox GetBox(const Matrix& world, int32 meshIndex) const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the bounding box combined for all meshes in this model LOD.
|
|
||||||
/// </summary>
|
|
||||||
API_PROPERTY() BoundingBox GetBox() const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws the meshes. Binds vertex and index buffers and invokes the draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">The GPU context to draw with.</param>
|
|
||||||
FORCE_INLINE void Render(GPUContext* context)
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
{
|
|
||||||
Meshes.Get()[i].Render(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws all the meshes from the model LOD.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderContext">The rendering context.</param>
|
|
||||||
/// <param name="info">The packed drawing info data.</param>
|
|
||||||
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
|
||||||
FORCE_INLINE void Draw(const RenderContext& renderContext, const SkinnedMesh::DrawInfo& info, float lodDitherFactor) const
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
{
|
|
||||||
Meshes.Get()[i].Draw(renderContext, info, lodDitherFactor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws all the meshes from the model LOD.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderContextBatch">The rendering context batch.</param>
|
|
||||||
/// <param name="info">The packed drawing info data.</param>
|
|
||||||
/// <param name="lodDitherFactor">The LOD transition dither factor.</param>
|
|
||||||
FORCE_INLINE void Draw(const RenderContextBatch& renderContextBatch, const SkinnedMesh::DrawInfo& info, float lodDitherFactor) const
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < Meshes.Count(); i++)
|
|
||||||
{
|
|
||||||
Meshes.Get()[i].Draw(renderContextBatch, info, lodDitherFactor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user