Merge branch 'master' into vulkan
Former-commit-id: 9f8a7fd431d09c2c656f0692c897a0a41a04f26e [formerly e007bba02b960164ab806d72f052044ccb7dec1c] Former-commit-id: b881a70547ff9cc63d3dbd2123d9de7951ae59a3
This commit is contained in:
commit
cdd96dd4aa
|
|
@ -31,6 +31,10 @@ namespace Ndk
|
||||||
|
|
||||||
inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0);
|
inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0);
|
||||||
|
|
||||||
|
inline void Clear();
|
||||||
|
|
||||||
|
inline void Detach(const Nz::InstancedRenderableRef& renderable);
|
||||||
|
|
||||||
inline void EnsureBoundingVolumeUpdate() const;
|
inline void EnsureBoundingVolumeUpdate() const;
|
||||||
inline void EnsureTransformMatrixUpdate() const;
|
inline void EnsureTransformMatrixUpdate() const;
|
||||||
|
|
||||||
|
|
@ -63,6 +67,22 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderable(Renderable&& renderable) noexcept :
|
||||||
|
data(std::move(renderable.data)),
|
||||||
|
renderable(std::move(renderable.renderable)),
|
||||||
|
dataUpdated(renderable.dataUpdated)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderable& operator=(Renderable&& r) noexcept
|
||||||
|
{
|
||||||
|
data = std::move(r.data);
|
||||||
|
dataUpdated = r.dataUpdated;
|
||||||
|
renderable = std::move(r.renderable);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableInvalidateData, renderableInvalidationSlot);
|
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableInvalidateData, renderableInvalidationSlot);
|
||||||
|
|
||||||
mutable Nz::InstancedRenderable::InstanceData data;
|
mutable Nz::InstancedRenderable::InstanceData data;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "GraphicsComponent.hpp"
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
|
@ -46,6 +47,26 @@ namespace Ndk
|
||||||
InvalidateBoundingVolume();
|
InvalidateBoundingVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void GraphicsComponent::Clear()
|
||||||
|
{
|
||||||
|
m_renderables.clear();
|
||||||
|
|
||||||
|
InvalidateBoundingVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GraphicsComponent::Detach(const Nz::InstancedRenderableRef& renderable)
|
||||||
|
{
|
||||||
|
for (auto it = m_renderables.begin(); it != m_renderables.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->renderable == renderable)
|
||||||
|
{
|
||||||
|
InvalidateBoundingVolume();
|
||||||
|
m_renderables.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void GraphicsComponent::EnsureBoundingVolumeUpdate() const
|
inline void GraphicsComponent::EnsureBoundingVolumeUpdate() const
|
||||||
{
|
{
|
||||||
if (!m_boundingVolumeUpdated)
|
if (!m_boundingVolumeUpdated)
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,33 @@ namespace Nz
|
||||||
T* m_object;
|
T* m_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> struct PointedType<ObjectRef<T>> {typedef T type;};
|
template<typename T> bool operator==(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs);
|
||||||
template<typename T> struct PointedType<ObjectRef<T> const> {typedef T type;};
|
template<typename T> bool operator==(const T& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator==(const ObjectRef<T>& lhs, const T& rhs);
|
||||||
|
|
||||||
|
template<typename T> bool operator!=(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator!=(const T& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator!=(const ObjectRef<T>& lhs, const T& rhs);
|
||||||
|
|
||||||
|
template<typename T> bool operator<(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator<(const T& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator<(const ObjectRef<T>& lhs, const T& rhs);
|
||||||
|
|
||||||
|
template<typename T> bool operator<=(const ObjectRef<T>, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator<=(const T& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator<=(const ObjectRef<T>& lhs, const T& rhs);
|
||||||
|
|
||||||
|
template<typename T> bool operator>(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator>(const T& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator>(const ObjectRef<T>& lhs, const T& rhs);
|
||||||
|
|
||||||
|
template<typename T> bool operator>=(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator>=(const T& lhs, const ObjectRef<T>& rhs);
|
||||||
|
template<typename T> bool operator>=(const ObjectRef<T>& lhs, const T& rhs);
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T> struct PointedType<ObjectRef<T>> { typedef T type; };
|
||||||
|
template<typename T> struct PointedType<ObjectRef<T> const> { typedef T type; };
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Core/ObjectRef.inl>
|
#include <Nazara/Core/ObjectRef.inl>
|
||||||
|
|
|
||||||
|
|
@ -245,6 +245,241 @@ namespace Nz
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is equal to the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator==(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return lhs.Get() == rhs.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the object is equal to the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first Object to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator==(const T& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return &lhs == rhs.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the object handle is equal to the second object
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second Object to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator==(const ObjectRef<T>& lhs, const T& rhs)
|
||||||
|
{
|
||||||
|
return lhs.Get() == &rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is equal to the second object handle
|
||||||
|
* \return false if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator!=(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the object is equal to the second object handle
|
||||||
|
* \return false if it is the case
|
||||||
|
*
|
||||||
|
* \param first Object to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator!=(const T& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the object handle is equal to the second object
|
||||||
|
* \return false if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second Object to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator!=(const ObjectRef<T>& lhs, const T& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is less than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator<(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_object < rhs.m_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is less than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator<(const T& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return &lhs < rhs.m_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is less than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator<(const ObjectRef<T>& lhs, const T& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_object < &rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is less or equal than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator<=(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs > rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is less or equal than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator<=(const T& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs > rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is less or equal than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator<=(const ObjectRef<T>& lhs, const T& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs > rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is greather than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator>(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is greather than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator>(const T& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is greather than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator>(const ObjectRef<T>& lhs, const T& rhs)
|
||||||
|
{
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is greather or equal than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator>=(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is greather or equal than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator>=(const T& lhs, const ObjectRef<T>& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the first object handle is greather or equal than the second object handle
|
||||||
|
* \return true if it is the case
|
||||||
|
*
|
||||||
|
* \param first ObjectRef to compare in left hand side
|
||||||
|
* \param second ObjectRef to compare in right hand side
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool operator>=(const ObjectRef<T>& lhs, const T& rhs)
|
||||||
|
{
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@ namespace Nz
|
||||||
StringStream(const StringStream&) = default;
|
StringStream(const StringStream&) = default;
|
||||||
StringStream(StringStream&&) noexcept = default;
|
StringStream(StringStream&&) noexcept = default;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
std::size_t GetBufferSize() const;
|
||||||
|
|
||||||
String ToString() const;
|
String ToString() const;
|
||||||
|
|
||||||
StringStream& operator=(const StringStream&) = default;
|
StringStream& operator=(const StringStream&) = default;
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,27 @@ namespace Nz
|
||||||
struct InstanceData
|
struct InstanceData
|
||||||
{
|
{
|
||||||
InstanceData(Matrix4f& referenceMatrix) :
|
InstanceData(Matrix4f& referenceMatrix) :
|
||||||
transformMatrix(referenceMatrix),
|
transformMatrix(&referenceMatrix),
|
||||||
flags(0)
|
flags(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstanceData(InstanceData&& instanceData) noexcept = default;
|
||||||
|
|
||||||
|
InstanceData& operator=(InstanceData&& instanceData) noexcept
|
||||||
|
{
|
||||||
|
data = std::move(instanceData.data);
|
||||||
|
flags = instanceData.flags;
|
||||||
|
renderOrder = instanceData.renderOrder;
|
||||||
|
transformMatrix = instanceData.transformMatrix;
|
||||||
|
volume = instanceData.volume;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<UInt8> data;
|
std::vector<UInt8> data;
|
||||||
BoundingVolumef volume;
|
BoundingVolumef volume;
|
||||||
Matrix4f& transformMatrix;
|
Matrix4f* transformMatrix;
|
||||||
UInt32 flags;
|
UInt32 flags;
|
||||||
int renderOrder;
|
int renderOrder;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,8 @@ namespace Nz
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
void SaveToParameters(ParameterList* matData);
|
||||||
|
|
||||||
inline bool SetAlphaMap(const String& textureName);
|
inline bool SetAlphaMap(const String& textureName);
|
||||||
inline void SetAlphaMap(TextureRef alphaMap);
|
inline void SetAlphaMap(TextureRef alphaMap);
|
||||||
inline void SetAlphaThreshold(float alphaThreshold);
|
inline void SetAlphaThreshold(float alphaThreshold);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
||||||
explicit Vector4(T scale);
|
explicit Vector4(T scale);
|
||||||
Vector4(const T vec[4]);
|
Vector4(const T vec[4]);
|
||||||
Vector4(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
|
Vector4(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||||
Vector4(const Vector3<T>& vec, T W = 0.0);
|
Vector4(const Vector3<T>& vec, T W = 1.0);
|
||||||
template<typename U> explicit Vector4(const Vector4<U>& vec);
|
template<typename U> explicit Vector4(const Vector4<U>& vec);
|
||||||
Vector4(const Vector4& vec) = default;
|
Vector4(const Vector4& vec) = default;
|
||||||
~Vector4() = default;
|
~Vector4() = default;
|
||||||
|
|
|
||||||
|
|
@ -65,12 +65,11 @@ namespace Nz
|
||||||
protected:
|
protected:
|
||||||
bool Activate() const override;
|
bool Activate() const override;
|
||||||
void EnsureTargetUpdated() const override;
|
void EnsureTargetUpdated() const override;
|
||||||
|
|
||||||
private:
|
|
||||||
bool OnWindowCreated() override;
|
bool OnWindowCreated() override;
|
||||||
void OnWindowDestroy() override;
|
void OnWindowDestroy() override;
|
||||||
void OnWindowResized() override;
|
void OnWindowResized() override;
|
||||||
|
|
||||||
|
private:
|
||||||
mutable std::vector<UInt8> m_buffer;
|
mutable std::vector<UInt8> m_buffer;
|
||||||
Clock m_clock;
|
Clock m_clock;
|
||||||
ContextParameters m_parameters;
|
ContextParameters m_parameters;
|
||||||
|
|
|
||||||
|
|
@ -29,51 +29,61 @@ namespace Nz
|
||||||
|
|
||||||
struct Face
|
struct Face
|
||||||
{
|
{
|
||||||
std::vector<FaceVertex> vertices;
|
std::size_t firstVertex;
|
||||||
|
std::size_t vertexCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mesh
|
struct Mesh
|
||||||
{
|
{
|
||||||
std::vector<Face> faces;
|
std::vector<Face> faces;
|
||||||
|
std::vector<FaceVertex> vertices;
|
||||||
String name;
|
String name;
|
||||||
unsigned int material;
|
std::size_t material;
|
||||||
};
|
};
|
||||||
|
|
||||||
OBJParser(Stream& stream$);
|
OBJParser() = default;
|
||||||
~OBJParser();
|
~OBJParser() = default;
|
||||||
|
|
||||||
const String* GetMaterials() const;
|
inline const String* GetMaterials() const;
|
||||||
unsigned int GetMaterialCount() const;
|
inline unsigned int GetMaterialCount() const;
|
||||||
const Mesh* GetMeshes() const;
|
inline const Mesh* GetMeshes() const;
|
||||||
unsigned int GetMeshCount() const;
|
inline unsigned int GetMeshCount() const;
|
||||||
const String& GetMtlLib() const;
|
inline const String& GetMtlLib() const;
|
||||||
const Vector3f* GetNormals() const;
|
inline const Vector3f* GetNormals() const;
|
||||||
unsigned int GetNormalCount() const;
|
inline unsigned int GetNormalCount() const;
|
||||||
const Vector4f* GetPositions() const;
|
inline const Vector4f* GetPositions() const;
|
||||||
unsigned int GetPositionCount() const;
|
inline unsigned int GetPositionCount() const;
|
||||||
const Vector3f* GetTexCoords() const;
|
inline const Vector3f* GetTexCoords() const;
|
||||||
unsigned int GetTexCoordCount() const;
|
inline unsigned int GetTexCoordCount() const;
|
||||||
|
|
||||||
bool Parse(std::size_t reservedVertexCount = 100);
|
bool Parse(Stream& stream, std::size_t reservedVertexCount = 100);
|
||||||
|
|
||||||
|
bool Save(Stream& stream) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Advance(bool required = true);
|
bool Advance(bool required = true);
|
||||||
void Error(const String& message);
|
template<typename T> void Emit(const T& text) const;
|
||||||
void Warning(const String& message);
|
inline void EmitLine() const;
|
||||||
void UnrecognizedLine(bool error = false);
|
template<typename T> void EmitLine(const T& line) const;
|
||||||
|
inline void Error(const String& message);
|
||||||
|
inline void Flush() const;
|
||||||
|
inline void Warning(const String& message);
|
||||||
|
inline void UnrecognizedLine(bool error = false);
|
||||||
|
|
||||||
std::vector<Mesh> m_meshes;
|
std::vector<Mesh> m_meshes;
|
||||||
std::vector<String> m_materials;
|
std::vector<String> m_materials;
|
||||||
std::vector<Vector3f> m_normals;
|
std::vector<Vector3f> m_normals;
|
||||||
std::vector<Vector4f> m_positions;
|
std::vector<Vector4f> m_positions;
|
||||||
std::vector<Vector3f> m_texCoords;
|
std::vector<Vector3f> m_texCoords;
|
||||||
Stream& m_stream;
|
mutable Stream* m_currentStream;
|
||||||
String m_currentLine;
|
String m_currentLine;
|
||||||
String m_mtlLib;
|
String m_mtlLib;
|
||||||
|
mutable StringStream m_outputStream;
|
||||||
bool m_keepLastLine;
|
bool m_keepLastLine;
|
||||||
unsigned int m_lineCount;
|
unsigned int m_lineCount;
|
||||||
unsigned int m_streamFlags;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Utility/Formats/OBJParser.inl>
|
||||||
|
|
||||||
#endif // NAZARA_FORMATS_OBJPARSER_HPP
|
#endif // NAZARA_FORMATS_OBJPARSER_HPP
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright (C) 2016 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/Formats/OBJParser.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
inline const String* OBJParser::GetMaterials() const
|
||||||
|
{
|
||||||
|
return m_materials.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int OBJParser::GetMaterialCount() const
|
||||||
|
{
|
||||||
|
return m_materials.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const OBJParser::Mesh* OBJParser::GetMeshes() const
|
||||||
|
{
|
||||||
|
return m_meshes.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int OBJParser::GetMeshCount() const
|
||||||
|
{
|
||||||
|
return m_meshes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const String& OBJParser::GetMtlLib() const
|
||||||
|
{
|
||||||
|
return m_mtlLib;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Vector3f* OBJParser::GetNormals() const
|
||||||
|
{
|
||||||
|
return m_normals.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int OBJParser::GetNormalCount() const
|
||||||
|
{
|
||||||
|
return m_normals.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Vector4f* OBJParser::GetPositions() const
|
||||||
|
{
|
||||||
|
return m_positions.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int OBJParser::GetPositionCount() const
|
||||||
|
{
|
||||||
|
return m_positions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Vector3f* OBJParser::GetTexCoords() const
|
||||||
|
{
|
||||||
|
return m_texCoords.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int OBJParser::GetTexCoordCount() const
|
||||||
|
{
|
||||||
|
return m_texCoords.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void OBJParser::Emit(const T& text) const
|
||||||
|
{
|
||||||
|
m_outputStream << text;
|
||||||
|
if (m_outputStream.GetBufferSize() > 1024 * 1024)
|
||||||
|
Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OBJParser::EmitLine() const
|
||||||
|
{
|
||||||
|
Emit('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void OBJParser::EmitLine(const T& line) const
|
||||||
|
{
|
||||||
|
Emit(line);
|
||||||
|
Emit('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OBJParser::Error(const String& message)
|
||||||
|
{
|
||||||
|
NazaraError(message + " at line #" + String::Number(m_lineCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OBJParser::Flush() const
|
||||||
|
{
|
||||||
|
m_currentStream->Write(m_outputStream);
|
||||||
|
m_outputStream.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OBJParser::Warning(const String& message)
|
||||||
|
{
|
||||||
|
NazaraWarning(message + " at line #" + String::Number(m_lineCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OBJParser::UnrecognizedLine(bool error)
|
||||||
|
{
|
||||||
|
String message = "Unrecognized \"" + m_currentLine + '"';
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
Error(message);
|
||||||
|
else
|
||||||
|
Warning(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Utility/DebugOff.hpp>
|
||||||
|
|
@ -22,6 +22,7 @@ namespace Nz
|
||||||
static constexpr const char* BackFaceStencilReference = "MatBackFaceStencilReference";
|
static constexpr const char* BackFaceStencilReference = "MatBackFaceStencilReference";
|
||||||
static constexpr const char* BackFaceStencilZFail = "MatBackFaceStencilZFail";
|
static constexpr const char* BackFaceStencilZFail = "MatBackFaceStencilZFail";
|
||||||
static constexpr const char* Blending = "MatBlending";
|
static constexpr const char* Blending = "MatBlending";
|
||||||
|
static constexpr const char* CullingSide = "MatCullingSide";
|
||||||
static constexpr const char* CustomDefined = "MatCustomDefined";
|
static constexpr const char* CustomDefined = "MatCustomDefined";
|
||||||
static constexpr const char* ColorWrite = "MatColorWrite";
|
static constexpr const char* ColorWrite = "MatColorWrite";
|
||||||
static constexpr const char* DepthBuffer = "MatDepthBuffer";
|
static constexpr const char* DepthBuffer = "MatDepthBuffer";
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@ namespace Nz
|
||||||
|
|
||||||
String s_pluginFiles[] =
|
String s_pluginFiles[] =
|
||||||
{
|
{
|
||||||
"NazaraAssimp", // Plugin_Assimp
|
"PluginAssimp", // Plugin_Assimp
|
||||||
"NazaraFreetype" // Plugin_FreeType
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +79,13 @@ namespace Nz
|
||||||
|
|
||||||
bool PluginManager::Mount(Plugin plugin)
|
bool PluginManager::Mount(Plugin plugin)
|
||||||
{
|
{
|
||||||
return Mount(s_pluginFiles[plugin]);
|
Nz::String pluginName = s_pluginFiles[plugin];
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (Mount(pluginName + "-d", true))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Mount(pluginName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,7 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String::String(const std::string& string) :
|
String::String(const std::string& string) :
|
||||||
String(string.c_str(), string.size())
|
String(string.data(), string.size())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "..\..\..\include\Nazara\Core\StringStream.hpp"
|
||||||
// Copyright (C) 2015 Jérôme Leclercq
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
// This file is part of the "Nazara Engine - Core module"
|
// This file is part of the "Nazara Engine - Core module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
@ -16,7 +17,6 @@ namespace Nz
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a StringStream object by default
|
* \brief Constructs a StringStream object by default
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream::StringStream() :
|
StringStream::StringStream() :
|
||||||
m_bufferSize(0)
|
m_bufferSize(0)
|
||||||
{
|
{
|
||||||
|
|
@ -27,18 +27,34 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param str First value of the stream
|
* \param str First value of the stream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream::StringStream(const String& str) :
|
StringStream::StringStream(const String& str) :
|
||||||
m_bufferSize(str.GetSize())
|
m_bufferSize(str.GetSize())
|
||||||
{
|
{
|
||||||
m_strings.push_back(str);
|
m_strings.push_back(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Resets the state of the stream, erasing every contained text
|
||||||
|
*/
|
||||||
|
void StringStream::Clear()
|
||||||
|
{
|
||||||
|
m_bufferSize = 0;
|
||||||
|
m_strings.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the current buffer size
|
||||||
|
* \return The internal accumulation buffer size, this is equivalent to the size of the final string
|
||||||
|
*/
|
||||||
|
std::size_t StringStream::GetBufferSize() const
|
||||||
|
{
|
||||||
|
return m_bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gives a string representation
|
* \brief Gives a string representation
|
||||||
* \return A string representation of the object where every objects of the stream has been converted with Nz::String
|
* \return A string representation of the object where every objects of the stream has been converted with Nz::String
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String StringStream::ToString() const
|
String StringStream::ToString() const
|
||||||
{
|
{
|
||||||
String string;
|
String string;
|
||||||
|
|
@ -56,7 +72,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param boolean Boolean value
|
* \param boolean Boolean value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(bool boolean)
|
StringStream& StringStream::operator<<(bool boolean)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Boolean(boolean));
|
m_strings.push_back(String::Boolean(boolean));
|
||||||
|
|
@ -71,7 +86,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Short value
|
* \param number Short value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(short number)
|
StringStream& StringStream::operator<<(short number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -86,7 +100,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Short value
|
* \param number Short value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(unsigned short number)
|
StringStream& StringStream::operator<<(unsigned short number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -101,7 +114,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Int value
|
* \param number Int value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(int number)
|
StringStream& StringStream::operator<<(int number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -116,7 +128,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Int value
|
* \param number Int value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(unsigned int number)
|
StringStream& StringStream::operator<<(unsigned int number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -131,7 +142,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Long value
|
* \param number Long value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(long number)
|
StringStream& StringStream::operator<<(long number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -146,7 +156,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Long value
|
* \param number Long value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(unsigned long number)
|
StringStream& StringStream::operator<<(unsigned long number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -161,7 +170,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Long long value
|
* \param number Long long value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(long long number)
|
StringStream& StringStream::operator<<(long long number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -176,7 +184,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Long long value
|
* \param number Long long value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(unsigned long long number)
|
StringStream& StringStream::operator<<(unsigned long long number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -191,7 +198,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Float value
|
* \param number Float value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(float number)
|
StringStream& StringStream::operator<<(float number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -206,7 +212,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Double value
|
* \param number Double value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(double number)
|
StringStream& StringStream::operator<<(double number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -221,7 +226,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param number Long double value
|
* \param number Long double value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(long double number)
|
StringStream& StringStream::operator<<(long double number)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Number(number));
|
m_strings.push_back(String::Number(number));
|
||||||
|
|
@ -236,7 +240,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param character Char value
|
* \param character Char value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(char character)
|
StringStream& StringStream::operator<<(char character)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String(character));
|
m_strings.push_back(String(character));
|
||||||
|
|
@ -251,7 +254,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param character Char value
|
* \param character Char value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(unsigned char character)
|
StringStream& StringStream::operator<<(unsigned char character)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String(static_cast<char>(character)));
|
m_strings.push_back(String(static_cast<char>(character)));
|
||||||
|
|
@ -266,7 +268,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param string String value
|
* \param string String value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(const char* string)
|
StringStream& StringStream::operator<<(const char* string)
|
||||||
{
|
{
|
||||||
m_strings.push_back(string);
|
m_strings.push_back(string);
|
||||||
|
|
@ -281,7 +282,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param string String value
|
* \param string String value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(const std::string& string)
|
StringStream& StringStream::operator<<(const std::string& string)
|
||||||
{
|
{
|
||||||
m_strings.push_back(string);
|
m_strings.push_back(string);
|
||||||
|
|
@ -296,7 +296,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param string String value
|
* \param string String value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(const String& string)
|
StringStream& StringStream::operator<<(const String& string)
|
||||||
{
|
{
|
||||||
m_strings.push_back(string);
|
m_strings.push_back(string);
|
||||||
|
|
@ -311,7 +310,6 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param ptr Pointer value
|
* \param ptr Pointer value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream& StringStream::operator<<(const void* ptr)
|
StringStream& StringStream::operator<<(const void* ptr)
|
||||||
{
|
{
|
||||||
m_strings.push_back(String::Pointer(ptr));
|
m_strings.push_back(String::Pointer(ptr));
|
||||||
|
|
@ -324,7 +322,6 @@ namespace Nz
|
||||||
* \brief Converts this to Nz::String
|
* \brief Converts this to Nz::String
|
||||||
* \return The string representation of the stream
|
* \return The string representation of the stream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
StringStream::operator String() const
|
StringStream::operator String() const
|
||||||
{
|
{
|
||||||
return ToString();
|
return ToString();
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Nz
|
||||||
if (!m_material)
|
if (!m_material)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
renderQueue->AddBillboard(instanceData.renderOrder, m_material, instanceData.transformMatrix.GetTranslation(), m_size, m_sinCos, m_color);
|
renderQueue->AddBillboard(instanceData.renderOrder, m_material, instanceData.transformMatrix->GetTranslation(), m_size, m_sinCos, m_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ namespace Nz
|
||||||
NazaraAssert(instanceData, "Invalid instance data");
|
NazaraAssert(instanceData, "Invalid instance data");
|
||||||
NazaraUnused(instanceData);
|
NazaraUnused(instanceData);
|
||||||
|
|
||||||
instanceData->volume.Update(instanceData->transformMatrix);
|
instanceData->volume.Update(*instanceData->transformMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,9 @@ namespace Nz
|
||||||
if (matData.GetColorParameter(MaterialData::AmbientColor, &color))
|
if (matData.GetColorParameter(MaterialData::AmbientColor, &color))
|
||||||
SetAmbientColor(color);
|
SetAmbientColor(color);
|
||||||
|
|
||||||
|
if (matData.GetIntegerParameter(MaterialData::CullingSide, &iValue))
|
||||||
|
SetFaceCulling(static_cast<FaceSide>(iValue));
|
||||||
|
|
||||||
if (matData.GetIntegerParameter(MaterialData::DepthFunc, &iValue))
|
if (matData.GetIntegerParameter(MaterialData::DepthFunc, &iValue))
|
||||||
SetDepthFunc(static_cast<RendererComparison>(iValue));
|
SetDepthFunc(static_cast<RendererComparison>(iValue));
|
||||||
|
|
||||||
|
|
@ -182,9 +185,6 @@ namespace Nz
|
||||||
if (matData.GetIntegerParameter(MaterialData::DstBlend, &iValue))
|
if (matData.GetIntegerParameter(MaterialData::DstBlend, &iValue))
|
||||||
SetDstBlend(static_cast<BlendFunc>(iValue));
|
SetDstBlend(static_cast<BlendFunc>(iValue));
|
||||||
|
|
||||||
if (matData.GetIntegerParameter(MaterialData::FaceCulling, &iValue))
|
|
||||||
SetFaceCulling(static_cast<FaceSide>(iValue));
|
|
||||||
|
|
||||||
if (matData.GetIntegerParameter(MaterialData::FaceFilling, &iValue))
|
if (matData.GetIntegerParameter(MaterialData::FaceFilling, &iValue))
|
||||||
SetFaceFilling(static_cast<FaceFilling>(iValue));
|
SetFaceFilling(static_cast<FaceFilling>(iValue));
|
||||||
|
|
||||||
|
|
@ -310,10 +310,108 @@ namespace Nz
|
||||||
SetShader(matParams.shaderName);
|
SetShader(matParams.shaderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Material::SaveToParameters(ParameterList* matData)
|
||||||
|
{
|
||||||
|
NazaraAssert(matData, "Invalid ParameterList");
|
||||||
|
|
||||||
|
matData->SetParameter(MaterialData::AlphaTest, IsAlphaTestEnabled());
|
||||||
|
matData->SetParameter(MaterialData::AlphaThreshold, GetAlphaThreshold());
|
||||||
|
matData->SetParameter(MaterialData::AmbientColor, GetAmbientColor());
|
||||||
|
matData->SetParameter(MaterialData::CullingSide, int(GetFaceCulling()));
|
||||||
|
matData->SetParameter(MaterialData::DepthFunc, int(GetDepthFunc()));
|
||||||
|
matData->SetParameter(MaterialData::DepthSorting, IsDepthSortingEnabled());
|
||||||
|
matData->SetParameter(MaterialData::DiffuseColor, GetDiffuseColor());
|
||||||
|
matData->SetParameter(MaterialData::DstBlend, int(GetDstBlend()));
|
||||||
|
matData->SetParameter(MaterialData::FaceFilling, int(GetFaceFilling()));
|
||||||
|
matData->SetParameter(MaterialData::Lighting, IsLightingEnabled());
|
||||||
|
matData->SetParameter(MaterialData::LineWidth, GetRenderStates().lineWidth);
|
||||||
|
matData->SetParameter(MaterialData::PointSize, GetRenderStates().pointSize);
|
||||||
|
matData->SetParameter(MaterialData::Shininess, GetShininess());
|
||||||
|
matData->SetParameter(MaterialData::SpecularColor, GetSpecularColor());
|
||||||
|
matData->SetParameter(MaterialData::SrcBlend, int(GetSrcBlend()));
|
||||||
|
matData->SetParameter(MaterialData::Transform, IsTransformEnabled());
|
||||||
|
|
||||||
|
// RendererParameter
|
||||||
|
matData->SetParameter(MaterialData::Blending, GetRenderStates().parameters[RendererParameter_Blend]);
|
||||||
|
matData->SetParameter(MaterialData::ColorWrite, GetRenderStates().parameters[RendererParameter_ColorWrite]);
|
||||||
|
matData->SetParameter(MaterialData::DepthBuffer, GetRenderStates().parameters[RendererParameter_DepthBuffer]);
|
||||||
|
matData->SetParameter(MaterialData::DepthWrite, GetRenderStates().parameters[RendererParameter_DepthWrite]);
|
||||||
|
matData->SetParameter(MaterialData::FaceCulling, GetRenderStates().parameters[RendererParameter_FaceCulling]);
|
||||||
|
matData->SetParameter(MaterialData::ScissorTest, GetRenderStates().parameters[RendererParameter_ScissorTest]);
|
||||||
|
matData->SetParameter(MaterialData::StencilTest, GetRenderStates().parameters[RendererParameter_StencilTest]);
|
||||||
|
|
||||||
|
// Samplers
|
||||||
|
matData->SetParameter(MaterialData::DiffuseAnisotropyLevel, int(GetDiffuseSampler().GetAnisotropicLevel()));
|
||||||
|
matData->SetParameter(MaterialData::DiffuseFilter, int(GetDiffuseSampler().GetFilterMode()));
|
||||||
|
matData->SetParameter(MaterialData::DiffuseWrap, int(GetDiffuseSampler().GetWrapMode()));
|
||||||
|
|
||||||
|
matData->SetParameter(MaterialData::SpecularAnisotropyLevel, int(GetSpecularSampler().GetAnisotropicLevel()));
|
||||||
|
matData->SetParameter(MaterialData::SpecularFilter, int(GetSpecularSampler().GetFilterMode()));
|
||||||
|
matData->SetParameter(MaterialData::SpecularWrap, int(GetSpecularSampler().GetWrapMode()));
|
||||||
|
|
||||||
|
// Stencil
|
||||||
|
matData->SetParameter(MaterialData::StencilCompare, int(GetRenderStates().frontFace.stencilCompare));
|
||||||
|
matData->SetParameter(MaterialData::StencilFail, int(GetRenderStates().frontFace.stencilFail));
|
||||||
|
matData->SetParameter(MaterialData::StencilPass, int(GetRenderStates().frontFace.stencilPass));
|
||||||
|
matData->SetParameter(MaterialData::StencilZFail, int(GetRenderStates().frontFace.stencilZFail));
|
||||||
|
matData->SetParameter(MaterialData::StencilMask, int(GetRenderStates().frontFace.stencilMask));
|
||||||
|
matData->SetParameter(MaterialData::StencilReference, int(GetRenderStates().frontFace.stencilReference));
|
||||||
|
|
||||||
|
// Stencil (back)
|
||||||
|
matData->SetParameter(MaterialData::BackFaceStencilCompare, int(GetRenderStates().backFace.stencilCompare));
|
||||||
|
matData->SetParameter(MaterialData::BackFaceStencilFail, int(GetRenderStates().backFace.stencilFail));
|
||||||
|
matData->SetParameter(MaterialData::BackFaceStencilPass, int(GetRenderStates().backFace.stencilPass));
|
||||||
|
matData->SetParameter(MaterialData::BackFaceStencilZFail, int(GetRenderStates().backFace.stencilZFail));
|
||||||
|
matData->SetParameter(MaterialData::BackFaceStencilMask, int(GetRenderStates().backFace.stencilMask));
|
||||||
|
matData->SetParameter(MaterialData::BackFaceStencilReference, int(GetRenderStates().backFace.stencilReference));
|
||||||
|
|
||||||
|
// Textures
|
||||||
|
if (HasAlphaMap())
|
||||||
|
{
|
||||||
|
const String& path = GetAlphaMap()->GetFilePath();
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
matData->SetParameter(MaterialData::AlphaTexturePath, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasDiffuseMap())
|
||||||
|
{
|
||||||
|
const String& path = GetDiffuseMap()->GetFilePath();
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
matData->SetParameter(MaterialData::DiffuseTexturePath, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasEmissiveMap())
|
||||||
|
{
|
||||||
|
const String& path = GetEmissiveMap()->GetFilePath();
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
matData->SetParameter(MaterialData::EmissiveTexturePath, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasHeightMap())
|
||||||
|
{
|
||||||
|
const String& path = GetHeightMap()->GetFilePath();
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
matData->SetParameter(MaterialData::HeightTexturePath, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasNormalMap())
|
||||||
|
{
|
||||||
|
const String& path = GetNormalMap()->GetFilePath();
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
matData->SetParameter(MaterialData::NormalTexturePath, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasSpecularMap())
|
||||||
|
{
|
||||||
|
const String& path = GetSpecularMap()->GetFilePath();
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
matData->SetParameter(MaterialData::SpecularTexturePath, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Resets the material, cleans everything
|
* \brief Resets the material, cleans everything
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Material::Reset()
|
void Material::Reset()
|
||||||
{
|
{
|
||||||
OnMaterialReset(this);
|
OnMaterialReset(this);
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace Nz
|
||||||
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
||||||
meshData.vertexBuffer = mesh->GetVertexBuffer();
|
meshData.vertexBuffer = mesh->GetVertexBuffer();
|
||||||
|
|
||||||
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, mesh->GetAABB(), instanceData.transformMatrix);
|
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, mesh->GetAABB(), *instanceData.transformMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ namespace Nz
|
||||||
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
meshData.primitiveMode = mesh->GetPrimitiveMode();
|
||||||
meshData.vertexBuffer = SkinningManager::GetBuffer(mesh, &m_skeleton);
|
meshData.vertexBuffer = SkinningManager::GetBuffer(mesh, &m_skeleton);
|
||||||
|
|
||||||
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, m_skeleton.GetAABB(), instanceData.transformMatrix);
|
renderQueue->AddMesh(instanceData.renderOrder, material, meshData, m_skeleton.GetAABB(), *instanceData.transformMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,19 +58,19 @@ namespace Nz
|
||||||
SparsePtr<Vector2f> texCoordPtr(&vertices[0].uv, sizeof(VertexStruct_XYZ_Color_UV));
|
SparsePtr<Vector2f> texCoordPtr(&vertices[0].uv, sizeof(VertexStruct_XYZ_Color_UV));
|
||||||
|
|
||||||
*colorPtr++ = m_color;
|
*colorPtr++ = m_color;
|
||||||
*posPtr++ = instanceData->transformMatrix.Transform(Vector3f(0.f));
|
*posPtr++ = instanceData->transformMatrix->Transform(Vector3f(0.f));
|
||||||
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_LeftTop);
|
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_LeftTop);
|
||||||
|
|
||||||
*colorPtr++ = m_color;
|
*colorPtr++ = m_color;
|
||||||
*posPtr++ = instanceData->transformMatrix.Transform(m_size.x*Vector3f::Right());
|
*posPtr++ = instanceData->transformMatrix->Transform(m_size.x*Vector3f::Right());
|
||||||
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightTop);
|
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightTop);
|
||||||
|
|
||||||
*colorPtr++ = m_color;
|
*colorPtr++ = m_color;
|
||||||
*posPtr++ = instanceData->transformMatrix.Transform(m_size.y*Vector3f::Down());
|
*posPtr++ = instanceData->transformMatrix->Transform(m_size.y*Vector3f::Down());
|
||||||
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_LeftBottom);
|
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_LeftBottom);
|
||||||
|
|
||||||
*colorPtr++ = m_color;
|
*colorPtr++ = m_color;
|
||||||
*posPtr++ = instanceData->transformMatrix.Transform(m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down());
|
*posPtr++ = instanceData->transformMatrix->Transform(m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down());
|
||||||
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightBottom);
|
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ namespace Nz
|
||||||
Vector3f localPos = localVertex->position.x*Vector3f::Right() + localVertex->position.y*Vector3f::Down();
|
Vector3f localPos = localVertex->position.x*Vector3f::Right() + localVertex->position.y*Vector3f::Down();
|
||||||
localPos *= m_scale;
|
localPos *= m_scale;
|
||||||
|
|
||||||
*pos++ = instanceData->transformMatrix.Transform(localPos);
|
*pos++ = instanceData->transformMatrix->Transform(localPos);
|
||||||
*color++ = m_color * localVertex->color;
|
*color++ = m_color * localVertex->color;
|
||||||
*uv++ = localVertex->uv;
|
*uv++ = localVertex->uv;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -582,6 +582,9 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep resource path info
|
||||||
|
SetFilePath(image.GetFilePath());
|
||||||
|
|
||||||
destroyOnExit.Reset();
|
destroyOnExit.Reset();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,8 @@ namespace Nz
|
||||||
if (!parameters.custom.GetIntegerParameter("NativeOBJLoader_VertexCount", &reservedVertexCount))
|
if (!parameters.custom.GetIntegerParameter("NativeOBJLoader_VertexCount", &reservedVertexCount))
|
||||||
reservedVertexCount = 100;
|
reservedVertexCount = 100;
|
||||||
|
|
||||||
OBJParser parser(stream);
|
OBJParser parser;
|
||||||
if (!parser.Parse(reservedVertexCount))
|
if (!parser.Parse(stream, reservedVertexCount))
|
||||||
{
|
{
|
||||||
NazaraError("OBJ parser failed");
|
NazaraError("OBJ parser failed");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -184,16 +184,17 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<OBJParser::FaceVertex, unsigned int, FaceVertexHasher, FaceVertexComparator> vertices;
|
std::unordered_map<OBJParser::FaceVertex, unsigned int, FaceVertexHasher, FaceVertexComparator> vertices;
|
||||||
|
vertices.reserve(meshes[i].vertices.size());
|
||||||
|
|
||||||
unsigned int vertexCount = 0;
|
unsigned int vertexCount = 0;
|
||||||
for (unsigned int j = 0; j < faceCount; ++j)
|
for (unsigned int j = 0; j < faceCount; ++j)
|
||||||
{
|
{
|
||||||
unsigned int faceVertexCount = meshes[i].faces[j].vertices.size();
|
unsigned int faceVertexCount = meshes[i].faces[j].vertexCount;
|
||||||
faceIndices.resize(faceVertexCount);
|
faceIndices.resize(faceVertexCount);
|
||||||
|
|
||||||
for (unsigned int k = 0; k < faceVertexCount; ++k)
|
for (unsigned int k = 0; k < faceVertexCount; ++k)
|
||||||
{
|
{
|
||||||
const OBJParser::FaceVertex& vertex = meshes[i].faces[j].vertices[k];
|
const OBJParser::FaceVertex& vertex = meshes[i].vertices[meshes[i].faces[j].firstVertex + k];
|
||||||
|
|
||||||
auto it = vertices.find(vertex);
|
auto it = vertices.find(vertex);
|
||||||
if (it == vertices.end())
|
if (it == vertices.end())
|
||||||
|
|
@ -202,6 +203,7 @@ namespace Nz
|
||||||
faceIndices[k] = it->second;
|
faceIndices[k] = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Triangulation
|
||||||
for (unsigned int k = 1; k < faceVertexCount-1; ++k)
|
for (unsigned int k = 1; k < faceVertexCount-1; ++k)
|
||||||
{
|
{
|
||||||
indices.push_back(faceIndices[0]);
|
indices.push_back(faceIndices[0]);
|
||||||
|
|
@ -233,17 +235,17 @@ namespace Nz
|
||||||
|
|
||||||
MeshVertex& vertex = meshVertices[index];
|
MeshVertex& vertex = meshVertices[index];
|
||||||
|
|
||||||
const Vector4f& vec = positions[vertexIndices.position];
|
const Vector4f& vec = positions[vertexIndices.position-1];
|
||||||
vertex.position = Vector3f(parameters.matrix * vec);
|
vertex.position = Vector3f(parameters.matrix * vec);
|
||||||
|
|
||||||
if (vertexIndices.normal >= 0)
|
if (vertexIndices.normal > 0)
|
||||||
vertex.normal = normals[vertexIndices.normal];
|
vertex.normal = normals[vertexIndices.normal-1];
|
||||||
else
|
else
|
||||||
hasNormals = false;
|
hasNormals = false;
|
||||||
|
|
||||||
if (vertexIndices.texCoord >= 0)
|
if (vertexIndices.texCoord > 0)
|
||||||
{
|
{
|
||||||
const Vector3f& uvw = texCoords[vertexIndices.texCoord];
|
const Vector3f& uvw = texCoords[vertexIndices.texCoord-1];
|
||||||
vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé
|
vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Utility/Formats/OBJParser.hpp>
|
#include <Nazara/Utility/Formats/OBJParser.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/Core/Log.hpp>
|
#include <Nazara/Core/Log.hpp>
|
||||||
#include <Nazara/Utility/Config.hpp>
|
#include <Nazara/Utility/Config.hpp>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
@ -13,77 +13,22 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
OBJParser::OBJParser(Stream& stream) :
|
bool OBJParser::Parse(Nz::Stream& stream, std::size_t reservedVertexCount)
|
||||||
m_stream(stream),
|
|
||||||
m_streamFlags(stream.GetStreamOptions()) //< Saves stream flags
|
|
||||||
{
|
{
|
||||||
m_stream.EnableTextMode(true);
|
m_currentStream = &stream;
|
||||||
|
|
||||||
|
// Force stream in text mode, reset it at the end
|
||||||
|
Nz::CallOnExit resetTextMode;
|
||||||
|
if ((stream.GetStreamOptions() & StreamOption_Text) == 0)
|
||||||
|
{
|
||||||
|
stream.EnableTextMode(true);
|
||||||
|
|
||||||
|
resetTextMode.Reset([&stream] ()
|
||||||
|
{
|
||||||
|
stream.EnableTextMode(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJParser::~OBJParser()
|
|
||||||
{
|
|
||||||
// Reset stream flags
|
|
||||||
if ((m_streamFlags & StreamOption_Text) == 0)
|
|
||||||
m_stream.EnableTextMode(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const String* OBJParser::GetMaterials() const
|
|
||||||
{
|
|
||||||
return m_materials.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int OBJParser::GetMaterialCount() const
|
|
||||||
{
|
|
||||||
return m_materials.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const OBJParser::Mesh* OBJParser::GetMeshes() const
|
|
||||||
{
|
|
||||||
return m_meshes.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int OBJParser::GetMeshCount() const
|
|
||||||
{
|
|
||||||
return m_meshes.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const String& OBJParser::GetMtlLib() const
|
|
||||||
{
|
|
||||||
return m_mtlLib;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3f* OBJParser::GetNormals() const
|
|
||||||
{
|
|
||||||
return m_normals.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int OBJParser::GetNormalCount() const
|
|
||||||
{
|
|
||||||
return m_normals.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector4f* OBJParser::GetPositions() const
|
|
||||||
{
|
|
||||||
return m_positions.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int OBJParser::GetPositionCount() const
|
|
||||||
{
|
|
||||||
return m_positions.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector3f* OBJParser::GetTexCoords() const
|
|
||||||
{
|
|
||||||
return m_texCoords.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int OBJParser::GetTexCoordCount() const
|
|
||||||
{
|
|
||||||
return m_texCoords.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OBJParser::Parse(std::size_t reservedVertexCount)
|
|
||||||
{
|
|
||||||
String matName, meshName;
|
String matName, meshName;
|
||||||
matName = meshName = "default";
|
matName = meshName = "default";
|
||||||
m_keepLastLine = false;
|
m_keepLastLine = false;
|
||||||
|
|
@ -100,32 +45,56 @@ namespace Nz
|
||||||
m_positions.reserve(reservedVertexCount);
|
m_positions.reserve(reservedVertexCount);
|
||||||
m_texCoords.reserve(reservedVertexCount);
|
m_texCoords.reserve(reservedVertexCount);
|
||||||
|
|
||||||
// On va regrouper les meshs par nom et par matériau
|
// Sort meshes by material and group
|
||||||
using FaceVec = std::vector<Face>;
|
using MatPair = std::pair<Mesh, unsigned int>;
|
||||||
using MatPair = std::pair<FaceVec, unsigned int>;
|
std::unordered_map<String, std::unordered_map<String, MatPair>> meshesByName;
|
||||||
std::unordered_map<String, std::unordered_map<String, MatPair>> meshes;
|
|
||||||
|
|
||||||
unsigned int matIndex = 0;
|
std::size_t faceReserve = 0;
|
||||||
auto GetMaterial = [&meshes, &matIndex] (const String& mesh, const String& material) -> FaceVec*
|
std::size_t vertexReserve = 0;
|
||||||
|
unsigned int matCount = 0;
|
||||||
|
auto GetMaterial = [&] (const String& meshName, const String& matName) -> Mesh*
|
||||||
{
|
{
|
||||||
auto& map = meshes[mesh];
|
auto& map = meshesByName[meshName];
|
||||||
auto it = map.find(material);
|
auto it = map.find(matName);
|
||||||
if (it == map.end())
|
if (it == map.end())
|
||||||
it = map.insert(std::make_pair(material, MatPair(FaceVec(), matIndex++))).first;
|
it = map.insert(std::make_pair(matName, MatPair(Mesh(), matCount++))).first;
|
||||||
|
|
||||||
|
Mesh& mesh = it->second.first;
|
||||||
|
|
||||||
|
mesh.faces.reserve(faceReserve);
|
||||||
|
mesh.vertices.reserve(vertexReserve);
|
||||||
|
faceReserve = 0;
|
||||||
|
vertexReserve = 0;
|
||||||
|
|
||||||
return &(it->second.first);
|
return &(it->second.first);
|
||||||
};
|
};
|
||||||
|
|
||||||
// On prépare le mesh par défaut
|
// On prépare le mesh par défaut
|
||||||
FaceVec* currentMesh = nullptr;
|
Mesh* currentMesh = nullptr;
|
||||||
|
|
||||||
while (Advance(false))
|
while (Advance(false))
|
||||||
{
|
{
|
||||||
switch (std::tolower(m_currentLine[0]))
|
switch (std::tolower(m_currentLine[0]))
|
||||||
{
|
{
|
||||||
case 'f': // Une face
|
case '#': //< Comment
|
||||||
|
// Some softwares write comments to gives the number of vertex/faces an importer can expect
|
||||||
|
std::size_t data;
|
||||||
|
if (std::sscanf(m_currentLine.GetConstBuffer(), "# position count: %zu", &data) == 1)
|
||||||
|
m_positions.reserve(data);
|
||||||
|
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# normal count: %zu", &data) == 1)
|
||||||
|
m_normals.reserve(data);
|
||||||
|
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# texcoords count: %zu", &data) == 1)
|
||||||
|
m_texCoords.reserve(data);
|
||||||
|
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# face count: %zu", &data) == 1)
|
||||||
|
faceReserve = data;
|
||||||
|
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# vertex count: %zu", &data) == 1)
|
||||||
|
vertexReserve = data;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f': //< Face
|
||||||
{
|
{
|
||||||
if (m_currentLine.GetSize() < 7) // Le minimum syndical pour définir une face de trois sommets (f 1 2 3)
|
if (m_currentLine.GetSize() < 7) // Since we only treat triangles, this is the minimum length of a face line (f 1 2 3)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||||
UnrecognizedLine();
|
UnrecognizedLine();
|
||||||
|
|
@ -142,17 +111,23 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!currentMesh)
|
||||||
|
currentMesh = GetMaterial(meshName, matName);
|
||||||
|
|
||||||
Face face;
|
Face face;
|
||||||
face.vertices.resize(vertexCount);
|
face.firstVertex = currentMesh->vertices.size();
|
||||||
|
face.vertexCount = vertexCount;
|
||||||
|
|
||||||
|
currentMesh->vertices.resize(face.firstVertex + vertexCount, FaceVertex{0, 0, 0});
|
||||||
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
unsigned int pos = 2;
|
unsigned int pos = 2;
|
||||||
for (unsigned int i = 0; i < vertexCount; ++i)
|
for (unsigned int i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
int& n = face.vertices[i].normal;
|
int& n = currentMesh->vertices[face.firstVertex + i].normal;
|
||||||
int& p = face.vertices[i].position;
|
int& p = currentMesh->vertices[face.firstVertex + i].position;
|
||||||
int& t = face.vertices[i].texCoord;
|
int& t = currentMesh->vertices[face.firstVertex + i].texCoord;
|
||||||
|
|
||||||
if (std::sscanf(&m_currentLine[pos], "%d/%d/%d%n", &p, &t, &n, &offset) != 3)
|
if (std::sscanf(&m_currentLine[pos], "%d/%d/%d%n", &p, &t, &n, &offset) != 3)
|
||||||
{
|
{
|
||||||
|
|
@ -168,22 +143,13 @@ namespace Nz
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
n = 0;
|
|
||||||
t = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
t = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p < 0)
|
if (p < 0)
|
||||||
{
|
{
|
||||||
p += m_positions.size();
|
p += m_positions.size() - 1;
|
||||||
if (p < 0)
|
if (p < 0)
|
||||||
{
|
{
|
||||||
Error("Vertex index out of range (" + String::Number(p) + " < 0");
|
Error("Vertex index out of range (" + String::Number(p) + " < 0");
|
||||||
|
|
@ -191,48 +157,42 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
p--;
|
|
||||||
|
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
n += m_normals.size();
|
n += m_normals.size() - 1;
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
Error("Vertex index out of range (" + String::Number(n) + " < 0");
|
Error("Normal index out of range (" + String::Number(n) + " < 0");
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
n--;
|
|
||||||
|
|
||||||
if (t < 0)
|
if (t < 0)
|
||||||
{
|
{
|
||||||
t += m_texCoords.size();
|
t += m_texCoords.size() - 1;
|
||||||
if (t < 0)
|
if (t < 0)
|
||||||
{
|
{
|
||||||
Error("Vertex index out of range (" + String::Number(t) + " < 0");
|
Error("Texture coordinates index out of range (" + String::Number(t) + " < 0");
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
t--;
|
|
||||||
|
|
||||||
if (static_cast<unsigned int>(p) >= m_positions.size())
|
if (static_cast<std::size_t>(p) > m_positions.size())
|
||||||
{
|
{
|
||||||
Error("Vertex index out of range (" + String::Number(p) + " >= " + String::Number(m_positions.size()) + ')');
|
Error("Vertex index out of range (" + String::Number(p) + " >= " + String::Number(m_positions.size()) + ')');
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (n >= 0 && static_cast<unsigned int>(n) >= m_normals.size())
|
else if (n != 0 && static_cast<std::size_t>(n) > m_normals.size())
|
||||||
{
|
{
|
||||||
Error("Normal index out of range (" + String::Number(n) + " >= " + String::Number(m_normals.size()) + ')');
|
Error("Normal index out of range (" + String::Number(n) + " >= " + String::Number(m_normals.size()) + ')');
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (t >= 0 && static_cast<unsigned int>(t) >= m_texCoords.size())
|
else if (t != 0 && static_cast<std::size_t>(t) > m_texCoords.size())
|
||||||
{
|
{
|
||||||
Error("TexCoord index out of range (" + String::Number(t) + " >= " + String::Number(m_texCoords.size()) + ')');
|
Error("TexCoord index out of range (" + String::Number(t) + " >= " + String::Number(m_texCoords.size()) + ')');
|
||||||
error = true;
|
error = true;
|
||||||
|
|
@ -243,17 +203,14 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
currentMesh->faces.push_back(std::move(face));
|
||||||
if (!currentMesh)
|
else
|
||||||
currentMesh = GetMaterial(meshName, matName);
|
currentMesh->vertices.resize(face.firstVertex); //< Remove vertices
|
||||||
|
|
||||||
currentMesh->push_back(std::move(face));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'm':
|
case 'm': //< MTLLib
|
||||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||||
if (m_currentLine.GetWord(0).ToLower() != "mtllib")
|
if (m_currentLine.GetWord(0).ToLower() != "mtllib")
|
||||||
UnrecognizedLine();
|
UnrecognizedLine();
|
||||||
|
|
@ -262,8 +219,8 @@ namespace Nz
|
||||||
m_mtlLib = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
m_mtlLib = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g': //< Group (inside a mesh)
|
||||||
case 'o':
|
case 'o': //< Object (defines a mesh)
|
||||||
{
|
{
|
||||||
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] != ' ')
|
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] != ' ')
|
||||||
{
|
{
|
||||||
|
|
@ -283,12 +240,12 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
meshName = objectName;
|
meshName = objectName;
|
||||||
currentMesh = GetMaterial(meshName, matName);
|
currentMesh = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||||
case 's':
|
case 's': //< Smooth
|
||||||
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ')
|
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ')
|
||||||
{
|
{
|
||||||
String param = m_currentLine.SubString(2);
|
String param = m_currentLine.SubString(2);
|
||||||
|
|
@ -300,13 +257,14 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 'u':
|
case 'u': //< Usemtl
|
||||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||||
if (m_currentLine.GetWord(0) != "usemtl")
|
if (m_currentLine.GetWord(0) != "usemtl")
|
||||||
UnrecognizedLine();
|
UnrecognizedLine();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
matName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
matName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
||||||
|
currentMesh = nullptr;
|
||||||
if (matName.IsEmpty())
|
if (matName.IsEmpty())
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||||
|
|
@ -314,18 +272,16 @@ namespace Nz
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentMesh = GetMaterial(meshName, matName);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v': //< Position/Normal/Texcoords
|
||||||
{
|
{
|
||||||
String word = m_currentLine.GetWord(0).ToLower();
|
String word = m_currentLine.GetWord(0).ToLower();
|
||||||
if (word == 'v')
|
if (word == 'v')
|
||||||
{
|
{
|
||||||
Vector4f vertex(Vector3f::Zero(), 1.f);
|
Vector4f vertex(Vector3f::Zero(), 1.f);
|
||||||
unsigned int paramCount = std::sscanf(&m_currentLine[2], "%f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w);
|
unsigned int paramCount = std::sscanf(&m_currentLine[2], "%f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w);
|
||||||
if (paramCount >= 3)
|
if (paramCount >= 1)
|
||||||
m_positions.push_back(vertex);
|
m_positions.push_back(vertex);
|
||||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||||
else
|
else
|
||||||
|
|
@ -371,26 +327,24 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<String, unsigned int> materials;
|
std::unordered_map<String, unsigned int> materials;
|
||||||
m_materials.resize(matIndex);
|
m_materials.resize(matCount);
|
||||||
|
|
||||||
for (auto& meshIt : meshes)
|
for (auto& meshPair : meshesByName)
|
||||||
{
|
{
|
||||||
for (auto& matIt : meshIt.second)
|
for (auto& matPair : meshPair.second)
|
||||||
{
|
{
|
||||||
auto& faceVec = matIt.second.first;
|
Mesh& mesh = matPair.second.first;
|
||||||
unsigned int index = matIt.second.second;
|
unsigned int index = matPair.second.second;
|
||||||
if (!faceVec.empty())
|
if (!mesh.faces.empty())
|
||||||
{
|
{
|
||||||
Mesh mesh;
|
mesh.name = meshPair.first;
|
||||||
mesh.faces = std::move(faceVec);
|
|
||||||
mesh.name = meshIt.first;
|
|
||||||
|
|
||||||
auto it = materials.find(matIt.first);
|
auto it = materials.find(matPair.first);
|
||||||
if (it == materials.end())
|
if (it == materials.end())
|
||||||
{
|
{
|
||||||
mesh.material = index;
|
mesh.material = index;
|
||||||
materials[matIt.first] = index;
|
materials[matPair.first] = index;
|
||||||
m_materials[index] = matIt.first;
|
m_materials[index] = matPair.first;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mesh.material = it->second;
|
mesh.material = it->second;
|
||||||
|
|
@ -409,13 +363,155 @@ namespace Nz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OBJParser::Save(Stream& stream) const
|
||||||
|
{
|
||||||
|
m_currentStream = &stream;
|
||||||
|
|
||||||
|
// Force stream in text mode, reset it at the end
|
||||||
|
Nz::CallOnExit resetTextMode;
|
||||||
|
if ((stream.GetStreamOptions() & StreamOption_Text) == 0)
|
||||||
|
{
|
||||||
|
stream.EnableTextMode(true);
|
||||||
|
|
||||||
|
resetTextMode.Reset([&stream] ()
|
||||||
|
{
|
||||||
|
stream.EnableTextMode(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
m_outputStream.Clear();
|
||||||
|
|
||||||
|
EmitLine("# Exported by Nazara Engine");
|
||||||
|
|
||||||
|
if (!m_mtlLib.IsEmpty())
|
||||||
|
{
|
||||||
|
Emit("mtlib ");
|
||||||
|
EmitLine(m_mtlLib);
|
||||||
|
EmitLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
Emit("# position count: ");
|
||||||
|
EmitLine(m_positions.size());
|
||||||
|
|
||||||
|
for (const Nz::Vector4f& position : m_positions)
|
||||||
|
{
|
||||||
|
Emit("v ");
|
||||||
|
Emit(position.x);
|
||||||
|
Emit(' ');
|
||||||
|
Emit(position.y);
|
||||||
|
if (!NumberEquals(position.z, 0.f) || !NumberEquals(position.w, 1.f))
|
||||||
|
{
|
||||||
|
Emit(' ');
|
||||||
|
Emit(position.z);
|
||||||
|
|
||||||
|
if (!NumberEquals(position.w, 1.f))
|
||||||
|
{
|
||||||
|
Emit(' ');
|
||||||
|
Emit(position.w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
|
||||||
|
Emit("# normal count: ");
|
||||||
|
EmitLine(m_normals.size());
|
||||||
|
|
||||||
|
for (const Nz::Vector3f& normal : m_normals)
|
||||||
|
{
|
||||||
|
Emit("vn ");
|
||||||
|
Emit(normal.x);
|
||||||
|
Emit(' ');
|
||||||
|
Emit(normal.y);
|
||||||
|
Emit(' ');
|
||||||
|
Emit(normal.y);
|
||||||
|
EmitLine();
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
|
||||||
|
Emit("# texcoords count: ");
|
||||||
|
EmitLine(m_texCoords.size());
|
||||||
|
|
||||||
|
for (const Nz::Vector3f& uvw : m_texCoords)
|
||||||
|
{
|
||||||
|
Emit("vt ");
|
||||||
|
Emit(uvw.x);
|
||||||
|
Emit(' ');
|
||||||
|
Emit(uvw.y);
|
||||||
|
if (NumberEquals(uvw.z, 0.f))
|
||||||
|
{
|
||||||
|
Emit(' ');
|
||||||
|
Emit(uvw.z);
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
|
||||||
|
std::unordered_map<std::size_t /* mesh */, std::vector<std::size_t> /* meshes*/> meshesByMaterials;
|
||||||
|
std::size_t meshIndex = 0;
|
||||||
|
for (const Mesh& mesh : m_meshes)
|
||||||
|
meshesByMaterials[mesh.material].push_back(meshIndex++);
|
||||||
|
|
||||||
|
for (auto& pair : meshesByMaterials)
|
||||||
|
{
|
||||||
|
Emit("usemtl ");
|
||||||
|
EmitLine(m_materials[pair.first]);
|
||||||
|
Emit("# groups count: ");
|
||||||
|
EmitLine(pair.second.size());
|
||||||
|
EmitLine();
|
||||||
|
|
||||||
|
for (std::size_t meshIndex : pair.second)
|
||||||
|
{
|
||||||
|
const Mesh& mesh = m_meshes[meshIndex];
|
||||||
|
|
||||||
|
Emit("g ");
|
||||||
|
EmitLine(mesh.name);
|
||||||
|
EmitLine();
|
||||||
|
|
||||||
|
Emit("# face count: ");
|
||||||
|
EmitLine(mesh.faces.size());
|
||||||
|
Emit("# vertex count: ");
|
||||||
|
EmitLine(mesh.vertices.size());
|
||||||
|
|
||||||
|
for (const Face& face : mesh.faces)
|
||||||
|
{
|
||||||
|
Emit('f');
|
||||||
|
for (std::size_t i = 0; i < face.vertexCount; ++i)
|
||||||
|
{
|
||||||
|
Emit(' ');
|
||||||
|
const FaceVertex& faceVertex = mesh.vertices[face.firstVertex + i];
|
||||||
|
Emit(faceVertex.position);
|
||||||
|
if (faceVertex.texCoord != 0 || faceVertex.normal != 0)
|
||||||
|
{
|
||||||
|
Emit('/');
|
||||||
|
if (faceVertex.texCoord != 0)
|
||||||
|
Emit(faceVertex.texCoord);
|
||||||
|
|
||||||
|
if (faceVertex.normal != 0)
|
||||||
|
{
|
||||||
|
Emit('/');
|
||||||
|
Emit(faceVertex.normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EmitLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
Flush();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool OBJParser::Advance(bool required)
|
bool OBJParser::Advance(bool required)
|
||||||
{
|
{
|
||||||
if (!m_keepLastLine)
|
if (!m_keepLastLine)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (m_stream.EndOfStream())
|
if (m_currentStream->EndOfStream())
|
||||||
{
|
{
|
||||||
if (required)
|
if (required)
|
||||||
Error("Incomplete OBJ file");
|
Error("Incomplete OBJ file");
|
||||||
|
|
@ -425,9 +521,8 @@ namespace Nz
|
||||||
|
|
||||||
m_lineCount++;
|
m_lineCount++;
|
||||||
|
|
||||||
m_currentLine = m_stream.ReadLine();
|
m_currentLine = m_currentStream->ReadLine();
|
||||||
m_currentLine = m_currentLine.SubStringTo("#"); // On ignore les commentaires
|
m_currentLine.Simplify(); // Simplify lines (convert multiple blanks into a single space and trims)
|
||||||
m_currentLine.Simplify(); // Pour un traitement plus simple
|
|
||||||
}
|
}
|
||||||
while (m_currentLine.IsEmpty());
|
while (m_currentLine.IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
@ -436,24 +531,4 @@ namespace Nz
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBJParser::Error(const String& message)
|
|
||||||
{
|
|
||||||
NazaraError(message + " at line #" + String::Number(m_lineCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJParser::Warning(const String& message)
|
|
||||||
{
|
|
||||||
NazaraWarning(message + " at line #" + String::Number(m_lineCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
void OBJParser::UnrecognizedLine(bool error)
|
|
||||||
{
|
|
||||||
String message = "Unrecognized \"" + m_currentLine + '"';
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
Error(message);
|
|
||||||
else
|
|
||||||
Warning(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue