Merge branch 'ubo' into vulkan

This commit is contained in:
Lynix 2018-06-12 19:07:58 +02:00
commit d7a2e9aad1
64 changed files with 1041 additions and 430 deletions

View File

@ -16,10 +16,11 @@ Miscellaneous:
- Add Lua unit tests
- NDEBUG is now defined in Release
- Replaced typedefs keywords with modern using keywords
- When supported, projects are now parts of a virtual "workspace group" according to their kind
Nazara Engine:
- VertexMapper:GetComponentPtr no longer throw an error if component is disabled or incompatible with template type, instead a null pointer is returned.
- Bitset swap operation is now correctly marked as noexcept`
- Bitset swap operation is now correctly marked as noexcept
- Mesh loaders now takes MeshParams vertexDeclaration into account
- ⚠️ Replaced RenderTarget::Get[Height|Width] by RenderTarget::GetSize
- ⚠️ Removed Window::Get[Height|Width] methods
@ -94,6 +95,22 @@ Nazara Engine:
- ⚠️ Stream::ReadLine will now returns empty lines if present in the file
- Fixed cubemaps seams with OpenGL
- HandledObject movement constructor/assignement operator are now marked noexcept
- ⚠️ PhysWorld2D callbacks OnPhysWorld2DPreStep and OnPhysWorld2DPostStep now takes a invStepCount depending on the number of step taken this update, fixing force application and other
- ⚠️ Refactored Mesh/SubMesh, allowing a submesh to be attached to multiple meshes, deprecating Create/Destroy methods
- SubMesh class now has a OnSubMeshInvalidateAABB signal, triggered when a new AABB is set to the submesh
- Mesh class now has a OnMeshInvalidateAABB signal, triggered when a mesh invalidates its AABB, which is also submesh updates its AABB
- Model now invalidate properly their bounding volume when their mesh AABB is updated
- Added operator&/|/^ taking an enumeration value and a Flags object using the same enumeration type.
- Added LuaState::CallWithHandler methods, allowing to setup a error handler function
- Added LuaState::Traceback method
- Added ModelLibrary, ModelManager and ModelSaver
- Added AbstractViewer::Project and AbstractViewer::Unproject methods
- Added AbstractViewer::ProjectDepth method
- Fixed SocketPoller not be able to recover from some errors (like invalid sockets and such)
- ⚠️ Replaced currentBitPos and currentByte fields by [read|write][BitPos][Byte] to handle properly bit reading/writing.
- InstancedRenderable::SetMaterial methods are now public.
- Fixed Model copy constructor not copying materials
- ⚠️ Added InstancedRenderable::Clone() method
Nazara Development Kit:
- Added ImageWidget (#139)
@ -142,6 +159,7 @@ Nazara Development Kit:
- ⚠️ TextAreaWidget::GetHoveredGlyph now returns a two-dimensional position instead of a single glyph position
- Fixed Entity::OnEntityDestruction signal not being properly moved and thus not being called.
- Fixed EntityOwner move assignment which was losing entity ownership
- Add GraphicsComponent:ForEachRenderable method
# 0.4:
@ -187,7 +205,8 @@ Nazara Engine:
- Added VertexMapper::GetVertexCount()
- Added VertexMapper::HasComponentOfType()
- Fixed SimpleTextDrawer bounds computation
- Added LuaState::Load methods which allows to load (compile) lua code to function without executing it.
- Added ENetPeer::GetLastReceiveTime() which gives the last time a reliable packet was received.
Nazara Development Kit:
- ⚠️ Components no longer need to be copyable by assignation

View File

@ -44,6 +44,8 @@ namespace Ndk
inline bool DoesRequireRealTimeReflections() const;
template<typename Func> void ForEachRenderable(const Func& func) const;
inline void EnsureBoundingVolumeUpdate() const;
inline void EnsureTransformMatrixUpdate() const;

View File

@ -107,6 +107,18 @@ namespace Ndk
return m_reflectiveMaterialCount != 0 && m_reflectionMap;
}
/*!
* \brief Calls a function for every renderable attached to this component
*
* \param func Callback function which will be called with renderable data
*/
template<typename Func>
void GraphicsComponent::ForEachRenderable(const Func& func) const
{
for (const auto& renderableData : m_renderables)
func(renderableData.renderable, renderableData.data.localMatrix, renderableData.data.renderOrder);
}
/*!
* \brief Ensures the bounding volume is up to date
*/

View File

@ -62,12 +62,19 @@ namespace Ndk
const DebugComponent& entityDebug = m_entityOwner->GetComponent<DebugComponent>();
const GraphicsComponent& entityGfx = m_entityOwner->GetComponent<GraphicsComponent>();
Nz::Boxf aabb = entityGfx.GetBoundingVolume().aabb;
Nz::Matrix4f transformMatrix = Nz::Matrix4f::Identity();
transformMatrix.SetScale(entityGfx.GetBoundingVolume().aabb.GetLengths());
transformMatrix.SetTranslation(entityGfx.GetBoundingVolume().aabb.GetCenter());
transformMatrix.SetScale(aabb.GetLengths());
transformMatrix.SetTranslation(aabb.GetCenter());
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
}
std::unique_ptr<InstancedRenderable> Clone() const override
{
return nullptr;
}
};
class OBBDebugRenderable : public DebugRenderable
@ -82,11 +89,21 @@ namespace Ndk
const DebugComponent& entityDebug = m_entityOwner->GetComponent<DebugComponent>();
const GraphicsComponent& entityGfx = m_entityOwner->GetComponent<GraphicsComponent>();
Nz::Boxf obb = entityGfx.GetBoundingVolume().obb.localBox;
Nz::Matrix4f transformMatrix = instanceData.transformMatrix;
transformMatrix.ApplyScale(entityGfx.GetBoundingVolume().obb.localBox.GetLengths());
Nz::Vector3f obbCenter = transformMatrix.Transform(obb.GetCenter(), 0.f); //< Apply rotation/scale to obb center, to display it at a correct position
transformMatrix.ApplyScale(obb.GetLengths());
transformMatrix.ApplyTranslation(obbCenter);
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
}
std::unique_ptr<InstancedRenderable> Clone() const override
{
return nullptr;
}
};
}
@ -300,9 +317,7 @@ namespace Ndk
Nz::MeshRef mesh = Nz::Mesh::New();
mesh->CreateStatic();
Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(mesh);
subMesh->Create(vertexBuffer);
subMesh->SetIndexBuffer(indexBuffer);
Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer);
subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList);
subMesh->SetMaterialIndex(0);
subMesh->GenerateAABB();

View File

@ -71,10 +71,19 @@ function NazaraBuild:Execute()
configurations(configs)
end
if (self.Config["PremakeProject"] and os.ishost("windows")) then
group("_Premake")
local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ')
project("Regenerate premake")
kind("Utility")
prebuildcommands("cd .. && " .. commandLine)
end
-- Extern libraries
if (self.Config["BuildDependencies"]) then
self:FilterLibDirectory("../thirdparty/genlib/", targetdir) -- For generated libraries
group("Thirdparties")
for k, libTable in ipairs(self.OrderedExtLibs) do
project(libTable.Name)
@ -94,6 +103,8 @@ function NazaraBuild:Execute()
links(libTable.Libraries)
libdirs("../thirdparty/lib/common")
self:FilterLibDirectory("../thirdparty/genlib/", targetdir) -- For generated libraries
filter(clangGccActions)
buildoptions("-U__STRICT_ANSI__")
@ -112,14 +123,9 @@ function NazaraBuild:Execute()
end
end
if (self.Config["PremakeProject"] and os.ishost("windows")) then
local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ')
project("_PremakeProject")
kind("Utility")
prebuildcommands("cd .. && " .. commandLine)
end
-- Modules
group("Engine Modules")
if (_OPTIONS["united"]) then
project("NazaraEngine")
@ -175,6 +181,8 @@ function NazaraBuild:Execute()
end
-- Tools
group("Engine SDK - Tools")
for k, toolTable in ipairs(self.OrderedTools) do
local prefix = "Nazara"
if (toolTable.Kind == "plugin") then
@ -243,6 +251,8 @@ function NazaraBuild:Execute()
filter({})
end
group("Examples")
for k, exampleTable in ipairs(self.OrderedExamples) do
local destPath = "../examples/bin"

View File

@ -219,17 +219,17 @@ namespace Nz
*/
inline bool Serialize(SerializationContext& context, bool value, TypeTag<bool>)
{
if (context.currentBitPos == 8)
if (context.writeBitPos == 8)
{
context.currentBitPos = 0;
context.currentByte = 0;
context.writeBitPos = 0;
context.writeByte = 0;
}
if (value)
context.currentByte |= 1 << context.currentBitPos;
context.writeByte |= 1 << context.writeBitPos;
if (++context.currentBitPos >= 8)
return Serialize(context, context.currentByte, TypeTag<UInt8>());
if (++context.writeBitPos >= 8)
return Serialize(context, context.writeByte, TypeTag<UInt8>());
else
return true;
}
@ -291,18 +291,18 @@ namespace Nz
*/
inline bool Unserialize(SerializationContext& context, bool* value, TypeTag<bool>)
{
if (context.currentBitPos == 8)
if (context.readBitPos == 8)
{
if (!Unserialize(context, &context.currentByte, TypeTag<UInt8>()))
if (!Unserialize(context, &context.readByte, TypeTag<UInt8>()))
return false;
context.currentBitPos = 0;
context.readBitPos = 0;
}
if (value)
*value = (context.currentByte & (1 << context.currentBitPos)) != 0;
*value = (context.readByte & (1 << context.readBitPos)) != 0;
context.currentBitPos++;
context.readBitPos++;
return true;
}
@ -341,7 +341,7 @@ namespace Nz
{
NazaraAssert(value, "Invalid data pointer");
context.ResetBitPosition();
context.ResetReadBitPosition();
if (context.stream->Read(value, sizeof(T)) == sizeof(T))
{

View File

@ -86,11 +86,11 @@ namespace Nz
if (!m_context.stream)
return true;
if (m_context.currentBitPos != 8)
if (m_context.writeBitPos != 8)
{
m_context.currentBitPos = 8; //< To prevent Serialize to flush bits itself
m_context.writeBitPos = 8; //< To prevent Serialize to flush bits itself
if (!Serialize(m_context, m_context.currentByte))
if (!Serialize(m_context, m_context.writeByte))
return false;
}

View File

@ -73,12 +73,16 @@ namespace Nz
BitField m_value;
};
template<typename E> constexpr Flags<E> operator&(E lhs, Flags<E> rhs);
template<typename E> constexpr Flags<E> operator|(E lhs, Flags<E> rhs);
template<typename E> constexpr Flags<E> operator^(E lhs, Flags<E> rhs);
// Little hack to have them in both Nz and global scope
namespace FlagsOperators
{
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator~(E lhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator|(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator&(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator|(E lhs, E rhs);
template<typename E> constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator^(E lhs, E rhs);
}

View File

@ -221,6 +221,51 @@ namespace Nz
return 1U << static_cast<BitField>(enumValue);
}
/*!
* \brief Compare flag states
* \return Compared flags
*
* This will returns a copy of the Flags object compared with the enum state.
*
* \param lhs Enum to compare with flags.
* \param rhs Flags object.
*/
template<typename E>
constexpr Flags<E> operator&(E lhs, Flags<E> rhs)
{
return rhs & lhs;
}
/*!
* \brief Combine flag states
* \return Combined flags
*
* This will returns a copy of the Flags object combined with the enum state.
*
* \param lhs Enum to combine with flags.
* \param rhs Flags object.
*/
template<typename E>
constexpr Flags<E> operator|(E lhs, Flags<E> rhs)
{
return rhs | lhs;
}
/*!
* \brief XOR flag states
* \return XORed flags
*
* This will returns a copy of the Flags object XORed with the enum state.
*
* \param lhs Enum to XOR with flags.
* \param rhs Flags object.
*/
template<typename E>
constexpr Flags<E> operator^(E lhs, Flags<E> rhs)
{
return rhs ^ lhs;
}
namespace FlagsOperators
{
@ -238,21 +283,6 @@ namespace Nz
return ~Flags<E>(lhs);
}
/*!
* \brief Override binary OR operator on enum to turns into a Flags object.
* \return A Flags object with combined enum states.
*
* \param lhs First enumeration value to combine.
* \param rhs Second enumeration value to combine.
*
* Returns a Flags object with combined states from the two enumeration values.
*/
template<typename E>
constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator|(E lhs, E rhs)
{
return Flags<E>(lhs) | rhs;
}
/*!
* \brief Override binary AND operator on enum to turns into a Flags object.
* \return A Flags object with compare enum states.
@ -269,6 +299,21 @@ namespace Nz
return Flags<E>(lhs) & rhs;
}
/*!
* \brief Override binary OR operator on enum to turns into a Flags object.
* \return A Flags object with combined enum states.
*
* \param lhs First enumeration value to combine.
* \param rhs Second enumeration value to combine.
*
* Returns a Flags object with combined states from the two enumeration values.
*/
template<typename E>
constexpr std::enable_if_t<IsEnumFlag<E>::value, Flags<E>> operator|(E lhs, E rhs)
{
return Flags<E>(lhs) | rhs;
}
/*!
* \brief Override binary XOR operator on enum to turns into a Flags object.
* \return A Flags object with XORed enum states.

View File

@ -20,11 +20,14 @@ namespace Nz
{
Stream* stream;
Endianness endianness = Endianness_BigEndian; //< Default to Big Endian encoding
UInt8 currentBitPos = 8; //< 8 means no bit is currently wrote
UInt8 currentByte; //< Undefined value, will be initialized at the first bit write
UInt8 readBitPos = 8; //< 8 means no bit is currently read
UInt8 readByte; //< Undefined value, will be initialized at the first bit read
UInt8 writeBitPos = 8; //< 8 means no bit is currently wrote
UInt8 writeByte; //< Undefined value, will be initialized at the first bit write
void FlushBits();
inline void ResetBitPosition();
inline void ResetReadBitPosition();
inline void ResetWriteBitPosition();
};
}

View File

@ -7,16 +7,24 @@
namespace Nz
{
/*!
* \brief Reset the current bit cursor
* \brief Reset the current read bit cursor
*/
inline void SerializationContext::ResetReadBitPosition()
{
readBitPos = 8;
}
/*!
* \brief Reset the current read bit cursor
* \remark This function only reset the cursor position, it doesn't do any writing
if you wish to write all bits and reset bit position, call FlushBits
if you wish to write all bits and reset bit position, call FlushBits
\see FlushBits
\see FlushBits
*/
inline void SerializationContext::ResetBitPosition()
inline void SerializationContext::ResetWriteBitPosition()
{
currentBitPos = 8;
writeBitPos = 8;
}
}

View File

@ -40,6 +40,11 @@ namespace Nz
virtual float GetZFar() const = 0;
virtual float GetZNear() const = 0;
Nz::Vector3f Project(const Nz::Vector3f& worldPosition) const;
float ProjectDepth(float depth);
Nz::Vector3f Unproject(const Nz::Vector3f& screenPos) const;
AbstractViewer& operator=(const AbstractViewer&) = default;
AbstractViewer& operator=(AbstractViewer&&) noexcept = default;
};

View File

@ -31,6 +31,8 @@ namespace Nz
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
std::unique_ptr<InstancedRenderable> Clone() const override;
inline const Color& GetColor() const;
inline float GetRotation() const;
inline const Vector2f& GetSize() const;

View File

@ -39,6 +39,8 @@ namespace Nz
virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const = 0;
virtual std::unique_ptr<InstancedRenderable> Clone() const = 0;
virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const;
inline void EnsureBoundingVolumeUpdated() const;
@ -53,6 +55,8 @@ namespace Nz
virtual void InvalidateData(InstanceData* instanceData, UInt32 flags) const;
inline void SetMaterial(std::size_t matIndex, MaterialRef material);
inline void SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material);
inline void SetSkin(std::size_t skinIndex);
inline void SetSkinCount(std::size_t skinCount);
@ -108,9 +112,6 @@ namespace Nz
inline void ResetMaterials(std::size_t matCount, std::size_t skinCount = 1);
inline void SetMaterial(std::size_t matIndex, MaterialRef material);
inline void SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material);
mutable BoundingVolumef m_boundingVolume;
private:

View File

@ -110,6 +110,51 @@ namespace Nz
return m_skinCount;
}
/*!
* \brief Changes the material used at the specified index by another one
*
* This function changes the active material at the specified index, depending on the current active skin, to the one passed as parameter.
*
* \param matIndex Material index
* \param material New material, cannot be null
*
* \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault)
*
* \see SetMaterial
*/
inline void InstancedRenderable::SetMaterial(std::size_t matIndex, MaterialRef material)
{
SetMaterial(m_skin, matIndex, std::move(material));
}
/*!
* \brief Changes the material used at the specified index by another one, independently from the active skin.
*
* This function changes the active material at the specified index and for the specified skin index, to the one passed as parameter.
*
* \param skinIndex Skin index
* \param matIndex Material index
* \param material New material, cannot be null
*
* \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault)
*
* \see SetMaterial
*/
inline void InstancedRenderable::SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material)
{
NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds");
NazaraAssert(matIndex < m_materials.size(), "Material index out of bounds");
NazaraAssert(material.IsValid(), "Material must be valid");
MaterialRef& matEntry = m_materials[m_matCount * skinIndex + matIndex];
if (matEntry != material)
{
OnInstancedRenderableInvalidateMaterial(this, skinIndex, matIndex, material);
matEntry = std::move(material);
}
}
/*!
* \brief Changes the active skin
*
@ -201,51 +246,6 @@ namespace Nz
m_skin = 0;
}
/*!
* \brief Changes the material used at the specified index by another one
*
* This function changes the active material at the specified index, depending on the current active skin, to the one passed as parameter.
*
* \param matIndex Material index
* \param material New material, cannot be null
*
* \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault)
*
* \see SetMaterial
*/
inline void InstancedRenderable::SetMaterial(std::size_t matIndex, MaterialRef material)
{
SetMaterial(m_skin, matIndex, std::move(material));
}
/*!
* \brief Changes the material used at the specified index by another one, independently from the active skin.
*
* This function changes the active material at the specified index and for the specified skin index, to the one passed as parameter.
*
* \param skinIndex Skin index
* \param matIndex Material index
* \param material New material, cannot be null
*
* \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault)
*
* \see SetMaterial
*/
inline void InstancedRenderable::SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material)
{
NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds");
NazaraAssert(matIndex < m_materials.size(), "Material index out of bounds");
NazaraAssert(material.IsValid(), "Material must be valid");
MaterialRef& matEntry = m_materials[m_matCount * skinIndex + matIndex];
if (matEntry != material)
{
OnInstancedRenderableInvalidateMaterial(this, skinIndex, matIndex, material);
matEntry = std::move(material);
}
}
/*!
* \brief Sets the current instanced renderable with the content of the other one
* \return A reference to this

View File

@ -8,9 +8,11 @@
#define NAZARA_MODEL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/ResourceSaver.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Material.hpp>
@ -32,22 +34,30 @@ namespace Nz
class Model;
using ModelConstRef = ObjectRef<const Model>;
using ModelLibrary = ObjectLibrary<Model>;
using ModelLoader = ResourceLoader<Model, ModelParameters>;
using ModelManager = ResourceManager<Model, ModelParameters>;
using ModelRef = ObjectRef<Model>;
using ModelSaver = ResourceSaver<Model, ModelParameters>;
class NAZARA_GRAPHICS_API Model : public InstancedRenderable, public Resource
{
friend ModelLibrary;
friend ModelLoader;
friend ModelManager;
friend ModelSaver;
public:
inline Model();
Model(const Model& model) = default;
Model(Model&& model) = default;
Model(const Model& model);
Model(Model&& model) = delete;
virtual ~Model();
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder = 0, const Recti& scissorRect = Recti(-1, -1, -1, -1)) const;
std::unique_ptr<InstancedRenderable> Clone() const override;
using InstancedRenderable::GetMaterial;
const MaterialRef& GetMaterial(const String& subMeshName) const;
const MaterialRef& GetMaterial(std::size_t skinIndex, const String& subMeshName) const;
@ -66,7 +76,7 @@ namespace Nz
virtual void SetMesh(Mesh* mesh);
Model& operator=(const Model& node) = default;
Model& operator=(Model&& node) = default;
Model& operator=(Model&& node) = delete;
template<typename... Args> static ModelRef New(Args&&... args);
@ -75,7 +85,13 @@ namespace Nz
MeshRef m_mesh;
NazaraSlot(Mesh, OnMeshInvalidateAABB, m_meshAABBInvalidationSlot);
static ModelLibrary::LibraryMap s_library;
static ModelLoader::LoaderList s_loaders;
static ModelManager::ManagerMap s_managerMap;
static ModelManager::ManagerParams s_managerParameters;
static ModelSaver::SaverList s_savers;
};
}

View File

@ -2,6 +2,7 @@
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Model.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
@ -10,11 +11,22 @@ namespace Nz
/*!
* \brief Constructs a Model object by default
*/
Model::Model()
inline Model::Model()
{
ResetMaterials(0);
}
/*!
* \brief Constructs a Model object by copying another
*
* \param model Model to copy
*/
inline Model::Model(const Model& model) :
InstancedRenderable(model)
{
SetMesh(model.m_mesh);
}
/*!
* \brief Adds this model to a render queue, using user-specified transform matrix and render order
*
@ -25,8 +37,8 @@ namespace Nz
* \param renderOrder Specify the render queue layer to be used
* \param scissorRect The Scissor rect to uses for rendering
*/
void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder, const Recti& scissorRect) const
{
inline void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder, const Recti& scissorRect) const
{
InstanceData instanceData(Nz::Matrix4f::Identity());
instanceData.renderOrder = renderOrder;
instanceData.transformMatrix = transformMatrix;

View File

@ -41,7 +41,7 @@ namespace Nz
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
void AdvanceAnimation(float elapsedTime);
SkeletalModel* Clone() const;
std::unique_ptr<InstancedRenderable> Clone() const override;
SkeletalModel* Create() const;
void EnableAnimation(bool animation);

View File

@ -35,6 +35,8 @@ namespace Nz
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
std::unique_ptr<InstancedRenderable> Clone() const override;
inline const Color& GetColor() const;
inline const Color& GetCornerColor(RectCorner corner) const;
inline const Vector3f& GetOrigin() const;

View File

@ -34,11 +34,14 @@ namespace Nz
inline void Clear();
std::unique_ptr<InstancedRenderable> Clone() const override;
inline const Color& GetColor() const;
inline float GetScale() const;
inline void SetColor(const Color& color);
inline void SetDefaultMaterial();
using InstancedRenderable::SetMaterial;
inline void SetMaterial(MaterialRef material);
inline void SetMaterial(std::size_t skinIndex, MaterialRef material);
inline void SetScale(float scale);

View File

@ -14,6 +14,7 @@ namespace Nz
inline TextSprite::TextSprite() :
m_color(Color::White),
m_localBounds(Nz::Recti::Zero()),
m_scale(1.f)
{
ResetMaterials(1U);

View File

@ -35,6 +35,8 @@ namespace Nz
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
std::unique_ptr<InstancedRenderable> Clone() const override;
inline void DisableTile(const Vector2ui& tilePos);
inline void DisableTiles();
inline void DisableTiles(const Vector2ui* tilesPos, std::size_t tileCount);

View File

@ -31,7 +31,7 @@ namespace Nz
private:
LuaCoroutine(lua_State* internalState, int refIndex);
bool Run(int argCount, int resultCount) override;
bool Run(int argCount, int resultCount, int errHandler) override;
int m_ref;
};

View File

@ -43,6 +43,8 @@ namespace Nz
bool Call(unsigned int argCount);
bool Call(unsigned int argCount, unsigned int resultCount);
bool CallWithHandler(unsigned int argCount, int errorHandler);
bool CallWithHandler(unsigned int argCount, unsigned int resultCount, int errorHandler);
template<typename T> T Check(int* index) const;
template<typename T> T Check(int* index, T defValue) const;
@ -84,10 +86,10 @@ namespace Nz
void Error(const char* message) const;
void Error(const String& message) const;
bool Execute(const String& code);
bool ExecuteFromFile(const String& filePath);
bool ExecuteFromMemory(const void* data, std::size_t size);
bool ExecuteFromStream(Stream& stream);
bool Execute(const String& code, int errorHandler = 0);
bool ExecuteFromFile(const String& filePath, int errorHandler = 0);
bool ExecuteFromMemory(const void* data, std::size_t size, int errorHandler = 0);
bool ExecuteFromStream(Stream& stream, int errorHandler = 0);
int GetAbsIndex(int index) const;
LuaType GetField(const char* fieldName, int tableIndex = -1) const;
@ -112,6 +114,11 @@ namespace Nz
bool IsOfType(int index, const String& tname) const;
bool IsValid(int index) const;
bool Load(const String& code);
bool LoadFromFile(const String& filePath);
bool LoadFromMemory(const void* data, std::size_t size);
bool LoadFromStream(Stream& stream);
long long Length(int index) const;
std::size_t LengthRaw(int index) const;
@ -134,7 +141,6 @@ namespace Nz
template<typename R, typename... Args, typename... DefArgs> void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const;
template<typename T> void PushGlobal(const char* name, T&& arg);
template<typename T> void PushGlobal(const String& name, T&& arg);
template<typename T> void PushInstance(const char* tname, const T& instance) const;
template<typename T> void PushInstance(const char* tname, T&& instance) const;
template<typename T, typename... Args> void PushInstance(const char* tname, Args&&... args) const;
void PushInteger(long long value) const;
@ -173,6 +179,8 @@ namespace Nz
void* ToUserdata(int index, const char* tname) const;
void* ToUserdata(int index, const String& tname) const;
void Traceback(const char* message = nullptr, int level = 0);
LuaState& operator=(const LuaState&) = default;
LuaState& operator=(LuaState&& instance) = default;
@ -185,7 +193,7 @@ namespace Nz
template<typename T> std::enable_if_t<std::is_signed<T>::value, T> CheckBounds(int index, long long value) const;
template<typename T> std::enable_if_t<std::is_unsigned<T>::value, T> CheckBounds(int index, long long value) const;
virtual bool Run(int argCount, int resultCount);
virtual bool Run(int argCount, int resultCount, int errHandler);
static int ProxyFunc(lua_State* internalState);

View File

@ -706,7 +706,7 @@ namespace Nz
template<typename T>
void LuaState::PushField(const char* name, T&& arg, int tableIndex) const
{
Push<T>(std::forward<T>(arg));
Push(std::forward<T>(arg));
SetField(name, tableIndex);
}
@ -732,7 +732,7 @@ namespace Nz
template<typename T>
void LuaState::PushGlobal(const char* name, T&& arg)
{
Push<T>(std::forward<T>(arg));
Push(std::forward<T>(arg));
SetGlobal(name);
}
@ -742,15 +742,6 @@ namespace Nz
PushGlobal(name.GetConstBuffer(), std::forward<T>(arg));
}
template<typename T>
void LuaState::PushInstance(const char* tname, const T& instance) const
{
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
PlacementNew(userdata, instance);
SetMetatable(tname);
}
template<typename T>
void LuaState::PushInstance(const char* tname, T&& instance) const
{

View File

@ -47,6 +47,7 @@ namespace Nz
void DisconnectNow(UInt32 data);
inline const IpAddress& GetAddress() const;
inline UInt32 GetLastReceiveTime() const;
inline UInt32 GetMtu() const;
inline UInt32 GetPacketThrottleAcceleration() const;
inline UInt32 GetPacketThrottleDeceleration() const;

View File

@ -22,6 +22,11 @@ namespace Nz
return m_address;
}
inline UInt32 ENetPeer::GetLastReceiveTime() const
{
return m_lastReceiveTime;
}
inline UInt32 ENetPeer::GetMtu() const
{
return m_mtu;

View File

@ -123,8 +123,8 @@ namespace Nz
float fraction;
};
NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/);
NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/);
NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/);
NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/);
private:
void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks);

View File

@ -36,7 +36,7 @@ namespace Nz
static void DrawCone(const Vector3f& origin, const Quaternionf& rotation, float angle, float length);
static void DrawLine(const Vector3f& p1, const Vector3f& p2);
static void DrawPoints(const Vector3f* ptr, unsigned int pointCount);
static void DrawNormals(const StaticMesh* subMesh);
static void DrawNormals(const StaticMesh* subMesh, float normalLength = 0.01f);
static void DrawTangents(const StaticMesh* subMesh);
static void EnableDepthBuffer(bool depthBuffer);

View File

@ -15,8 +15,23 @@
namespace Nz
{
<<<<<<< HEAD
class AbstractBuffer;
class Buffer;
=======
class Color;
class Context;
class GpuQuery;
class IndexBuffer;
class RenderTarget;
struct RenderStates;
class Shader;
class Texture;
class TextureSampler;
class UniformBuffer;
class VertexBuffer;
class VertexDeclaration;
>>>>>>> ubo
class NAZARA_RENDERER_API Renderer
{
@ -24,7 +39,46 @@ namespace Nz
Renderer() = delete;
~Renderer() = delete;
<<<<<<< HEAD
static inline RendererImpl* GetRendererImpl();
=======
static void BeginCondition(const GpuQuery& query, GpuQueryCondition condition);
static void BindUniformBuffer(unsigned int bindingPoint, const UniformBuffer* uniformBuffer);
static void Clear(UInt32 flags = RendererBuffer_Color | RendererBuffer_Depth);
static void DrawFullscreenQuad();
static void DrawIndexedPrimitives(PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount);
static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount);
static void DrawPrimitives(PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount);
static void DrawPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount);
static void Enable(RendererParameter parameter, bool enable);
static void EndCondition();
static void Flush();
static RendererComparison GetDepthFunc();
static VertexBuffer* GetInstanceBuffer();
static float GetLineWidth();
static Matrix4f GetMatrix(MatrixType type);
static UInt8 GetMaxAnisotropyLevel();
static unsigned int GetMaxColorAttachments();
static unsigned int GetMaxRenderTargets();
static unsigned int GetMaxTextureSize();
static unsigned int GetMaxTextureUnits();
static unsigned int GetMaxVertexAttribs();
static float GetPointSize();
static const RenderStates& GetRenderStates();
static Recti GetScissorRect();
static const Shader* GetShader();
static const RenderTarget* GetTarget();
static Recti GetViewport();
static bool HasCapability(RendererCap capability);
>>>>>>> ubo
static bool Initialize();

View File

@ -49,8 +49,9 @@ namespace Nz
{
BufferType_Index,
BufferType_Vertex,
BufferType_Uniform,
BufferType_Max = BufferType_Vertex
BufferType_Max = BufferType_Uniform
};
enum BufferUsage

View File

@ -38,7 +38,6 @@ namespace Nz
inline const BufferRef& GetBuffer() const;
inline UInt32 GetEndOffset() const;
inline UInt32 GetIndexCount() const;
inline DataStorage GetStorage() const;
inline UInt32 GetStride() const;
inline UInt32 GetStartOffset() const;

View File

@ -22,11 +22,6 @@ namespace Nz
return m_indexCount;
}
inline DataStorage IndexBuffer::GetStorage() const
{
return DataStorage();
}
inline UInt32 IndexBuffer::GetStride() const
{
return static_cast<UInt32>((m_largeIndices) ? sizeof(UInt32) : sizeof(UInt16));

View File

@ -20,8 +20,12 @@
#include <Nazara/Math/Box.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <Nazara/Utility/Skeleton.hpp>
#include <Nazara/Utility/SubMesh.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Utility/VertexStruct.hpp>
#include <unordered_map>
#include <vector>
namespace Nz
{
@ -56,7 +60,6 @@ namespace Nz
class Mesh;
struct Primitive;
class PrimitiveList;
class Skeleton;
class SubMesh;
using MeshVertex = VertexStruct_XYZ_Normal_UV_Tangent;
@ -80,8 +83,10 @@ namespace Nz
friend class Utility;
public:
Mesh() = default;
~Mesh();
inline Mesh();
Mesh(const Mesh&) = delete;
Mesh(Mesh&&) = delete;
inline ~Mesh();
void AddSubMesh(SubMesh* subMesh);
void AddSubMesh(const String& identifier, SubMesh* subMesh);
@ -141,14 +146,34 @@ namespace Nz
void Transform(const Matrix4f& matrix);
Mesh& operator=(const Mesh&) = delete;
Mesh& operator=(Mesh&&) = delete;
template<typename... Args> static MeshRef New(Args&&... args);
// Signals:
NazaraSignal(OnMeshDestroy, const Mesh* /*mesh*/);
NazaraSignal(OnMeshInvalidateAABB, const Mesh* /*mesh*/);
NazaraSignal(OnMeshRelease, const Mesh* /*mesh*/);
private:
MeshImpl* m_impl = nullptr;
struct SubMeshData
{
SubMeshRef subMesh;
NazaraSlot(SubMesh, OnSubMeshInvalidateAABB, onSubMeshInvalidated);
};
std::unordered_map<String, UInt32> m_subMeshMap;
std::vector<ParameterList> m_materialData;
std::vector<SubMeshData> m_subMeshes;
AnimationType m_animationType;
mutable Boxf m_aabb;
Skeleton m_skeleton; // Only used by skeletal meshes
String m_animationPath;
mutable bool m_aabbUpdated;
bool m_isValid;
UInt32 m_jointCount; // Only used by skeletal meshes
static bool Initialize();
static void Uninitialize();

View File

@ -2,11 +2,25 @@
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/Mesh.hpp>
#include <memory>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
Mesh::Mesh() :
m_materialData(1),
m_aabbUpdated(false)
{
}
Mesh::~Mesh()
{
OnMeshRelease(this);
Destroy();
}
template<typename... Args>
MeshRef Mesh::New(Args&&... args)
{

View File

@ -24,9 +24,14 @@ namespace Nz
class NAZARA_UTILITY_API SkeletalMesh final : public SubMesh
{
public:
SkeletalMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer);
NAZARA_DEPRECATED("SkeletalMesh constructor taking a mesh is deprecated, submeshes no longer require to be part of a single mesh")
SkeletalMesh(const Mesh* parent);
~SkeletalMesh();
NAZARA_DEPRECATED("SkeletalMesh create/destroy functions are deprecated, please use constructor")
bool Create(VertexBuffer* vertexBuffer);
void Destroy();
@ -51,8 +56,8 @@ namespace Nz
private:
Boxf m_aabb;
IndexBufferConstRef m_indexBuffer = nullptr;
VertexBufferRef m_vertexBuffer = nullptr;
IndexBufferConstRef m_indexBuffer;
VertexBufferRef m_vertexBuffer;
};
}

View File

@ -21,11 +21,16 @@ namespace Nz
class NAZARA_UTILITY_API StaticMesh final : public SubMesh
{
public:
StaticMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer);
NAZARA_DEPRECATED("StaticMesh constructor taking a mesh is deprecated, submeshes no longer require to be part of a single mesh")
StaticMesh(const Mesh* parent);
~StaticMesh();
void Center();
NAZARA_DEPRECATED("StaticMesh create/destroy functions are deprecated, please use constructor")
bool Create(VertexBuffer* vertexBuffer);
void Destroy();
@ -52,8 +57,8 @@ namespace Nz
private:
Boxf m_aabb;
IndexBufferConstRef m_indexBuffer = nullptr;
VertexBufferRef m_vertexBuffer = nullptr;
IndexBufferConstRef m_indexBuffer;
VertexBufferRef m_vertexBuffer;
};
}

View File

@ -28,7 +28,13 @@ namespace Nz
friend Mesh;
public:
SubMesh();
NAZARA_DEPRECATED("Submesh constructor taking a mesh is deprecated, submeshes no longer require to be part of a single mesh")
SubMesh(const Mesh* parent);
SubMesh(const SubMesh&) = delete;
SubMesh(SubMesh&&) = delete;
virtual ~SubMesh();
void GenerateNormals();
@ -39,7 +45,6 @@ namespace Nz
virtual AnimationType GetAnimationType() const = 0;
virtual const IndexBuffer* GetIndexBuffer() const = 0;
UInt32 GetMaterialIndex() const;
const Mesh* GetParent() const;
PrimitiveMode GetPrimitiveMode() const;
UInt32 GetTriangleCount() const;
virtual UInt32 GetVertexCount() const = 0;
@ -49,12 +54,15 @@ namespace Nz
void SetMaterialIndex(UInt32 matIndex);
void SetPrimitiveMode(PrimitiveMode mode);
SubMesh& operator=(const SubMesh&) = delete;
SubMesh& operator=(SubMesh&&) = delete;
// Signals:
NazaraSignal(OnSubMeshInvalidateAABB, const SubMesh* /*subMesh*/);
NazaraSignal(OnSubMeshRelease, const SubMesh* /*subMesh*/);
protected:
PrimitiveMode m_primitiveMode;
const Mesh* m_parent;
UInt32 m_matIndex;
};
}

View File

@ -0,0 +1,69 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UNIFORMBUFFER_HPP
#define NAZARA_UNIFORMBUFFER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Utility/Buffer.hpp>
namespace Nz
{
class UniformBuffer;
using UniformBufferConstRef = ObjectRef<const UniformBuffer>;
using UniformBufferRef = ObjectRef<UniformBuffer>;
class NAZARA_UTILITY_API UniformBuffer : public RefCounted
{
public:
UniformBuffer() = default;
UniformBuffer(BufferRef buffer);
UniformBuffer(BufferRef buffer, UInt32 offset, UInt32 size);
UniformBuffer(UInt32 length, DataStorage storage, BufferUsageFlags usage);
UniformBuffer(const UniformBuffer& uniformBuffer);
UniformBuffer(UniformBuffer&&) = delete;
~UniformBuffer();
bool Fill(const void* data, UInt32 offset, UInt32 size);
inline const BufferRef& GetBuffer() const;
inline UInt32 GetEndOffset() const;
inline UInt32 GetStartOffset() const;
inline bool IsValid() const;
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0);
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) const;
void Reset();
void Reset(BufferRef buffer);
void Reset(BufferRef buffer, UInt32 offset, UInt32 size);
void Reset(UInt32 size, DataStorage storage, BufferUsageFlags usage);
void Reset(const UniformBuffer& uniformBuffer);
void Unmap() const;
UniformBuffer& operator=(const UniformBuffer& uniformBuffer);
UniformBuffer& operator=(UniformBuffer&&) = delete;
template<typename... Args> static UniformBufferRef New(Args&&... args);
// Signals:
NazaraSignal(OnUniformBufferRelease, const UniformBuffer* /*UniformBuffer*/);
private:
BufferRef m_buffer;
UInt32 m_endOffset;
UInt32 m_startOffset;
};
}
#include <Nazara/Utility/UniformBuffer.inl>
#endif // NAZARA_UNIFORMBUFFER_HPP

View File

@ -0,0 +1,41 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/UniformBuffer.hpp>
#include <memory>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
inline const BufferRef& UniformBuffer::GetBuffer() const
{
return m_buffer;
}
inline UInt32 UniformBuffer::GetEndOffset() const
{
return m_endOffset;
}
inline UInt32 UniformBuffer::GetStartOffset() const
{
return m_startOffset;
}
inline bool UniformBuffer::IsValid() const
{
return m_buffer.IsValid();
}
template<typename... Args>
UniformBufferRef UniformBuffer::New(Args&&... args)
{
std::unique_ptr<UniformBuffer> object(new UniformBuffer(std::forward<Args>(args)...));
object->SetPersistent(false);
return object.release();
}
}
#include <Nazara/Utility/DebugOff.hpp>

View File

@ -279,10 +279,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
vertexMapper.Unmap();
// Submesh
StaticMeshRef subMesh = StaticMesh::New(mesh);
subMesh->Create(vertexBuffer);
subMesh->SetIndexBuffer(indexBuffer);
StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer);
subMesh->GenerateAABB();
subMesh->SetMaterialIndex(iMesh->mMaterialIndex);

View File

@ -19,16 +19,16 @@ namespace Nz
/*!
* Write bits to the stream (if any) and reset the current bit cursor
* \see ResetBitPosition
* \see ResetWriteBitPosition
*/
void SerializationContext::FlushBits()
{
if (currentBitPos != 8)
if (writeBitPos != 8)
{
ResetBitPosition();
ResetWriteBitPosition();
// Serialize will reset the bit position
if (!Serialize(*this, currentByte))
if (!Serialize(*this, writeByte))
NazaraWarning("Failed to flush bits");
}
}

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
@ -16,4 +17,50 @@ namespace Nz
*/
AbstractViewer::~AbstractViewer() = default;
Vector3f AbstractViewer::Project(const Nz::Vector3f& worldPosition) const
{
Vector4f pos4D(worldPosition, 1.f);
pos4D = GetViewMatrix() * pos4D;
pos4D = GetProjectionMatrix() * pos4D;
pos4D /= pos4D.w;
Rectf viewport = Rectf(GetViewport());
Nz::Vector3f screenPosition(pos4D.x * 0.5f + 0.5f, -pos4D.y * 0.5f + 0.5f, pos4D.z * 0.5f + 0.5f);
screenPosition.x = screenPosition.x * viewport.width + viewport.x;
screenPosition.y = screenPosition.y * viewport.height + viewport.y;
return screenPosition;
}
float AbstractViewer::ProjectDepth(float depth)
{
const Matrix4f& projectionMatrix = GetProjectionMatrix();
float a = projectionMatrix(2, 2);
float b = projectionMatrix(2, 3);
return (0.5f * (-a * depth + b) / depth + 0.5f);
}
Vector3f AbstractViewer::Unproject(const Nz::Vector3f& screenPos) const
{
Rectf viewport = Rectf(GetViewport());
Nz::Vector4f normalizedPosition;
normalizedPosition.x = (screenPos.x - viewport.x) / viewport.width * 2.f - 1.f;
normalizedPosition.y = (screenPos.y - viewport.y) / viewport.height * 2.f - 1.f;
normalizedPosition.z = screenPos.z * 2.f - 1.f;
normalizedPosition.w = 1.f;
normalizedPosition.y = -normalizedPosition.y;
Nz::Matrix4f invMatrix = GetViewMatrix() * GetProjectionMatrix();
invMatrix.Inverse();
Nz::Vector4f worldPos = invMatrix * normalizedPosition;
worldPos /= worldPos.w;
return Nz::Vector3f(worldPos.x, worldPos.y, worldPos.z);
}
}

View File

@ -27,6 +27,14 @@ namespace Nz
renderQueue->AddBillboards(instanceData.renderOrder, GetMaterial(), 1, scissorRect, &position, &m_size, &m_sinCos, &m_color);
}
/*!
* \brief Clones this billboard
*/
std::unique_ptr<InstancedRenderable> Billboard::Clone() const
{
return std::make_unique<Billboard>(*this);
}
/*
* \brief Makes the bounding volume of this billboard
*/

View File

@ -51,7 +51,6 @@ namespace Nz
* \param renderQueue Queue to be added
* \param instanceData Data used for this instance
*/
void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
{
unsigned int submeshCount = m_mesh->GetSubMeshCount();
@ -69,6 +68,14 @@ namespace Nz
}
}
/*!
* \brief Clones this model
*/
std::unique_ptr<InstancedRenderable> Model::Clone() const
{
return std::make_unique<Model>(*this);
}
/*!
* \brief Gets the material of the named submesh
* \return Pointer to the current material
@ -252,9 +259,15 @@ namespace Nz
m_mesh = mesh;
if (m_mesh)
{
ResetMaterials(mesh->GetMaterialCount());
m_meshAABBInvalidationSlot.Connect(m_mesh->OnMeshInvalidateAABB, [this](const Nz::Mesh*) { InvalidateBoundingVolume(); });
}
else
{
ResetMaterials(0);
m_meshAABBInvalidationSlot.Disconnect();
}
InvalidateBoundingVolume();
}
@ -271,5 +284,9 @@ namespace Nz
m_boundingVolume.MakeNull();
}
ModelLibrary::LibraryMap Model::s_library;
ModelLoader::LoaderList Model::s_loaders;
ModelManager::ManagerMap Model::s_managerMap;
ModelManager::ManagerParams Model::s_managerParameters;
ModelSaver::SaverList Model::s_savers;
}

View File

@ -126,10 +126,9 @@ namespace Nz
* \brief Clones this skeletal model
* \return Pointer to newly allocated SkeletalModel
*/
SkeletalModel* SkeletalModel::Clone() const
std::unique_ptr<InstancedRenderable> SkeletalModel::Clone() const
{
return new SkeletalModel(*this);
return std::make_unique<SkeletalModel>(*this);
}
/*!

View File

@ -21,17 +21,23 @@ namespace Nz
* \param renderQueue Queue to be added
* \param instanceData Data for the instance
*/
void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const
{
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), vertices, 1, scissorRect);
}
/*!
* \brief Clones this sprite
*/
std::unique_ptr<InstancedRenderable> Sprite::Clone() const
{
return std::make_unique<Sprite>(*this);
}
/*!
* \brief Makes the bounding volume of this text
*/
void Sprite::MakeBoundingVolume() const
{
Vector3f origin(m_origin.x, -m_origin.y, m_origin.z);

View File

@ -41,6 +41,14 @@ namespace Nz
}
}
/*!
* \brief Clones this text sprite
*/
std::unique_ptr<InstancedRenderable> TextSprite::Clone() const
{
return std::make_unique<TextSprite>(*this);
}
/*!
* \brief Updates the text
*

View File

@ -37,6 +37,14 @@ namespace Nz
}
}
/*!
* \brief Clones this tilemap
*/
std::unique_ptr<InstancedRenderable> TileMap::Clone() const
{
return std::make_unique<TileMap>(*this);
}
void TileMap::MakeBoundingVolume() const
{
Nz::Vector2f size = GetSize();

View File

@ -47,7 +47,7 @@ namespace Nz
}
}
bool LuaCoroutine::Run(int argCount, int /*resultCount*/)
bool LuaCoroutine::Run(int argCount, int /*resultCount*/, int /*errHandler*/)
{
return Resume(argCount) != Ternary_False;
}

View File

@ -144,12 +144,22 @@ namespace Nz
bool LuaState::Call(unsigned int argCount)
{
return Run(argCount, LUA_MULTRET);
return Run(argCount, LUA_MULTRET, 0);
}
bool LuaState::Call(unsigned int argCount, unsigned int resultCount)
{
return Run(argCount, resultCount);
return Run(argCount, resultCount, 0);
}
bool LuaState::CallWithHandler(unsigned int argCount, int errorHandler)
{
return Run(argCount, LUA_MULTRET, errorHandler);
}
bool LuaState::CallWithHandler(unsigned int argCount, unsigned int resultCount, int errorHandler)
{
return Run(argCount, resultCount, errorHandler);
}
void LuaState::CheckAny(int index) const
@ -350,66 +360,37 @@ namespace Nz
luaL_error(m_state, message.GetConstBuffer());
}
bool LuaState::Execute(const String& code)
bool LuaState::Execute(const String& code, int errorHandler)
{
if (code.IsEmpty())
return true;
if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
if (!Load(code))
return false;
}
return Run(0, LUA_MULTRET);
return CallWithHandler(errorHandler, 0);
}
bool LuaState::ExecuteFromFile(const String& filePath)
bool LuaState::ExecuteFromFile(const String& filePath, int errorHandler)
{
File file(filePath);
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
{
NazaraError("Failed to open file");
if (!LoadFromFile(filePath))
return false;
}
std::size_t length = static_cast<std::size_t>(file.GetSize());
String source(length, '\0');
if (file.Read(&source[0], length) != length)
{
NazaraError("Failed to read file");
return false;
}
file.Close();
return Execute(source);
return CallWithHandler(errorHandler, 0);
}
bool LuaState::ExecuteFromMemory(const void* data, std::size_t size)
bool LuaState::ExecuteFromMemory(const void* data, std::size_t size, int errorHandler)
{
MemoryView stream(data, size);
return ExecuteFromStream(stream);
return ExecuteFromStream(stream, errorHandler);
}
bool LuaState::ExecuteFromStream(Stream& stream)
bool LuaState::ExecuteFromStream(Stream& stream, int errorHandler)
{
StreamData data;
data.stream = &stream;
if (lua_load(m_state, StreamReader, &data, "C++", nullptr) != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
if (!LoadFromStream(stream))
return false;
}
return Run(0, LUA_MULTRET);
return CallWithHandler(errorHandler, 0);
}
int LuaState::GetAbsIndex(int index) const
@ -545,6 +526,65 @@ namespace Nz
return lua_isnoneornil(m_state, index) == 0;
}
bool LuaState::Load(const String& code)
{
if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
return false;
}
return true;
}
bool LuaState::LoadFromFile(const String& filePath)
{
File file(filePath);
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
{
NazaraError("Failed to open file");
return false;
}
std::size_t length = static_cast<std::size_t>(file.GetSize());
String source(length, '\0');
if (file.Read(&source[0], length) != length)
{
NazaraError("Failed to read file");
return false;
}
file.Close();
return Load(source);
}
bool LuaState::LoadFromMemory(const void* data, std::size_t size)
{
MemoryView stream(data, size);
return LoadFromStream(stream);
}
bool LuaState::LoadFromStream(Stream& stream)
{
StreamData data;
data.stream = &stream;
if (lua_load(m_state, StreamReader, &data, "C++", nullptr) != 0)
{
m_lastError = lua_tostring(m_state, -1);
lua_pop(m_state, 1);
return false;
}
return true;
}
long long LuaState::Length(int index) const
{
return luaL_len(m_state, index);
@ -779,14 +819,19 @@ namespace Nz
return luaL_testudata(m_state, index, tname.GetConstBuffer());
}
bool LuaState::Run(int argCount, int resultCount)
void LuaState::Traceback(const char* message, int level)
{
luaL_traceback(m_state, m_state, message, level);
}
bool LuaState::Run(int argCount, int resultCount, int errHandler)
{
LuaInstance& instance = GetInstance(m_state);
if (instance.m_level++ == 0)
instance.m_clock.Restart();
int status = lua_pcall(m_state, argCount, resultCount, 0);
int status = lua_pcall(m_state, argCount, resultCount, errHandler);
instance.m_level--;

View File

@ -100,17 +100,17 @@ namespace Nz
if (entry.revents & (POLLWRNORM | POLLERR))
m_readyToWriteSockets.insert(entry.fd);
entry.revents = 0;
if (--socketRemaining == 0)
break;
}
else
{
NazaraWarning("Socket " + String::Number(entry.fd) + " was returned by WSAPoll without POLLRDNORM nor POLLWRNORM events (events: 0x" + String::Number(entry.revents, 16) + ')');
activeSockets--;
}
entry.revents = 0;
if (--socketRemaining == 0)
break;
}
}

View File

@ -154,17 +154,17 @@ namespace Nz
if (entry.revents & (POLLWRNORM | POLLERR))
m_readyToWriteSockets.insert(entry.fd);
entry.revents = 0;
if (--socketRemaining == 0)
break;
}
else
{
NazaraWarning("Socket " + String::Number(entry.fd) + " was returned by WSAPoll without POLLRDNORM nor POLLWRNORM events (events: 0x" + String::Number(entry.revents, 16) + ')');
activeSockets--;
}
entry.revents = 0;
if (--socketRemaining == 0)
break;
}
}
#else

View File

@ -311,14 +311,15 @@ namespace Nz
{
m_timestepAccumulator += timestep;
std::size_t stepCount = 0;
while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount)
std::size_t stepCount = std::min(static_cast<std::size_t>(m_timestepAccumulator / m_stepSize), m_maxStepCount);
float invStepCount = 1.f / stepCount;
for (std::size_t i = 0; i < stepCount; ++i)
{
OnPhysWorld2DPreStep(this);
OnPhysWorld2DPreStep(this, invStepCount);
cpSpaceStep(m_handle, m_stepSize);
OnPhysWorld2DPostStep(this);
OnPhysWorld2DPostStep(this, invStepCount);
if (!m_rigidPostSteps.empty())
{
for (const auto& pair : m_rigidPostSteps)
@ -331,7 +332,6 @@ namespace Nz
}
m_timestepAccumulator -= m_stepSize;
stepCount++;
}
}

View File

@ -158,12 +158,7 @@ namespace Nz
#endif
VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, header.num_vertices, parameters.storage, parameters.vertexBufferFlags);
StaticMeshRef subMesh = StaticMesh::New(mesh);
if (!subMesh->Create(vertexBuffer))
{
NazaraError("Failed to create SubMesh");
return false;
}
StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer);
// Extracting vertices
stream.SetCursorPos(header.offset_frames);

View File

@ -202,13 +202,9 @@ namespace Nz
mesh->SetMaterialData(i, std::move(matData));
// Submesh
SkeletalMeshRef subMesh = SkeletalMesh::New(mesh);
subMesh->Create(vertexBuffer);
subMesh->SetIndexBuffer(indexBuffer);
SkeletalMeshRef subMesh = SkeletalMesh::New(vertexBuffer, indexBuffer);
subMesh->GenerateNormalsAndTangents();
subMesh->SetMaterialIndex(i);
subMesh->SetPrimitiveMode(PrimitiveMode_TriangleList);
mesh->AddSubMesh(subMesh);
@ -255,6 +251,9 @@ namespace Nz
}
indexMapper.Unmap();
if (parameters.optimizeIndexBuffers)
indexBuffer->Optimize();
// Vertex buffer
VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, UInt32(vertexCount), parameters.storage, parameters.vertexBufferFlags);
@ -287,13 +286,7 @@ namespace Nz
vertexMapper.Unmap();
// Submesh
StaticMeshRef subMesh = StaticMesh::New(mesh);
subMesh->Create(vertexBuffer);
if (parameters.optimizeIndexBuffers)
indexBuffer->Optimize();
subMesh->SetIndexBuffer(indexBuffer);
StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer);
subMesh->GenerateAABB();
subMesh->SetMaterialIndex(i);

View File

@ -259,6 +259,9 @@ namespace Nz
indexMapper.Unmap(); // Pour laisser les autres tâches affecter l'index buffer
if (parameters.optimizeIndexBuffers)
indexBuffer->Optimize();
// Remplissage des vertices
// Make sure the normal matrix won't rescale our normals
@ -311,20 +314,9 @@ namespace Nz
vertexMapper.Unmap();
StaticMeshRef subMesh = StaticMesh::New(mesh);
if (!subMesh->Create(vertexBuffer))
{
NazaraError("Failed to create StaticMesh");
continue;
}
if (parameters.optimizeIndexBuffers)
indexBuffer->Optimize();
StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer);
subMesh->GenerateAABB();
subMesh->SetIndexBuffer(indexBuffer);
subMesh->SetMaterialIndex(meshes[i].material);
subMesh->SetPrimitiveMode(PrimitiveMode_TriangleList);
// Ce que nous pouvons générer dépend des données à disposition (par exemple les tangentes nécessitent des coordonnées de texture)
if (hasNormals && hasTexCoords)

View File

@ -106,6 +106,7 @@ namespace Nz
void IndexBuffer::Reset(bool largeIndices, BufferRef buffer, UInt32 offset, UInt32 size)
{
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
NazaraAssert(buffer->GetType() == BufferType_Index, "Buffer must be an index buffer");
NazaraAssert(size > 0, "Invalid size");
NazaraAssert(offset + size > buffer->GetSize(), "Virtual buffer exceed buffer bounds");

View File

@ -1,4 +1,4 @@
// Copyright (C) 2017 Jérôme Leclercq
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
@ -56,62 +56,40 @@ namespace Nz
return true;
}
struct MeshImpl
{
MeshImpl()
{
materialData.resize(1); // One material by default
}
std::unordered_map<String, UInt32> subMeshMap;
std::vector<ParameterList> materialData;
std::vector<SubMeshRef> subMeshes;
AnimationType animationType;
Boxf aabb;
Skeleton skeleton; // Only used by skeletal meshes
String animationPath;
bool aabbUpdated = false;
UInt32 jointCount; // Only used by skeletal meshes
};
Mesh::~Mesh()
{
OnMeshRelease(this);
Destroy();
}
void Mesh::AddSubMesh(SubMesh* subMesh)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(subMesh, "Invalid submesh");
NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type");
NazaraAssert(subMesh->GetAnimationType() == m_animationType, "Submesh animation type doesn't match mesh animation type");
m_impl->subMeshes.emplace_back(subMesh);
m_subMeshes.emplace_back();
SubMeshData& subMeshData = m_subMeshes.back();
subMeshData.subMesh = subMesh;
subMeshData.onSubMeshInvalidated.Connect(subMesh->OnSubMeshInvalidateAABB, [this](const SubMesh* /*subMesh*/) { InvalidateAABB(); });
InvalidateAABB();
}
void Mesh::AddSubMesh(const String& identifier, SubMesh* subMesh)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(!identifier.IsEmpty(), "Identifier is empty");
NazaraAssert(m_impl->subMeshMap.find(identifier) == m_impl->subMeshMap.end(), "SubMesh identifier \"" + identifier + "\" is already in use");
NazaraAssert(m_subMeshMap.find(identifier) == m_subMeshMap.end(), "SubMesh identifier \"" + identifier + "\" is already in use");
NazaraAssert(subMesh, "Invalid submesh");
NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type");
NazaraAssert(subMesh->GetAnimationType() == m_animationType, "Submesh animation type doesn't match mesh animation type");
std::size_t index = m_impl->subMeshes.size();
std::size_t index = m_subMeshes.size();
m_impl->subMeshes.emplace_back(subMesh);
m_impl->subMeshMap[identifier] = static_cast<UInt32>(index);
AddSubMesh(subMesh);
InvalidateAABB();
m_subMeshMap[identifier] = static_cast<UInt32>(index);
}
SubMesh* Mesh::BuildSubMesh(const Primitive& primitive, const MeshParams& params)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_impl->animationType == AnimationType_Static, "Submesh building only works for static meshes");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(m_animationType == AnimationType_Static, "Submesh building only works for static meshes");
NazaraAssert(params.IsValid(), "Invalid parameters");
NazaraAssert(params.vertexDeclaration->HasComponentOfType<Vector3f>(VertexComponent_Position), "The vertex declaration doesn't have a Vector3 position component");
@ -266,18 +244,11 @@ namespace Nz
}
}
StaticMeshRef subMesh = StaticMesh::New(this);
if (!subMesh->Create(vertexBuffer))
{
NazaraError("Failed to create StaticMesh");
return nullptr;
}
if (params.optimizeIndexBuffers)
indexBuffer->Optimize();
StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer);
subMesh->SetAABB(aabb);
subMesh->SetIndexBuffer(indexBuffer);
AddSubMesh(subMesh);
return subMesh;
@ -293,16 +264,15 @@ namespace Nz
{
Destroy();
std::unique_ptr<MeshImpl> impl(new MeshImpl);
impl->animationType = AnimationType_Skeletal;
impl->jointCount = jointCount;
if (!impl->skeleton.Create(jointCount))
m_animationType = AnimationType_Skeletal;
m_jointCount = jointCount;
if (!m_skeleton.Create(jointCount))
{
NazaraError("Failed to create skeleton");
return false;
}
m_impl = impl.release();
m_isValid = true;
return true;
}
@ -311,236 +281,244 @@ namespace Nz
{
Destroy();
m_impl = new MeshImpl;
m_impl->animationType = AnimationType_Static;
m_animationType = AnimationType_Static;
m_isValid = true;
return true;
}
void Mesh::Destroy()
{
if (m_impl)
if (m_isValid)
{
OnMeshDestroy(this);
delete m_impl;
m_impl = nullptr;
m_animationPath.Clear();
m_materialData.clear();
m_materialData.resize(1);
m_skeleton.Destroy();
m_subMeshes.clear();
m_subMeshMap.clear();
m_isValid = false;
}
}
void Mesh::GenerateNormals()
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
for (SubMesh* subMesh : m_impl->subMeshes)
subMesh->GenerateNormals();
for (SubMeshData& data : m_subMeshes)
data.subMesh->GenerateNormals();
}
void Mesh::GenerateNormalsAndTangents()
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
for (SubMesh* subMesh : m_impl->subMeshes)
subMesh->GenerateNormalsAndTangents();
for (SubMeshData& data : m_subMeshes)
data.subMesh->GenerateNormalsAndTangents();
}
void Mesh::GenerateTangents()
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
for (SubMesh* subMesh : m_impl->subMeshes)
subMesh->GenerateTangents();
for (SubMeshData& data : m_subMeshes)
data.subMesh->GenerateTangents();
}
const Boxf& Mesh::GetAABB() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
if (!m_impl->aabbUpdated)
if (!m_aabbUpdated)
{
std::size_t subMeshCount = m_impl->subMeshes.size();
std::size_t subMeshCount = m_subMeshes.size();
if (subMeshCount > 0)
{
m_impl->aabb.Set(m_impl->subMeshes[0]->GetAABB());
m_aabb.Set(m_subMeshes.front().subMesh->GetAABB());
for (std::size_t i = 1; i < subMeshCount; ++i)
m_impl->aabb.ExtendTo(m_impl->subMeshes[i]->GetAABB());
m_aabb.ExtendTo(m_subMeshes[i].subMesh->GetAABB());
}
else
m_impl->aabb.MakeZero();
m_aabb.MakeZero();
m_impl->aabbUpdated = true;
m_aabbUpdated = true;
}
return m_impl->aabb;
return m_aabb;
}
String Mesh::GetAnimation() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return m_impl->animationPath;
return m_animationPath;
}
AnimationType Mesh::GetAnimationType() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return m_impl->animationType;
return m_animationType;
}
UInt32 Mesh::GetJointCount() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal");
return m_impl->jointCount;
return m_jointCount;
}
ParameterList& Mesh::GetMaterialData(UInt32 index)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(index < m_impl->materialData.size(), "Material index out of range");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(index < m_materialData.size(), "Material index out of range");
return m_impl->materialData[index];
return m_materialData[index];
}
const ParameterList& Mesh::GetMaterialData(UInt32 index) const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(index < m_impl->materialData.size(), "Material index out of range");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(index < m_materialData.size(), "Material index out of range");
return m_impl->materialData[index];
return m_materialData[index];
}
UInt32 Mesh::GetMaterialCount() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return static_cast<UInt32>(m_impl->materialData.size());
return static_cast<UInt32>(m_materialData.size());
}
Skeleton* Mesh::GetSkeleton()
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal");
return &m_impl->skeleton;
return &m_skeleton;
}
const Skeleton* Mesh::GetSkeleton() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal");
return &m_impl->skeleton;
return &m_skeleton;
}
SubMesh* Mesh::GetSubMesh(const String& identifier)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
auto it = m_impl->subMeshMap.find(identifier);
NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found");
auto it = m_subMeshMap.find(identifier);
NazaraAssert(it != m_subMeshMap.end(), "SubMesh " + identifier + " not found");
return m_impl->subMeshes[it->second];
return m_subMeshes[it->second].subMesh;
}
SubMesh* Mesh::GetSubMesh(UInt32 index)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range");
return m_impl->subMeshes[index];
return m_subMeshes[index].subMesh;
}
const SubMesh* Mesh::GetSubMesh(const String& identifier) const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
auto it = m_impl->subMeshMap.find(identifier);
NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found");
auto it = m_subMeshMap.find(identifier);
NazaraAssert(it != m_subMeshMap.end(), "SubMesh " + identifier + " not found");
return m_impl->subMeshes[it->second];
return m_subMeshes[it->second].subMesh;
}
const SubMesh* Mesh::GetSubMesh(UInt32 index) const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range");
return m_impl->subMeshes[index];
return m_subMeshes[index].subMesh;
}
UInt32 Mesh::GetSubMeshCount() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return static_cast<UInt32>(m_impl->subMeshes.size());
return static_cast<UInt32>(m_subMeshes.size());
}
UInt32 Mesh::GetSubMeshIndex(const String& identifier) const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
auto it = m_impl->subMeshMap.find(identifier);
NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found");
auto it = m_subMeshMap.find(identifier);
NazaraAssert(it != m_subMeshMap.end(), "SubMesh " + identifier + " not found");
return it->second;
}
UInt32 Mesh::GetTriangleCount() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
UInt32 triangleCount = 0;
for (SubMesh* subMesh : m_impl->subMeshes)
triangleCount += subMesh->GetTriangleCount();
for (const SubMeshData& data : m_subMeshes)
triangleCount += data.subMesh->GetTriangleCount();
return triangleCount;
}
UInt32 Mesh::GetVertexCount() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
UInt32 vertexCount = 0;
for (SubMesh* subMesh : m_impl->subMeshes)
vertexCount += subMesh->GetVertexCount();
for (const SubMeshData& data : m_subMeshes)
vertexCount += data.subMesh->GetVertexCount();
return vertexCount;
}
void Mesh::InvalidateAABB() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
m_impl->aabbUpdated = false;
m_aabbUpdated = false;
OnMeshInvalidateAABB(this);
}
bool Mesh::HasSubMesh(const String& identifier) const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end();
return m_subMeshMap.find(identifier) != m_subMeshMap.end();
}
bool Mesh::HasSubMesh(UInt32 index) const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return index < m_impl->subMeshes.size();
return index < m_subMeshes.size();
}
bool Mesh::IsAnimable() const
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
return m_impl->animationType != AnimationType_Static;
return m_animationType != AnimationType_Static;
}
bool Mesh::IsValid() const
{
return m_impl != nullptr;
return m_isValid;
}
bool Mesh::LoadFromFile(const String& filePath, const MeshParams& params)
@ -560,20 +538,20 @@ namespace Nz
void Mesh::Recenter()
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_impl->animationType == AnimationType_Static, "Mesh is not static");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(m_animationType == AnimationType_Static, "Mesh is not static");
// The center of our mesh is the center of our *global* AABB
Vector3f center = GetAABB().GetCenter();
for (SubMesh* subMesh : m_impl->subMeshes)
for (SubMeshData& data : m_subMeshes)
{
StaticMesh* staticMesh = static_cast<StaticMesh*>(subMesh);
StaticMesh& staticMesh = static_cast<StaticMesh&>(*data.subMesh);
BufferMapper<VertexBuffer> mapper(staticMesh->GetVertexBuffer(), BufferAccess_ReadWrite);
BufferMapper<VertexBuffer> mapper(staticMesh.GetVertexBuffer(), BufferAccess_ReadWrite);
MeshVertex* vertices = static_cast<MeshVertex*>(mapper.GetPointer());
UInt32 vertexCount = staticMesh->GetVertexCount();
UInt32 vertexCount = staticMesh.GetVertexCount();
for (UInt32 i = 0; i < vertexCount; ++i)
{
vertices->position -= center;
@ -581,13 +559,11 @@ namespace Nz
}
// Our AABB doesn't change shape, only position
Boxf aabb = staticMesh->GetAABB();
Boxf aabb = staticMesh.GetAABB();
aabb.Translate(-center);
staticMesh->SetAABB(aabb);
staticMesh.SetAABB(aabb); // This will invalidate our AABB
}
InvalidateAABB();
}
void Mesh::RemoveSubMesh(const String& identifier)
@ -595,22 +571,22 @@ namespace Nz
UInt32 index = GetSubMeshIndex(identifier);
// On déplace l'itérateur du début d'une distance de x
auto it2 = m_impl->subMeshes.begin();
auto it2 = m_subMeshes.begin();
std::advance(it2, index);
m_impl->subMeshes.erase(it2);
m_subMeshes.erase(it2);
InvalidateAABB();
}
void Mesh::RemoveSubMesh(UInt32 index)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range");
// On déplace l'itérateur du début de x
auto it = m_impl->subMeshes.begin();
auto it = m_subMeshes.begin();
std::advance(it, index);
m_impl->subMeshes.erase(it);
m_subMeshes.erase(it);
InvalidateAABB();
}
@ -627,34 +603,34 @@ namespace Nz
void Mesh::SetAnimation(const String& animationPath)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
m_impl->animationPath = animationPath;
m_animationPath = animationPath;
}
void Mesh::SetMaterialData(UInt32 matIndex, ParameterList data)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(matIndex < m_impl->materialData.size(), "Material index out of range");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(matIndex < m_materialData.size(), "Material index out of range");
m_impl->materialData[matIndex] = std::move(data);
m_materialData[matIndex] = std::move(data);
}
void Mesh::SetMaterialCount(UInt32 matCount)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(matCount > 0, "A mesh should have at least a material");
m_impl->materialData.resize(matCount);
m_materialData.resize(matCount);
#ifdef NAZARA_DEBUG
for (SubMesh* subMesh : m_impl->subMeshes)
for (SubMeshData& data : m_subMeshes)
{
UInt32 matIndex = subMesh->GetMaterialIndex();
UInt32 matIndex = data.subMesh->GetMaterialIndex();
if (matIndex >= matCount)
{
subMesh->SetMaterialIndex(0); // To prevent a crash
NazaraWarning("SubMesh " + String::Pointer(subMesh) + " material index is over mesh new material count (" + String::Number(matIndex) + " >= " + String::Number(matCount) + "), setting it to first material");
data.subMesh->SetMaterialIndex(0); // To prevent a crash
NazaraWarning("SubMesh " + String::Pointer(data.subMesh) + " material index is over mesh new material count (" + String::Number(matIndex) + " >= " + String::Number(matCount) + "), setting it to first material");
}
}
#endif
@ -662,19 +638,19 @@ namespace Nz
void Mesh::Transform(const Matrix4f& matrix)
{
NazaraAssert(m_impl, "Mesh should be created first");
NazaraAssert(m_impl->animationType == AnimationType_Static, "Mesh is not static");
NazaraAssert(m_isValid, "Mesh should be created first");
NazaraAssert(m_animationType == AnimationType_Static, "Mesh is not static");
for (SubMesh* subMesh : m_impl->subMeshes)
for (SubMeshData& data : m_subMeshes)
{
StaticMesh* staticMesh = static_cast<StaticMesh*>(subMesh);
StaticMesh& staticMesh = static_cast<StaticMesh&>(*data.subMesh);
BufferMapper<VertexBuffer> mapper(staticMesh->GetVertexBuffer(), BufferAccess_ReadWrite);
BufferMapper<VertexBuffer> mapper(staticMesh.GetVertexBuffer(), BufferAccess_ReadWrite);
MeshVertex* vertices = static_cast<MeshVertex*>(mapper.GetPointer());
Boxf aabb(vertices->position.x, vertices->position.y, vertices->position.z, 0.f, 0.f, 0.f);
UInt32 vertexCount = staticMesh->GetVertexCount();
UInt32 vertexCount = staticMesh.GetVertexCount();
for (UInt32 i = 0; i < vertexCount; ++i)
{
vertices->position = matrix.Transform(vertices->position);
@ -683,10 +659,8 @@ namespace Nz
vertices++;
}
staticMesh->SetAABB(aabb);
staticMesh.SetAABB(aabb); //< This will invalidate our AABB
}
InvalidateAABB();
}
bool Mesh::Initialize()

View File

@ -8,8 +8,16 @@
namespace Nz
{
SkeletalMesh::SkeletalMesh(const Mesh* parent) :
SubMesh(parent)
SkeletalMesh::SkeletalMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer) :
m_aabb(Nz::Boxf::Zero()),
m_indexBuffer(indexBuffer),
m_vertexBuffer(vertexBuffer)
{
NazaraAssert(m_vertexBuffer, "Invalid vertex buffer");
}
SkeletalMesh::SkeletalMesh(const Mesh* /*parent*/) :
m_aabb(Nz::Boxf::Zero())
{
}
@ -90,6 +98,8 @@ namespace Nz
void SkeletalMesh::SetAABB(const Boxf& aabb)
{
m_aabb = aabb;
OnSubMeshInvalidateAABB(this);
}
void SkeletalMesh::SetIndexBuffer(const IndexBuffer* indexBuffer)

View File

@ -10,8 +10,16 @@
namespace Nz
{
StaticMesh::StaticMesh(const Mesh* parent) :
SubMesh(parent)
StaticMesh::StaticMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer) :
m_aabb(Nz::Boxf::Zero()),
m_indexBuffer(indexBuffer),
m_vertexBuffer(vertexBuffer)
{
NazaraAssert(m_vertexBuffer, "Invalid vertex buffer");
}
StaticMesh::StaticMesh(const Mesh* /*parent*/) :
m_aabb(Nz::Boxf::Zero())
{
}
@ -69,7 +77,7 @@ namespace Nz
{
// On lock le buffer pour itérer sur toutes les positions et composer notre AABB
VertexMapper mapper(m_vertexBuffer, BufferAccess_ReadOnly);
m_aabb = ComputeAABB(mapper.GetComponentPtr<const Vector3f>(VertexComponent_Position), m_vertexBuffer->GetVertexCount());
SetAABB(ComputeAABB(mapper.GetComponentPtr<const Vector3f>(VertexComponent_Position), m_vertexBuffer->GetVertexCount()));
return true;
}
@ -117,10 +125,12 @@ namespace Nz
void StaticMesh::SetAABB(const Boxf& aabb)
{
m_aabb = aabb;
OnSubMeshInvalidateAABB(this);
}
void StaticMesh::SetIndexBuffer(const IndexBuffer* indexBuffer)
{
m_indexBuffer = indexBuffer;
}
}
}

View File

@ -12,14 +12,18 @@
namespace Nz
{
SubMesh::SubMesh(const Mesh* parent) :
RefCounted(false), // Un SubMesh n'est pas persistant par défaut
SubMesh::SubMesh() :
RefCounted(false), // wut
m_primitiveMode(PrimitiveMode_TriangleList),
m_parent(parent),
m_matIndex(0)
{
}
SubMesh::SubMesh(const Mesh* /*parent*/) :
SubMesh()
{
}
SubMesh::~SubMesh()
{
OnSubMeshRelease(this);
@ -160,11 +164,6 @@ namespace Nz
while (iterator.Advance());
}
const Mesh* SubMesh::GetParent() const
{
return m_parent;
}
PrimitiveMode SubMesh::GetPrimitiveMode() const
{
return m_primitiveMode;

View File

@ -0,0 +1,118 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/UniformBuffer.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
UniformBuffer::UniformBuffer(BufferRef buffer)
{
ErrorFlags(ErrorFlag_ThrowException, true);
Reset(std::move(buffer));
}
UniformBuffer::UniformBuffer(BufferRef buffer, UInt32 offset, UInt32 size)
{
ErrorFlags(ErrorFlag_ThrowException, true);
Reset(std::move(buffer), offset, size);
}
UniformBuffer::UniformBuffer(UInt32 length, DataStorage storage, BufferUsageFlags usage)
{
ErrorFlags(ErrorFlag_ThrowException, true);
Reset(length, storage, usage);
}
UniformBuffer::UniformBuffer(const UniformBuffer& uniformBuffer) :
RefCounted(),
m_buffer(uniformBuffer.m_buffer),
m_endOffset(uniformBuffer.m_endOffset),
m_startOffset(uniformBuffer.m_startOffset)
{
}
UniformBuffer::~UniformBuffer()
{
OnUniformBufferRelease(this);
}
bool UniformBuffer::Fill(const void* data, UInt32 offset, UInt32 size)
{
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
return m_buffer->Fill(data, m_startOffset + offset, size);
}
void* UniformBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size)
{
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
return m_buffer->Map(access, offset, size);
}
void* UniformBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size) const
{
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
return m_buffer->Map(access, offset, size);
}
void UniformBuffer::Reset()
{
m_buffer.Reset();
}
void UniformBuffer::Reset(BufferRef buffer)
{
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
Reset(buffer, 0, buffer->GetSize());
}
void UniformBuffer::Reset(BufferRef buffer, UInt32 offset, UInt32 size)
{
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
NazaraAssert(buffer->GetType() == BufferType_Uniform, "Buffer must be an uniform buffer");
NazaraAssert(size > 0, "Invalid size");
NazaraAssert(offset + size > buffer->GetSize(), "Virtual buffer exceed buffer bounds");
m_buffer = buffer;
m_endOffset = offset + size;
m_startOffset = offset;
}
void UniformBuffer::Reset(UInt32 size, DataStorage storage, BufferUsageFlags usage)
{
m_endOffset = size;
m_startOffset = 0;
m_buffer = Buffer::New(BufferType_Uniform, m_endOffset, storage, usage);
}
void UniformBuffer::Reset(const UniformBuffer& UniformBuffer)
{
m_buffer = UniformBuffer.m_buffer;
m_endOffset = UniformBuffer.m_endOffset;
m_startOffset = UniformBuffer.m_startOffset;
}
void UniformBuffer::Unmap() const
{
m_buffer->Unmap();
}
UniformBuffer& UniformBuffer::operator=(const UniformBuffer& uniformBuffer)
{
Reset(uniformBuffer);
return *this;
}
}

View File

@ -98,6 +98,7 @@ namespace Nz
void VertexBuffer::Reset(VertexDeclarationConstRef vertexDeclaration, BufferRef buffer)
{
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
NazaraAssert(buffer->GetType() == BufferType_Vertex, "Buffer must be a vertex buffer");
UInt32 size = buffer->GetSize();
Reset(std::move(vertexDeclaration), std::move(buffer), 0, size);