Merge branch 'Font-Update'
Former-commit-id: d293f78c891a74554c6b990afafdc1eb1cc0a584
This commit is contained in:
commit
86502df849
|
|
@ -19,6 +19,7 @@ class NzCallOnExit : NzNonCopyable
|
||||||
NzCallOnExit(Func func = nullptr);
|
NzCallOnExit(Func func = nullptr);
|
||||||
~NzCallOnExit();
|
~NzCallOnExit();
|
||||||
|
|
||||||
|
void CallAndReset(Func func = nullptr);
|
||||||
void Reset(Func func = nullptr);
|
void Reset(Func func = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
inline NzCallOnExit::NzCallOnExit(Func func) :
|
inline NzCallOnExit::NzCallOnExit(Func func) :
|
||||||
|
|
@ -15,6 +16,14 @@ inline NzCallOnExit::~NzCallOnExit()
|
||||||
m_func();
|
m_func();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void NzCallOnExit::CallAndReset(Func func)
|
||||||
|
{
|
||||||
|
if (m_func)
|
||||||
|
m_func();
|
||||||
|
|
||||||
|
Reset(func);
|
||||||
|
}
|
||||||
|
|
||||||
inline void NzCallOnExit::Reset(Func func)
|
inline void NzCallOnExit::Reset(Func func)
|
||||||
{
|
{
|
||||||
m_func = func;
|
m_func = func;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
// Copyright (C) 2014 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Core module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
// Implémentation originale de Jukka Jylänki (Merci de sa contribution au domaine public)
|
||||||
|
// http://clb.demon.fi/projects/even-more-rectangle-bin-packing
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_GUILLOTINEBINPACK_HPP
|
||||||
|
#define NAZARA_GUILLOTINEBINPACK_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/SparsePtr.hpp>
|
||||||
|
#include <Nazara/Math/Rect.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class NAZARA_API NzGuillotineBinPack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum FreeRectChoiceHeuristic
|
||||||
|
{
|
||||||
|
RectBestAreaFit,
|
||||||
|
RectBestLongSideFit,
|
||||||
|
RectBestShortSideFit,
|
||||||
|
RectWorstAreaFit,
|
||||||
|
RectWorstLongSideFit,
|
||||||
|
RectWorstShortSideFit
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GuillotineSplitHeuristic
|
||||||
|
{
|
||||||
|
SplitLongerAxis,
|
||||||
|
SplitLongerLeftoverAxis,
|
||||||
|
SplitMaximizeArea,
|
||||||
|
SplitMinimizeArea,
|
||||||
|
SplitShorterAxis,
|
||||||
|
SplitShorterLeftoverAxis
|
||||||
|
};
|
||||||
|
|
||||||
|
NzGuillotineBinPack();
|
||||||
|
NzGuillotineBinPack(unsigned int width, unsigned int height);
|
||||||
|
NzGuillotineBinPack(const NzVector2ui& size);
|
||||||
|
NzGuillotineBinPack(const NzGuillotineBinPack&) = default;
|
||||||
|
NzGuillotineBinPack(NzGuillotineBinPack&&) = default;
|
||||||
|
~NzGuillotineBinPack() = default;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
void Expand(unsigned int newWidth, unsigned newHeight);
|
||||||
|
void Expand(const NzVector2ui& newSize);
|
||||||
|
|
||||||
|
void FreeRectangle(const NzRectui& rect);
|
||||||
|
|
||||||
|
unsigned int GetHeight() const;
|
||||||
|
float GetOccupancy() const;
|
||||||
|
NzVector2ui GetSize() const;
|
||||||
|
unsigned int GetWidth() const;
|
||||||
|
|
||||||
|
bool Insert(NzRectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||||
|
bool Insert(NzRectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||||
|
bool Insert(NzRectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||||
|
|
||||||
|
bool MergeFreeRectangles();
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
void Reset(unsigned int width, unsigned int height);
|
||||||
|
void Reset(const NzVector2ui& size);
|
||||||
|
|
||||||
|
NzGuillotineBinPack& operator=(const NzGuillotineBinPack&) = default;
|
||||||
|
NzGuillotineBinPack& operator=(NzGuillotineBinPack&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SplitFreeRectAlongAxis(const NzRectui& freeRect, const NzRectui& placedRect, bool splitHorizontal);
|
||||||
|
void SplitFreeRectByHeuristic(const NzRectui& freeRect, const NzRectui& placedRect, GuillotineSplitHeuristic method);
|
||||||
|
|
||||||
|
static int ScoreByHeuristic(int width, int height, const NzRectui& freeRect, FreeRectChoiceHeuristic rectChoice);
|
||||||
|
|
||||||
|
std::vector<NzRectui> m_freeRectangles;
|
||||||
|
unsigned int m_height;
|
||||||
|
unsigned int m_usedArea;
|
||||||
|
unsigned int m_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_GUILLOTINEBINPACK_HPP
|
||||||
|
|
@ -23,6 +23,8 @@ class NAZARA_API NzResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzResource(bool persistent = true);
|
NzResource(bool persistent = true);
|
||||||
|
NzResource(const NzResource& resource) = delete;
|
||||||
|
NzResource(NzResource&& resource) = delete;
|
||||||
virtual ~NzResource();
|
virtual ~NzResource();
|
||||||
|
|
||||||
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
|
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
|
||||||
|
|
@ -37,6 +39,9 @@ class NAZARA_API NzResource
|
||||||
|
|
||||||
bool SetPersistent(bool persistent = true, bool checkReferenceCount = false);
|
bool SetPersistent(bool persistent = true, bool checkReferenceCount = false);
|
||||||
|
|
||||||
|
NzResource& operator=(const NzResource& resource) = delete;
|
||||||
|
NzResource& operator=(NzResource&& resource) = delete;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void NotifyCreated();
|
void NotifyCreated();
|
||||||
void NotifyDestroy();
|
void NotifyDestroy();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,9 @@ class NzSparsePtr
|
||||||
T& operator[](int index) const;
|
T& operator[](int index) const;
|
||||||
|
|
||||||
NzSparsePtr operator+(int count) const;
|
NzSparsePtr operator+(int count) const;
|
||||||
|
NzSparsePtr operator+(unsigned int count) const;
|
||||||
NzSparsePtr operator-(int count) const;
|
NzSparsePtr operator-(int count) const;
|
||||||
|
NzSparsePtr operator-(unsigned int count) const;
|
||||||
std::ptrdiff_t operator-(const NzSparsePtr& ptr) const;
|
std::ptrdiff_t operator-(const NzSparsePtr& ptr) const;
|
||||||
|
|
||||||
NzSparsePtr& operator+=(int count);
|
NzSparsePtr& operator+=(int count);
|
||||||
|
|
|
||||||
|
|
@ -127,12 +127,24 @@ NzSparsePtr<T> NzSparsePtr<T>::operator+(int count) const
|
||||||
return NzSparsePtr(m_ptr + count*m_stride, m_stride);
|
return NzSparsePtr(m_ptr + count*m_stride, m_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzSparsePtr<T> NzSparsePtr<T>::operator+(unsigned int count) const
|
||||||
|
{
|
||||||
|
return NzSparsePtr(m_ptr + count*m_stride, m_stride);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzSparsePtr<T> NzSparsePtr<T>::operator-(int count) const
|
NzSparsePtr<T> NzSparsePtr<T>::operator-(int count) const
|
||||||
{
|
{
|
||||||
return NzSparsePtr(m_ptr - count*m_stride, m_stride);
|
return NzSparsePtr(m_ptr - count*m_stride, m_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzSparsePtr<T> NzSparsePtr<T>::operator-(unsigned int count) const
|
||||||
|
{
|
||||||
|
return NzSparsePtr(m_ptr - count*m_stride, m_stride);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::ptrdiff_t NzSparsePtr<T>::operator-(const NzSparsePtr& ptr) const
|
std::ptrdiff_t NzSparsePtr<T>::operator-(const NzSparsePtr& ptr) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,13 @@
|
||||||
#include <Nazara/Math/Box.hpp>
|
#include <Nazara/Math/Box.hpp>
|
||||||
#include <Nazara/Math/Matrix4.hpp>
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
#include <Nazara/Utility/Enums.hpp>
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
|
|
||||||
class NzDrawable;
|
class NzDrawable;
|
||||||
class NzLight;
|
class NzLight;
|
||||||
class NzMaterial;
|
class NzMaterial;
|
||||||
class NzSprite;
|
class NzSprite;
|
||||||
|
class NzTexture;
|
||||||
struct NzMeshData;
|
struct NzMeshData;
|
||||||
|
|
||||||
class NAZARA_API NzAbstractRenderQueue : NzNonCopyable
|
class NAZARA_API NzAbstractRenderQueue : NzNonCopyable
|
||||||
|
|
@ -28,7 +30,7 @@ class NAZARA_API NzAbstractRenderQueue : NzNonCopyable
|
||||||
virtual void AddDrawable(const NzDrawable* drawable) = 0;
|
virtual void AddDrawable(const NzDrawable* drawable) = 0;
|
||||||
virtual void AddLight(const NzLight* light) = 0;
|
virtual void AddLight(const NzLight* light) = 0;
|
||||||
virtual void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) = 0;
|
virtual void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) = 0;
|
||||||
virtual void AddSprite(const NzSprite* sprite) = 0;
|
virtual void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) = 0;
|
||||||
|
|
||||||
virtual void Clear(bool fully) = 0;
|
virtual void Clear(bool fully) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ class NAZARA_API NzAbstractViewer
|
||||||
virtual NzVector3f GetEyePosition() const = 0;
|
virtual NzVector3f GetEyePosition() const = 0;
|
||||||
virtual NzVector3f GetForward() const = 0;
|
virtual NzVector3f GetForward() const = 0;
|
||||||
virtual const NzFrustumf& GetFrustum() const = 0;
|
virtual const NzFrustumf& GetFrustum() const = 0;
|
||||||
|
virtual NzVector3f GetGlobalForward() const = 0;
|
||||||
|
virtual NzVector3f GetGlobalRight() const = 0;
|
||||||
|
virtual NzVector3f GetGlobalUp() const = 0;
|
||||||
virtual const NzMatrix4f& GetProjectionMatrix() const = 0;
|
virtual const NzMatrix4f& GetProjectionMatrix() const = 0;
|
||||||
virtual const NzRenderTarget* GetTarget() const = 0;
|
virtual const NzRenderTarget* GetTarget() const = 0;
|
||||||
virtual const NzMatrix4f& GetViewMatrix() const = 0;
|
virtual const NzMatrix4f& GetViewMatrix() const = 0;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ class NAZARA_API NzCamera : public NzAbstractViewer, public NzNode, NzRenderTarg
|
||||||
NzVector3f GetForward() const;
|
NzVector3f GetForward() const;
|
||||||
float GetFOV() const;
|
float GetFOV() const;
|
||||||
const NzFrustumf& GetFrustum() const;
|
const NzFrustumf& GetFrustum() const;
|
||||||
|
NzVector3f GetGlobalForward() const;
|
||||||
|
NzVector3f GetGlobalRight() const;
|
||||||
|
NzVector3f GetGlobalUp() const;
|
||||||
const NzMatrix4f& GetProjectionMatrix() const;
|
const NzMatrix4f& GetProjectionMatrix() const;
|
||||||
const NzRenderTarget* GetTarget() const;
|
const NzRenderTarget* GetTarget() const;
|
||||||
const NzRectf& GetTargetRegion() const;
|
const NzRectf& GetTargetRegion() const;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
|
||||||
void AddDrawable(const NzDrawable* drawable) override;
|
void AddDrawable(const NzDrawable* drawable) override;
|
||||||
void AddLight(const NzLight* light) override;
|
void AddLight(const NzLight* light) override;
|
||||||
void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override;
|
void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override;
|
||||||
void AddSprite(const NzSprite* sprite) override;
|
void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) override;
|
||||||
|
|
||||||
void Clear(bool fully);
|
void Clear(bool fully);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,11 @@ enum nzRenderTechniqueType
|
||||||
|
|
||||||
enum nzSceneNodeType
|
enum nzSceneNodeType
|
||||||
{
|
{
|
||||||
nzSceneNodeType_Light, // NzLight
|
nzSceneNodeType_Light, // NzLight
|
||||||
nzSceneNodeType_Model, // NzModel
|
nzSceneNodeType_Model, // NzModel
|
||||||
nzSceneNodeType_Root, // NzSceneRoot
|
nzSceneNodeType_Root, // NzSceneRoot
|
||||||
nzSceneNodeType_Sprite, // NzSprite
|
nzSceneNodeType_Sprite, // NzSprite
|
||||||
|
nzSceneNodeType_TextSprite, // NzTextSprite
|
||||||
nzSceneNodeType_User,
|
nzSceneNodeType_User,
|
||||||
|
|
||||||
nzSceneNodeType_Max = nzSceneNodeType_User
|
nzSceneNodeType_Max = nzSceneNodeType_User
|
||||||
|
|
@ -85,10 +86,12 @@ enum nzShaderFlags
|
||||||
{
|
{
|
||||||
nzShaderFlags_None = 0,
|
nzShaderFlags_None = 0,
|
||||||
|
|
||||||
nzShaderFlags_Deferred = 0x1,
|
nzShaderFlags_Deferred = 0x1,
|
||||||
nzShaderFlags_Instancing = 0x2,
|
nzShaderFlags_Instancing = 0x2,
|
||||||
|
nzShaderFlags_TextureOverlay = 0x4,
|
||||||
|
nzShaderFlags_VertexColor = 0x8,
|
||||||
|
|
||||||
nzShaderFlags_Max = nzShaderFlags_Instancing*2-1
|
nzShaderFlags_Max = nzShaderFlags_VertexColor*2-1
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_ENUMS_GRAPHICS_HPP
|
#endif // NAZARA_ENUMS_GRAPHICS_HPP
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
|
||||||
void AddDrawable(const NzDrawable* drawable) override;
|
void AddDrawable(const NzDrawable* drawable) override;
|
||||||
void AddLight(const NzLight* light) override;
|
void AddLight(const NzLight* light) override;
|
||||||
void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override;
|
void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override;
|
||||||
void AddSprite(const NzSprite* sprite) override;
|
void AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay = nullptr) override;
|
||||||
|
|
||||||
void Clear(bool fully);
|
void Clear(bool fully);
|
||||||
|
|
||||||
|
|
@ -43,6 +43,12 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
|
||||||
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
||||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||||
|
|
||||||
|
struct SpriteChain_XYZ_Color_UV
|
||||||
|
{
|
||||||
|
const NzVertexStruct_XYZ_Color_UV* vertices;
|
||||||
|
unsigned int spriteCount;
|
||||||
|
};
|
||||||
|
|
||||||
struct TransparentModelData
|
struct TransparentModelData
|
||||||
{
|
{
|
||||||
NzMatrix4f transformMatrix;
|
NzMatrix4f transformMatrix;
|
||||||
|
|
@ -68,12 +74,13 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
|
||||||
|
|
||||||
typedef std::map<NzMeshData, std::pair<NzSpheref, std::vector<NzMatrix4f>>, MeshDataComparator> MeshInstanceContainer;
|
typedef std::map<NzMeshData, std::pair<NzSpheref, std::vector<NzMatrix4f>>, MeshDataComparator> MeshInstanceContainer;
|
||||||
typedef std::map<const NzMaterial*, std::tuple<bool, bool, MeshInstanceContainer>, BatchedModelMaterialComparator> ModelBatches;
|
typedef std::map<const NzMaterial*, std::tuple<bool, bool, MeshInstanceContainer>, BatchedModelMaterialComparator> ModelBatches;
|
||||||
typedef std::map<const NzMaterial*, std::vector<const NzSprite*>> BatchedSpriteContainer;
|
typedef std::map<const NzTexture*, std::vector<SpriteChain_XYZ_Color_UV>> BasicSpriteOverlayContainer;
|
||||||
|
typedef std::map<const NzMaterial*, BasicSpriteOverlayContainer> BasicSpriteBatches;
|
||||||
typedef std::vector<const NzLight*> LightContainer;
|
typedef std::vector<const NzLight*> LightContainer;
|
||||||
typedef std::vector<unsigned int> TransparentModelContainer;
|
typedef std::vector<unsigned int> TransparentModelContainer;
|
||||||
|
|
||||||
|
BasicSpriteBatches basicSprites;
|
||||||
ModelBatches opaqueModels;
|
ModelBatches opaqueModels;
|
||||||
BatchedSpriteContainer sprites;
|
|
||||||
TransparentModelContainer transparentModels;
|
TransparentModelContainer transparentModels;
|
||||||
std::vector<TransparentModelData> transparentModelData;
|
std::vector<TransparentModelData> transparentModelData;
|
||||||
std::vector<const NzDrawable*> otherDrawables;
|
std::vector<const NzDrawable*> otherDrawables;
|
||||||
|
|
|
||||||
|
|
@ -32,23 +32,27 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique, Nz
|
||||||
void SetMaxLightPassPerObject(unsigned int passCount);
|
void SetMaxLightPassPerObject(unsigned int passCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct LightUniforms;
|
struct ShaderUniforms;
|
||||||
|
|
||||||
|
void DrawBasicSprites(const NzScene* scene) const;
|
||||||
void DrawOpaqueModels(const NzScene* scene) const;
|
void DrawOpaqueModels(const NzScene* scene) const;
|
||||||
void DrawSprites(const NzScene* scene) const;
|
|
||||||
void DrawTransparentModels(const NzScene* scene) const;
|
void DrawTransparentModels(const NzScene* scene) const;
|
||||||
const LightUniforms* GetLightUniforms(const NzShader* shader) const;
|
const ShaderUniforms* GetShaderUniforms(const NzShader* shader) const;
|
||||||
|
|
||||||
struct LightUniforms
|
struct ShaderUniforms
|
||||||
{
|
{
|
||||||
NzLightUniforms uniforms;
|
NzLightUniforms lightUniforms;
|
||||||
bool exists;
|
bool hasLightUniforms;
|
||||||
int offset; // "Distance" entre Lights[0].type et Lights[1].type
|
|
||||||
/// Moins coûteux en mémoire que de stocker un NzLightUniforms par index de lumière,
|
/// Moins coûteux en mémoire que de stocker un NzLightUniforms par index de lumière,
|
||||||
/// à voir si ça fonctionne chez tout le monde
|
/// à voir si ça fonctionne chez tout le monde
|
||||||
|
int lightOffset; // "Distance" entre Lights[0].type et Lights[1].type
|
||||||
|
|
||||||
|
// Autre uniformes
|
||||||
|
int textureOverlay;
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable std::unordered_map<const NzShader*, LightUniforms> m_lightUniforms;
|
mutable std::unordered_map<const NzShader*, ShaderUniforms> m_shaderUniforms;
|
||||||
mutable NzForwardRenderQueue m_renderQueue;
|
mutable NzForwardRenderQueue m_renderQueue;
|
||||||
NzIndexBufferRef m_indexBuffer;
|
NzIndexBufferRef m_indexBuffer;
|
||||||
mutable NzLightManager m_directionalLights;
|
mutable NzLightManager m_directionalLights;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_GUILLOTINETEXTUREATLAS_HPP
|
||||||
|
#define NAZARA_GUILLOTINETEXTUREATLAS_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Utility/GuillotineImageAtlas.hpp>
|
||||||
|
|
||||||
|
class NAZARA_API NzGuillotineTextureAtlas : public NzGuillotineImageAtlas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzGuillotineTextureAtlas() = default;
|
||||||
|
~NzGuillotineTextureAtlas() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NzAbstractImage* ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_GUILLOTINETEXTUREATLAS_HPP
|
||||||
|
|
@ -46,7 +46,6 @@ class NAZARA_API NzMaterial : public NzResource
|
||||||
public:
|
public:
|
||||||
NzMaterial();
|
NzMaterial();
|
||||||
NzMaterial(const NzMaterial& material);
|
NzMaterial(const NzMaterial& material);
|
||||||
NzMaterial(NzMaterial&& material);
|
|
||||||
~NzMaterial();
|
~NzMaterial();
|
||||||
|
|
||||||
const NzShader* Apply(nzUInt32 shaderFlags = 0, nzUInt8 textureUnit = 0, nzUInt8* lastUsedUnit = nullptr) const;
|
const NzShader* Apply(nzUInt32 shaderFlags = 0, nzUInt8 textureUnit = 0, nzUInt8* lastUsedUnit = nullptr) const;
|
||||||
|
|
@ -127,7 +126,6 @@ class NAZARA_API NzMaterial : public NzResource
|
||||||
void SetSrcBlend(nzBlendFunc func);
|
void SetSrcBlend(nzBlendFunc func);
|
||||||
|
|
||||||
NzMaterial& operator=(const NzMaterial& material);
|
NzMaterial& operator=(const NzMaterial& material);
|
||||||
NzMaterial& operator=(NzMaterial&& material);
|
|
||||||
|
|
||||||
static NzMaterial* GetDefault();
|
static NzMaterial* GetDefault();
|
||||||
|
|
||||||
|
|
@ -140,6 +138,7 @@ class NAZARA_API NzMaterial : public NzResource
|
||||||
};
|
};
|
||||||
|
|
||||||
void Copy(const NzMaterial& material);
|
void Copy(const NzMaterial& material);
|
||||||
|
void Move(NzMaterial&& material);
|
||||||
void GenerateShader(nzUInt32 flags) const;
|
void GenerateShader(nzUInt32 flags) const;
|
||||||
void InvalidateShaders();
|
void InvalidateShaders();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ class NAZARA_API NzModel : public NzSceneNode
|
||||||
public:
|
public:
|
||||||
NzModel();
|
NzModel();
|
||||||
NzModel(const NzModel& model);
|
NzModel(const NzModel& model);
|
||||||
NzModel(NzModel&& model);
|
|
||||||
virtual ~NzModel();
|
virtual ~NzModel();
|
||||||
|
|
||||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
|
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
|
||||||
|
|
@ -83,7 +82,6 @@ class NAZARA_API NzModel : public NzSceneNode
|
||||||
void SetSkinCount(unsigned int skinCount);
|
void SetSkinCount(unsigned int skinCount);
|
||||||
|
|
||||||
NzModel& operator=(const NzModel& node);
|
NzModel& operator=(const NzModel& node);
|
||||||
NzModel& operator=(NzModel&& node);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InvalidateNode() override;
|
void InvalidateNode() override;
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,15 @@ class NAZARA_API NzScene
|
||||||
|
|
||||||
NzColor GetAmbientColor() const;
|
NzColor GetAmbientColor() const;
|
||||||
NzAbstractBackground* GetBackground() const;
|
NzAbstractBackground* GetBackground() const;
|
||||||
|
NzVector3f GetBackward() const;
|
||||||
|
NzVector3f GetDown() const;
|
||||||
|
NzVector3f GetForward() const;
|
||||||
|
NzVector3f GetLeft() const;
|
||||||
NzAbstractRenderTechnique* GetRenderTechnique() const;
|
NzAbstractRenderTechnique* GetRenderTechnique() const;
|
||||||
|
NzVector3f GetRight() const;
|
||||||
NzSceneNode& GetRoot() const;
|
NzSceneNode& GetRoot() const;
|
||||||
NzAbstractViewer* GetViewer() const;
|
NzAbstractViewer* GetViewer() const;
|
||||||
|
NzVector3f GetUp() const;
|
||||||
float GetUpdateTime() const;
|
float GetUpdateTime() const;
|
||||||
unsigned int GetUpdatePerSecond() const;
|
unsigned int GetUpdatePerSecond() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,30 @@ class NAZARA_API NzSceneNode : public NzNode
|
||||||
public:
|
public:
|
||||||
NzSceneNode();
|
NzSceneNode();
|
||||||
NzSceneNode(const NzSceneNode& sceneNode);
|
NzSceneNode(const NzSceneNode& sceneNode);
|
||||||
|
NzSceneNode(NzSceneNode& sceneNode) = delete;
|
||||||
virtual ~NzSceneNode();
|
virtual ~NzSceneNode();
|
||||||
|
|
||||||
virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0;
|
virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0;
|
||||||
|
|
||||||
void EnableDrawing(bool drawingEnabled);
|
void EnableDrawing(bool drawingEnabled);
|
||||||
|
|
||||||
|
NzVector3f GetBackward() const;
|
||||||
virtual const NzBoundingVolumef& GetBoundingVolume() const = 0;
|
virtual const NzBoundingVolumef& GetBoundingVolume() const = 0;
|
||||||
|
NzVector3f GetDown() const;
|
||||||
|
NzVector3f GetForward() const;
|
||||||
|
NzVector3f GetLeft() const;
|
||||||
nzNodeType GetNodeType() const final;
|
nzNodeType GetNodeType() const final;
|
||||||
|
NzVector3f GetRight() const;
|
||||||
NzScene* GetScene() const;
|
NzScene* GetScene() const;
|
||||||
virtual nzSceneNodeType GetSceneNodeType() const = 0;
|
virtual nzSceneNodeType GetSceneNodeType() const = 0;
|
||||||
|
NzVector3f GetUp() const;
|
||||||
|
|
||||||
virtual bool IsDrawable() const = 0;
|
virtual bool IsDrawable() const = 0;
|
||||||
bool IsDrawingEnabled() const;
|
bool IsDrawingEnabled() const;
|
||||||
bool IsVisible() const;
|
bool IsVisible() const;
|
||||||
|
|
||||||
NzSceneNode& operator=(const NzSceneNode& sceneNode);
|
NzSceneNode& operator=(const NzSceneNode& sceneNode);
|
||||||
NzSceneNode& operator=(NzSceneNode&& sceneNode);
|
NzSceneNode& operator=(NzSceneNode&& sceneNode) = delete;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool FrustumCull(const NzFrustumf& frustum) const;
|
virtual bool FrustumCull(const NzFrustumf& frustum) const;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
#include <Nazara/Graphics/SceneNode.hpp>
|
#include <Nazara/Graphics/SceneNode.hpp>
|
||||||
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
|
|
||||||
class NAZARA_API NzSprite : public NzSceneNode
|
class NAZARA_API NzSprite : public NzSceneNode
|
||||||
{
|
{
|
||||||
|
|
@ -17,12 +18,12 @@ class NAZARA_API NzSprite : public NzSceneNode
|
||||||
NzSprite();
|
NzSprite();
|
||||||
NzSprite(NzTexture* texture);
|
NzSprite(NzTexture* texture);
|
||||||
NzSprite(const NzSprite& sprite);
|
NzSprite(const NzSprite& sprite);
|
||||||
NzSprite(NzSprite&& sprite);
|
~NzSprite() = default;
|
||||||
~NzSprite();
|
|
||||||
|
|
||||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
|
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
|
||||||
|
|
||||||
const NzBoundingVolumef& GetBoundingVolume() const override;
|
const NzBoundingVolumef& GetBoundingVolume() const override;
|
||||||
|
const NzColor& GetColor() const;
|
||||||
NzMaterial* GetMaterial() const;
|
NzMaterial* GetMaterial() const;
|
||||||
nzSceneNodeType GetSceneNodeType() const override;
|
nzSceneNodeType GetSceneNodeType() const override;
|
||||||
const NzVector2f& GetSize() const;
|
const NzVector2f& GetSize() const;
|
||||||
|
|
@ -30,6 +31,8 @@ class NAZARA_API NzSprite : public NzSceneNode
|
||||||
|
|
||||||
bool IsDrawable() const;
|
bool IsDrawable() const;
|
||||||
|
|
||||||
|
void SetColor(const NzColor& color);
|
||||||
|
void SetDefaultMaterial();
|
||||||
void SetMaterial(NzMaterial* material, bool resizeSprite = true);
|
void SetMaterial(NzMaterial* material, bool resizeSprite = true);
|
||||||
void SetSize(const NzVector2f& size);
|
void SetSize(const NzVector2f& size);
|
||||||
void SetSize(float sizeX, float sizeY);
|
void SetSize(float sizeX, float sizeY);
|
||||||
|
|
@ -37,17 +40,23 @@ class NAZARA_API NzSprite : public NzSceneNode
|
||||||
void SetTextureCoords(const NzRectf& coords);
|
void SetTextureCoords(const NzRectf& coords);
|
||||||
void SetTextureRect(const NzRectui& rect);
|
void SetTextureRect(const NzRectui& rect);
|
||||||
|
|
||||||
|
NzSprite& operator=(const NzSprite& sprite);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InvalidateNode() override;
|
void InvalidateNode() override;
|
||||||
void Register() override;
|
void Register() override;
|
||||||
void Unregister() override;
|
void Unregister() override;
|
||||||
void UpdateBoundingVolume() const;
|
void UpdateBoundingVolume() const;
|
||||||
|
void UpdateVertices() const;
|
||||||
|
|
||||||
mutable NzBoundingVolumef m_boundingVolume;
|
mutable NzBoundingVolumef m_boundingVolume;
|
||||||
|
NzColor m_color;
|
||||||
NzMaterialRef m_material;
|
NzMaterialRef m_material;
|
||||||
NzRectf m_textureCoords;
|
NzRectf m_textureCoords;
|
||||||
NzVector2f m_size;
|
NzVector2f m_size;
|
||||||
|
mutable NzVertexStruct_XYZ_Color_UV m_vertices[4];
|
||||||
mutable bool m_boundingVolumeUpdated;
|
mutable bool m_boundingVolumeUpdated;
|
||||||
|
mutable bool m_verticesUpdated;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_SPRITE_HPP
|
#endif // NAZARA_SPRITE_HPP
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
// Copyright (C) 2014 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Graphics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_TEXTSPRITE_HPP
|
||||||
|
#define NAZARA_TEXTSPRITE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
|
#include <Nazara/Graphics/SceneNode.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractAtlas.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractTextDrawer.hpp>
|
||||||
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
class NAZARA_API NzTextSprite : public NzSceneNode, NzAbstractAtlas::Listener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzTextSprite();
|
||||||
|
NzTextSprite(const NzTextSprite& sprite);
|
||||||
|
~NzTextSprite();
|
||||||
|
|
||||||
|
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
const NzBoundingVolumef& GetBoundingVolume() const override;
|
||||||
|
const NzColor& GetColor() const;
|
||||||
|
NzMaterial* GetMaterial() const;
|
||||||
|
nzSceneNodeType GetSceneNodeType() const override;
|
||||||
|
|
||||||
|
void InvalidateVertices();
|
||||||
|
bool IsDrawable() const;
|
||||||
|
|
||||||
|
void SetColor(const NzColor& color);
|
||||||
|
void SetDefaultMaterial();
|
||||||
|
void SetMaterial(NzMaterial* material);
|
||||||
|
void SetText(const NzAbstractTextDrawer& drawer);
|
||||||
|
|
||||||
|
NzTextSprite& operator=(const NzTextSprite& text);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ClearAtlases();
|
||||||
|
void InvalidateNode() override;
|
||||||
|
bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) override;
|
||||||
|
bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) override;
|
||||||
|
void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) override;
|
||||||
|
void Register() override;
|
||||||
|
void Unregister() override;
|
||||||
|
void UpdateBoundingVolume() const;
|
||||||
|
void UpdateVertices() const;
|
||||||
|
|
||||||
|
struct RenderIndices
|
||||||
|
{
|
||||||
|
unsigned int first;
|
||||||
|
unsigned int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::set<const NzAbstractAtlas*> m_atlases;
|
||||||
|
mutable std::unordered_map<NzTexture*, RenderIndices> m_renderInfos;
|
||||||
|
mutable std::vector<NzVertexStruct_XY_Color> m_localVertices;
|
||||||
|
mutable std::vector<NzVertexStruct_XYZ_Color_UV> m_vertices;
|
||||||
|
mutable NzBoundingVolumef m_boundingVolume;
|
||||||
|
NzColor m_color;
|
||||||
|
NzMaterialRef m_material;
|
||||||
|
NzRectui m_localBounds;
|
||||||
|
mutable bool m_boundingVolumeUpdated;
|
||||||
|
mutable bool m_verticesUpdated;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_TEXTSPRITE_HPP
|
||||||
|
|
@ -32,6 +32,9 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget
|
||||||
NzVector3f GetEyePosition() const;
|
NzVector3f GetEyePosition() const;
|
||||||
NzVector3f GetForward() const;
|
NzVector3f GetForward() const;
|
||||||
const NzFrustumf& GetFrustum() const;
|
const NzFrustumf& GetFrustum() const;
|
||||||
|
NzVector3f GetGlobalForward() const;
|
||||||
|
NzVector3f GetGlobalRight() const;
|
||||||
|
NzVector3f GetGlobalUp() const;
|
||||||
const NzMatrix4f& GetProjectionMatrix() const;
|
const NzMatrix4f& GetProjectionMatrix() const;
|
||||||
const NzVector2f& GetSize() const;
|
const NzVector2f& GetSize() const;
|
||||||
const NzRenderTarget* GetTarget() const;
|
const NzRenderTarget* GetTarget() const;
|
||||||
|
|
@ -42,6 +45,7 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget
|
||||||
float GetZNear() const;
|
float GetZNear() const;
|
||||||
|
|
||||||
void SetSize(const NzVector2f& size);
|
void SetSize(const NzVector2f& size);
|
||||||
|
void SetSize(float width, float height);
|
||||||
void SetTarget(const NzRenderTarget* renderTarget);
|
void SetTarget(const NzRenderTarget* renderTarget);
|
||||||
void SetTarget(const NzRenderTarget& renderTarget);
|
void SetTarget(const NzRenderTarget& renderTarget);
|
||||||
void SetTargetRegion(const NzRectf& region);
|
void SetTargetRegion(const NzRectf& region);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class NzBox
|
||||||
NzBox& ExtendTo(const NzVector3<T>& point);
|
NzBox& ExtendTo(const NzVector3<T>& point);
|
||||||
|
|
||||||
NzSphere<T> GetBoundingSphere() const;
|
NzSphere<T> GetBoundingSphere() const;
|
||||||
NzVector3<T> GetCorner(nzCorner corner) const;
|
NzVector3<T> GetCorner(nzBoxCorner corner) const;
|
||||||
NzVector3<T> GetCenter() const;
|
NzVector3<T> GetCenter() const;
|
||||||
NzVector3<T> GetLengths() const;
|
NzVector3<T> GetLengths() const;
|
||||||
NzVector3<T> GetMaximum() const;
|
NzVector3<T> GetMaximum() const;
|
||||||
|
|
|
||||||
|
|
@ -117,32 +117,32 @@ NzBox<T>& NzBox<T>::ExtendTo(const NzVector3<T>& point)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector3<T> NzBox<T>::GetCorner(nzCorner corner) const
|
NzVector3<T> NzBox<T>::GetCorner(nzBoxCorner corner) const
|
||||||
{
|
{
|
||||||
switch (corner)
|
switch (corner)
|
||||||
{
|
{
|
||||||
case nzCorner_FarLeftBottom:
|
case nzBoxCorner_FarLeftBottom:
|
||||||
return NzVector3<T>(x, y, z);
|
return NzVector3<T>(x, y, z);
|
||||||
|
|
||||||
case nzCorner_FarLeftTop:
|
case nzBoxCorner_FarLeftTop:
|
||||||
return NzVector3<T>(x, y + height, z);
|
return NzVector3<T>(x, y + height, z);
|
||||||
|
|
||||||
case nzCorner_FarRightBottom:
|
case nzBoxCorner_FarRightBottom:
|
||||||
return NzVector3<T>(x + width, y, z);
|
return NzVector3<T>(x + width, y, z);
|
||||||
|
|
||||||
case nzCorner_FarRightTop:
|
case nzBoxCorner_FarRightTop:
|
||||||
return NzVector3<T>(x + width, y + height, z);
|
return NzVector3<T>(x + width, y + height, z);
|
||||||
|
|
||||||
case nzCorner_NearLeftBottom:
|
case nzBoxCorner_NearLeftBottom:
|
||||||
return NzVector3<T>(x, y, z + depth);
|
return NzVector3<T>(x, y, z + depth);
|
||||||
|
|
||||||
case nzCorner_NearLeftTop:
|
case nzBoxCorner_NearLeftTop:
|
||||||
return NzVector3<T>(x, y + height, z + depth);
|
return NzVector3<T>(x, y + height, z + depth);
|
||||||
|
|
||||||
case nzCorner_NearRightBottom:
|
case nzBoxCorner_NearRightBottom:
|
||||||
return NzVector3<T>(x + width, y, z + depth);
|
return NzVector3<T>(x + width, y, z + depth);
|
||||||
|
|
||||||
case nzCorner_NearRightTop:
|
case nzBoxCorner_NearRightTop:
|
||||||
return NzVector3<T>(x + width, y + height, z + depth);
|
return NzVector3<T>(x + width, y + height, z + depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,18 +7,18 @@
|
||||||
#ifndef NAZARA_ENUMS_MATH_HPP
|
#ifndef NAZARA_ENUMS_MATH_HPP
|
||||||
#define NAZARA_ENUMS_MATH_HPP
|
#define NAZARA_ENUMS_MATH_HPP
|
||||||
|
|
||||||
enum nzCorner
|
enum nzBoxCorner
|
||||||
{
|
{
|
||||||
nzCorner_FarLeftBottom,
|
nzBoxCorner_FarLeftBottom,
|
||||||
nzCorner_FarLeftTop,
|
nzBoxCorner_FarLeftTop,
|
||||||
nzCorner_FarRightBottom,
|
nzBoxCorner_FarRightBottom,
|
||||||
nzCorner_FarRightTop,
|
nzBoxCorner_FarRightTop,
|
||||||
nzCorner_NearLeftBottom,
|
nzBoxCorner_NearLeftBottom,
|
||||||
nzCorner_NearLeftTop,
|
nzBoxCorner_NearLeftTop,
|
||||||
nzCorner_NearRightBottom,
|
nzBoxCorner_NearRightBottom,
|
||||||
nzCorner_NearRightTop,
|
nzBoxCorner_NearRightTop,
|
||||||
|
|
||||||
nzCorner_Max = nzCorner_NearRightTop
|
nzBoxCorner_Max = nzBoxCorner_NearRightTop
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzExtend
|
enum nzExtend
|
||||||
|
|
@ -51,4 +51,14 @@ enum nzIntersectionSide
|
||||||
nzIntersectionSide_Max = nzIntersectionSide_Outside
|
nzIntersectionSide_Max = nzIntersectionSide_Outside
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum nzRectCorner
|
||||||
|
{
|
||||||
|
nzRectCorner_LeftBottom,
|
||||||
|
nzRectCorner_LeftTop,
|
||||||
|
nzRectCorner_RightBottom,
|
||||||
|
nzRectCorner_RightTop,
|
||||||
|
|
||||||
|
nzRectCorner_Max = nzRectCorner_RightTop
|
||||||
|
};
|
||||||
|
|
||||||
#endif // NAZARA_ENUMS_MATH_HPP
|
#endif // NAZARA_ENUMS_MATH_HPP
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class NzFrustum
|
||||||
NzFrustum& Extract(const NzMatrix4<T>& clipMatrix);
|
NzFrustum& Extract(const NzMatrix4<T>& clipMatrix);
|
||||||
NzFrustum& Extract(const NzMatrix4<T>& view, const NzMatrix4<T>& projection);
|
NzFrustum& Extract(const NzMatrix4<T>& view, const NzMatrix4<T>& projection);
|
||||||
|
|
||||||
const NzVector3<T>& GetCorner(nzCorner corner) const;
|
const NzVector3<T>& GetCorner(nzBoxCorner corner) const;
|
||||||
const NzPlane<T>& GetPlane(nzFrustumPlane plane) const;
|
const NzPlane<T>& GetPlane(nzFrustumPlane plane) const;
|
||||||
|
|
||||||
nzIntersectionSide Intersect(const NzBoundingVolume<T>& volume) const;
|
nzIntersectionSide Intersect(const NzBoundingVolume<T>& volume) const;
|
||||||
|
|
@ -52,7 +52,7 @@ class NzFrustum
|
||||||
NzString ToString() const;
|
NzString ToString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NzVector3<T> m_corners[nzCorner_Max+1];
|
NzVector3<T> m_corners[nzBoxCorner_Max+1];
|
||||||
NzPlane<T> m_planes[nzFrustumPlane_Max+1];
|
NzPlane<T> m_planes[nzFrustumPlane_Max+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,23 +44,23 @@ NzFrustum<T>& NzFrustum<T>::Build(T angle, T ratio, T zNear, T zFar, const NzVec
|
||||||
NzVector3<T> fc = eye + f * zFar;
|
NzVector3<T> fc = eye + f * zFar;
|
||||||
|
|
||||||
// Calcul du frustum
|
// Calcul du frustum
|
||||||
m_corners[nzCorner_FarLeftBottom] = fc - u*farH - s*farW;
|
m_corners[nzBoxCorner_FarLeftBottom] = fc - u*farH - s*farW;
|
||||||
m_corners[nzCorner_FarLeftTop] = fc + u*farH - s*farW;
|
m_corners[nzBoxCorner_FarLeftTop] = fc + u*farH - s*farW;
|
||||||
m_corners[nzCorner_FarRightTop] = fc + u*farH + s*farW;
|
m_corners[nzBoxCorner_FarRightTop] = fc + u*farH + s*farW;
|
||||||
m_corners[nzCorner_FarRightBottom] = fc - u*farH + s*farW;
|
m_corners[nzBoxCorner_FarRightBottom] = fc - u*farH + s*farW;
|
||||||
|
|
||||||
m_corners[nzCorner_NearLeftBottom] = nc - u*nearH - s*nearW;
|
m_corners[nzBoxCorner_NearLeftBottom] = nc - u*nearH - s*nearW;
|
||||||
m_corners[nzCorner_NearLeftTop] = nc + u*nearH - s*nearW;
|
m_corners[nzBoxCorner_NearLeftTop] = nc + u*nearH - s*nearW;
|
||||||
m_corners[nzCorner_NearRightTop] = nc + u*nearH + s*nearW;
|
m_corners[nzBoxCorner_NearRightTop] = nc + u*nearH + s*nearW;
|
||||||
m_corners[nzCorner_NearRightBottom] = nc - u*nearH + s*nearW;
|
m_corners[nzBoxCorner_NearRightBottom] = nc - u*nearH + s*nearW;
|
||||||
|
|
||||||
// Construction des plans du frustum
|
// Construction des plans du frustum
|
||||||
m_planes[nzFrustumPlane_Bottom].Set(m_corners[nzCorner_NearLeftBottom], m_corners[nzCorner_NearRightBottom], m_corners[nzCorner_FarRightBottom]);
|
m_planes[nzFrustumPlane_Bottom].Set(m_corners[nzBoxCorner_NearLeftBottom], m_corners[nzBoxCorner_NearRightBottom], m_corners[nzBoxCorner_FarRightBottom]);
|
||||||
m_planes[nzFrustumPlane_Far].Set(m_corners[nzCorner_FarRightTop], m_corners[nzCorner_FarLeftTop], m_corners[nzCorner_FarLeftBottom]);
|
m_planes[nzFrustumPlane_Far].Set(m_corners[nzBoxCorner_FarRightTop], m_corners[nzBoxCorner_FarLeftTop], m_corners[nzBoxCorner_FarLeftBottom]);
|
||||||
m_planes[nzFrustumPlane_Left].Set(m_corners[nzCorner_NearLeftTop], m_corners[nzCorner_NearLeftBottom], m_corners[nzCorner_FarLeftBottom]);
|
m_planes[nzFrustumPlane_Left].Set(m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_NearLeftBottom], m_corners[nzBoxCorner_FarLeftBottom]);
|
||||||
m_planes[nzFrustumPlane_Near].Set(m_corners[nzCorner_NearLeftTop], m_corners[nzCorner_NearRightTop], m_corners[nzCorner_NearRightBottom]);
|
m_planes[nzFrustumPlane_Near].Set(m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_NearRightBottom]);
|
||||||
m_planes[nzFrustumPlane_Right].Set(m_corners[nzCorner_NearRightBottom], m_corners[nzCorner_NearRightTop], m_corners[nzCorner_FarRightBottom]);
|
m_planes[nzFrustumPlane_Right].Set(m_corners[nzBoxCorner_NearRightBottom], m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_FarRightBottom]);
|
||||||
m_planes[nzFrustumPlane_Top].Set(m_corners[nzCorner_NearRightTop], m_corners[nzCorner_NearLeftTop], m_corners[nzCorner_FarLeftTop]);
|
m_planes[nzFrustumPlane_Top].Set(m_corners[nzBoxCorner_NearRightTop], m_corners[nzBoxCorner_NearLeftTop], m_corners[nzBoxCorner_FarLeftTop]);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -272,56 +272,56 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& clipMatrix)
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_FarLeftBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_FarLeftBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// FarLeftTop
|
// FarLeftTop
|
||||||
corner.Set(F(-1.0), F(1.0), F(1.0));
|
corner.Set(F(-1.0), F(1.0), F(1.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_FarLeftTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_FarLeftTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// FarRightBottom
|
// FarRightBottom
|
||||||
corner.Set(F(1.0), F(-1.0), F(1.0));
|
corner.Set(F(1.0), F(-1.0), F(1.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_FarRightBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_FarRightBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// FarRightTop
|
// FarRightTop
|
||||||
corner.Set(F(1.0), F(1.0), F(1.0));
|
corner.Set(F(1.0), F(1.0), F(1.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_FarRightTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_FarRightTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// NearLeftBottom
|
// NearLeftBottom
|
||||||
corner.Set(F(-1.0), F(-1.0), F(0.0));
|
corner.Set(F(-1.0), F(-1.0), F(0.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_NearLeftBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_NearLeftBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// NearLeftTop
|
// NearLeftTop
|
||||||
corner.Set(F(-1.0), F(1.0), F(0.0));
|
corner.Set(F(-1.0), F(1.0), F(0.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_NearLeftTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_NearLeftTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// NearRightBottom
|
// NearRightBottom
|
||||||
corner.Set(F(1.0), F(-1.0), F(0.0));
|
corner.Set(F(1.0), F(-1.0), F(0.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_NearRightBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_NearRightBottom] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
|
|
||||||
// NearRightTop
|
// NearRightTop
|
||||||
corner.Set(F(1.0), F(1.0), F(0.0));
|
corner.Set(F(1.0), F(1.0), F(0.0));
|
||||||
corner = invClipMatrix.Transform(corner);
|
corner = invClipMatrix.Transform(corner);
|
||||||
corner.Normalize();
|
corner.Normalize();
|
||||||
|
|
||||||
m_corners[nzCorner_NearRightTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
m_corners[nzBoxCorner_NearRightTop] = NzVector3<T>(corner.x, corner.y, corner.z);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
NazaraWarning("Clip matrix is not invertible, failed to compute frustum corners");
|
NazaraWarning("Clip matrix is not invertible, failed to compute frustum corners");
|
||||||
|
|
@ -339,10 +339,10 @@ NzFrustum<T>& NzFrustum<T>::Extract(const NzMatrix4<T>& view, const NzMatrix4<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const NzVector3<T>& NzFrustum<T>::GetCorner(nzCorner corner) const
|
const NzVector3<T>& NzFrustum<T>::GetCorner(nzBoxCorner corner) const
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
if (corner > nzCorner_Max)
|
if (corner > nzBoxCorner_Max)
|
||||||
{
|
{
|
||||||
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
||||||
|
|
||||||
|
|
@ -481,7 +481,7 @@ template<typename T>
|
||||||
template<typename U>
|
template<typename U>
|
||||||
NzFrustum<T>& NzFrustum<T>::Set(const NzFrustum<U>& frustum)
|
NzFrustum<T>& NzFrustum<T>::Set(const NzFrustum<U>& frustum)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i <= nzCorner_Max; ++i)
|
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||||
m_corners[i].Set(frustum.m_corners[i]);
|
m_corners[i].Set(frustum.m_corners[i]);
|
||||||
|
|
||||||
for (unsigned int i = 0; i <= nzFrustumPlane_Max; ++i)
|
for (unsigned int i = 0; i <= nzFrustumPlane_Max; ++i)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class NzOrientedBox
|
||||||
NzOrientedBox(const NzOrientedBox& orientedBox) = default;
|
NzOrientedBox(const NzOrientedBox& orientedBox) = default;
|
||||||
~NzOrientedBox() = default;
|
~NzOrientedBox() = default;
|
||||||
|
|
||||||
const NzVector3<T>& GetCorner(nzCorner corner) const;
|
const NzVector3<T>& GetCorner(nzBoxCorner corner) const;
|
||||||
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ class NzOrientedBox
|
||||||
NzBox<T> localBox;
|
NzBox<T> localBox;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NzVector3<T> m_corners[nzCorner_Max+1]; // Ne peuvent pas être modifiés directement
|
NzVector3<T> m_corners[nzBoxCorner_Max+1]; // Ne peuvent pas être modifiés directement
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,10 @@ NzOrientedBox<T>::NzOrientedBox(const NzOrientedBox<U>& orientedBox)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const NzVector3<T>& NzOrientedBox<T>::GetCorner(nzCorner corner) const
|
const NzVector3<T>& NzOrientedBox<T>::GetCorner(nzBoxCorner corner) const
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
if (corner > nzCorner_Max)
|
if (corner > nzBoxCorner_Max)
|
||||||
{
|
{
|
||||||
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
||||||
|
|
||||||
|
|
@ -102,7 +102,7 @@ template<typename T>
|
||||||
template<typename U>
|
template<typename U>
|
||||||
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzOrientedBox<U>& orientedBox)
|
NzOrientedBox<T>& NzOrientedBox<T>::Set(const NzOrientedBox<U>& orientedBox)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i <= nzCorner_Max; ++i)
|
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||||
m_corners[i].Set(orientedBox.m_corners[i]);
|
m_corners[i].Set(orientedBox.m_corners[i]);
|
||||||
|
|
||||||
localBox = orientedBox.localBox;
|
localBox = orientedBox.localBox;
|
||||||
|
|
@ -115,21 +115,21 @@ NzString NzOrientedBox<T>::ToString() const
|
||||||
{
|
{
|
||||||
NzStringStream ss;
|
NzStringStream ss;
|
||||||
|
|
||||||
return ss << "OrientedBox(FLB: " << m_corners[nzCorner_FarLeftBottom].ToString() << "\n"
|
return ss << "OrientedBox(FLB: " << m_corners[nzBoxCorner_FarLeftBottom].ToString() << "\n"
|
||||||
<< " FLT: " << m_corners[nzCorner_FarLeftTop].ToString() << "\n"
|
<< " FLT: " << m_corners[nzBoxCorner_FarLeftTop].ToString() << "\n"
|
||||||
<< " FRB: " << m_corners[nzCorner_FarRightBottom].ToString() << "\n"
|
<< " FRB: " << m_corners[nzBoxCorner_FarRightBottom].ToString() << "\n"
|
||||||
<< " FRT: " << m_corners[nzCorner_FarRightTop].ToString() << "\n"
|
<< " FRT: " << m_corners[nzBoxCorner_FarRightTop].ToString() << "\n"
|
||||||
<< " NLB: " << m_corners[nzCorner_NearLeftBottom].ToString() << "\n"
|
<< " NLB: " << m_corners[nzBoxCorner_NearLeftBottom].ToString() << "\n"
|
||||||
<< " NLT: " << m_corners[nzCorner_NearLeftTop].ToString() << "\n"
|
<< " NLT: " << m_corners[nzBoxCorner_NearLeftTop].ToString() << "\n"
|
||||||
<< " NRB: " << m_corners[nzCorner_NearRightBottom].ToString() << "\n"
|
<< " NRB: " << m_corners[nzBoxCorner_NearRightBottom].ToString() << "\n"
|
||||||
<< " NRT: " << m_corners[nzCorner_NearRightTop].ToString() << ")\n";
|
<< " NRT: " << m_corners[nzBoxCorner_NearRightTop].ToString() << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzOrientedBox<T>::Update(const NzMatrix4<T>& transformMatrix)
|
void NzOrientedBox<T>::Update(const NzMatrix4<T>& transformMatrix)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i <= nzCorner_Max; ++i)
|
for (unsigned int i = 0; i <= nzBoxCorner_Max; ++i)
|
||||||
m_corners[i] = transformMatrix.Transform(localBox.GetCorner(static_cast<nzCorner>(i)));
|
m_corners[i] = transformMatrix.Transform(localBox.GetCorner(static_cast<nzBoxCorner>(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -148,7 +148,7 @@ template<typename T>
|
||||||
NzVector3<T>& NzOrientedBox<T>::operator()(unsigned int i)
|
NzVector3<T>& NzOrientedBox<T>::operator()(unsigned int i)
|
||||||
{
|
{
|
||||||
#if NAZARA_MATH_SAFE
|
#if NAZARA_MATH_SAFE
|
||||||
if (i > nzCorner_Max)
|
if (i > nzBoxCorner_Max)
|
||||||
{
|
{
|
||||||
NzStringStream ss;
|
NzStringStream ss;
|
||||||
ss << "Index out of range: (" << i << " >= 3)";
|
ss << "Index out of range: (" << i << " >= 3)";
|
||||||
|
|
@ -165,7 +165,7 @@ template<typename T>
|
||||||
NzVector3<T> NzOrientedBox<T>::operator()(unsigned int i) const
|
NzVector3<T> NzOrientedBox<T>::operator()(unsigned int i) const
|
||||||
{
|
{
|
||||||
#if NAZARA_MATH_SAFE
|
#if NAZARA_MATH_SAFE
|
||||||
if (i > nzCorner_Max)
|
if (i > nzBoxCorner_Max)
|
||||||
{
|
{
|
||||||
NzStringStream ss;
|
NzStringStream ss;
|
||||||
ss << "Index out of range: (" << i << " >= 3)";
|
ss << "Index out of range: (" << i << " >= 3)";
|
||||||
|
|
|
||||||
|
|
@ -204,9 +204,9 @@ bool NzRay<T>::Intersect(const NzBox<T>& box, const NzMatrix4<T>& transform, T*
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool NzRay<T>::Intersect(const NzOrientedBox<T>& orientedBox, T* closestHit, T* farthestHit) const
|
bool NzRay<T>::Intersect(const NzOrientedBox<T>& orientedBox, T* closestHit, T* farthestHit) const
|
||||||
{
|
{
|
||||||
NzVector3<T> width = (orientedBox.GetCorner(nzCorner_NearLeftBottom) - orientedBox.GetCorner(nzCorner_FarLeftBottom)).Normalize();
|
NzVector3<T> width = (orientedBox.GetCorner(nzBoxCorner_NearLeftBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize();
|
||||||
NzVector3<T> height = (orientedBox.GetCorner(nzCorner_FarLeftTop) - orientedBox.GetCorner(nzCorner_FarLeftBottom)).Normalize();
|
NzVector3<T> height = (orientedBox.GetCorner(nzBoxCorner_FarLeftTop) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize();
|
||||||
NzVector3<T> depth = (orientedBox.GetCorner(nzCorner_FarRightBottom) - orientedBox.GetCorner(nzCorner_FarLeftBottom)).Normalize();
|
NzVector3<T> depth = (orientedBox.GetCorner(nzBoxCorner_FarRightBottom) - orientedBox.GetCorner(nzBoxCorner_FarLeftBottom)).Normalize();
|
||||||
|
|
||||||
// Construction de la matrice de transformation de l'OBB
|
// Construction de la matrice de transformation de l'OBB
|
||||||
NzMatrix4<T> matrix(width.x, height.x, depth.x, F(0.0),
|
NzMatrix4<T> matrix(width.x, height.x, depth.x, F(0.0),
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#define NAZARA_RECT_HPP
|
#define NAZARA_RECT_HPP
|
||||||
|
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
|
#include <Nazara/Math/Enums.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -33,6 +34,7 @@ class NzRect
|
||||||
NzRect& ExtendTo(const NzRect& rect);
|
NzRect& ExtendTo(const NzRect& rect);
|
||||||
|
|
||||||
NzVector2<T> GetCenter() const;
|
NzVector2<T> GetCenter() const;
|
||||||
|
NzVector2<T> GetCorner(nzRectCorner corner) const;
|
||||||
NzVector2<T> GetLengths() const;
|
NzVector2<T> GetLengths() const;
|
||||||
NzVector2<T> GetMaximum() const;
|
NzVector2<T> GetMaximum() const;
|
||||||
NzVector2<T> GetMinimum() const;
|
NzVector2<T> GetMinimum() const;
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,28 @@ NzVector2<T> NzRect<T>::GetCenter() const
|
||||||
return GetPosition() + GetLengths() / F(2.0);
|
return GetPosition() + GetLengths() / F(2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector2<T> NzRect<T>::GetCorner(nzRectCorner corner) const
|
||||||
|
{
|
||||||
|
switch (corner)
|
||||||
|
{
|
||||||
|
case nzRectCorner_LeftBottom:
|
||||||
|
return NzVector2<T>(x, y + height);
|
||||||
|
|
||||||
|
case nzRectCorner_LeftTop:
|
||||||
|
return NzVector2<T>(x, y);
|
||||||
|
|
||||||
|
case nzRectCorner_RightBottom:
|
||||||
|
return NzVector2<T>(x + width, y + height);
|
||||||
|
|
||||||
|
case nzRectCorner_RightTop:
|
||||||
|
return NzVector2<T>(x + width, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Corner not handled (0x" + NzString::Number(corner, 16) + ')');
|
||||||
|
return NzVector2<T>();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector2<T> NzRect<T>::GetLengths() const
|
NzVector2<T> NzRect<T>::GetLengths() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
|
|
||||||
|
template<typename T> class NzVector3;
|
||||||
|
template<typename T> class NzVector4;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class NzVector2
|
class NzVector2
|
||||||
{
|
{
|
||||||
|
|
@ -19,6 +22,8 @@ class NzVector2
|
||||||
NzVector2(const T vec[2]);
|
NzVector2(const T vec[2]);
|
||||||
template<typename U> explicit NzVector2(const NzVector2<U>& vec);
|
template<typename U> explicit NzVector2(const NzVector2<U>& vec);
|
||||||
NzVector2(const NzVector2& vec) = default;
|
NzVector2(const NzVector2& vec) = default;
|
||||||
|
explicit NzVector2(const NzVector3<T>& vec);
|
||||||
|
explicit NzVector2(const NzVector4<T>& vec);
|
||||||
~NzVector2() = default;
|
~NzVector2() = default;
|
||||||
|
|
||||||
T AbsDotProduct(const NzVector2& vec) const;
|
T AbsDotProduct(const NzVector2& vec) const;
|
||||||
|
|
@ -48,6 +53,8 @@ class NzVector2
|
||||||
NzVector2& Set(T scale);
|
NzVector2& Set(T scale);
|
||||||
NzVector2& Set(const T vec[2]);
|
NzVector2& Set(const T vec[2]);
|
||||||
NzVector2& Set(const NzVector2& vec);
|
NzVector2& Set(const NzVector2& vec);
|
||||||
|
NzVector2& Set(const NzVector3<T>& vec);
|
||||||
|
NzVector2& Set(const NzVector4<T>& vec);
|
||||||
template<typename U> NzVector2& Set(const NzVector2<U>& vec);
|
template<typename U> NzVector2& Set(const NzVector2<U>& vec);
|
||||||
|
|
||||||
T SquaredDistance(const NzVector2& vec) const;
|
T SquaredDistance(const NzVector2& vec) const;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,18 @@ NzVector2<T>::NzVector2(const NzVector2<U>& vec)
|
||||||
Set(vec);
|
Set(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector2<T>::NzVector2(const NzVector3<T>& vec)
|
||||||
|
{
|
||||||
|
Set(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector2<T>::NzVector2(const NzVector4<T>& vec)
|
||||||
|
{
|
||||||
|
Set(vec);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T NzVector2<T>::AbsDotProduct(const NzVector2& vec) const
|
T NzVector2<T>::AbsDotProduct(const NzVector2& vec) const
|
||||||
{
|
{
|
||||||
|
|
@ -208,6 +220,24 @@ NzVector2<T>& NzVector2<T>::Set(const NzVector2<U>& vec)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector2<T>& NzVector2<T>::Set(const NzVector3<T>& vec)
|
||||||
|
{
|
||||||
|
x = vec.x;
|
||||||
|
y = vec.y;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector2<T>& NzVector2<T>::Set(const NzVector4<T>& vec)
|
||||||
|
{
|
||||||
|
x = vec.x;
|
||||||
|
y = vec.y;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T NzVector2<T>::SquaredDistance(const NzVector2& vec) const
|
T NzVector2<T>::SquaredDistance(const NzVector2& vec) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,23 @@
|
||||||
#define NAZARA_VECTOR3_HPP
|
#define NAZARA_VECTOR3_HPP
|
||||||
|
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
|
||||||
|
|
||||||
template<typename T> class NzVector3
|
template<typename T> class NzVector2;
|
||||||
|
template<typename T> class NzVector4;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class NzVector3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzVector3() = default;
|
NzVector3() = default;
|
||||||
NzVector3(T X, T Y, T Z);
|
NzVector3(T X, T Y, T Z);
|
||||||
|
NzVector3(T X, const NzVector2<T>& vec);
|
||||||
explicit NzVector3(T scale);
|
explicit NzVector3(T scale);
|
||||||
NzVector3(const T vec[3]);
|
NzVector3(const T vec[3]);
|
||||||
NzVector3(const NzVector2<T>& vec, T Z = 0.0);
|
NzVector3(const NzVector2<T>& vec, T Z = 0.0);
|
||||||
template<typename U> explicit NzVector3(const NzVector3<U>& vec);
|
template<typename U> explicit NzVector3(const NzVector3<U>& vec);
|
||||||
NzVector3(const NzVector3& vec) = default;
|
NzVector3(const NzVector3& vec) = default;
|
||||||
|
explicit NzVector3(const NzVector4<T>& vec);
|
||||||
~NzVector3() = default;
|
~NzVector3() = default;
|
||||||
|
|
||||||
T AbsDotProduct(const NzVector3& vec) const;
|
T AbsDotProduct(const NzVector3& vec) const;
|
||||||
|
|
@ -56,11 +61,13 @@ template<typename T> class NzVector3
|
||||||
NzVector3& Normalize(T* length = nullptr);
|
NzVector3& Normalize(T* length = nullptr);
|
||||||
|
|
||||||
NzVector3& Set(T X, T Y, T Z);
|
NzVector3& Set(T X, T Y, T Z);
|
||||||
|
NzVector3& Set(T X, const NzVector2<T>& vec);
|
||||||
NzVector3& Set(T scale);
|
NzVector3& Set(T scale);
|
||||||
NzVector3& Set(const T vec[3]);
|
NzVector3& Set(const T vec[3]);
|
||||||
NzVector3& Set(const NzVector2<T>& vec, T Z = 0.0);
|
NzVector3& Set(const NzVector2<T>& vec, T Z = 0.0);
|
||||||
NzVector3& Set(const NzVector3<T>& vec);
|
NzVector3& Set(const NzVector3<T>& vec);
|
||||||
template<typename U> NzVector3& Set(const NzVector3<U>& vec);
|
template<typename U> NzVector3& Set(const NzVector3<U>& vec);
|
||||||
|
NzVector3& Set(const NzVector4<T>& vec);
|
||||||
|
|
||||||
T SquaredDistance(const NzVector3& vec) const;
|
T SquaredDistance(const NzVector3& vec) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@ NzVector3<T>::NzVector3(T X, T Y, T Z)
|
||||||
Set(X, Y, Z);
|
Set(X, Y, Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector3<T>::NzVector3(T X, const NzVector2<T>& vec)
|
||||||
|
{
|
||||||
|
Set(X, vec);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector3<T>::NzVector3(T scale)
|
NzVector3<T>::NzVector3(T scale)
|
||||||
{
|
{
|
||||||
|
|
@ -42,6 +48,12 @@ NzVector3<T>::NzVector3(const NzVector3<U>& vec)
|
||||||
Set(vec);
|
Set(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector3<T>::NzVector3(const NzVector4<T>& vec)
|
||||||
|
{
|
||||||
|
Set(vec);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T NzVector3<T>::AbsDotProduct(const NzVector3& vec) const
|
T NzVector3<T>::AbsDotProduct(const NzVector3& vec) const
|
||||||
{
|
{
|
||||||
|
|
@ -255,6 +267,16 @@ NzVector3<T>& NzVector3<T>::Set(T X, T Y, T Z)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector3<T>& NzVector3<T>::Set(T X, const NzVector2<T>& vec)
|
||||||
|
{
|
||||||
|
x = X;
|
||||||
|
y = vec.x;
|
||||||
|
z = vec.y;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector3<T>& NzVector3<T>::Set(T scale)
|
NzVector3<T>& NzVector3<T>::Set(T scale)
|
||||||
{
|
{
|
||||||
|
|
@ -302,6 +324,16 @@ NzVector3<T>& NzVector3<T>::Set(const NzVector3<U>& vec)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector3<T>& NzVector3<T>::Set(const NzVector4<T>& vec)
|
||||||
|
{
|
||||||
|
x = vec.x;
|
||||||
|
y = vec.y;
|
||||||
|
z = vec.z;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T NzVector3<T>::SquaredDistance(const NzVector3& vec) const
|
T NzVector3<T>::SquaredDistance(const NzVector3& vec) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,23 @@
|
||||||
#define NAZARA_VECTOR4_HPP
|
#define NAZARA_VECTOR4_HPP
|
||||||
|
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
|
||||||
|
|
||||||
template<typename T> class NzVector4
|
template<typename T> class NzVector2;
|
||||||
|
template<typename T> class NzVector3;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class NzVector4
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzVector4() = default;
|
NzVector4() = default;
|
||||||
NzVector4(T X, T Y, T Z, T W = 1.0);
|
NzVector4(T X, T Y, T Z, T W = 1.0);
|
||||||
|
NzVector4(T X, T Y, const NzVector2<T>& vec);
|
||||||
|
NzVector4(T X, const NzVector2<T>& vec, T W);
|
||||||
|
NzVector4(T X, const NzVector3<T>& vec);
|
||||||
explicit NzVector4(T scale);
|
explicit NzVector4(T scale);
|
||||||
NzVector4(const T vec[4]);
|
NzVector4(const T vec[4]);
|
||||||
NzVector4(const NzVector3<T>& vec, T W = 1.0);
|
NzVector4(const NzVector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||||
|
NzVector4(const NzVector3<T>& vec, T W = 0.0);
|
||||||
template<typename U> explicit NzVector4(const NzVector4<U>& vec);
|
template<typename U> explicit NzVector4(const NzVector4<U>& vec);
|
||||||
NzVector4(const NzVector4& vec) = default;
|
NzVector4(const NzVector4& vec) = default;
|
||||||
~NzVector4() = default;
|
~NzVector4() = default;
|
||||||
|
|
@ -39,8 +46,12 @@ template<typename T> class NzVector4
|
||||||
NzVector4& Normalize(T* length = nullptr);
|
NzVector4& Normalize(T* length = nullptr);
|
||||||
|
|
||||||
NzVector4& Set(T X, T Y, T Z, T W = 1.0);
|
NzVector4& Set(T X, T Y, T Z, T W = 1.0);
|
||||||
|
NzVector4& Set(T X, T Y, const NzVector2<T>& vec);
|
||||||
|
NzVector4& Set(T X, const NzVector2<T>& vec, T W);
|
||||||
|
NzVector4& Set(T X, const NzVector3<T>& vec);
|
||||||
NzVector4& Set(T scale);
|
NzVector4& Set(T scale);
|
||||||
NzVector4& Set(const T vec[4]);
|
NzVector4& Set(const T vec[4]);
|
||||||
|
NzVector4& Set(const NzVector2<T>& vec, T Z = 0.0, T W = 1.0);
|
||||||
NzVector4& Set(const NzVector3<T>& vec, T W = 1.0);
|
NzVector4& Set(const NzVector3<T>& vec, T W = 1.0);
|
||||||
NzVector4& Set(const NzVector4<T>& vec);
|
NzVector4& Set(const NzVector4<T>& vec);
|
||||||
template<typename U> NzVector4& Set(const NzVector4<U>& vec);
|
template<typename U> NzVector4& Set(const NzVector4<U>& vec);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,24 @@ NzVector4<T>::NzVector4(T X, T Y, T Z, T W)
|
||||||
Set(X, Y, Z, W);
|
Set(X, Y, Z, W);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>::NzVector4(T X, T Y, const NzVector2<T>& vec)
|
||||||
|
{
|
||||||
|
Set(X, Y, vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>::NzVector4(T X, const NzVector2<T>& vec, T W)
|
||||||
|
{
|
||||||
|
Set(X, vec, W);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>::NzVector4(T X, const NzVector3<T>& vec)
|
||||||
|
{
|
||||||
|
Set(X, vec);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector4<T>::NzVector4(T scale)
|
NzVector4<T>::NzVector4(T scale)
|
||||||
{
|
{
|
||||||
|
|
@ -30,6 +48,12 @@ NzVector4<T>::NzVector4(const T vec[4])
|
||||||
Set(vec);
|
Set(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>::NzVector4(const NzVector2<T>& vec, T Z, T W)
|
||||||
|
{
|
||||||
|
Set(vec, Z, W);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector4<T>::NzVector4(const NzVector3<T>& vec, T W)
|
NzVector4<T>::NzVector4(const NzVector3<T>& vec, T W)
|
||||||
{
|
{
|
||||||
|
|
@ -155,10 +179,43 @@ NzVector4<T>& NzVector4<T>::Normalize(T* length)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector4<T>& NzVector4<T>::Set(T X, T Y, T Z, T W)
|
NzVector4<T>& NzVector4<T>::Set(T X, T Y, T Z, T W)
|
||||||
{
|
{
|
||||||
w = W;
|
|
||||||
x = X;
|
x = X;
|
||||||
y = Y;
|
y = Y;
|
||||||
z = Z;
|
z = Z;
|
||||||
|
w = W;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>& NzVector4<T>::Set(T X, T Y, const NzVector2<T>& vec)
|
||||||
|
{
|
||||||
|
x = X;
|
||||||
|
y = Y;
|
||||||
|
z = vec.x;
|
||||||
|
w = vec.y;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>& NzVector4<T>::Set(T X, const NzVector2<T>& vec, T W)
|
||||||
|
{
|
||||||
|
x = X;
|
||||||
|
y = vec.x;
|
||||||
|
z = vec.y;
|
||||||
|
w = W;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>& NzVector4<T>::Set(T X, const NzVector3<T>& vec)
|
||||||
|
{
|
||||||
|
x = X;
|
||||||
|
y = vec.x;
|
||||||
|
z = vec.y;
|
||||||
|
w = vec.z;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -166,10 +223,10 @@ NzVector4<T>& NzVector4<T>::Set(T X, T Y, T Z, T W)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector4<T>& NzVector4<T>::Set(T scale)
|
NzVector4<T>& NzVector4<T>::Set(T scale)
|
||||||
{
|
{
|
||||||
w = scale;
|
|
||||||
x = scale;
|
x = scale;
|
||||||
y = scale;
|
y = scale;
|
||||||
z = scale;
|
z = scale;
|
||||||
|
w = scale;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -182,6 +239,17 @@ NzVector4<T>& NzVector4<T>::Set(const T vec[4])
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector4<T>& NzVector4<T>::Set(const NzVector2<T>& vec, T Z, T W)
|
||||||
|
{
|
||||||
|
x = vec.x;
|
||||||
|
y = vec.y;
|
||||||
|
z = Z;
|
||||||
|
w = W;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector4<T>& NzVector4<T>::Set(const NzVector3<T>& vec, T W)
|
NzVector4<T>& NzVector4<T>::Set(const NzVector3<T>& vec, T W)
|
||||||
{
|
{
|
||||||
|
|
@ -205,10 +273,10 @@ template<typename T>
|
||||||
template<typename U>
|
template<typename U>
|
||||||
NzVector4<T>& NzVector4<T>::Set(const NzVector4<U>& vec)
|
NzVector4<T>& NzVector4<T>::Set(const NzVector4<U>& vec)
|
||||||
{
|
{
|
||||||
w = F(vec.w);
|
|
||||||
x = F(vec.x);
|
x = F(vec.x);
|
||||||
y = F(vec.y);
|
y = F(vec.y);
|
||||||
z = F(vec.z);
|
z = F(vec.z);
|
||||||
|
w = F(vec.w);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class NAZARA_API NzDebugDrawer
|
||||||
static void Draw(const NzFrustumf& frustum);
|
static void Draw(const NzFrustumf& frustum);
|
||||||
static void Draw(const NzOrientedBoxf& orientedBox);
|
static void Draw(const NzOrientedBoxf& orientedBox);
|
||||||
static void Draw(const NzSkeleton* skeleton);
|
static void Draw(const NzSkeleton* skeleton);
|
||||||
|
static void Draw(const NzVector3f& position, float size = 0.1f);
|
||||||
static void DrawBinormals(const NzStaticMesh* subMesh);
|
static void DrawBinormals(const NzStaticMesh* subMesh);
|
||||||
static void DrawCone(const NzVector3f& origin, const NzQuaternionf& rotation, float angle, float length);
|
static void DrawCone(const NzVector3f& origin, const NzQuaternionf& rotation, float angle, float length);
|
||||||
static void DrawLine(const NzVector3f& p1, const NzVector3f& p2);
|
static void DrawLine(const NzVector3f& p1, const NzVector3f& p2);
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,7 @@ enum nzSamplerWrap
|
||||||
|
|
||||||
enum nzShaderUniform
|
enum nzShaderUniform
|
||||||
{
|
{
|
||||||
|
///FIXME: Virer EyePosition, SceneAmbient et TargetSize de l'énumération (ils n'ont rien à faire dans le module de rendu)
|
||||||
nzShaderUniform_EyePosition,
|
nzShaderUniform_EyePosition,
|
||||||
nzShaderUniform_InvProjMatrix,
|
nzShaderUniform_InvProjMatrix,
|
||||||
nzShaderUniform_InvTargetSize,
|
nzShaderUniform_InvTargetSize,
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ class NAZARA_API NzOpenGL
|
||||||
GLenum dataFormat;
|
GLenum dataFormat;
|
||||||
GLenum dataType;
|
GLenum dataType;
|
||||||
GLint internalFormat;
|
GLint internalFormat;
|
||||||
|
GLint swizzle[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
NzOpenGL() = delete;
|
NzOpenGL() = delete;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class NAZARA_API NzRenderTarget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Listener() = default;
|
Listener() = default;
|
||||||
~Listener();
|
virtual ~Listener();
|
||||||
|
|
||||||
virtual bool OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata);
|
virtual bool OnRenderTargetParametersChange(const NzRenderTarget* renderTarget, void* userdata);
|
||||||
virtual void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata);
|
virtual void OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata);
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ class NAZARA_API NzRenderer
|
||||||
static nzUInt8 GetMaxAnisotropyLevel();
|
static nzUInt8 GetMaxAnisotropyLevel();
|
||||||
static unsigned int GetMaxColorAttachments();
|
static unsigned int GetMaxColorAttachments();
|
||||||
static unsigned int GetMaxRenderTargets();
|
static unsigned int GetMaxRenderTargets();
|
||||||
|
static unsigned int GetMaxTextureSize();
|
||||||
static unsigned int GetMaxTextureUnits();
|
static unsigned int GetMaxTextureUnits();
|
||||||
static unsigned int GetMaxVertexAttribs();
|
static unsigned int GetMaxVertexAttribs();
|
||||||
static float GetPointSize();
|
static float GetPointSize();
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@
|
||||||
#include <Nazara/Core/Resource.hpp>
|
#include <Nazara/Core/Resource.hpp>
|
||||||
#include <Nazara/Core/ResourceRef.hpp>
|
#include <Nazara/Core/ResourceRef.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractImage.hpp>
|
||||||
#include <Nazara/Utility/CubemapParams.hpp>
|
#include <Nazara/Utility/CubemapParams.hpp>
|
||||||
#include <Nazara/Utility/Image.hpp>
|
#include <Nazara/Utility/Image.hpp>
|
||||||
#include <Nazara/Utility/PixelFormat.hpp>
|
|
||||||
|
|
||||||
class NzTexture;
|
class NzTexture;
|
||||||
|
|
||||||
|
|
@ -23,13 +23,13 @@ using NzTextureRef = NzResourceRef<NzTexture>;
|
||||||
|
|
||||||
struct NzTextureImpl;
|
struct NzTextureImpl;
|
||||||
|
|
||||||
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
class NAZARA_API NzTexture : public NzAbstractImage, public NzResource, NzNonCopyable
|
||||||
{
|
{
|
||||||
friend class NzRenderer;
|
friend class NzRenderer;
|
||||||
friend class NzRenderTexture;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NzTexture() = default;
|
NzTexture() = default;
|
||||||
|
NzTexture(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1);
|
||||||
explicit NzTexture(const NzImage& image);
|
explicit NzTexture(const NzImage& image);
|
||||||
~NzTexture();
|
~NzTexture();
|
||||||
|
|
||||||
|
|
@ -42,18 +42,20 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
|
|
||||||
void EnsureMipmapsUpdate() const;
|
void EnsureMipmapsUpdate() const;
|
||||||
|
|
||||||
nzUInt8 GetBytesPerPixel() const;
|
unsigned int GetDepth(nzUInt8 level = 0) const;
|
||||||
unsigned int GetDepth() const;
|
|
||||||
nzPixelFormat GetFormat() const;
|
nzPixelFormat GetFormat() const;
|
||||||
unsigned int GetHeight() const;
|
unsigned int GetHeight(nzUInt8 level = 0) const;
|
||||||
NzVector2ui GetSize() const;
|
nzUInt8 GetLevelCount() const;
|
||||||
|
nzUInt8 GetMaxLevel() const;
|
||||||
|
unsigned int GetMemoryUsage() const;
|
||||||
|
unsigned int GetMemoryUsage(nzUInt8 level) const;
|
||||||
|
NzVector3ui GetSize(nzUInt8 level = 0) const;
|
||||||
nzImageType GetType() const;
|
nzImageType GetType() const;
|
||||||
unsigned int GetWidth() const;
|
unsigned int GetWidth(nzUInt8 level = 0) const;
|
||||||
|
|
||||||
bool HasMipmaps() const;
|
bool HasMipmaps() const;
|
||||||
|
|
||||||
bool IsCompressed() const;
|
void InvalidateMipmaps();
|
||||||
bool IsCubemap() const;
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
|
|
@ -87,10 +89,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0);
|
|
||||||
bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0);
|
|
||||||
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
|
||||||
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
|
||||||
|
|
||||||
// Fonctions OpenGL
|
// Fonctions OpenGL
|
||||||
unsigned int GetOpenGLID() const;
|
unsigned int GetOpenGLID() const;
|
||||||
|
|
@ -101,7 +99,7 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
static bool IsTypeSupported(nzImageType type);
|
static bool IsTypeSupported(nzImageType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InvalidateMipmaps();
|
bool CreateTexture(bool proxy);
|
||||||
|
|
||||||
NzTextureImpl* m_impl = nullptr;
|
NzTextureImpl* m_impl = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (C) 2015 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_ABSTRACTATLAS_HPP
|
||||||
|
#define NAZARA_ABSTRACTATLAS_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/SparsePtr.hpp>
|
||||||
|
#include <Nazara/Math/Rect.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class NzAbstractImage;
|
||||||
|
class NzImage;
|
||||||
|
|
||||||
|
class NAZARA_API NzAbstractAtlas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Listener;
|
||||||
|
|
||||||
|
NzAbstractAtlas();
|
||||||
|
virtual ~NzAbstractAtlas();
|
||||||
|
|
||||||
|
void AddListener(Listener* font, void* userdata = nullptr) const;
|
||||||
|
|
||||||
|
virtual void Clear() = 0;
|
||||||
|
virtual void Free(NzSparsePtr<const NzRectui> rects, NzSparsePtr<unsigned int> layers, unsigned int count) = 0;
|
||||||
|
virtual NzAbstractImage* GetLayer(unsigned int layerIndex) const = 0;
|
||||||
|
virtual unsigned int GetLayerCount() const = 0;
|
||||||
|
virtual bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex) = 0;
|
||||||
|
|
||||||
|
void RemoveListener(Listener* font) const;
|
||||||
|
|
||||||
|
class Listener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Listener() = default;
|
||||||
|
virtual ~Listener();
|
||||||
|
|
||||||
|
virtual bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata);
|
||||||
|
virtual bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata);
|
||||||
|
virtual void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata);
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NotifyCleared();
|
||||||
|
void NotifyLayerChange(NzAbstractImage* oldLayer, NzAbstractImage* newLayer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::unordered_map<Listener*, void*> m_listeners;
|
||||||
|
bool m_listenersLocked;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_ABSTRACTATLAS_HPP
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (C) 2015 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_ABSTRACTIMAGE_HPP
|
||||||
|
#define NAZARA_ABSTRACTIMAGE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Math/Box.hpp>
|
||||||
|
#include <Nazara/Math/Rect.hpp>
|
||||||
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
|
|
||||||
|
class NAZARA_API NzAbstractImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzAbstractImage() = default;
|
||||||
|
virtual ~NzAbstractImage();
|
||||||
|
|
||||||
|
nzUInt8 GetBytesPerPixel() const;
|
||||||
|
virtual unsigned int GetDepth(nzUInt8 level = 0) const = 0;
|
||||||
|
virtual nzPixelFormat GetFormat() const = 0;
|
||||||
|
virtual unsigned int GetHeight(nzUInt8 level = 0) const = 0;
|
||||||
|
virtual nzUInt8 GetLevelCount() const = 0;
|
||||||
|
virtual nzUInt8 GetMaxLevel() const = 0;
|
||||||
|
virtual unsigned int GetMemoryUsage() const = 0;
|
||||||
|
virtual unsigned int GetMemoryUsage(nzUInt8 level) const = 0;
|
||||||
|
virtual NzVector3ui GetSize(nzUInt8 level = 0) const = 0;
|
||||||
|
virtual nzImageType GetType() const = 0;
|
||||||
|
virtual unsigned int GetWidth(nzUInt8 level = 0) const = 0;
|
||||||
|
|
||||||
|
bool IsCompressed() const;
|
||||||
|
bool IsCubemap() const;
|
||||||
|
|
||||||
|
virtual bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0) = 0;
|
||||||
|
virtual bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0) = 0;
|
||||||
|
virtual bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_IMAGE_HPP
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (C) 2015 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_ABSTRACTTEXTDRAWER_HPP
|
||||||
|
#define NAZARA_ABSTRACTTEXTDRAWER_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/Color.hpp>
|
||||||
|
#include <Nazara/Math/Rect.hpp>
|
||||||
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
|
|
||||||
|
class NzAbstractImage;
|
||||||
|
class NzFont;
|
||||||
|
|
||||||
|
class NAZARA_API NzAbstractTextDrawer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Glyph;
|
||||||
|
|
||||||
|
NzAbstractTextDrawer() = default;
|
||||||
|
virtual ~NzAbstractTextDrawer();
|
||||||
|
|
||||||
|
virtual const NzRectui& GetBounds() const = 0;
|
||||||
|
virtual NzFont* GetFont(unsigned int index) const = 0;
|
||||||
|
virtual unsigned int GetFontCount() const = 0;
|
||||||
|
virtual const Glyph& GetGlyph(unsigned int index) const = 0;
|
||||||
|
virtual unsigned int GetGlyphCount() const = 0;
|
||||||
|
|
||||||
|
struct Glyph
|
||||||
|
{
|
||||||
|
NzColor color;
|
||||||
|
NzRectui atlasRect;
|
||||||
|
NzVector2f corners[4];
|
||||||
|
NzAbstractImage* atlas;
|
||||||
|
bool flipped;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_ABSTRACTTEXTDRAWER_HPP
|
||||||
|
|
@ -25,22 +25,22 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable
|
||||||
friend class NzUtility;
|
friend class NzUtility;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using BufferFunction = NzAbstractBuffer* (*)(NzBuffer* parent, nzBufferType type);
|
using BufferFactory = NzAbstractBuffer* (*)(NzBuffer* parent, nzBufferType type);
|
||||||
|
|
||||||
NzBuffer(nzBufferType type);
|
NzBuffer(nzBufferType type);
|
||||||
NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
NzBuffer(nzBufferType type, unsigned int size, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
~NzBuffer();
|
~NzBuffer();
|
||||||
|
|
||||||
bool CopyContent(const NzBuffer& buffer);
|
bool CopyContent(const NzBuffer& buffer);
|
||||||
|
|
||||||
bool Create(unsigned int size, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
bool Create(unsigned int size, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false);
|
bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false);
|
||||||
|
|
||||||
NzAbstractBuffer* GetImpl() const;
|
NzAbstractBuffer* GetImpl() const;
|
||||||
unsigned int GetSize() const;
|
unsigned int GetSize() const;
|
||||||
nzBufferStorage GetStorage() const;
|
nzUInt32 GetStorage() const;
|
||||||
nzBufferType GetType() const;
|
nzBufferType GetType() const;
|
||||||
nzBufferUsage GetUsage() const;
|
nzBufferUsage GetUsage() const;
|
||||||
|
|
||||||
|
|
@ -50,24 +50,24 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable
|
||||||
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0);
|
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0);
|
||||||
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const;
|
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const;
|
||||||
|
|
||||||
bool SetStorage(nzBufferStorage storage);
|
bool SetStorage(nzUInt32 storage);
|
||||||
|
|
||||||
void Unmap() const;
|
void Unmap() const;
|
||||||
|
|
||||||
static bool IsSupported(nzBufferStorage storage);
|
static bool IsStorageSupported(nzUInt32 storage);
|
||||||
static void SetBufferFunction(nzBufferStorage storage, BufferFunction func);
|
static void SetBufferFactory(nzUInt32 storage, BufferFactory func);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
nzBufferStorage m_storage;
|
|
||||||
nzBufferType m_type;
|
nzBufferType m_type;
|
||||||
nzBufferUsage m_usage;
|
nzBufferUsage m_usage;
|
||||||
|
nzUInt32 m_storage;
|
||||||
NzAbstractBuffer* m_impl;
|
NzAbstractBuffer* m_impl;
|
||||||
unsigned int m_size;
|
unsigned int m_size;
|
||||||
|
|
||||||
static BufferFunction s_bufferFunctions[nzBufferStorage_Max+1];
|
static BufferFactory s_bufferFactories[nzDataStorage_Max+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_BUFFER_HPP
|
#endif // NAZARA_BUFFER_HPP
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,6 @@ enum nzBufferAccess
|
||||||
nzBufferAccess_Max = nzBufferAccess_WriteOnly
|
nzBufferAccess_Max = nzBufferAccess_WriteOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzBufferStorage
|
|
||||||
{
|
|
||||||
//nzBufferStorage_Both, ///TODO
|
|
||||||
nzBufferStorage_Hardware,
|
|
||||||
nzBufferStorage_Software,
|
|
||||||
|
|
||||||
nzBufferStorage_Max = nzBufferStorage_Software
|
|
||||||
};
|
|
||||||
|
|
||||||
enum nzBufferType
|
enum nzBufferType
|
||||||
{
|
{
|
||||||
nzBufferType_Index,
|
nzBufferType_Index,
|
||||||
|
|
@ -84,6 +75,16 @@ enum nzCubemapFace
|
||||||
nzCubemapFace_Max = nzCubemapFace_NegativeZ
|
nzCubemapFace_Max = nzCubemapFace_NegativeZ
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum nzDataStorageFlags
|
||||||
|
{
|
||||||
|
nzDataStorage_Hardware = 0x1,
|
||||||
|
nzDataStorage_Software = 0x2,
|
||||||
|
|
||||||
|
nzDataStorage_Both = nzDataStorage_Hardware | nzDataStorage_Software,
|
||||||
|
|
||||||
|
nzDataStorage_Max = nzDataStorage_Software*2-1
|
||||||
|
};
|
||||||
|
|
||||||
enum nzEventType
|
enum nzEventType
|
||||||
{
|
{
|
||||||
nzEventType_GainedFocus,
|
nzEventType_GainedFocus,
|
||||||
|
|
@ -130,6 +131,7 @@ enum nzPixelFormat
|
||||||
{
|
{
|
||||||
nzPixelFormat_Undefined = -1,
|
nzPixelFormat_Undefined = -1,
|
||||||
|
|
||||||
|
nzPixelFormat_A8, // 1*uint8
|
||||||
nzPixelFormat_BGR8, // 3*uint8
|
nzPixelFormat_BGR8, // 3*uint8
|
||||||
nzPixelFormat_BGRA8, // 4*uint8
|
nzPixelFormat_BGRA8, // 4*uint8
|
||||||
nzPixelFormat_DXT1,
|
nzPixelFormat_DXT1,
|
||||||
|
|
@ -217,6 +219,27 @@ enum nzPrimitiveMode
|
||||||
nzPrimitiveMode_Max = nzPrimitiveMode_TriangleFan
|
nzPrimitiveMode_Max = nzPrimitiveMode_TriangleFan
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum nzTextAlign
|
||||||
|
{
|
||||||
|
nzTextAlign_Left,
|
||||||
|
nzTextAlign_Middle,
|
||||||
|
nzTextAlign_Right,
|
||||||
|
|
||||||
|
nzTextAlign_Max = nzTextAlign_Right
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nzTextStyleFlags
|
||||||
|
{
|
||||||
|
nzTextStyle_Regular = 0x0,
|
||||||
|
|
||||||
|
nzTextStyle_Bold = 0x1,
|
||||||
|
nzTextStyle_Italic = 0x2,
|
||||||
|
nzTextStyle_StrikeThrough = 0x4,
|
||||||
|
nzTextStyle_Underlined = 0x8,
|
||||||
|
|
||||||
|
nzTextStyle_Max = nzTextStyle_Underlined*2-1
|
||||||
|
};
|
||||||
|
|
||||||
enum nzVertexComponent
|
enum nzVertexComponent
|
||||||
{
|
{
|
||||||
nzVertexComponent_Unused = -1,
|
nzVertexComponent_Unused = -1,
|
||||||
|
|
@ -251,8 +274,11 @@ enum nzVertexLayout
|
||||||
{
|
{
|
||||||
// Déclarations destinées au rendu
|
// Déclarations destinées au rendu
|
||||||
nzVertexLayout_XY,
|
nzVertexLayout_XY,
|
||||||
|
nzVertexLayout_XY_Color,
|
||||||
nzVertexLayout_XY_UV,
|
nzVertexLayout_XY_UV,
|
||||||
nzVertexLayout_XYZ,
|
nzVertexLayout_XYZ,
|
||||||
|
nzVertexLayout_XYZ_Color,
|
||||||
|
nzVertexLayout_XYZ_Color_UV,
|
||||||
nzVertexLayout_XYZ_Normal,
|
nzVertexLayout_XYZ_Normal,
|
||||||
nzVertexLayout_XYZ_Normal_UV,
|
nzVertexLayout_XYZ_Normal_UV,
|
||||||
nzVertexLayout_XYZ_Normal_UV_Tangent,
|
nzVertexLayout_XYZ_Normal_UV_Tangent,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
// Copyright (C) 2014 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_FONT_HPP
|
||||||
|
#define NAZARA_FONT_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/NonCopyable.hpp>
|
||||||
|
#include <Nazara/Core/ResourceRef.hpp>
|
||||||
|
#include <Nazara/Core/ResourceLoader.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractAtlas.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct NAZARA_API NzFontParams
|
||||||
|
{
|
||||||
|
bool IsValid() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NzFont;
|
||||||
|
class NzFontData;
|
||||||
|
|
||||||
|
struct NzFontGlyph;
|
||||||
|
|
||||||
|
using NzFontConstRef = NzResourceRef<const NzFont>;
|
||||||
|
using NzFontLoader = NzResourceLoader<NzFont, NzFontParams>;
|
||||||
|
using NzFontRef = NzResourceRef<NzFont>;
|
||||||
|
|
||||||
|
class NAZARA_API NzFont : public NzResource, NzAbstractAtlas::Listener, NzNonCopyable
|
||||||
|
{
|
||||||
|
friend NzFontLoader;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Glyph;
|
||||||
|
struct SizeInfo;
|
||||||
|
|
||||||
|
NzFont();
|
||||||
|
NzFont(NzFont&& font) = default;
|
||||||
|
~NzFont();
|
||||||
|
|
||||||
|
void ClearGlyphCache();
|
||||||
|
void ClearKerningCache();
|
||||||
|
void ClearSizeInfoCache();
|
||||||
|
|
||||||
|
bool Create(NzFontData* data);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* glyph) const;
|
||||||
|
|
||||||
|
const NzAbstractAtlas* GetAtlas() const;
|
||||||
|
unsigned int GetCachedGlyphCount(unsigned int characterSize, nzUInt32 style) const;
|
||||||
|
unsigned int GetCachedGlyphCount() const;
|
||||||
|
NzString GetFamilyName() const;
|
||||||
|
int GetKerning(unsigned int characterSize, char32_t first, char32_t second) const;
|
||||||
|
const Glyph& GetGlyph(unsigned int characterSize, nzUInt32 style, char32_t character) const;
|
||||||
|
unsigned int GetGlyphBorder() const;
|
||||||
|
unsigned int GetMinimumStepSize() const;
|
||||||
|
const SizeInfo& GetSizeInfo(unsigned int characterSize) const;
|
||||||
|
NzString GetStyleName() const;
|
||||||
|
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
bool Precache(unsigned int characterSize, nzUInt32 style, char32_t character) const;
|
||||||
|
bool Precache(unsigned int characterSize, nzUInt32 style, const NzString& characterSet) const;
|
||||||
|
|
||||||
|
// Open
|
||||||
|
bool OpenFromFile(const NzString& filePath, const NzFontParams& params = NzFontParams());
|
||||||
|
bool OpenFromMemory(const void* data, std::size_t size, const NzFontParams& params = NzFontParams());
|
||||||
|
bool OpenFromStream(NzInputStream& stream, const NzFontParams& params = NzFontParams());
|
||||||
|
|
||||||
|
void SetAtlas(std::shared_ptr<NzAbstractAtlas> atlas);
|
||||||
|
void SetGlyphBorder(unsigned int borderSize);
|
||||||
|
void SetMinimumStepSize(unsigned int minimumSizeStep);
|
||||||
|
|
||||||
|
NzFont& operator=(NzFont&& font) = default;
|
||||||
|
|
||||||
|
enum ModicationCode
|
||||||
|
{
|
||||||
|
ModificationCode_AtlasChanged,
|
||||||
|
ModificationCode_AtlasLayerChanged,
|
||||||
|
ModificationCode_GlyphCacheCleared,
|
||||||
|
ModificationCode_KerningCacheCleared,
|
||||||
|
ModificationCode_SizeInfoCacheCleared
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Glyph
|
||||||
|
{
|
||||||
|
NzRecti aabb;
|
||||||
|
NzRectui atlasRect;
|
||||||
|
bool requireFauxBold;
|
||||||
|
bool requireFauxItalic;
|
||||||
|
bool flipped;
|
||||||
|
bool valid;
|
||||||
|
int advance;
|
||||||
|
unsigned int layerIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SizeInfo
|
||||||
|
{
|
||||||
|
int spaceAdvance;
|
||||||
|
unsigned int lineHeight;
|
||||||
|
float underlinePosition;
|
||||||
|
float underlineThickness;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
using GlyphMap = std::unordered_map<char32_t, Glyph>;
|
||||||
|
|
||||||
|
nzUInt64 ComputeKey(unsigned int characterSize, nzUInt32 style) const;
|
||||||
|
bool OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata) override;
|
||||||
|
bool OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata) override;
|
||||||
|
void OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata) override;
|
||||||
|
const Glyph& PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const;
|
||||||
|
|
||||||
|
std::shared_ptr<NzAbstractAtlas> m_atlas;
|
||||||
|
std::unique_ptr<NzFontData> m_data;
|
||||||
|
mutable std::unordered_map<nzUInt64, std::unordered_map<nzUInt64, int>> m_kerningCache;
|
||||||
|
mutable std::unordered_map<nzUInt64, GlyphMap> m_glyphes;
|
||||||
|
mutable std::unordered_map<nzUInt64, SizeInfo> m_sizeInfoCache;
|
||||||
|
unsigned int m_glyphBorder;
|
||||||
|
unsigned int m_minimumSizeStep;
|
||||||
|
|
||||||
|
static NzFontLoader::LoaderList s_loaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_FONT_HPP
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (C) 2014 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_FONTDATA_HPP
|
||||||
|
#define NAZARA_FONTDATA_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/String.hpp>
|
||||||
|
|
||||||
|
struct NzFontGlyph;
|
||||||
|
|
||||||
|
class NAZARA_API NzFontData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzFontData() = default;
|
||||||
|
virtual ~NzFontData();
|
||||||
|
|
||||||
|
virtual bool ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* dst) = 0;
|
||||||
|
|
||||||
|
virtual NzString GetFamilyName() const = 0;
|
||||||
|
virtual NzString GetStyleName() const = 0;
|
||||||
|
|
||||||
|
virtual bool HasKerning() const = 0;
|
||||||
|
|
||||||
|
virtual bool IsScalable() const = 0;
|
||||||
|
|
||||||
|
virtual int QueryKerning(unsigned int characterSize, char32_t first, char32_t second) const = 0;
|
||||||
|
virtual unsigned int QueryLineHeight(unsigned int characterSize) const = 0;
|
||||||
|
virtual float QueryUnderlinePosition(unsigned int characterSize) const = 0;
|
||||||
|
virtual float QueryUnderlineThickness(unsigned int characterSize) const = 0;
|
||||||
|
|
||||||
|
virtual bool SupportsStyle(nzUInt32 style) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_FONTDATA_HPP
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (C) 2014 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_FONTGLYPH_HPP
|
||||||
|
#define NAZARA_FONTGLYPH_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Utility/Image.hpp>
|
||||||
|
|
||||||
|
struct NzFontGlyph
|
||||||
|
{
|
||||||
|
NzImage image;
|
||||||
|
NzRecti aabb;
|
||||||
|
int advance;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_FONTGLYPH_HPP
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright (C) 2015 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_GUILLOTINEIMAGEATLAS_HPP
|
||||||
|
#define NAZARA_GUILLOTINEIMAGEATLAS_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/GuillotineBinPack.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractAtlas.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractImage.hpp>
|
||||||
|
#include <Nazara/Utility/Image.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class NAZARA_API NzGuillotineImageAtlas : public NzAbstractAtlas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzGuillotineImageAtlas();
|
||||||
|
virtual ~NzGuillotineImageAtlas();
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void Free(NzSparsePtr<const NzRectui> rects, NzSparsePtr<unsigned int> layers, unsigned int count);
|
||||||
|
|
||||||
|
NzGuillotineBinPack::FreeRectChoiceHeuristic GetRectChoiceHeuristic() const;
|
||||||
|
NzGuillotineBinPack::GuillotineSplitHeuristic GetRectSplitHeuristic() const;
|
||||||
|
NzAbstractImage* GetLayer(unsigned int layerIndex) const;
|
||||||
|
unsigned int GetLayerCount() const;
|
||||||
|
|
||||||
|
bool Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex);
|
||||||
|
|
||||||
|
void SetRectChoiceHeuristic(NzGuillotineBinPack::FreeRectChoiceHeuristic heuristic);
|
||||||
|
void SetRectSplitHeuristic(NzGuillotineBinPack::GuillotineSplitHeuristic heuristic);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Layer;
|
||||||
|
|
||||||
|
virtual NzAbstractImage* ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const;
|
||||||
|
bool ResizeLayer(Layer& layer, const NzVector2ui& size);
|
||||||
|
|
||||||
|
struct QueuedGlyph
|
||||||
|
{
|
||||||
|
NzImage image;
|
||||||
|
NzRectui rect;
|
||||||
|
bool flipped;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Layer
|
||||||
|
{
|
||||||
|
std::vector<QueuedGlyph> queuedGlyphs;
|
||||||
|
std::unique_ptr<NzAbstractImage> image;
|
||||||
|
NzGuillotineBinPack binPack;
|
||||||
|
unsigned int freedRectangles = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ProcessGlyphQueue(Layer& layer) const;
|
||||||
|
|
||||||
|
mutable std::vector<Layer> m_layers;
|
||||||
|
NzGuillotineBinPack::FreeRectChoiceHeuristic m_rectChoiceHeuristic;
|
||||||
|
NzGuillotineBinPack::GuillotineSplitHeuristic m_rectSplitHeuristic;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_GUILLOTINEIMAGEATLAS_HPP
|
||||||
|
|
@ -13,12 +13,8 @@
|
||||||
#include <Nazara/Core/Resource.hpp>
|
#include <Nazara/Core/Resource.hpp>
|
||||||
#include <Nazara/Core/ResourceLoader.hpp>
|
#include <Nazara/Core/ResourceLoader.hpp>
|
||||||
#include <Nazara/Core/ResourceRef.hpp>
|
#include <Nazara/Core/ResourceRef.hpp>
|
||||||
#include <Nazara/Math/Box.hpp>
|
#include <Nazara/Utility/AbstractImage.hpp>
|
||||||
#include <Nazara/Math/Rect.hpp>
|
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
|
||||||
#include <Nazara/Utility/CubemapParams.hpp>
|
#include <Nazara/Utility/CubemapParams.hpp>
|
||||||
#include <Nazara/Utility/Enums.hpp>
|
|
||||||
#include <Nazara/Utility/PixelFormat.hpp>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
///TODO: Filtres
|
///TODO: Filtres
|
||||||
|
|
@ -40,7 +36,7 @@ using NzImageConstRef = NzResourceRef<const NzImage>;
|
||||||
using NzImageLoader = NzResourceLoader<NzImage, NzImageParams>;
|
using NzImageLoader = NzResourceLoader<NzImage, NzImageParams>;
|
||||||
using NzImageRef = NzResourceRef<NzImage>;
|
using NzImageRef = NzResourceRef<NzImage>;
|
||||||
|
|
||||||
class NAZARA_API NzImage : public NzResource
|
class NAZARA_API NzImage : public NzAbstractImage, public NzResource
|
||||||
{
|
{
|
||||||
friend NzImageLoader;
|
friend NzImageLoader;
|
||||||
|
|
||||||
|
|
@ -50,7 +46,6 @@ class NAZARA_API NzImage : public NzResource
|
||||||
NzImage();
|
NzImage();
|
||||||
NzImage(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1);
|
NzImage(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1);
|
||||||
NzImage(const NzImage& image);
|
NzImage(const NzImage& image);
|
||||||
NzImage(NzImage&& image) noexcept;
|
|
||||||
NzImage(SharedImage* sharedImage);
|
NzImage(SharedImage* sharedImage);
|
||||||
~NzImage();
|
~NzImage();
|
||||||
|
|
||||||
|
|
@ -68,22 +63,20 @@ class NAZARA_API NzImage : public NzResource
|
||||||
bool FlipHorizontally();
|
bool FlipHorizontally();
|
||||||
bool FlipVertically();
|
bool FlipVertically();
|
||||||
|
|
||||||
nzUInt8 GetBytesPerPixel() const;
|
|
||||||
const nzUInt8* GetConstPixels(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0, nzUInt8 level = 0) const;
|
const nzUInt8* GetConstPixels(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0, nzUInt8 level = 0) const;
|
||||||
unsigned int GetDepth(nzUInt8 level = 0) const;
|
unsigned int GetDepth(nzUInt8 level = 0) const;
|
||||||
nzPixelFormat GetFormat() const;
|
nzPixelFormat GetFormat() const;
|
||||||
unsigned int GetHeight(nzUInt8 level = 0) const;
|
unsigned int GetHeight(nzUInt8 level = 0) const;
|
||||||
nzUInt8 GetLevelCount() const;
|
nzUInt8 GetLevelCount() const;
|
||||||
nzUInt8 GetMaxLevel() const;
|
nzUInt8 GetMaxLevel() const;
|
||||||
|
unsigned int GetMemoryUsage() const;
|
||||||
|
unsigned int GetMemoryUsage(nzUInt8 level) const;
|
||||||
NzColor GetPixelColor(unsigned int x, unsigned int y = 0, unsigned int z = 0) const;
|
NzColor GetPixelColor(unsigned int x, unsigned int y = 0, unsigned int z = 0) const;
|
||||||
nzUInt8* GetPixels(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0, nzUInt8 level = 0);
|
nzUInt8* GetPixels(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0, nzUInt8 level = 0);
|
||||||
unsigned int GetSize() const;
|
NzVector3ui GetSize(nzUInt8 level = 0) const;
|
||||||
unsigned int GetSize(nzUInt8 level) const;
|
|
||||||
nzImageType GetType() const;
|
nzImageType GetType() const;
|
||||||
unsigned int GetWidth(nzUInt8 level = 0) const;
|
unsigned int GetWidth(nzUInt8 level = 0) const;
|
||||||
|
|
||||||
bool IsCompressed() const;
|
|
||||||
bool IsCubemap() const;
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
|
|
@ -106,12 +99,11 @@ class NAZARA_API NzImage : public NzResource
|
||||||
void SetLevelCount(nzUInt8 levelCount);
|
void SetLevelCount(nzUInt8 levelCount);
|
||||||
bool SetPixelColor(const NzColor& color, unsigned int x, unsigned int y = 0, unsigned int z = 0);
|
bool SetPixelColor(const NzColor& color, unsigned int x, unsigned int y = 0, unsigned int z = 0);
|
||||||
|
|
||||||
void Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
void Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
void Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0);
|
||||||
|
|
||||||
NzImage& operator=(const NzImage& image);
|
NzImage& operator=(const NzImage& image);
|
||||||
NzImage& operator=(NzImage&& image) noexcept;
|
|
||||||
|
|
||||||
static void Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0);
|
static void Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0);
|
||||||
static nzUInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1);
|
static nzUInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class NAZARA_API NzIndexBuffer : public NzResource
|
||||||
NzIndexBuffer() = default;
|
NzIndexBuffer() = default;
|
||||||
NzIndexBuffer(bool largeIndices, NzBuffer* buffer);
|
NzIndexBuffer(bool largeIndices, NzBuffer* buffer);
|
||||||
NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
||||||
NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
NzIndexBuffer(bool largeIndices, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
NzIndexBuffer(const NzIndexBuffer& indexBuffer);
|
NzIndexBuffer(const NzIndexBuffer& indexBuffer);
|
||||||
NzIndexBuffer(NzIndexBuffer&& indexBuffer) noexcept;
|
NzIndexBuffer(NzIndexBuffer&& indexBuffer) noexcept;
|
||||||
~NzIndexBuffer();
|
~NzIndexBuffer();
|
||||||
|
|
@ -54,11 +54,11 @@ class NAZARA_API NzIndexBuffer : public NzResource
|
||||||
void Reset();
|
void Reset();
|
||||||
void Reset(bool largeIndices, NzBuffer* buffer);
|
void Reset(bool largeIndices, NzBuffer* buffer);
|
||||||
void Reset(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
void Reset(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
||||||
void Reset(bool largeIndices, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
void Reset(bool largeIndices, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
void Reset(const NzIndexBuffer& indexBuffer);
|
void Reset(const NzIndexBuffer& indexBuffer);
|
||||||
void Reset(NzIndexBuffer&& indexBuffer) noexcept;
|
void Reset(NzIndexBuffer&& indexBuffer) noexcept;
|
||||||
|
|
||||||
bool SetStorage(nzBufferStorage storage);
|
bool SetStorage(nzUInt32 storage);
|
||||||
|
|
||||||
void Unmap() const;
|
void Unmap() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,12 @@ struct NAZARA_API NzMeshParams
|
||||||
{
|
{
|
||||||
NzMeshParams(); // Vérifie que le storage par défaut est supporté (software autrement)
|
NzMeshParams(); // Vérifie que le storage par défaut est supporté (software autrement)
|
||||||
|
|
||||||
// Si ceci sera le stockage utilisé par les buffers
|
|
||||||
nzBufferStorage storage = nzBufferStorage_Hardware;
|
|
||||||
|
|
||||||
// La mise à l'échelle éventuelle que subira le mesh
|
// La mise à l'échelle éventuelle que subira le mesh
|
||||||
NzVector3f scale = NzVector3f::Unit();
|
NzVector3f scale = NzVector3f::Unit();
|
||||||
|
|
||||||
|
// Si ceci sera le stockage utilisé par les buffers
|
||||||
|
nzUInt32 storage = nzDataStorage_Hardware;
|
||||||
|
|
||||||
// Charger une version animée du mesh si possible ?
|
// Charger une version animée du mesh si possible ?
|
||||||
bool animated = true;
|
bool animated = true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,26 +24,26 @@ class NAZARA_API NzNode
|
||||||
void EnsureDerivedUpdate() const;
|
void EnsureDerivedUpdate() const;
|
||||||
void EnsureTransformMatrixUpdate() const;
|
void EnsureTransformMatrixUpdate() const;
|
||||||
|
|
||||||
NzVector3f GetBackward() const;
|
virtual NzVector3f GetBackward() const;
|
||||||
const std::vector<NzNode*>& GetChilds() const;
|
const std::vector<NzNode*>& GetChilds() const;
|
||||||
NzVector3f GetDown() const;
|
virtual NzVector3f GetDown() const;
|
||||||
NzVector3f GetForward() const;
|
virtual NzVector3f GetForward() const;
|
||||||
bool GetInheritPosition() const;
|
bool GetInheritPosition() const;
|
||||||
bool GetInheritRotation() const;
|
bool GetInheritRotation() const;
|
||||||
bool GetInheritScale() const;
|
bool GetInheritScale() const;
|
||||||
NzVector3f GetInitialPosition() const;
|
NzVector3f GetInitialPosition() const;
|
||||||
NzQuaternionf GetInitialRotation() const;
|
NzQuaternionf GetInitialRotation() const;
|
||||||
NzVector3f GetInitialScale() const;
|
NzVector3f GetInitialScale() const;
|
||||||
NzVector3f GetLeft() const;
|
virtual NzVector3f GetLeft() const;
|
||||||
const NzString& GetName() const;
|
const NzString& GetName() const;
|
||||||
virtual nzNodeType GetNodeType() const;
|
virtual nzNodeType GetNodeType() const;
|
||||||
const NzNode* GetParent() const;
|
const NzNode* GetParent() const;
|
||||||
NzVector3f GetPosition(nzCoordSys coordSys = nzCoordSys_Global) const;
|
NzVector3f GetPosition(nzCoordSys coordSys = nzCoordSys_Global) const;
|
||||||
NzVector3f GetRight() const;
|
virtual NzVector3f GetRight() const;
|
||||||
NzQuaternionf GetRotation(nzCoordSys coordSys = nzCoordSys_Global) const;
|
NzQuaternionf GetRotation(nzCoordSys coordSys = nzCoordSys_Global) const;
|
||||||
NzVector3f GetScale(nzCoordSys coordSys = nzCoordSys_Global) const;
|
NzVector3f GetScale(nzCoordSys coordSys = nzCoordSys_Global) const;
|
||||||
const NzMatrix4f& GetTransformMatrix() const;
|
const NzMatrix4f& GetTransformMatrix() const;
|
||||||
NzVector3f GetUp() const;
|
virtual NzVector3f GetUp() const;
|
||||||
|
|
||||||
bool HasChilds() const;
|
bool HasChilds() const;
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ class NAZARA_API NzNode
|
||||||
virtual void InvalidateNode();
|
virtual void InvalidateNode();
|
||||||
virtual void OnParenting(const NzNode* parent);
|
virtual void OnParenting(const NzNode* parent);
|
||||||
void RemoveChild(NzNode* node) const;
|
void RemoveChild(NzNode* node) const;
|
||||||
void UpdateDerived() const;
|
virtual void UpdateDerived() const;
|
||||||
virtual void UpdateTransformMatrix() const;
|
virtual void UpdateTransformMatrix() const;
|
||||||
|
|
||||||
mutable std::vector<NzNode*> m_childs;
|
mutable std::vector<NzNode*> m_childs;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
///TODO: Permettre la conversion automatique entre les formats via des renseignements de bits et de type pour chaque format.
|
||||||
|
/// Ce serait plus lent que la conversion spécialisée (qui ne disparaît donc pas) mais ça permettrait au moteur de faire la conversion
|
||||||
|
/// entre n'importe quel formats non-compressés.
|
||||||
|
|
||||||
class NzPixelFormat
|
class NzPixelFormat
|
||||||
{
|
{
|
||||||
friend class NzUtility;
|
friend class NzUtility;
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,9 @@ inline nzUInt8 NzPixelFormat::GetBitsPerPixel(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
|
case nzPixelFormat_A8:
|
||||||
|
return 8;
|
||||||
|
|
||||||
case nzPixelFormat_BGR8:
|
case nzPixelFormat_BGR8:
|
||||||
return 24;
|
return 24;
|
||||||
|
|
||||||
|
|
@ -287,20 +290,14 @@ inline nzUInt8 NzPixelFormat::GetBitsPerPixel(nzPixelFormat format)
|
||||||
|
|
||||||
inline nzUInt8 NzPixelFormat::GetBytesPerPixel(nzPixelFormat format)
|
inline nzUInt8 NzPixelFormat::GetBytesPerPixel(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
nzUInt8 bytesPerPixel = GetBitsPerPixel(format)/8;
|
return GetBitsPerPixel(format)/8;
|
||||||
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
|
||||||
if (bytesPerPixel == 0)
|
|
||||||
NazaraWarning("This format is either invalid or using less than one byte per pixel");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return bytesPerPixel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format)
|
inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
|
case nzPixelFormat_A8:
|
||||||
case nzPixelFormat_BGR8:
|
case nzPixelFormat_BGR8:
|
||||||
case nzPixelFormat_BGRA8:
|
case nzPixelFormat_BGRA8:
|
||||||
case nzPixelFormat_DXT1:
|
case nzPixelFormat_DXT1:
|
||||||
|
|
@ -372,6 +369,7 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
|
case nzPixelFormat_A8:
|
||||||
case nzPixelFormat_BGRA8:
|
case nzPixelFormat_BGRA8:
|
||||||
case nzPixelFormat_DXT3:
|
case nzPixelFormat_DXT3:
|
||||||
case nzPixelFormat_DXT5:
|
case nzPixelFormat_DXT5:
|
||||||
|
|
@ -444,6 +442,7 @@ inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
|
||||||
case nzPixelFormat_DXT5:
|
case nzPixelFormat_DXT5:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case nzPixelFormat_A8:
|
||||||
case nzPixelFormat_BGR8:
|
case nzPixelFormat_BGR8:
|
||||||
case nzPixelFormat_BGRA8:
|
case nzPixelFormat_BGRA8:
|
||||||
case nzPixelFormat_L8:
|
case nzPixelFormat_L8:
|
||||||
|
|
@ -529,6 +528,9 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
|
case nzPixelFormat_A8:
|
||||||
|
return "A8";
|
||||||
|
|
||||||
case nzPixelFormat_BGR8:
|
case nzPixelFormat_BGR8:
|
||||||
return "BGR8";
|
return "BGR8";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (C) 2015 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_SIMPLETEXTDRAWER_HPP
|
||||||
|
#define NAZARA_SIMPLETEXTDRAWER_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
|
#include <Nazara/Core/String.hpp>
|
||||||
|
#include <Nazara/Utility/AbstractTextDrawer.hpp>
|
||||||
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
|
#include <Nazara/Utility/Font.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class NAZARA_API NzSimpleTextDrawer : public NzAbstractTextDrawer, NzResourceListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzSimpleTextDrawer();
|
||||||
|
virtual ~NzSimpleTextDrawer();
|
||||||
|
|
||||||
|
const NzRectui& GetBounds() const;
|
||||||
|
unsigned int GetCharacterSize() const;
|
||||||
|
const NzColor& GetColor() const;
|
||||||
|
NzFont* GetFont() const;
|
||||||
|
nzUInt32 GetStyle() const;
|
||||||
|
|
||||||
|
void SetCharacterSize(unsigned int characterSize);
|
||||||
|
void SetColor(const NzColor& color);
|
||||||
|
void SetFont(NzFont* font);
|
||||||
|
void SetStyle(nzUInt32 style);
|
||||||
|
void SetText(const NzString& str);
|
||||||
|
|
||||||
|
static NzSimpleTextDrawer Draw(unsigned int characterSize, const NzString& str, nzUInt32 style = nzTextStyle_Regular, const NzColor& color = NzColor::White);
|
||||||
|
static NzSimpleTextDrawer Draw(NzFont* font, unsigned int characterSize, const NzString& str, nzUInt32 style = nzTextStyle_Regular, const NzColor& color = NzColor::White);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NzFont* GetFont(unsigned int index) const override;
|
||||||
|
unsigned int GetFontCount() const override;
|
||||||
|
const Glyph& GetGlyph(unsigned int index) const override;
|
||||||
|
unsigned int GetGlyphCount() const override;
|
||||||
|
|
||||||
|
bool OnResourceModified(const NzResource* resource, int index, unsigned int code) override;
|
||||||
|
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||||
|
void UpdateGlyphs() const;
|
||||||
|
|
||||||
|
mutable std::vector<Glyph> m_glyphs;
|
||||||
|
NzColor m_color;
|
||||||
|
NzFontRef m_font;
|
||||||
|
mutable NzRectui m_bounds;
|
||||||
|
NzString m_text;
|
||||||
|
nzUInt32 m_style;
|
||||||
|
mutable bool m_glyphUpdated;
|
||||||
|
unsigned int m_characterSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_SIMPLETEXTDRAWER_HPP
|
||||||
|
|
@ -24,7 +24,7 @@ class NAZARA_API NzVertexBuffer : public NzResource
|
||||||
NzVertexBuffer() = default;
|
NzVertexBuffer() = default;
|
||||||
NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer);
|
NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer);
|
||||||
NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
||||||
NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
NzVertexBuffer(const NzVertexBuffer& vertexBuffer);
|
NzVertexBuffer(const NzVertexBuffer& vertexBuffer);
|
||||||
NzVertexBuffer(NzVertexBuffer&& vertexBuffer) noexcept;
|
NzVertexBuffer(NzVertexBuffer&& vertexBuffer) noexcept;
|
||||||
~NzVertexBuffer();
|
~NzVertexBuffer();
|
||||||
|
|
@ -50,11 +50,11 @@ class NAZARA_API NzVertexBuffer : public NzResource
|
||||||
void Reset();
|
void Reset();
|
||||||
void Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer);
|
void Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer);
|
||||||
void Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
void Reset(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset);
|
||||||
void Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
void Reset(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzUInt32 storage = nzDataStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
void Reset(const NzVertexBuffer& vertexBuffer);
|
void Reset(const NzVertexBuffer& vertexBuffer);
|
||||||
void Reset(NzVertexBuffer&& vertexBuffer) noexcept;
|
void Reset(NzVertexBuffer&& vertexBuffer) noexcept;
|
||||||
|
|
||||||
bool SetStorage(nzBufferStorage storage);
|
bool SetStorage(nzUInt32 storage);
|
||||||
void SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration);
|
void SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration);
|
||||||
|
|
||||||
void Unmap() const;
|
void Unmap() const;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#ifndef NAZARA_VERTEXSTRUCT_HPP
|
#ifndef NAZARA_VERTEXSTRUCT_HPP
|
||||||
#define NAZARA_VERTEXSTRUCT_HPP
|
#define NAZARA_VERTEXSTRUCT_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/Color.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
|
||||||
|
|
@ -17,7 +18,12 @@ struct NzVertexStruct_XY
|
||||||
NzVector2f position;
|
NzVector2f position;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NzVertexStruct_XY_UV : public NzVertexStruct_XY
|
struct NzVertexStruct_XY_Color : NzVertexStruct_XY
|
||||||
|
{
|
||||||
|
NzColor color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NzVertexStruct_XY_UV : NzVertexStruct_XY
|
||||||
{
|
{
|
||||||
NzVector2f uv;
|
NzVector2f uv;
|
||||||
};
|
};
|
||||||
|
|
@ -29,29 +35,39 @@ struct NzVertexStruct_XYZ
|
||||||
NzVector3f position;
|
NzVector3f position;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NzVertexStruct_XYZ_Normal : public NzVertexStruct_XYZ
|
struct NzVertexStruct_XYZ_Color : NzVertexStruct_XYZ
|
||||||
{
|
{
|
||||||
NzVector3f normal;
|
NzColor color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NzVertexStruct_XYZ_Normal_UV : public NzVertexStruct_XYZ_Normal
|
struct NzVertexStruct_XYZ_Color_UV : NzVertexStruct_XYZ_Color
|
||||||
{
|
{
|
||||||
NzVector2f uv;
|
NzVector2f uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NzVertexStruct_XYZ_Normal_UV_Tangent : public NzVertexStruct_XYZ_Normal_UV
|
struct NzVertexStruct_XYZ_Normal : NzVertexStruct_XYZ
|
||||||
|
{
|
||||||
|
NzVector3f normal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NzVertexStruct_XYZ_Normal_UV : NzVertexStruct_XYZ_Normal
|
||||||
|
{
|
||||||
|
NzVector2f uv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NzVertexStruct_XYZ_Normal_UV_Tangent : NzVertexStruct_XYZ_Normal_UV
|
||||||
{
|
{
|
||||||
NzVector3f tangent;
|
NzVector3f tangent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NzVertexStruct_XYZ_UV : public NzVertexStruct_XYZ
|
struct NzVertexStruct_XYZ_UV : NzVertexStruct_XYZ
|
||||||
{
|
{
|
||||||
NzVector2f uv;
|
NzVector2f uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************* Structures 3D (+ Skinning) ************************/
|
/************************* Structures 3D (+ Skinning) ************************/
|
||||||
|
|
||||||
struct NzVertexStruct_XYZ_Normal_UV_Tangent_Skinning : public NzVertexStruct_XYZ_Normal_UV_Tangent
|
struct NzVertexStruct_XYZ_Normal_UV_Tangent_Skinning : NzVertexStruct_XYZ_Normal_UV_Tangent
|
||||||
{
|
{
|
||||||
nzInt32 weightCount;
|
nzInt32 weightCount;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,446 @@
|
||||||
|
// Copyright (C) 2014 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Core module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
// Implémentation originale de Jukka Jylänki (Merci de sa contribution au domaine public)
|
||||||
|
// http://clb.demon.fi/projects/even-more-rectangle-bin-packing
|
||||||
|
// Je n'ai vraiment fait qu'adapter le code au moteur (Avec quelques améliorations), je n'ai aucun mérite sur le code ci-dessous
|
||||||
|
|
||||||
|
#include <Nazara/Core/GuillotineBinPack.hpp>
|
||||||
|
#include <Nazara/Core/Config.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int ScoreBestAreaFit(int width, int height, const NzRectui& freeRectSize)
|
||||||
|
{
|
||||||
|
return freeRectSize.width * freeRectSize.height - width * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScoreBestLongSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||||
|
{
|
||||||
|
int leftoverHoriz = std::abs(freeRectSize.width - width);
|
||||||
|
int leftoverVert = std::abs(freeRectSize.height - height);
|
||||||
|
int leftover = std::max(leftoverHoriz, leftoverVert);
|
||||||
|
|
||||||
|
return leftover;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScoreBestShortSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||||
|
{
|
||||||
|
int leftoverHoriz = std::abs(freeRectSize.width - width);
|
||||||
|
int leftoverVert = std::abs(freeRectSize.height - height);
|
||||||
|
int leftover = std::min(leftoverHoriz, leftoverVert);
|
||||||
|
|
||||||
|
return leftover;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScoreWorstAreaFit(int width, int height, const NzRectui& freeRectSize)
|
||||||
|
{
|
||||||
|
return -ScoreBestAreaFit(width, height, freeRectSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScoreWorstLongSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||||
|
{
|
||||||
|
return -ScoreBestLongSideFit(width, height, freeRectSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScoreWorstShortSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||||
|
{
|
||||||
|
return -ScoreBestShortSideFit(width, height, freeRectSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineBinPack::NzGuillotineBinPack()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineBinPack::NzGuillotineBinPack(unsigned int width, unsigned int height)
|
||||||
|
{
|
||||||
|
Reset(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineBinPack::NzGuillotineBinPack(const NzVector2ui& size)
|
||||||
|
{
|
||||||
|
Reset(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::Clear()
|
||||||
|
{
|
||||||
|
m_freeRectangles.clear();
|
||||||
|
m_freeRectangles.push_back(NzRectui(0, 0, m_width, m_height));
|
||||||
|
|
||||||
|
m_usedArea = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::Expand(unsigned int newWidth, unsigned newHeight)
|
||||||
|
{
|
||||||
|
unsigned int oldWidth = m_width;
|
||||||
|
unsigned int oldHeight = m_height;
|
||||||
|
|
||||||
|
m_width = std::max(newWidth, m_width);
|
||||||
|
m_height = std::max(newHeight, m_height);
|
||||||
|
|
||||||
|
if (m_width > oldWidth)
|
||||||
|
m_freeRectangles.push_back(NzRectui(oldWidth, 0, m_width - oldWidth, oldHeight));
|
||||||
|
|
||||||
|
if (m_height > oldHeight)
|
||||||
|
m_freeRectangles.push_back(NzRectui(0, oldHeight, m_width, m_height - oldHeight));
|
||||||
|
|
||||||
|
// On va ensuite fusionner les rectangles tant que possible
|
||||||
|
while (MergeFreeRectangles());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::Expand(const NzVector2ui& newSize)
|
||||||
|
{
|
||||||
|
Expand(newSize.x, newSize.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::FreeRectangle(const NzRectui& rect)
|
||||||
|
{
|
||||||
|
///DOC: Cette méthode ne devrait recevoir que des rectangles calculés par la méthode Insert et peut provoquer de la fragmentation
|
||||||
|
m_freeRectangles.push_back(rect);
|
||||||
|
|
||||||
|
m_usedArea -= rect.width * rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzGuillotineBinPack::GetHeight() const
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
float NzGuillotineBinPack::GetOccupancy() const
|
||||||
|
{
|
||||||
|
return static_cast<float>(m_usedArea)/(m_width*m_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector2ui NzGuillotineBinPack::GetSize() const
|
||||||
|
{
|
||||||
|
return NzVector2ui(m_width, m_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzGuillotineBinPack::GetWidth() const
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzGuillotineBinPack::Insert(NzRectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||||
|
{
|
||||||
|
return Insert(rects, nullptr, nullptr, count, merge, rectChoice, splitMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||||
|
{
|
||||||
|
return Insert(rects, flipped, nullptr, count, merge, rectChoice, splitMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||||
|
{
|
||||||
|
std::vector<NzRectui*> remainingRects(count); // La position du rectangle
|
||||||
|
for (unsigned int i = 0; i < count; ++i)
|
||||||
|
remainingRects[i] = &rects[i];
|
||||||
|
|
||||||
|
// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
|
||||||
|
while (!remainingRects.empty())
|
||||||
|
{
|
||||||
|
// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
|
||||||
|
bool bestFlipped;
|
||||||
|
int bestFreeRect;
|
||||||
|
int bestRect;
|
||||||
|
int bestScore = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
|
||||||
|
{
|
||||||
|
NzRectui& freeRect = m_freeRectangles[i];
|
||||||
|
|
||||||
|
for (std::size_t j = 0; j < remainingRects.size(); ++j)
|
||||||
|
{
|
||||||
|
NzRectui& rect = *remainingRects[j];
|
||||||
|
|
||||||
|
// If this rectangle is a perfect match, we pick it instantly.
|
||||||
|
if (rect.width == freeRect.width && rect.height == freeRect.height)
|
||||||
|
{
|
||||||
|
bestFreeRect = i;
|
||||||
|
bestRect = j;
|
||||||
|
bestFlipped = false;
|
||||||
|
bestScore = std::numeric_limits<int>::min();
|
||||||
|
i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// If flipping this rectangle is a perfect match, pick that then.
|
||||||
|
else if (rect.height == freeRect.width && rect.width == freeRect.height)
|
||||||
|
{
|
||||||
|
bestFreeRect = i;
|
||||||
|
bestRect = j;
|
||||||
|
bestFlipped = true;
|
||||||
|
bestScore = std::numeric_limits<int>::min();
|
||||||
|
i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Try if we can fit the rectangle upright.
|
||||||
|
else if (rect.width <= freeRect.width && rect.height <= freeRect.height)
|
||||||
|
{
|
||||||
|
int score = ScoreByHeuristic(rect.width, rect.height, freeRect, rectChoice);
|
||||||
|
if (score < bestScore)
|
||||||
|
{
|
||||||
|
bestFreeRect = i;
|
||||||
|
bestRect = j;
|
||||||
|
bestFlipped = false;
|
||||||
|
bestScore = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If not, then perhaps flipping sideways will make it fit?
|
||||||
|
else if (rect.height <= freeRect.width && rect.width <= freeRect.height)
|
||||||
|
{
|
||||||
|
int score = ScoreByHeuristic(rect.height, rect.width, freeRect, rectChoice);
|
||||||
|
if (score < bestScore)
|
||||||
|
{
|
||||||
|
bestFreeRect = i;
|
||||||
|
bestRect = j;
|
||||||
|
bestFlipped = true;
|
||||||
|
bestScore = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't manage to find any rectangle to pack, abort.
|
||||||
|
if (bestScore == std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
// Si nous le pouvons, on marque les rectangles n'ayant pas pu être insérés
|
||||||
|
if (inserted)
|
||||||
|
{
|
||||||
|
for (NzRectui* rect : remainingRects)
|
||||||
|
{
|
||||||
|
unsigned int position = rect - rects;
|
||||||
|
inserted[position] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we're good to go and do the actual packing.
|
||||||
|
unsigned int position = remainingRects[bestRect] - rects;
|
||||||
|
NzRectui& rect = *remainingRects[bestRect];
|
||||||
|
rect.x = m_freeRectangles[bestFreeRect].x;
|
||||||
|
rect.y = m_freeRectangles[bestFreeRect].y;
|
||||||
|
|
||||||
|
if (bestFlipped)
|
||||||
|
std::swap(rect.width, rect.height);
|
||||||
|
|
||||||
|
if (flipped)
|
||||||
|
flipped[position] = bestFlipped;
|
||||||
|
|
||||||
|
if (inserted)
|
||||||
|
inserted[position] = true;
|
||||||
|
|
||||||
|
// Remove the free space we lost in the bin.
|
||||||
|
SplitFreeRectByHeuristic(m_freeRectangles[bestFreeRect], rect, splitMethod);
|
||||||
|
m_freeRectangles.erase(m_freeRectangles.begin() + bestFreeRect);
|
||||||
|
|
||||||
|
// Remove the rectangle we just packed from the input list.
|
||||||
|
remainingRects.erase(remainingRects.begin() + bestRect);
|
||||||
|
|
||||||
|
// Perform a Rectangle Merge step if desired.
|
||||||
|
if (merge)
|
||||||
|
MergeFreeRectangles();
|
||||||
|
|
||||||
|
m_usedArea += rect.width * rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzGuillotineBinPack::MergeFreeRectangles()
|
||||||
|
{
|
||||||
|
///DOC: Renvoie true s'il y a eu fusion (et donc si une fusion est encore possible)
|
||||||
|
std::size_t oriSize = m_freeRectangles.size();
|
||||||
|
|
||||||
|
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
|
||||||
|
// Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that)
|
||||||
|
for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
|
||||||
|
{
|
||||||
|
NzRectui& firstRect = m_freeRectangles[i];
|
||||||
|
|
||||||
|
for (std::size_t j = i+1; j < m_freeRectangles.size(); ++j)
|
||||||
|
{
|
||||||
|
NzRectui& secondRect = m_freeRectangles[j];
|
||||||
|
|
||||||
|
if (firstRect.width == secondRect.width && firstRect.x == secondRect.x)
|
||||||
|
{
|
||||||
|
if (firstRect.y == secondRect.y + secondRect.height)
|
||||||
|
{
|
||||||
|
firstRect.y -= secondRect.height;
|
||||||
|
firstRect.height += secondRect.height;
|
||||||
|
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
else if (firstRect.y + firstRect.height == secondRect.y)
|
||||||
|
{
|
||||||
|
firstRect.height += secondRect.height;
|
||||||
|
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (firstRect.height == secondRect.height && firstRect.y == secondRect.y)
|
||||||
|
{
|
||||||
|
if (firstRect.x == secondRect.x + secondRect.width)
|
||||||
|
{
|
||||||
|
firstRect.x -= secondRect.width;
|
||||||
|
firstRect.width += secondRect.width;
|
||||||
|
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
else if (firstRect.x + firstRect.width == secondRect.x)
|
||||||
|
{
|
||||||
|
firstRect.width += secondRect.width;
|
||||||
|
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_freeRectangles.size() < oriSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::Reset()
|
||||||
|
{
|
||||||
|
m_height = 0;
|
||||||
|
m_width = 0;
|
||||||
|
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::Reset(unsigned int width, unsigned int height)
|
||||||
|
{
|
||||||
|
m_height = height;
|
||||||
|
m_width = width;
|
||||||
|
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::Reset(const NzVector2ui& size)
|
||||||
|
{
|
||||||
|
Reset(size.x, size.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::SplitFreeRectAlongAxis(const NzRectui& freeRect, const NzRectui& placedRect, bool splitHorizontal)
|
||||||
|
{
|
||||||
|
// Form the two new rectangles.
|
||||||
|
NzRectui bottom;
|
||||||
|
bottom.x = freeRect.x;
|
||||||
|
bottom.y = freeRect.y + placedRect.height;
|
||||||
|
bottom.height = freeRect.height - placedRect.height;
|
||||||
|
|
||||||
|
NzRectui right;
|
||||||
|
right.x = freeRect.x + placedRect.width;
|
||||||
|
right.y = freeRect.y;
|
||||||
|
right.width = freeRect.width - placedRect.width;
|
||||||
|
|
||||||
|
if (splitHorizontal)
|
||||||
|
{
|
||||||
|
bottom.width = freeRect.width;
|
||||||
|
right.height = placedRect.height;
|
||||||
|
}
|
||||||
|
else // Split vertically
|
||||||
|
{
|
||||||
|
bottom.width = placedRect.width;
|
||||||
|
right.height = freeRect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new rectangles into the free rectangle pool if they weren't degenerate.
|
||||||
|
if (bottom.width > 0 && bottom.height > 0)
|
||||||
|
m_freeRectangles.push_back(bottom);
|
||||||
|
|
||||||
|
if (right.width > 0 && right.height > 0)
|
||||||
|
m_freeRectangles.push_back(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineBinPack::SplitFreeRectByHeuristic(const NzRectui& freeRect, const NzRectui& placedRect, GuillotineSplitHeuristic method)
|
||||||
|
{
|
||||||
|
// Compute the lengths of the leftover area.
|
||||||
|
const int w = freeRect.width - placedRect.width;
|
||||||
|
const int h = freeRect.height - placedRect.height;
|
||||||
|
|
||||||
|
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
|
||||||
|
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
|
||||||
|
// We have two choices: horizontal or vertical.
|
||||||
|
|
||||||
|
// Use the given heuristic to decide which choice to make.
|
||||||
|
|
||||||
|
bool splitHorizontal;
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case SplitLongerAxis:
|
||||||
|
// Split along the longer total axis.
|
||||||
|
splitHorizontal = (freeRect.width > freeRect.height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SplitLongerLeftoverAxis:
|
||||||
|
// Split along the longer leftover axis.
|
||||||
|
splitHorizontal = (w > h);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SplitMaximizeArea:
|
||||||
|
// Maximize the smaller area == minimize the larger area.
|
||||||
|
// Tries to make the rectangles more even-sized.
|
||||||
|
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SplitMinimizeArea:
|
||||||
|
// Maximize the larger area == minimize the smaller area.
|
||||||
|
// Tries to make the single bigger rectangle.
|
||||||
|
splitHorizontal = (placedRect.width * h > w * placedRect.height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SplitShorterAxis:
|
||||||
|
// Split along the shorter total axis.
|
||||||
|
splitHorizontal = (freeRect.width <= freeRect.height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SplitShorterLeftoverAxis:
|
||||||
|
// Split along the shorter leftover axis.
|
||||||
|
splitHorizontal = (w <= h);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NazaraError("Split heuristic out of enum (0x" + NzString::Number(method, 16) + ')');
|
||||||
|
splitHorizontal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the actual split.
|
||||||
|
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NzGuillotineBinPack::ScoreByHeuristic(int width, int height, const NzRectui& freeRect, FreeRectChoiceHeuristic rectChoice)
|
||||||
|
{
|
||||||
|
switch (rectChoice)
|
||||||
|
{
|
||||||
|
case RectBestAreaFit:
|
||||||
|
return ScoreBestAreaFit(width, height, freeRect);
|
||||||
|
|
||||||
|
case RectBestLongSideFit:
|
||||||
|
return ScoreBestLongSideFit(width, height, freeRect);
|
||||||
|
|
||||||
|
case RectBestShortSideFit:
|
||||||
|
return ScoreBestShortSideFit(width, height, freeRect);
|
||||||
|
|
||||||
|
case RectWorstAreaFit:
|
||||||
|
return ScoreWorstAreaFit(width, height, freeRect);
|
||||||
|
|
||||||
|
case RectWorstLongSideFit:
|
||||||
|
return ScoreWorstLongSideFit(width, height, freeRect);
|
||||||
|
|
||||||
|
case RectWorstShortSideFit:
|
||||||
|
return ScoreWorstShortSideFit(width, height, freeRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Rect choice heuristic out of enum (0x" + NzString::Number(rectChoice, 16) + ')');
|
||||||
|
return std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
|
@ -80,6 +80,21 @@ const NzFrustumf& NzCamera::GetFrustum() const
|
||||||
return m_frustum;
|
return m_frustum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzCamera::GetGlobalForward() const
|
||||||
|
{
|
||||||
|
return NzVector3f::Forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzCamera::GetGlobalRight() const
|
||||||
|
{
|
||||||
|
return NzVector3f::Right();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzCamera::GetGlobalUp() const
|
||||||
|
{
|
||||||
|
return NzVector3f::Up();
|
||||||
|
}
|
||||||
|
|
||||||
const NzMatrix4f& NzCamera::GetProjectionMatrix() const
|
const NzMatrix4f& NzCamera::GetProjectionMatrix() const
|
||||||
{
|
{
|
||||||
if (!m_projectionMatrixUpdated)
|
if (!m_projectionMatrixUpdated)
|
||||||
|
|
|
||||||
|
|
@ -103,29 +103,15 @@ void NzDeferredRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzDeferredRenderQueue::AddSprite(const NzSprite* sprite)
|
void NzDeferredRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay)
|
||||||
{
|
{
|
||||||
#if NAZARA_GRAPHICS_SAFE
|
|
||||||
if (!sprite)
|
|
||||||
{
|
|
||||||
NazaraError("Invalid sprite");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sprite->IsDrawable())
|
|
||||||
{
|
|
||||||
NazaraError("Sprite is not drawable");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*NzMaterial* material = sprite->GetMaterial();
|
/*NzMaterial* material = sprite->GetMaterial();
|
||||||
if (!material->IsLightingEnabled() || material->IsEnabled(nzRendererParameter_Blend))
|
if (!material->IsLightingEnabled() || material->IsEnabled(nzRendererParameter_Blend))
|
||||||
m_forwardQueue->AddSprite(sprite);
|
m_forwardQueue->AddSprite(sprite);
|
||||||
else
|
else
|
||||||
sprites[material].push_back(sprite);*/
|
sprites[material].push_back(sprite);*/
|
||||||
|
|
||||||
m_forwardQueue->AddSprite(sprite);
|
m_forwardQueue->AddSprites(material, vertices, spriteCount, overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzDeferredRenderQueue::Clear(bool fully)
|
void NzDeferredRenderQueue::Clear(bool fully)
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,15 @@
|
||||||
#include <Nazara/Utility/StaticMesh.hpp>
|
#include <Nazara/Utility/StaticMesh.hpp>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
///FIXME: Régler ce problème de dépendance aux ressources
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
enum ResourceType
|
enum ResourceType
|
||||||
{
|
{
|
||||||
ResourceType_IndexBuffer,
|
ResourceType_IndexBuffer,
|
||||||
ResourceType_Material,
|
ResourceType_Material,
|
||||||
|
ResourceType_Texture,
|
||||||
ResourceType_VertexBuffer
|
ResourceType_VertexBuffer
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -121,23 +124,26 @@ void NzForwardRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzForwardRenderQueue::AddSprite(const NzSprite* sprite)
|
void NzForwardRenderQueue::AddSprites(const NzMaterial* material, const NzVertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const NzTexture* overlay)
|
||||||
{
|
{
|
||||||
#if NAZARA_GRAPHICS_SAFE
|
auto matIt = basicSprites.find(material);
|
||||||
if (!sprite)
|
if (matIt == basicSprites.end())
|
||||||
{
|
{
|
||||||
NazaraError("Invalid sprite");
|
matIt = basicSprites.insert(std::make_pair(material, BasicSpriteBatches::mapped_type())).first;
|
||||||
return;
|
material->AddResourceListener(this, ResourceType_Material);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sprite->IsDrawable())
|
auto& overlayMap = matIt->second;
|
||||||
|
auto overlayIt = overlayMap.find(overlay);
|
||||||
|
if (overlayIt == overlayMap.end())
|
||||||
{
|
{
|
||||||
NazaraError("Sprite is not drawable");
|
overlayIt = overlayMap.insert(std::make_pair(overlay, BasicSpriteOverlayContainer::mapped_type())).first;
|
||||||
return;
|
if (overlay)
|
||||||
|
overlay->AddResourceListener(this, ResourceType_Texture);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
sprites[sprite->GetMaterial()].push_back(sprite);
|
auto& spriteVector = overlayIt->second;
|
||||||
|
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzForwardRenderQueue::Clear(bool fully)
|
void NzForwardRenderQueue::Clear(bool fully)
|
||||||
|
|
@ -150,12 +156,27 @@ void NzForwardRenderQueue::Clear(bool fully)
|
||||||
|
|
||||||
if (fully)
|
if (fully)
|
||||||
{
|
{
|
||||||
for (auto& matIt : opaqueModels)
|
for (auto& matPair : basicSprites)
|
||||||
{
|
{
|
||||||
const NzMaterial* material = matIt.first;
|
const NzMaterial* material = matPair.first;
|
||||||
material->RemoveResourceListener(this);
|
material->RemoveResourceListener(this);
|
||||||
|
|
||||||
MeshInstanceContainer& instances = std::get<2>(matIt.second);
|
auto& overlayMap = matPair.second;
|
||||||
|
for (auto& overlayPair : overlayMap)
|
||||||
|
{
|
||||||
|
const NzTexture* overlay = overlayPair.first;
|
||||||
|
if (overlay)
|
||||||
|
overlay->RemoveResourceListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
basicSprites.clear();
|
||||||
|
|
||||||
|
for (auto& matPair : opaqueModels)
|
||||||
|
{
|
||||||
|
const NzMaterial* material = matPair.first;
|
||||||
|
material->RemoveResourceListener(this);
|
||||||
|
|
||||||
|
MeshInstanceContainer& instances = std::get<2>(matPair.second);
|
||||||
for (auto& instanceIt : instances)
|
for (auto& instanceIt : instances)
|
||||||
{
|
{
|
||||||
const NzMeshData& renderData = instanceIt.first;
|
const NzMeshData& renderData = instanceIt.first;
|
||||||
|
|
@ -167,7 +188,6 @@ void NzForwardRenderQueue::Clear(bool fully)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opaqueModels.clear();
|
opaqueModels.clear();
|
||||||
sprites.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,6 +230,7 @@ bool NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind
|
||||||
}
|
}
|
||||||
|
|
||||||
case ResourceType_Material:
|
case ResourceType_Material:
|
||||||
|
basicSprites.erase(static_cast<const NzMaterial*>(resource));
|
||||||
opaqueModels.erase(static_cast<const NzMaterial*>(resource));
|
opaqueModels.erase(static_cast<const NzMaterial*>(resource));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -260,6 +281,15 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in
|
||||||
|
|
||||||
case ResourceType_Material:
|
case ResourceType_Material:
|
||||||
{
|
{
|
||||||
|
for (auto it = basicSprites.begin(); it != basicSprites.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == resource)
|
||||||
|
{
|
||||||
|
basicSprites.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto it = opaqueModels.begin(); it != opaqueModels.end(); ++it)
|
for (auto it = opaqueModels.begin(); it != opaqueModels.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->first == resource)
|
if (it->first == resource)
|
||||||
|
|
@ -268,6 +298,25 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ResourceType_Texture:
|
||||||
|
{
|
||||||
|
for (auto matIt = basicSprites.begin(); matIt != basicSprites.end(); ++matIt)
|
||||||
|
{
|
||||||
|
auto& overlayMap = matIt->second;
|
||||||
|
for (auto overlayIt = overlayMap.begin(); overlayIt != overlayMap.end(); ++overlayIt)
|
||||||
|
{
|
||||||
|
if (overlayIt->first == resource)
|
||||||
|
{
|
||||||
|
overlayMap.erase(overlayIt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -299,7 +348,6 @@ bool NzForwardRenderQueue::BatchedModelMaterialComparator::operator()(const NzMa
|
||||||
|
|
||||||
const NzShader* shader1 = mat1->GetShaderInstance()->GetShader();
|
const NzShader* shader1 = mat1->GetShaderInstance()->GetShader();
|
||||||
const NzShader* shader2 = mat2->GetShaderInstance()->GetShader();
|
const NzShader* shader2 = mat2->GetShaderInstance()->GetShader();
|
||||||
|
|
||||||
if (shader1 != shader2)
|
if (shader1 != shader2)
|
||||||
return shader1 < shader2;
|
return shader1 < shader2;
|
||||||
|
|
||||||
|
|
@ -320,7 +368,6 @@ bool NzForwardRenderQueue::BatchedSpriteMaterialComparator::operator()(const NzM
|
||||||
|
|
||||||
const NzShader* shader1 = mat1->GetShaderInstance()->GetShader();
|
const NzShader* shader1 = mat1->GetShaderInstance()->GetShader();
|
||||||
const NzShader* shader2 = mat2->GetShaderInstance()->GetShader();
|
const NzShader* shader2 = mat2->GetShaderInstance()->GetShader();
|
||||||
|
|
||||||
if (shader1 != shader2)
|
if (shader1 != shader2)
|
||||||
return shader1 < shader2;
|
return shader1 < shader2;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace
|
||||||
|
|
||||||
NzIndexBuffer* BuildIndexBuffer()
|
NzIndexBuffer* BuildIndexBuffer()
|
||||||
{
|
{
|
||||||
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(false, s_maxSprites*6, nzBufferStorage_Hardware, nzBufferUsage_Static));
|
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(false, s_maxSprites*6, nzDataStorage_Hardware, nzBufferUsage_Static));
|
||||||
indexBuffer->SetPersistent(false);
|
indexBuffer->SetPersistent(false);
|
||||||
|
|
||||||
NzBufferMapper<NzIndexBuffer> mapper(indexBuffer.get(), nzBufferAccess_WriteOnly);
|
NzBufferMapper<NzIndexBuffer> mapper(indexBuffer.get(), nzBufferAccess_WriteOnly);
|
||||||
|
|
@ -49,7 +49,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
NzForwardRenderTechnique::NzForwardRenderTechnique() :
|
NzForwardRenderTechnique::NzForwardRenderTechnique() :
|
||||||
m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_UV), s_maxSprites*4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic),
|
m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), s_maxSprites*4, nzDataStorage_Hardware, nzBufferUsage_Dynamic),
|
||||||
m_maxLightPassPerObject(3)
|
m_maxLightPassPerObject(3)
|
||||||
{
|
{
|
||||||
if (!s_indexBuffer)
|
if (!s_indexBuffer)
|
||||||
|
|
@ -87,8 +87,8 @@ bool NzForwardRenderTechnique::Draw(const NzScene* scene) const
|
||||||
if (!m_renderQueue.transparentModels.empty())
|
if (!m_renderQueue.transparentModels.empty())
|
||||||
DrawTransparentModels(scene);
|
DrawTransparentModels(scene);
|
||||||
|
|
||||||
if (!m_renderQueue.sprites.empty())
|
if (!m_renderQueue.basicSprites.empty())
|
||||||
DrawSprites(scene);
|
DrawBasicSprites(scene);
|
||||||
|
|
||||||
// Les autres drawables (Exemple: Terrain)
|
// Les autres drawables (Exemple: Terrain)
|
||||||
for (const NzDrawable* drawable : m_renderQueue.otherDrawables)
|
for (const NzDrawable* drawable : m_renderQueue.otherDrawables)
|
||||||
|
|
@ -162,11 +162,108 @@ void NzForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount)
|
||||||
m_maxLightPassPerObject = passCount;
|
m_maxLightPassPerObject = passCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
|
||||||
|
{
|
||||||
|
NzAbstractViewer* viewer = scene->GetViewer();
|
||||||
|
const NzShader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
|
||||||
|
NzRenderer::SetIndexBuffer(m_indexBuffer);
|
||||||
|
NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity());
|
||||||
|
NzRenderer::SetVertexBuffer(&m_spriteBuffer);
|
||||||
|
|
||||||
|
for (auto& matIt : m_renderQueue.basicSprites)
|
||||||
|
{
|
||||||
|
const NzMaterial* material = matIt.first;
|
||||||
|
auto& overlayMap = matIt.second;
|
||||||
|
|
||||||
|
for (auto& overlayIt : overlayMap)
|
||||||
|
{
|
||||||
|
const NzTexture* overlay = overlayIt.first;
|
||||||
|
auto& spriteChainVector = overlayIt.second;
|
||||||
|
|
||||||
|
unsigned int spriteChainCount = spriteChainVector.size();
|
||||||
|
if (spriteChainCount > 0)
|
||||||
|
{
|
||||||
|
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||||
|
nzUInt32 flags = nzShaderFlags_VertexColor;
|
||||||
|
if (overlay)
|
||||||
|
flags |= nzShaderFlags_TextureOverlay;
|
||||||
|
|
||||||
|
nzUInt8 overlayUnit;
|
||||||
|
const NzShader* shader = material->Apply(flags, 0, &overlayUnit);
|
||||||
|
|
||||||
|
if (overlay)
|
||||||
|
{
|
||||||
|
overlayUnit++;
|
||||||
|
NzRenderer::SetTexture(overlayUnit, overlay);
|
||||||
|
NzRenderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||||
|
if (shader != lastShader)
|
||||||
|
{
|
||||||
|
// Index des uniformes dans le shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
|
// Couleur ambiante de la scène
|
||||||
|
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
||||||
|
// Overlay
|
||||||
|
shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit);
|
||||||
|
// Position de la caméra
|
||||||
|
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
||||||
|
|
||||||
|
lastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int spriteChain = 0; // Quelle chaîne de sprite traitons-nous
|
||||||
|
unsigned int spriteChainOffset = 0; // À quel offset dans la dernière chaîne nous sommes-nous arrêtés
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// On ouvre le buffer en écriture
|
||||||
|
NzBufferMapper<NzVertexBuffer> vertexMapper(m_spriteBuffer, nzBufferAccess_DiscardAndWrite);
|
||||||
|
NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<NzVertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||||
|
|
||||||
|
unsigned int spriteCount = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
|
||||||
|
unsigned int count = std::min(s_maxSprites - spriteCount, currentChain.spriteCount - spriteChainOffset);
|
||||||
|
|
||||||
|
std::memcpy(vertices, currentChain.vertices + spriteChainOffset*4, 4*count*sizeof(NzVertexStruct_XYZ_Color_UV));
|
||||||
|
vertices += count*4;
|
||||||
|
|
||||||
|
spriteCount += count;
|
||||||
|
spriteChainOffset += count;
|
||||||
|
|
||||||
|
// Avons-nous traité la chaîne entière ?
|
||||||
|
if (spriteChainOffset == currentChain.spriteCount)
|
||||||
|
{
|
||||||
|
spriteChain++;
|
||||||
|
spriteChainOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (spriteCount < s_maxSprites && spriteChain < spriteChainCount);
|
||||||
|
|
||||||
|
vertexMapper.Unmap();
|
||||||
|
|
||||||
|
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6);
|
||||||
|
}
|
||||||
|
while (spriteChain < spriteChainCount);
|
||||||
|
|
||||||
|
spriteChainVector.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
{
|
{
|
||||||
NzAbstractViewer* viewer = scene->GetViewer();
|
NzAbstractViewer* viewer = scene->GetViewer();
|
||||||
const LightUniforms* lightUniforms = nullptr;
|
|
||||||
const NzShader* lastShader = nullptr;
|
const NzShader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
|
|
||||||
for (auto& matIt : m_renderQueue.opaqueModels)
|
for (auto& matIt : m_renderQueue.opaqueModels)
|
||||||
{
|
{
|
||||||
|
|
@ -191,14 +288,14 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||||
if (shader != lastShader)
|
if (shader != lastShader)
|
||||||
{
|
{
|
||||||
|
// Index des uniformes dans le shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
// Couleur ambiante de la scène
|
// Couleur ambiante de la scène
|
||||||
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
||||||
// Position de la caméra
|
// Position de la caméra
|
||||||
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
||||||
|
|
||||||
// Index des uniformes d'éclairage dans le shader
|
|
||||||
lightUniforms = GetLightUniforms(shader);
|
|
||||||
|
|
||||||
lastShader = shader;
|
lastShader = shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +347,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
|
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
|
||||||
for (unsigned int pass = 0; pass < passCount; ++pass)
|
for (unsigned int pass = 0; pass < passCount; ++pass)
|
||||||
{
|
{
|
||||||
if (lightUniforms->exists)
|
if (shaderUniforms->hasLightUniforms)
|
||||||
{
|
{
|
||||||
unsigned int renderedLightCount = std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
unsigned int renderedLightCount = std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
||||||
lightCount -= renderedLightCount;
|
lightCount -= renderedLightCount;
|
||||||
|
|
@ -267,15 +364,15 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < renderedLightCount; ++i)
|
for (unsigned int i = 0; i < renderedLightCount; ++i)
|
||||||
m_directionalLights.GetLight(lightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
m_directionalLights.GetLight(lightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
|
|
||||||
for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||||
NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzMatrix4f* instanceMatrices = &instances[0];
|
const NzMatrix4f* instanceMatrices = &instances[0];
|
||||||
unsigned int instanceCount = instances.size();
|
unsigned int instanceCount = instances.size();
|
||||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing)
|
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Le nombre maximum d'instances en une fois
|
||||||
|
|
||||||
while (instanceCount > 0)
|
while (instanceCount > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -298,7 +395,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lightUniforms->exists)
|
if (shaderUniforms->hasLightUniforms)
|
||||||
{
|
{
|
||||||
for (const NzMatrix4f& matrix : instances)
|
for (const NzMatrix4f& matrix : instances)
|
||||||
{
|
{
|
||||||
|
|
@ -332,14 +429,14 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
for (unsigned int i = 0; i < renderedLightCount; ++i)
|
for (unsigned int i = 0; i < renderedLightCount; ++i)
|
||||||
{
|
{
|
||||||
if (directionalLightIndex >= directionalLightCount)
|
if (directionalLightIndex >= directionalLightCount)
|
||||||
m_lights.GetResult(otherLightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
m_lights.GetResult(otherLightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
else
|
else
|
||||||
m_directionalLights.GetLight(directionalLightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
m_directionalLights.GetLight(directionalLightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On désactive l'éventuel surplus
|
// On désactive l'éventuel surplus
|
||||||
for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||||
NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
|
|
||||||
// Et on passe à l'affichage
|
// Et on passe à l'affichage
|
||||||
DrawFunc(meshData.primitiveMode, 0, indexCount);
|
DrawFunc(meshData.primitiveMode, 0, indexCount);
|
||||||
|
|
@ -351,7 +448,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Sans instancing, on doit effectuer un drawcall pour chaque instance
|
// Sans instancing, on doit effectuer un draw call pour chaque instance
|
||||||
// Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances
|
// Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances
|
||||||
// À cause du temps de modification du buffer d'instancing
|
// À cause du temps de modification du buffer d'instancing
|
||||||
for (const NzMatrix4f& matrix : instances)
|
for (const NzMatrix4f& matrix : instances)
|
||||||
|
|
@ -367,84 +464,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Et on remet à zéro les données
|
// Et on remet à zéro les données
|
||||||
renderQueueInstancing = false;
|
|
||||||
used = false;
|
used = false;
|
||||||
}
|
renderQueueInstancing = false;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) const
|
|
||||||
{
|
|
||||||
NzAbstractViewer* viewer = scene->GetViewer();
|
|
||||||
const NzShader* lastShader = nullptr;
|
|
||||||
|
|
||||||
NzRenderer::SetIndexBuffer(m_indexBuffer);
|
|
||||||
NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity());
|
|
||||||
NzRenderer::SetVertexBuffer(&m_spriteBuffer);
|
|
||||||
|
|
||||||
for (auto& matIt : m_renderQueue.sprites)
|
|
||||||
{
|
|
||||||
const NzMaterial* material = matIt.first;
|
|
||||||
auto& spriteVector = matIt.second;
|
|
||||||
|
|
||||||
unsigned int spriteCount = spriteVector.size();
|
|
||||||
if (spriteCount > 0)
|
|
||||||
{
|
|
||||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
|
||||||
const NzShader* shader = material->Apply();
|
|
||||||
|
|
||||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
|
||||||
if (shader != lastShader)
|
|
||||||
{
|
|
||||||
// Couleur ambiante de la scène
|
|
||||||
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
|
||||||
// Position de la caméra
|
|
||||||
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
|
||||||
|
|
||||||
lastShader = shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
const NzSprite** spritePtr = &spriteVector[0];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
unsigned int renderedSpriteCount = std::min(spriteCount, 64U);
|
|
||||||
spriteCount -= renderedSpriteCount;
|
|
||||||
|
|
||||||
NzBufferMapper<NzVertexBuffer> vertexMapper(m_spriteBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedSpriteCount*4);
|
|
||||||
NzVertexStruct_XYZ_UV* vertices = reinterpret_cast<NzVertexStruct_XYZ_UV*>(vertexMapper.GetPointer());
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < renderedSpriteCount; ++i)
|
|
||||||
{
|
|
||||||
const NzSprite* sprite = *spritePtr++;
|
|
||||||
const NzRectf& textureCoords = sprite->GetTextureCoords();
|
|
||||||
const NzVector2f& halfSize = sprite->GetSize()*0.5f;
|
|
||||||
NzVector3f center = sprite->GetPosition();
|
|
||||||
NzQuaternionf rotation = sprite->GetRotation();
|
|
||||||
|
|
||||||
vertices->position = center + rotation * NzVector3f(-halfSize.x, halfSize.y, 0.f);
|
|
||||||
vertices->uv.Set(textureCoords.x, textureCoords.y + textureCoords.height);
|
|
||||||
vertices++;
|
|
||||||
|
|
||||||
vertices->position = center + rotation * NzVector3f(halfSize.x, halfSize.y, 0.f);
|
|
||||||
vertices->uv.Set(textureCoords.width, textureCoords.y + textureCoords.height);
|
|
||||||
vertices++;
|
|
||||||
|
|
||||||
vertices->position = center + rotation * NzVector3f(-halfSize.x, -halfSize.y, 0.f);
|
|
||||||
vertices->uv.Set(textureCoords.x, textureCoords.y);
|
|
||||||
vertices++;
|
|
||||||
|
|
||||||
vertices->position = center + rotation * NzVector3f(halfSize.x, -halfSize.y, 0.f);
|
|
||||||
vertices->uv.Set(textureCoords.width, textureCoords.y);
|
|
||||||
vertices++;
|
|
||||||
}
|
|
||||||
|
|
||||||
vertexMapper.Unmap();
|
|
||||||
|
|
||||||
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, renderedSpriteCount*6);
|
|
||||||
}
|
|
||||||
while (spriteCount > 0);
|
|
||||||
|
|
||||||
spriteVector.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -452,8 +473,8 @@ void NzForwardRenderTechnique::DrawSprites(const NzScene* scene) const
|
||||||
void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
|
void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
|
||||||
{
|
{
|
||||||
NzAbstractViewer* viewer = scene->GetViewer();
|
NzAbstractViewer* viewer = scene->GetViewer();
|
||||||
const LightUniforms* lightUniforms = nullptr;
|
|
||||||
const NzShader* lastShader = nullptr;
|
const NzShader* lastShader = nullptr;
|
||||||
|
const ShaderUniforms* shaderUniforms = nullptr;
|
||||||
unsigned int lightCount = 0;
|
unsigned int lightCount = 0;
|
||||||
|
|
||||||
for (unsigned int index : m_renderQueue.transparentModels)
|
for (unsigned int index : m_renderQueue.transparentModels)
|
||||||
|
|
@ -469,18 +490,18 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
|
||||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||||
if (shader != lastShader)
|
if (shader != lastShader)
|
||||||
{
|
{
|
||||||
|
// Index des uniformes dans le shader
|
||||||
|
shaderUniforms = GetShaderUniforms(shader);
|
||||||
|
|
||||||
// Couleur ambiante de la scène
|
// Couleur ambiante de la scène
|
||||||
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
|
||||||
// Position de la caméra
|
// Position de la caméra
|
||||||
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
|
||||||
|
|
||||||
// Index des uniformes d'éclairage dans le shader
|
|
||||||
lightUniforms = GetLightUniforms(shader);
|
|
||||||
|
|
||||||
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
|
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
|
||||||
lightCount = std::min(m_directionalLights.GetLightCount(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
lightCount = std::min(m_directionalLights.GetLightCount(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
||||||
for (unsigned int i = 0; i < lightCount; ++i)
|
for (unsigned int i = 0; i < lightCount; ++i)
|
||||||
m_directionalLights.GetLight(i)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
m_directionalLights.GetLight(i)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
|
|
||||||
lastShader = shader;
|
lastShader = shader;
|
||||||
}
|
}
|
||||||
|
|
@ -515,45 +536,46 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
|
||||||
{
|
{
|
||||||
unsigned int count = std::min(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + modelData.boundingSphere.GetPosition(), modelData.boundingSphere.radius, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
|
unsigned int count = std::min(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + modelData.boundingSphere.GetPosition(), modelData.boundingSphere.radius, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
|
||||||
for (unsigned int i = 0; i < count; ++i)
|
for (unsigned int i = 0; i < count; ++i)
|
||||||
m_lights.GetResult(i)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*(lightCount++));
|
m_lights.GetResult(i)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*(lightCount++));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||||
NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
|
NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
|
||||||
|
|
||||||
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
|
||||||
DrawFunc(meshData.primitiveMode, 0, indexCount);
|
DrawFunc(meshData.primitiveMode, 0, indexCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzForwardRenderTechnique::LightUniforms* NzForwardRenderTechnique::GetLightUniforms(const NzShader* shader) const
|
const NzForwardRenderTechnique::ShaderUniforms* NzForwardRenderTechnique::GetShaderUniforms(const NzShader* shader) const
|
||||||
{
|
{
|
||||||
auto it = m_lightUniforms.find(shader);
|
auto it = m_shaderUniforms.find(shader);
|
||||||
if (it != m_lightUniforms.end())
|
if (it != m_shaderUniforms.end())
|
||||||
return &(it->second);
|
return &(it->second);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ShaderUniforms uniforms;
|
||||||
|
uniforms.textureOverlay = shader->GetUniformLocation("TextureOverlay");
|
||||||
|
|
||||||
int type0Location = shader->GetUniformLocation("Lights[0].type");
|
int type0Location = shader->GetUniformLocation("Lights[0].type");
|
||||||
int type1Location = shader->GetUniformLocation("Lights[1].type");
|
int type1Location = shader->GetUniformLocation("Lights[1].type");
|
||||||
|
|
||||||
LightUniforms lightUniforms;
|
|
||||||
|
|
||||||
if (type0Location > 0 && type1Location > 0)
|
if (type0Location > 0 && type1Location > 0)
|
||||||
{
|
{
|
||||||
lightUniforms.exists = true;
|
uniforms.hasLightUniforms = true;
|
||||||
lightUniforms.offset = type1Location - type0Location;
|
uniforms.lightOffset = type1Location - type0Location;
|
||||||
lightUniforms.uniforms.ubo = false;
|
uniforms.lightUniforms.ubo = false;
|
||||||
lightUniforms.uniforms.locations.type = type0Location;
|
uniforms.lightUniforms.locations.type = type0Location;
|
||||||
lightUniforms.uniforms.locations.color = shader->GetUniformLocation("Lights[0].color");
|
uniforms.lightUniforms.locations.color = shader->GetUniformLocation("Lights[0].color");
|
||||||
lightUniforms.uniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors");
|
uniforms.lightUniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors");
|
||||||
lightUniforms.uniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
|
uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
|
||||||
lightUniforms.uniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
|
uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
|
||||||
lightUniforms.uniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3");
|
uniforms.lightUniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lightUniforms.exists = false;
|
uniforms.hasLightUniforms = false;
|
||||||
|
|
||||||
auto pair = m_lightUniforms.emplace(shader, lightUniforms);
|
auto pair = m_shaderUniforms.emplace(shader, uniforms);
|
||||||
return &(pair.first->second);
|
return &(pair.first->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// 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/GuillotineTextureAtlas.hpp>
|
||||||
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
NzAbstractImage* NzGuillotineTextureAtlas::ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzTexture> newTexture(new NzTexture);
|
||||||
|
if (newTexture->Create(nzImageType_2D, nzPixelFormat_A8, size.x, size.y, 1, 0xFF))
|
||||||
|
{
|
||||||
|
if (oldImage)
|
||||||
|
{
|
||||||
|
NzTexture* oldTexture = static_cast<NzTexture*>(oldImage);
|
||||||
|
|
||||||
|
// Copie des anciennes données
|
||||||
|
///TODO: Copie de texture à texture
|
||||||
|
NzImage image;
|
||||||
|
if (!oldTexture->Download(&image))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to download old texture");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newTexture->Update(image, NzRectui(0, 0, image.GetWidth(), image.GetHeight())))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to update texture");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newTexture.release();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Si on arrive ici c'est que la taille demandée est trop grande pour la carte graphique
|
||||||
|
// ou que nous manquons de mémoire
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ m_innerAngle(light.m_innerAngle),
|
||||||
m_outerAngle(light.m_outerAngle),
|
m_outerAngle(light.m_outerAngle),
|
||||||
m_radius(light.m_radius)
|
m_radius(light.m_radius)
|
||||||
{
|
{
|
||||||
SetParent(light);
|
SetParent(light.GetParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||||
|
|
|
||||||
|
|
@ -34,20 +34,6 @@ NzResource()
|
||||||
Copy(material);
|
Copy(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzMaterial::NzMaterial(NzMaterial&& material)
|
|
||||||
{
|
|
||||||
Copy(material);
|
|
||||||
|
|
||||||
// Nous "volons" la référence du matériau
|
|
||||||
material.m_alphaMap.Reset();
|
|
||||||
material.m_diffuseMap.Reset();
|
|
||||||
material.m_emissiveMap.Reset();
|
|
||||||
material.m_heightMap.Reset();
|
|
||||||
material.m_normalMap.Reset();
|
|
||||||
material.m_specularMap.Reset();
|
|
||||||
material.m_uberShader.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
NzMaterial::~NzMaterial()
|
NzMaterial::~NzMaterial()
|
||||||
{
|
{
|
||||||
NotifyDestroy();
|
NotifyDestroy();
|
||||||
|
|
@ -622,22 +608,6 @@ NzMaterial& NzMaterial::operator=(const NzMaterial& material)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzMaterial& NzMaterial::operator=(NzMaterial&& material)
|
|
||||||
{
|
|
||||||
Copy(material);
|
|
||||||
|
|
||||||
// Comme ça nous volons la référence du matériau
|
|
||||||
material.m_alphaMap.Reset();
|
|
||||||
material.m_diffuseMap.Reset();
|
|
||||||
material.m_emissiveMap.Reset();
|
|
||||||
material.m_heightMap.Reset();
|
|
||||||
material.m_normalMap.Reset();
|
|
||||||
material.m_specularMap.Reset();
|
|
||||||
material.m_uberShader.Reset();
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzMaterial* NzMaterial::GetDefault()
|
NzMaterial* NzMaterial::GetDefault()
|
||||||
{
|
{
|
||||||
return s_defaultMaterial;
|
return s_defaultMaterial;
|
||||||
|
|
@ -645,33 +615,32 @@ NzMaterial* NzMaterial::GetDefault()
|
||||||
|
|
||||||
void NzMaterial::Copy(const NzMaterial& material)
|
void NzMaterial::Copy(const NzMaterial& material)
|
||||||
{
|
{
|
||||||
// On relache les références proprement
|
// Copie des états de base
|
||||||
m_alphaMap.Reset();
|
m_alphaTestEnabled = material.m_alphaTestEnabled;
|
||||||
m_diffuseMap.Reset();
|
m_alphaThreshold = material.m_alphaThreshold;
|
||||||
m_emissiveMap.Reset();
|
m_ambientColor = material.m_ambientColor;
|
||||||
m_heightMap.Reset();
|
m_diffuseColor = material.m_diffuseColor;
|
||||||
m_normalMap.Reset();
|
m_diffuseSampler = material.m_diffuseSampler;
|
||||||
m_specularMap.Reset();
|
m_lightingEnabled = material.m_lightingEnabled;
|
||||||
m_uberShader.Reset();
|
m_shininess = material.m_shininess;
|
||||||
|
m_specularColor = material.m_specularColor;
|
||||||
std::memcpy(this, &material, sizeof(NzMaterial)); // Autorisé dans notre cas, et bien plus rapide
|
m_specularSampler = material.m_specularSampler;
|
||||||
|
m_states = material.m_states;
|
||||||
// Ensuite une petite astuce pour récupérer correctement les références
|
m_transformEnabled = material.m_transformEnabled;
|
||||||
m_alphaMap.Release();
|
|
||||||
m_diffuseMap.Release();
|
|
||||||
m_emissiveMap.Release();
|
|
||||||
m_heightMap.Release();
|
|
||||||
m_normalMap.Release();
|
|
||||||
m_specularMap.Release();
|
|
||||||
m_uberShader.Release();
|
|
||||||
|
|
||||||
|
// Copie des références de texture
|
||||||
m_alphaMap = material.m_alphaMap;
|
m_alphaMap = material.m_alphaMap;
|
||||||
m_diffuseMap = material.m_diffuseMap;
|
m_diffuseMap = material.m_diffuseMap;
|
||||||
m_emissiveMap = material.m_emissiveMap;
|
m_emissiveMap = material.m_emissiveMap;
|
||||||
m_heightMap = material.m_heightMap;
|
m_heightMap = material.m_heightMap;
|
||||||
m_normalMap = material.m_normalMap;
|
m_normalMap = material.m_normalMap;
|
||||||
m_specularMap = material.m_specularMap;
|
m_specularMap = material.m_specularMap;
|
||||||
|
|
||||||
|
// Copie de la référence vers l'Über-Shader
|
||||||
m_uberShader = material.m_uberShader;
|
m_uberShader = material.m_uberShader;
|
||||||
|
|
||||||
|
// On copie les instances de shader par la même occasion
|
||||||
|
std::memcpy(&m_shaders[0], &material.m_shaders[0], (nzShaderFlags_Max+1)*sizeof(ShaderInstance));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzMaterial::GenerateShader(nzUInt32 flags) const
|
void NzMaterial::GenerateShader(nzUInt32 flags) const
|
||||||
|
|
@ -687,11 +656,14 @@ void NzMaterial::GenerateShader(nzUInt32 flags) const
|
||||||
list.SetParameter("PARALLAX_MAPPING", m_heightMap.IsValid());
|
list.SetParameter("PARALLAX_MAPPING", m_heightMap.IsValid());
|
||||||
list.SetParameter("SPECULAR_MAPPING", m_specularMap.IsValid());
|
list.SetParameter("SPECULAR_MAPPING", m_specularMap.IsValid());
|
||||||
list.SetParameter("TEXTURE_MAPPING", m_alphaMap.IsValid() || m_diffuseMap.IsValid() || m_emissiveMap.IsValid() ||
|
list.SetParameter("TEXTURE_MAPPING", m_alphaMap.IsValid() || m_diffuseMap.IsValid() || m_emissiveMap.IsValid() ||
|
||||||
m_normalMap.IsValid() || m_heightMap.IsValid() || m_specularMap.IsValid());
|
m_normalMap.IsValid() || m_heightMap.IsValid() || m_specularMap.IsValid() ||
|
||||||
|
flags & nzShaderFlags_TextureOverlay);
|
||||||
list.SetParameter("TRANSFORM", m_transformEnabled);
|
list.SetParameter("TRANSFORM", m_transformEnabled);
|
||||||
|
|
||||||
list.SetParameter("FLAG_DEFERRED", static_cast<bool>((flags & nzShaderFlags_Deferred) != 0));
|
list.SetParameter("FLAG_DEFERRED", static_cast<bool>((flags & nzShaderFlags_Deferred) != 0));
|
||||||
list.SetParameter("FLAG_INSTANCING", static_cast<bool>((flags & nzShaderFlags_Instancing) != 0));
|
list.SetParameter("FLAG_INSTANCING", static_cast<bool>((flags & nzShaderFlags_Instancing) != 0));
|
||||||
|
list.SetParameter("FLAG_TEXTUREOVERLAY", static_cast<bool>((flags & nzShaderFlags_TextureOverlay) != 0));
|
||||||
|
list.SetParameter("FLAG_VERTEXCOLOR", static_cast<bool>((flags & nzShaderFlags_VertexColor) != 0));
|
||||||
|
|
||||||
ShaderInstance& instance = m_shaders[flags];
|
ShaderInstance& instance = m_shaders[flags];
|
||||||
instance.uberInstance = m_uberShader->Get(list);
|
instance.uberInstance = m_uberShader->Get(list);
|
||||||
|
|
@ -758,8 +730,8 @@ bool NzMaterial::Initialize()
|
||||||
vertexShader.Set(reinterpret_cast<const char*>(compatibilityVertexShader), sizeof(compatibilityVertexShader));
|
vertexShader.Set(reinterpret_cast<const char*>(compatibilityVertexShader), sizeof(compatibilityVertexShader));
|
||||||
}
|
}
|
||||||
|
|
||||||
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING");
|
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING");
|
||||||
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_INSTANCING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
|
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
|
||||||
|
|
||||||
NzUberShaderLibrary::Register("Basic", uberShader.get());
|
NzUberShaderLibrary::Register("Basic", uberShader.get());
|
||||||
uberShader.release();
|
uberShader.release();
|
||||||
|
|
@ -799,8 +771,8 @@ bool NzMaterial::Initialize()
|
||||||
vertexShader.Set(reinterpret_cast<const char*>(compatibilityVertexShader), sizeof(compatibilityVertexShader));
|
vertexShader.Set(reinterpret_cast<const char*>(compatibilityVertexShader), sizeof(compatibilityVertexShader));
|
||||||
}
|
}
|
||||||
|
|
||||||
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_DEFERRED ALPHA_MAPPING ALPHA_TEST DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING");
|
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING");
|
||||||
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_DEFERRED FLAG_INSTANCING COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
|
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
|
||||||
|
|
||||||
NzUberShaderLibrary::Register("PhongLighting", uberShader.get());
|
NzUberShaderLibrary::Register("PhongLighting", uberShader.get());
|
||||||
uberShader.release();
|
uberShader.release();
|
||||||
|
|
|
||||||
|
|
@ -36,19 +36,13 @@ NzModel::NzModel(const NzModel& model) :
|
||||||
NzSceneNode(model),
|
NzSceneNode(model),
|
||||||
m_materials(model.m_materials),
|
m_materials(model.m_materials),
|
||||||
m_boundingVolume(model.m_boundingVolume),
|
m_boundingVolume(model.m_boundingVolume),
|
||||||
|
m_mesh(model.m_mesh),
|
||||||
m_boundingVolumeUpdated(model.m_boundingVolumeUpdated),
|
m_boundingVolumeUpdated(model.m_boundingVolumeUpdated),
|
||||||
m_matCount(model.m_matCount),
|
m_matCount(model.m_matCount),
|
||||||
m_skin(model.m_skin),
|
m_skin(model.m_skin),
|
||||||
m_skinCount(model.m_skinCount)
|
m_skinCount(model.m_skinCount)
|
||||||
{
|
{
|
||||||
if (model.m_mesh)
|
SetParent(model.GetParent());
|
||||||
{
|
|
||||||
// Nous n'avons des matériaux que si nous avons un mesh
|
|
||||||
m_mesh = model.m_mesh;
|
|
||||||
m_materials = model.m_materials;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetParent(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzModel::~NzModel()
|
NzModel::~NzModel()
|
||||||
|
|
@ -420,24 +414,6 @@ NzModel& NzModel::operator=(const NzModel& node)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzModel& NzModel::operator=(NzModel&& node)
|
|
||||||
{
|
|
||||||
NzSceneNode::operator=(node);
|
|
||||||
|
|
||||||
// Ressources
|
|
||||||
m_mesh = std::move(node.m_mesh);
|
|
||||||
m_materials = std::move(node.m_materials);
|
|
||||||
|
|
||||||
// Paramètres
|
|
||||||
m_boundingVolume = node.m_boundingVolume;
|
|
||||||
m_boundingVolumeUpdated = node.m_boundingVolumeUpdated;
|
|
||||||
m_matCount = node.m_matCount;
|
|
||||||
m_skin = node.m_skin;
|
|
||||||
m_skinCount = node.m_skinCount;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzModel::InvalidateNode()
|
void NzModel::InvalidateNode()
|
||||||
{
|
{
|
||||||
NzSceneNode::InvalidateNode();
|
NzSceneNode::InvalidateNode();
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,24 @@ layout(early_fragment_tests) in;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/********************Entrant********************/
|
/********************Entrant********************/
|
||||||
|
in vec4 vColor;
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
|
|
||||||
/********************Sortant********************/
|
/********************Sortant********************/
|
||||||
out vec4 RenderTarget0;
|
out vec4 RenderTarget0;
|
||||||
|
|
||||||
/********************Uniformes********************/
|
/********************Uniformes********************/
|
||||||
|
uniform vec2 InvTargetSize;
|
||||||
uniform sampler2D MaterialAlphaMap;
|
uniform sampler2D MaterialAlphaMap;
|
||||||
uniform float MaterialAlphaThreshold;
|
uniform float MaterialAlphaThreshold;
|
||||||
uniform vec4 MaterialDiffuse;
|
uniform vec4 MaterialDiffuse;
|
||||||
uniform sampler2D MaterialDiffuseMap;
|
uniform sampler2D MaterialDiffuseMap;
|
||||||
uniform vec2 InvTargetSize;
|
uniform sampler2D TextureOverlay;
|
||||||
|
|
||||||
/********************Fonctions********************/
|
/********************Fonctions********************/
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 fragmentColor = MaterialDiffuse;
|
vec4 fragmentColor = MaterialDiffuse * vColor;
|
||||||
|
|
||||||
#if AUTO_TEXCOORDS
|
#if AUTO_TEXCOORDS
|
||||||
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
|
||||||
|
|
@ -34,6 +36,10 @@ void main()
|
||||||
fragmentColor.a *= texture(MaterialAlphaMap, texCoord).r;
|
fragmentColor.a *= texture(MaterialAlphaMap, texCoord).r;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FLAG_TEXTUREOVERLAY
|
||||||
|
fragmentColor *= texture(TextureOverlay, texCoord);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ALPHA_TEST
|
#if ALPHA_TEST
|
||||||
if (fragmentColor.a < MaterialAlphaThreshold)
|
if (fragmentColor.a < MaterialAlphaThreshold)
|
||||||
discard;
|
discard;
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
35,105,102,32,69,65,82,76,89,95,70,82,65,71,77,69,78,84,95,84,69,83,84,83,32,38,38,32,33,65,76,80,72,65,95,84,69,83,84,13,10,108,97,121,111,117,116,40,101,97,114,108,121,95,102,114,97,103,109,101,110,116,95,116,101,115,116,115,41,32,105,110,59,13,10,35,101,110,100,105,102,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125,
|
35,105,102,32,69,65,82,76,89,95,70,82,65,71,77,69,78,84,95,84,69,83,84,83,32,38,38,32,33,65,76,80,72,65,95,84,69,83,84,13,10,108,97,121,111,117,116,40,101,97,114,108,121,95,102,114,97,103,109,101,110,116,95,116,101,115,116,115,41,32,105,110,59,13,10,35,101,110,100,105,102,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,105,110,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,84,101,120,116,117,114,101,79,118,101,114,108,97,121,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,32,42,32,118,67,111,108,111,114,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,70,76,65,71,95,84,69,88,84,85,82,69,79,86,69,82,76,65,89,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,40,84,101,120,116,117,114,101,79,118,101,114,108,97,121,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125,
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
/********************Entrant********************/
|
/********************Entrant********************/
|
||||||
in mat4 InstanceData0;
|
in mat4 InstanceData0;
|
||||||
|
in vec4 VertexColor;
|
||||||
in vec3 VertexPosition;
|
in vec3 VertexPosition;
|
||||||
in vec2 VertexTexCoord;
|
in vec2 VertexTexCoord;
|
||||||
|
|
||||||
/********************Sortant********************/
|
/********************Sortant********************/
|
||||||
|
out vec4 vColor;
|
||||||
out vec2 vTexCoord;
|
out vec2 vTexCoord;
|
||||||
|
|
||||||
/********************Uniformes********************/
|
/********************Uniformes********************/
|
||||||
|
|
@ -14,6 +16,12 @@ uniform mat4 WorldViewProjMatrix;
|
||||||
/********************Fonctions********************/
|
/********************Fonctions********************/
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
#if FLAG_VERTEXCOLOR
|
||||||
|
vec4 color = VertexColor;
|
||||||
|
#else
|
||||||
|
vec4 color = vec4(1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FLAG_INSTANCING
|
#if FLAG_INSTANCING
|
||||||
#if TRANSFORM
|
#if TRANSFORM
|
||||||
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
|
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
|
||||||
|
|
@ -36,6 +44,7 @@ void main()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vColor = color;
|
||||||
#if TEXTURE_MAPPING
|
#if TEXTURE_MAPPING
|
||||||
vTexCoord = vec2(VertexTexCoord);
|
vTexCoord = vec2(VertexTexCoord);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,105,110,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,86,101,114,116,101,120,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10,
|
47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,109,97,116,52,32,73,110,115,116,97,110,99,101,68,97,116,97,48,59,13,10,105,110,32,118,101,99,52,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,105,110,32,118,101,99,50,32,86,101,114,116,101,120,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,111,117,116,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,86,101,114,116,101,120,68,101,112,116,104,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,35,105,102,32,70,76,65,71,95,86,69,82,84,69,88,67,79,76,79,82,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,86,101,114,116,101,120,67,111,108,111,114,59,13,10,35,101,108,115,101,13,10,9,118,101,99,52,32,99,111,108,111,114,32,61,32,118,101,99,52,40,49,46,48,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,70,76,65,71,95,73,78,83,84,65,78,67,73,78,71,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,73,110,115,116,97,110,99,101,68,97,116,97,48,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,108,115,101,13,10,9,35,105,102,32,84,82,65,78,83,70,79,82,77,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,35,101,108,115,101,13,10,9,9,35,105,102,32,85,78,73,70,79,82,77,95,86,69,82,84,69,88,95,68,69,80,84,72,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,46,120,121,44,32,86,101,114,116,101,120,68,101,112,116,104,44,32,49,46,48,41,59,13,10,9,9,35,101,108,115,101,13,10,9,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,9,9,35,101,110,100,105,102,13,10,9,35,101,110,100,105,102,13,10,35,101,110,100,105,102,13,10,13,10,9,118,67,111,108,111,114,32,61,32,99,111,108,111,114,59,13,10,35,105,102,32,84,69,88,84,85,82,69,95,77,65,80,80,73,78,71,13,10,9,118,84,101,120,67,111,111,114,100,32,61,32,118,101,99,50,40,86,101,114,116,101,120,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10,
|
||||||
|
|
@ -7,6 +7,7 @@ layout(early_fragment_tests) in;
|
||||||
#define LIGHT_SPOT 2
|
#define LIGHT_SPOT 2
|
||||||
|
|
||||||
/********************Entrant********************/
|
/********************Entrant********************/
|
||||||
|
in vec4 vColor;
|
||||||
in mat3 vLightToWorld;
|
in mat3 vLightToWorld;
|
||||||
in vec3 vNormal;
|
in vec3 vNormal;
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
|
|
@ -49,6 +50,8 @@ uniform float ParallaxBias = -0.03;
|
||||||
uniform float ParallaxScale = 0.02;
|
uniform float ParallaxScale = 0.02;
|
||||||
uniform vec4 SceneAmbient;
|
uniform vec4 SceneAmbient;
|
||||||
|
|
||||||
|
uniform sampler2D TextureOverlay;
|
||||||
|
|
||||||
/********************Fonctions********************/
|
/********************Fonctions********************/
|
||||||
vec3 FloatToColor(float f)
|
vec3 FloatToColor(float f)
|
||||||
{
|
{
|
||||||
|
|
@ -76,7 +79,7 @@ vec4 EncodeNormal(in vec3 normal)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 diffuseColor = MaterialDiffuse;
|
vec4 diffuseColor = MaterialDiffuse * vColor;
|
||||||
vec2 texCoord = vTexCoord;
|
vec2 texCoord = vTexCoord;
|
||||||
#if LIGHTING && PARALLAX_MAPPING
|
#if LIGHTING && PARALLAX_MAPPING
|
||||||
float height = texture(MaterialHeightMap, texCoord).r;
|
float height = texture(MaterialHeightMap, texCoord).r;
|
||||||
|
|
@ -90,6 +93,10 @@ void main()
|
||||||
diffuseColor *= texture(MaterialDiffuseMap, texCoord);
|
diffuseColor *= texture(MaterialDiffuseMap, texCoord);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FLAG_TEXTUREOVERLAY
|
||||||
|
diffuseColor *= texture(TextureOverlay, texCoord);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FLAG_DEFERRED
|
#if FLAG_DEFERRED
|
||||||
#if ALPHA_TEST
|
#if ALPHA_TEST
|
||||||
#if ALPHA_MAPPING // Inutile de faire de l'alpha-mapping sans alpha-test en Deferred (l'alpha n'est pas sauvegardé)
|
#if ALPHA_MAPPING // Inutile de faire de l'alpha-mapping sans alpha-test en Deferred (l'alpha n'est pas sauvegardé)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,11 +1,13 @@
|
||||||
/********************Entrant********************/
|
/********************Entrant********************/
|
||||||
in mat4 InstanceData0;
|
in mat4 InstanceData0;
|
||||||
|
in vec4 VertexColor;
|
||||||
in vec3 VertexPosition;
|
in vec3 VertexPosition;
|
||||||
in vec3 VertexNormal;
|
in vec3 VertexNormal;
|
||||||
in vec3 VertexTangent;
|
in vec3 VertexTangent;
|
||||||
in vec2 VertexTexCoord;
|
in vec2 VertexTexCoord;
|
||||||
|
|
||||||
/********************Sortant********************/
|
/********************Sortant********************/
|
||||||
|
out vec4 vColor;
|
||||||
out mat3 vLightToWorld;
|
out mat3 vLightToWorld;
|
||||||
out vec3 vNormal;
|
out vec3 vNormal;
|
||||||
out vec2 vTexCoord;
|
out vec2 vTexCoord;
|
||||||
|
|
@ -22,6 +24,12 @@ uniform mat4 WorldViewProjMatrix;
|
||||||
/********************Fonctions********************/
|
/********************Fonctions********************/
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
#if FLAG_VERTEXCOLOR
|
||||||
|
vec4 color = VertexColor;
|
||||||
|
#else
|
||||||
|
vec4 color = vec4(1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if FLAG_INSTANCING
|
#if FLAG_INSTANCING
|
||||||
#if TRANSFORM
|
#if TRANSFORM
|
||||||
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
|
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
|
||||||
|
|
@ -44,6 +52,8 @@ void main()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vColor = color;
|
||||||
|
|
||||||
#if LIGHTING
|
#if LIGHTING
|
||||||
#if FLAG_INSTANCING
|
#if FLAG_INSTANCING
|
||||||
mat3 rotationMatrix = mat3(InstanceData0);
|
mat3 rotationMatrix = mat3(InstanceData0);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -134,6 +134,58 @@ NzAbstractBackground* NzScene::GetBackground() const
|
||||||
return m_impl->background.get();
|
return m_impl->background.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzScene::GetBackward() const
|
||||||
|
{
|
||||||
|
#if NAZARA_GRAPHICS_SAFE
|
||||||
|
if (!m_impl->viewer)
|
||||||
|
{
|
||||||
|
NazaraError("No viewer");
|
||||||
|
return NzVector3f::Backward();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -m_impl->viewer->GetGlobalForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzScene::GetDown() const
|
||||||
|
{
|
||||||
|
#if NAZARA_GRAPHICS_SAFE
|
||||||
|
if (!m_impl->viewer)
|
||||||
|
{
|
||||||
|
NazaraError("No viewer");
|
||||||
|
return NzVector3f::Down();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -m_impl->viewer->GetGlobalUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzScene::GetForward() const
|
||||||
|
{
|
||||||
|
#if NAZARA_GRAPHICS_SAFE
|
||||||
|
if (!m_impl->viewer)
|
||||||
|
{
|
||||||
|
NazaraError("No viewer");
|
||||||
|
return NzVector3f::Forward();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_impl->viewer->GetGlobalForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzScene::GetLeft() const
|
||||||
|
{
|
||||||
|
#if NAZARA_GRAPHICS_SAFE
|
||||||
|
if (!m_impl->viewer)
|
||||||
|
{
|
||||||
|
NazaraError("No viewer");
|
||||||
|
return NzVector3f::Left();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -m_impl->viewer->GetGlobalRight();
|
||||||
|
}
|
||||||
|
|
||||||
NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const
|
NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const
|
||||||
{
|
{
|
||||||
if (!m_impl->renderTechnique)
|
if (!m_impl->renderTechnique)
|
||||||
|
|
@ -142,6 +194,19 @@ NzAbstractRenderTechnique* NzScene::GetRenderTechnique() const
|
||||||
return m_impl->renderTechnique.get();
|
return m_impl->renderTechnique.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzScene::GetRight() const
|
||||||
|
{
|
||||||
|
#if NAZARA_GRAPHICS_SAFE
|
||||||
|
if (!m_impl->viewer)
|
||||||
|
{
|
||||||
|
NazaraError("No viewer");
|
||||||
|
return NzVector3f::Right();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_impl->viewer->GetGlobalRight();
|
||||||
|
}
|
||||||
|
|
||||||
NzSceneNode& NzScene::GetRoot() const
|
NzSceneNode& NzScene::GetRoot() const
|
||||||
{
|
{
|
||||||
return m_impl->root;
|
return m_impl->root;
|
||||||
|
|
@ -152,6 +217,19 @@ NzAbstractViewer* NzScene::GetViewer() const
|
||||||
return m_impl->viewer;
|
return m_impl->viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzScene::GetUp() const
|
||||||
|
{
|
||||||
|
#if NAZARA_GRAPHICS_SAFE
|
||||||
|
if (!m_impl->viewer)
|
||||||
|
{
|
||||||
|
NazaraError("No viewer");
|
||||||
|
return NzVector3f::Up();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_impl->viewer->GetGlobalUp();
|
||||||
|
}
|
||||||
|
|
||||||
float NzScene::GetUpdateTime() const
|
float NzScene::GetUpdateTime() const
|
||||||
{
|
{
|
||||||
return m_impl->updateTime;
|
return m_impl->updateTime;
|
||||||
|
|
@ -197,7 +275,13 @@ void NzScene::SetRenderTechnique(NzAbstractRenderTechnique* renderTechnique)
|
||||||
|
|
||||||
void NzScene::SetViewer(NzAbstractViewer* viewer)
|
void NzScene::SetViewer(NzAbstractViewer* viewer)
|
||||||
{
|
{
|
||||||
m_impl->viewer = viewer;
|
if (m_impl->viewer != viewer)
|
||||||
|
{
|
||||||
|
m_impl->viewer = viewer;
|
||||||
|
|
||||||
|
// Invalidation de tous les nodes de la scène (utile pour la régénération des sommets dépendant du viewer)
|
||||||
|
m_impl->root.InvalidateNode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzScene::SetViewer(NzAbstractViewer& viewer)
|
void NzScene::SetViewer(NzAbstractViewer& viewer)
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,94 @@ void NzSceneNode::EnableDrawing(bool drawingEnabled)
|
||||||
m_drawingEnabled = drawingEnabled;
|
m_drawingEnabled = drawingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzSceneNode::GetBackward() const
|
||||||
|
{
|
||||||
|
if (m_scene)
|
||||||
|
{
|
||||||
|
if (!m_derivedUpdated)
|
||||||
|
UpdateDerived();
|
||||||
|
|
||||||
|
return m_derivedRotation * m_scene->GetBackward();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NzNode::GetBackward();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzSceneNode::GetDown() const
|
||||||
|
{
|
||||||
|
if (m_scene)
|
||||||
|
{
|
||||||
|
if (!m_derivedUpdated)
|
||||||
|
UpdateDerived();
|
||||||
|
|
||||||
|
return m_derivedRotation * m_scene->GetDown();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NzNode::GetDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzSceneNode::GetForward() const
|
||||||
|
{
|
||||||
|
if (m_scene)
|
||||||
|
{
|
||||||
|
if (!m_derivedUpdated)
|
||||||
|
UpdateDerived();
|
||||||
|
|
||||||
|
return m_derivedRotation * m_scene->GetForward();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NzNode::GetForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzSceneNode::GetLeft() const
|
||||||
|
{
|
||||||
|
if (m_scene)
|
||||||
|
{
|
||||||
|
if (!m_derivedUpdated)
|
||||||
|
UpdateDerived();
|
||||||
|
|
||||||
|
return m_derivedRotation * m_scene->GetLeft();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NzNode::GetLeft();
|
||||||
|
}
|
||||||
|
|
||||||
nzNodeType NzSceneNode::GetNodeType() const
|
nzNodeType NzSceneNode::GetNodeType() const
|
||||||
{
|
{
|
||||||
return nzNodeType_Scene;
|
return nzNodeType_Scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzSceneNode::GetRight() const
|
||||||
|
{
|
||||||
|
if (m_scene)
|
||||||
|
{
|
||||||
|
if (!m_derivedUpdated)
|
||||||
|
UpdateDerived();
|
||||||
|
|
||||||
|
return m_derivedRotation * m_scene->GetRight();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NzNode::GetRight();
|
||||||
|
}
|
||||||
|
|
||||||
NzScene* NzSceneNode::GetScene() const
|
NzScene* NzSceneNode::GetScene() const
|
||||||
{
|
{
|
||||||
return m_scene;
|
return m_scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzSceneNode::GetUp() const
|
||||||
|
{
|
||||||
|
if (m_scene)
|
||||||
|
{
|
||||||
|
if (!m_derivedUpdated)
|
||||||
|
UpdateDerived();
|
||||||
|
|
||||||
|
return m_derivedRotation * m_scene->GetUp();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NzNode::GetUp();
|
||||||
|
}
|
||||||
|
|
||||||
bool NzSceneNode::IsDrawingEnabled() const
|
bool NzSceneNode::IsDrawingEnabled() const
|
||||||
{
|
{
|
||||||
return m_drawingEnabled;
|
return m_drawingEnabled;
|
||||||
|
|
@ -62,17 +140,6 @@ NzSceneNode& NzSceneNode::operator=(const NzSceneNode& sceneNode)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzSceneNode& NzSceneNode::operator=(NzSceneNode&& sceneNode)
|
|
||||||
{
|
|
||||||
NzNode::operator=(sceneNode);
|
|
||||||
|
|
||||||
// La scène est affectée via le parenting du node
|
|
||||||
m_drawingEnabled = sceneNode.m_drawingEnabled;
|
|
||||||
m_visible = sceneNode.m_visible;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzSceneNode::FrustumCull(const NzFrustumf& frustum) const
|
bool NzSceneNode::FrustumCull(const NzFrustumf& frustum) const
|
||||||
{
|
{
|
||||||
return frustum.Contains(GetBoundingVolume());
|
return frustum.Contains(GetBoundingVolume());
|
||||||
|
|
@ -82,6 +149,7 @@ void NzSceneNode::OnParenting(const NzNode* parent)
|
||||||
{
|
{
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
|
///FIXME: Remonter jusqu'au premier parent de type SceneNode plutôt que de s'arrêter au premier venu
|
||||||
if (parent->GetNodeType() == nzNodeType_Scene)
|
if (parent->GetNodeType() == nzNodeType_Scene)
|
||||||
SetScene(static_cast<const NzSceneNode*>(parent)->m_scene);
|
SetScene(static_cast<const NzSceneNode*>(parent)->m_scene);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@ NzVertexBuffer* NzSkinningManager::GetBuffer(const NzSkeletalMesh* mesh, const N
|
||||||
{
|
{
|
||||||
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer);
|
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer);
|
||||||
vertexBuffer->SetPersistent(false);
|
vertexBuffer->SetPersistent(false);
|
||||||
vertexBuffer->Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), mesh->GetVertexCount(), nzBufferStorage_Hardware, nzBufferUsage_Dynamic);
|
vertexBuffer->Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), mesh->GetVertexCount(), nzDataStorage_Hardware, nzBufferUsage_Dynamic);
|
||||||
|
|
||||||
BufferData data({vertexBuffer.get(), true});
|
BufferData data({vertexBuffer.get(), true});
|
||||||
meshMap.insert(std::make_pair(mesh, data));
|
meshMap.insert(std::make_pair(mesh, data));
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace
|
||||||
{
|
{
|
||||||
NzIndexBuffer* BuildIndexBuffer()
|
NzIndexBuffer* BuildIndexBuffer()
|
||||||
{
|
{
|
||||||
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(false, 36, nzBufferStorage_Hardware, nzBufferUsage_Static));
|
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(false, 36, nzDataStorage_Hardware, nzBufferUsage_Static));
|
||||||
indexBuffer->SetPersistent(false);
|
indexBuffer->SetPersistent(false);
|
||||||
|
|
||||||
nzUInt16 indices[6*6] =
|
nzUInt16 indices[6*6] =
|
||||||
|
|
@ -155,7 +155,7 @@ namespace
|
||||||
|
|
||||||
NzVertexBuffer* BuildVertexBuffer()
|
NzVertexBuffer* BuildVertexBuffer()
|
||||||
{
|
{
|
||||||
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 8, nzBufferStorage_Hardware, nzBufferUsage_Static));
|
std::unique_ptr<NzVertexBuffer> vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 8, nzDataStorage_Hardware, nzBufferUsage_Static));
|
||||||
vertexBuffer->SetPersistent(false);
|
vertexBuffer->SetPersistent(false);
|
||||||
|
|
||||||
float vertices[8*(sizeof(float)*3)] =
|
float vertices[8*(sizeof(float)*3)] =
|
||||||
|
|
|
||||||
|
|
@ -3,39 +3,31 @@
|
||||||
// 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/Graphics/Sprite.hpp>
|
#include <Nazara/Graphics/Sprite.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
NzSprite::NzSprite() :
|
NzSprite::NzSprite() :
|
||||||
m_boundingVolume(NzBoundingVolumef::Null()),
|
m_boundingVolume(NzBoundingVolumef::Null()),
|
||||||
|
m_color(NzColor::White),
|
||||||
m_textureCoords(0.f, 0.f, 1.f, 1.f),
|
m_textureCoords(0.f, 0.f, 1.f, 1.f),
|
||||||
m_size(64.f, 64.f),
|
m_size(64.f, 64.f),
|
||||||
m_boundingVolumeUpdated(true)
|
m_boundingVolumeUpdated(true),
|
||||||
|
m_verticesUpdated(false)
|
||||||
{
|
{
|
||||||
|
SetDefaultMaterial();
|
||||||
}
|
}
|
||||||
|
|
||||||
NzSprite::NzSprite(NzTexture* texture) :
|
NzSprite::NzSprite(NzTexture* texture) :
|
||||||
m_boundingVolume(NzBoundingVolumef::Null()),
|
m_boundingVolume(NzBoundingVolumef::Null()),
|
||||||
m_textureCoords(0.f, 0.f, 1.f, 1.f)
|
m_color(NzColor::White),
|
||||||
|
m_textureCoords(0.f, 0.f, 1.f, 1.f),
|
||||||
|
m_size(64.f, 64.f),
|
||||||
|
m_boundingVolumeUpdated(false),
|
||||||
|
m_verticesUpdated(false)
|
||||||
{
|
{
|
||||||
if (texture)
|
SetTexture(texture, true);
|
||||||
{
|
|
||||||
m_material = new NzMaterial;
|
|
||||||
m_material->SetPersistent(false);
|
|
||||||
m_material->SetDiffuseMap(texture);
|
|
||||||
|
|
||||||
if (texture->IsValid())
|
|
||||||
m_size.Set(texture->GetWidth(), texture->GetHeight());
|
|
||||||
else
|
|
||||||
m_size.Set(64.f, 64.f);
|
|
||||||
|
|
||||||
m_boundingVolumeUpdated = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_size.Set(64.f, 64.f);
|
|
||||||
m_boundingVolumeUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzSprite::NzSprite(const NzSprite& sprite) :
|
NzSprite::NzSprite(const NzSprite& sprite) :
|
||||||
|
|
@ -44,32 +36,32 @@ m_boundingVolume(sprite.m_boundingVolume),
|
||||||
m_material(sprite.m_material),
|
m_material(sprite.m_material),
|
||||||
m_textureCoords(sprite.m_textureCoords),
|
m_textureCoords(sprite.m_textureCoords),
|
||||||
m_size(sprite.m_size),
|
m_size(sprite.m_size),
|
||||||
m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated)
|
m_vertices(sprite.m_vertices),
|
||||||
|
m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated),
|
||||||
|
m_verticesUpdated(sprite.m_verticesUpdated)
|
||||||
{
|
{
|
||||||
SetParent(sprite);
|
SetParent(sprite.GetParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
NzSprite::NzSprite(NzSprite&& sprite) :
|
|
||||||
NzSceneNode(sprite),
|
|
||||||
m_boundingVolume(sprite.m_boundingVolume),
|
|
||||||
m_material(std::move(sprite.m_material)),
|
|
||||||
m_textureCoords(sprite.m_textureCoords),
|
|
||||||
m_size(sprite.m_size),
|
|
||||||
m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NzSprite::~NzSprite() = default;
|
|
||||||
|
|
||||||
void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
void NzSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||||
{
|
{
|
||||||
renderQueue->AddSprite(this);
|
if (!m_verticesUpdated)
|
||||||
|
UpdateVertices();
|
||||||
|
|
||||||
|
renderQueue->AddSprites(m_material, m_vertices, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzBoundingVolumef& NzSprite::GetBoundingVolume() const
|
const NzBoundingVolumef& NzSprite::GetBoundingVolume() const
|
||||||
{
|
{
|
||||||
static NzBoundingVolumef infinity(NzBoundingVolumef::Infinite());
|
if (!m_boundingVolumeUpdated)
|
||||||
return infinity;
|
UpdateBoundingVolume();
|
||||||
|
|
||||||
|
return m_boundingVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzColor& NzSprite::GetColor() const
|
||||||
|
{
|
||||||
|
return m_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzMaterial* NzSprite::GetMaterial() const
|
NzMaterial* NzSprite::GetMaterial() const
|
||||||
|
|
@ -97,13 +89,33 @@ bool NzSprite::IsDrawable() const
|
||||||
return m_material != nullptr;
|
return m_material != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzSprite::SetColor(const NzColor& color)
|
||||||
|
{
|
||||||
|
m_color = color;
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzSprite::SetDefaultMaterial()
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzMaterial> material(new NzMaterial);
|
||||||
|
material->Enable(nzRendererParameter_FaceCulling, false);
|
||||||
|
material->EnableLighting(false);
|
||||||
|
|
||||||
|
SetMaterial(material.get());
|
||||||
|
|
||||||
|
material->SetPersistent(false);
|
||||||
|
material.release();
|
||||||
|
}
|
||||||
|
|
||||||
void NzSprite::SetMaterial(NzMaterial* material, bool resizeSprite)
|
void NzSprite::SetMaterial(NzMaterial* material, bool resizeSprite)
|
||||||
{
|
{
|
||||||
m_material = material;
|
m_material = material;
|
||||||
|
if (m_material && resizeSprite)
|
||||||
NzTexture* diffuseMap = m_material->GetDiffuseMap();
|
{
|
||||||
if (resizeSprite && diffuseMap && diffuseMap->IsValid())
|
NzTexture* diffuseMap = m_material->GetDiffuseMap();
|
||||||
SetSize(NzVector2f(diffuseMap->GetSize()));
|
if (diffuseMap && diffuseMap->IsValid())
|
||||||
|
SetSize(NzVector2f(NzVector2ui(diffuseMap->GetSize())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzSprite::SetSize(const NzVector2f& size)
|
void NzSprite::SetSize(const NzVector2f& size)
|
||||||
|
|
@ -113,6 +125,7 @@ void NzSprite::SetSize(const NzVector2f& size)
|
||||||
// On invalide la bounding box
|
// On invalide la bounding box
|
||||||
m_boundingVolume.MakeNull();
|
m_boundingVolume.MakeNull();
|
||||||
m_boundingVolumeUpdated = false;
|
m_boundingVolumeUpdated = false;
|
||||||
|
m_verticesUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzSprite::SetSize(float sizeX, float sizeY)
|
void NzSprite::SetSize(float sizeX, float sizeY)
|
||||||
|
|
@ -122,20 +135,23 @@ void NzSprite::SetSize(float sizeX, float sizeY)
|
||||||
|
|
||||||
void NzSprite::SetTexture(NzTexture* texture, bool resizeSprite)
|
void NzSprite::SetTexture(NzTexture* texture, bool resizeSprite)
|
||||||
{
|
{
|
||||||
std::unique_ptr<NzMaterial> material(new NzMaterial);
|
if (!m_material)
|
||||||
material->SetPersistent(false);
|
SetDefaultMaterial();
|
||||||
|
else if (m_material->GetResourceReferenceCount() > 1)
|
||||||
|
{
|
||||||
|
m_material = new NzMaterial(*m_material);
|
||||||
|
m_material->SetPersistent(false);
|
||||||
|
}
|
||||||
|
|
||||||
material->Enable(nzRendererParameter_FaceCulling, false);
|
m_material->SetDiffuseMap(texture);
|
||||||
material->EnableLighting(false);
|
if (resizeSprite && texture && texture->IsValid())
|
||||||
material->SetDiffuseMap(texture);
|
SetSize(NzVector2f(NzVector2ui(texture->GetSize())));
|
||||||
|
|
||||||
SetMaterial(material.get(), resizeSprite);
|
|
||||||
material.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzSprite::SetTextureCoords(const NzRectf& coords)
|
void NzSprite::SetTextureCoords(const NzRectf& coords)
|
||||||
{
|
{
|
||||||
m_textureCoords = coords;
|
m_textureCoords = coords;
|
||||||
|
m_verticesUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzSprite::SetTextureRect(const NzRectui& rect)
|
void NzSprite::SetTextureRect(const NzRectui& rect)
|
||||||
|
|
@ -162,15 +178,34 @@ void NzSprite::SetTextureRect(const NzRectui& rect)
|
||||||
SetTextureCoords(NzRectf(invWidth*rect.x, invHeight*rect.y, invWidth*rect.width, invHeight*rect.height));
|
SetTextureCoords(NzRectf(invWidth*rect.x, invHeight*rect.y, invWidth*rect.width, invHeight*rect.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzSprite& NzSprite::operator=(const NzSprite& sprite)
|
||||||
|
{
|
||||||
|
NzSceneNode::operator=(sprite);
|
||||||
|
|
||||||
|
m_color = sprite.m_color;
|
||||||
|
m_material = sprite.m_material;
|
||||||
|
m_textureCoords = sprite.m_textureCoords;
|
||||||
|
m_size = sprite.m_size;
|
||||||
|
|
||||||
|
// On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon
|
||||||
|
m_boundingVolumeUpdated = false;
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void NzSprite::InvalidateNode()
|
void NzSprite::InvalidateNode()
|
||||||
{
|
{
|
||||||
NzSceneNode::InvalidateNode();
|
NzSceneNode::InvalidateNode();
|
||||||
|
|
||||||
m_boundingVolumeUpdated = false;
|
m_boundingVolumeUpdated = false;
|
||||||
|
m_verticesUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzSprite::Register()
|
void NzSprite::Register()
|
||||||
{
|
{
|
||||||
|
// Le changement de scène peut affecter les sommets
|
||||||
|
m_verticesUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzSprite::Unregister()
|
void NzSprite::Unregister()
|
||||||
|
|
@ -180,7 +215,12 @@ void NzSprite::Unregister()
|
||||||
void NzSprite::UpdateBoundingVolume() const
|
void NzSprite::UpdateBoundingVolume() const
|
||||||
{
|
{
|
||||||
if (m_boundingVolume.IsNull())
|
if (m_boundingVolume.IsNull())
|
||||||
m_boundingVolume.Set(-m_size.x*0.5f, -m_size.y*0.5f, 0.f, m_size.x, m_size.y, 0.f);
|
{
|
||||||
|
NzVector3f down = m_scene->GetDown();
|
||||||
|
NzVector3f right = m_scene->GetRight();
|
||||||
|
|
||||||
|
m_boundingVolume.Set(NzVector3f(0.f), m_size.x*right + m_size.y*down);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_transformMatrixUpdated)
|
if (!m_transformMatrixUpdated)
|
||||||
UpdateTransformMatrix();
|
UpdateTransformMatrix();
|
||||||
|
|
@ -188,3 +228,30 @@ void NzSprite::UpdateBoundingVolume() const
|
||||||
m_boundingVolume.Update(m_transformMatrix);
|
m_boundingVolume.Update(m_transformMatrix);
|
||||||
m_boundingVolumeUpdated = true;
|
m_boundingVolumeUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzSprite::UpdateVertices() const
|
||||||
|
{
|
||||||
|
if (!m_transformMatrixUpdated)
|
||||||
|
UpdateTransformMatrix();
|
||||||
|
|
||||||
|
NzVector3f down = m_scene->GetDown();
|
||||||
|
NzVector3f right = m_scene->GetRight();
|
||||||
|
|
||||||
|
m_vertices[0].color = m_color;
|
||||||
|
m_vertices[0].position = m_transformMatrix.Transform(NzVector3f(0.f));
|
||||||
|
m_vertices[0].uv.Set(m_textureCoords.GetCorner(nzRectCorner_LeftTop));
|
||||||
|
|
||||||
|
m_vertices[1].color = m_color;
|
||||||
|
m_vertices[1].position = m_transformMatrix.Transform(m_size.x*right);
|
||||||
|
m_vertices[1].uv.Set(m_textureCoords.GetCorner(nzRectCorner_RightTop));
|
||||||
|
|
||||||
|
m_vertices[2].color = m_color;
|
||||||
|
m_vertices[2].position = m_transformMatrix.Transform(m_size.y*down);
|
||||||
|
m_vertices[2].uv.Set(m_textureCoords.GetCorner(nzRectCorner_LeftBottom));
|
||||||
|
|
||||||
|
m_vertices[3].color = m_color;
|
||||||
|
m_vertices[3].position = m_transformMatrix.Transform(m_size.x*right + m_size.y*down);
|
||||||
|
m_vertices[3].uv.Set(m_textureCoords.GetCorner(nzRectCorner_RightBottom));
|
||||||
|
|
||||||
|
m_verticesUpdated = true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,407 @@
|
||||||
|
// Copyright (C) 2014 Jérôme Leclercq
|
||||||
|
// 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/TextSprite.hpp>
|
||||||
|
#include <Nazara/Core/SparsePtr.hpp>
|
||||||
|
#include <Nazara/Graphics/AbstractViewer.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <Nazara/Utility/Font.hpp>
|
||||||
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
///TODO: Gérer allocation nouvel atlas
|
||||||
|
|
||||||
|
NzTextSprite::NzTextSprite() :
|
||||||
|
m_boundingVolume(NzBoundingVolumef::Null()),
|
||||||
|
m_color(NzColor::White),
|
||||||
|
m_verticesUpdated(false)
|
||||||
|
{
|
||||||
|
SetDefaultMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzTextSprite::NzTextSprite(const NzTextSprite& sprite) :
|
||||||
|
NzSceneNode(sprite),
|
||||||
|
m_atlases(sprite.m_atlases),
|
||||||
|
m_renderInfos(sprite.m_renderInfos),
|
||||||
|
m_localVertices(sprite.m_localVertices),
|
||||||
|
m_vertices(sprite.m_vertices),
|
||||||
|
m_boundingVolume(sprite.m_boundingVolume),
|
||||||
|
m_color(sprite.m_color),
|
||||||
|
m_material(sprite.m_material),
|
||||||
|
m_localBounds(sprite.m_localBounds),
|
||||||
|
m_boundingVolumeUpdated(sprite.m_boundingVolumeUpdated),
|
||||||
|
m_verticesUpdated(sprite.m_verticesUpdated)
|
||||||
|
{
|
||||||
|
SetParent(sprite.GetParent());
|
||||||
|
|
||||||
|
for (const NzAbstractAtlas* atlas : m_atlases)
|
||||||
|
atlas->AddListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzTextSprite::~NzTextSprite()
|
||||||
|
{
|
||||||
|
ClearAtlases();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
||||||
|
{
|
||||||
|
if (!m_verticesUpdated)
|
||||||
|
UpdateVertices();
|
||||||
|
|
||||||
|
for (auto& pair : m_renderInfos)
|
||||||
|
{
|
||||||
|
NzTexture* overlay = pair.first;
|
||||||
|
RenderIndices& indices = pair.second;
|
||||||
|
|
||||||
|
if (indices.count > 0)
|
||||||
|
renderQueue->AddSprites(m_material, &m_vertices[indices.first*4], indices.count, overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::Clear()
|
||||||
|
{
|
||||||
|
ClearAtlases();
|
||||||
|
m_boundingVolume.MakeNull();
|
||||||
|
m_localVertices.clear();
|
||||||
|
m_renderInfos.clear();
|
||||||
|
m_vertices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzBoundingVolumef& NzTextSprite::GetBoundingVolume() const
|
||||||
|
{
|
||||||
|
if (!m_boundingVolumeUpdated)
|
||||||
|
UpdateBoundingVolume();
|
||||||
|
|
||||||
|
return m_boundingVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzColor& NzTextSprite::GetColor() const
|
||||||
|
{
|
||||||
|
return m_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzMaterial* NzTextSprite::GetMaterial() const
|
||||||
|
{
|
||||||
|
return m_material;
|
||||||
|
}
|
||||||
|
|
||||||
|
nzSceneNodeType NzTextSprite::GetSceneNodeType() const
|
||||||
|
{
|
||||||
|
return nzSceneNodeType_TextSprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::InvalidateVertices()
|
||||||
|
{
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzTextSprite::IsDrawable() const
|
||||||
|
{
|
||||||
|
return m_material != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::SetColor(const NzColor& color)
|
||||||
|
{
|
||||||
|
m_color = color;
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::SetDefaultMaterial()
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzMaterial> material(new NzMaterial);
|
||||||
|
material->Enable(nzRendererParameter_Blend, true);
|
||||||
|
material->Enable(nzRendererParameter_DepthWrite, false);
|
||||||
|
material->Enable(nzRendererParameter_FaceCulling, false);
|
||||||
|
material->EnableLighting(false);
|
||||||
|
material->SetDstBlend(nzBlendFunc_InvSrcAlpha);
|
||||||
|
material->SetSrcBlend(nzBlendFunc_SrcAlpha);
|
||||||
|
|
||||||
|
SetMaterial(material.get());
|
||||||
|
|
||||||
|
material->SetPersistent(false);
|
||||||
|
material.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::SetMaterial(NzMaterial* material)
|
||||||
|
{
|
||||||
|
m_material = material;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::SetText(const NzAbstractTextDrawer& drawer)
|
||||||
|
{
|
||||||
|
ClearAtlases();
|
||||||
|
|
||||||
|
unsigned int fontCount = drawer.GetFontCount();
|
||||||
|
for (unsigned int i = 0; i < fontCount; ++i)
|
||||||
|
{
|
||||||
|
const NzAbstractAtlas* atlas = drawer.GetFont(i)->GetAtlas();
|
||||||
|
if (m_atlases.insert(atlas).second)
|
||||||
|
atlas->AddListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int glyphCount = drawer.GetGlyphCount();
|
||||||
|
m_localVertices.resize(glyphCount * 4);
|
||||||
|
m_vertices.resize(glyphCount * 4);
|
||||||
|
|
||||||
|
NzTexture* lastTexture = nullptr;
|
||||||
|
unsigned int* count = nullptr;
|
||||||
|
for (unsigned int i = 0; i < glyphCount; ++i)
|
||||||
|
{
|
||||||
|
const NzAbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i);
|
||||||
|
|
||||||
|
NzTexture* texture = static_cast<NzTexture*>(glyph.atlas);
|
||||||
|
if (lastTexture != texture)
|
||||||
|
{
|
||||||
|
auto pair = m_renderInfos.insert(std::make_pair(texture, RenderIndices{0U, 0U}));
|
||||||
|
|
||||||
|
count = &pair.first->second.count;
|
||||||
|
lastTexture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*count)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attribution des indices
|
||||||
|
unsigned int index = 0;
|
||||||
|
for (auto& pair : m_renderInfos)
|
||||||
|
{
|
||||||
|
RenderIndices& indices = pair.second;
|
||||||
|
|
||||||
|
indices.first = index;
|
||||||
|
|
||||||
|
index += indices.count;
|
||||||
|
indices.count = 0; // On réinitialise count à zéro (on va s'en servir pour compteur dans la boucle suivante)
|
||||||
|
}
|
||||||
|
|
||||||
|
NzSparsePtr<NzVector2f> texCoordPtr(&m_vertices[0].uv, sizeof(NzVertexStruct_XYZ_Color_UV));
|
||||||
|
|
||||||
|
lastTexture = nullptr;
|
||||||
|
RenderIndices* indices = nullptr;
|
||||||
|
for (unsigned int i = 0; i < glyphCount; ++i)
|
||||||
|
{
|
||||||
|
const NzAbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i);
|
||||||
|
|
||||||
|
NzTexture* texture = static_cast<NzTexture*>(glyph.atlas);
|
||||||
|
if (lastTexture != texture)
|
||||||
|
{
|
||||||
|
indices = &m_renderInfos[texture]; // On a changé de texture, on ajuste le pointeur
|
||||||
|
lastTexture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affectation des positions et couleurs (locaux)
|
||||||
|
for (unsigned int j = 0; j < 4; ++j)
|
||||||
|
{
|
||||||
|
m_localVertices[i*4 + j].color = glyph.color;
|
||||||
|
m_localVertices[i*4 + j].position.Set(glyph.corners[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcul des coordonnées de texture (globaux)
|
||||||
|
|
||||||
|
// On commence par transformer les coordonnées entières en flottantes:
|
||||||
|
NzVector2ui size(texture->GetSize());
|
||||||
|
float invWidth = 1.f/size.x;
|
||||||
|
float invHeight = 1.f/size.y;
|
||||||
|
|
||||||
|
NzRectf uvRect(glyph.atlasRect);
|
||||||
|
uvRect.x *= invWidth;
|
||||||
|
uvRect.y *= invHeight;
|
||||||
|
uvRect.width *= invWidth;
|
||||||
|
uvRect.height *= invHeight;
|
||||||
|
|
||||||
|
// Extraction des quatre coins et attribution
|
||||||
|
NzSparsePtr<NzVector2f> texCoord = texCoordPtr + indices->first*4 + indices->count*4;
|
||||||
|
if (!glyph.flipped)
|
||||||
|
{
|
||||||
|
// Le glyphe n'est pas retourné, l'ordre des UV suit celui des sommets
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_LeftTop);
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_RightTop);
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_LeftBottom);
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_RightBottom);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Le glyphe a subit une rotation de 90° (sens antihoraire), on adapte les UV en conséquence
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_LeftBottom);
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_LeftTop);
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_RightBottom);
|
||||||
|
*texCoord++ = uvRect.GetCorner(nzRectCorner_RightTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Et on passe au prochain
|
||||||
|
indices->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_localBounds = drawer.GetBounds();
|
||||||
|
m_boundingVolume.MakeNull();
|
||||||
|
m_boundingVolumeUpdated = false;
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzTextSprite& NzTextSprite::operator=(const NzTextSprite& text)
|
||||||
|
{
|
||||||
|
NzSceneNode::operator=(text);
|
||||||
|
|
||||||
|
m_atlases = text.m_atlases;
|
||||||
|
m_color = text.m_color;
|
||||||
|
m_material = text.m_material;
|
||||||
|
m_renderInfos = text.m_renderInfos;
|
||||||
|
m_localBounds = text.m_localBounds;
|
||||||
|
m_localVertices = text.m_localVertices;
|
||||||
|
|
||||||
|
// On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon
|
||||||
|
m_boundingVolumeUpdated = false;
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::ClearAtlases()
|
||||||
|
{
|
||||||
|
for (const NzAbstractAtlas* atlas : m_atlases)
|
||||||
|
atlas->RemoveListener(this);
|
||||||
|
|
||||||
|
m_atlases.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::InvalidateNode()
|
||||||
|
{
|
||||||
|
NzSceneNode::InvalidateNode();
|
||||||
|
|
||||||
|
m_boundingVolumeUpdated = false;
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzTextSprite::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (m_atlases.find(atlas) == m_atlases.end())
|
||||||
|
{
|
||||||
|
NazaraInternalError("Not listening to " + NzString::Pointer(atlas));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " that was under use has been cleared");
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (m_atlases.find(atlas) == m_atlases.end())
|
||||||
|
{
|
||||||
|
NazaraInternalError("Not listening to " + NzString::Pointer(atlas));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NzTexture* oldTexture = static_cast<NzTexture*>(oldLayer);
|
||||||
|
NzTexture* newTexture = static_cast<NzTexture*>(newLayer);
|
||||||
|
|
||||||
|
auto it = m_renderInfos.find(oldTexture);
|
||||||
|
if (it != m_renderInfos.end())
|
||||||
|
{
|
||||||
|
// Nous utilisons bien cette texture, nous devons mettre à jour les coordonnées de texture
|
||||||
|
RenderIndices indices = std::move(it->second);
|
||||||
|
|
||||||
|
NzVector2ui oldSize(oldTexture->GetSize());
|
||||||
|
NzVector2ui newSize(newTexture->GetSize());
|
||||||
|
NzVector2f scale = NzVector2f(oldSize)/NzVector2f(newSize);
|
||||||
|
|
||||||
|
NzSparsePtr<NzVector2f> texCoordPtr(&m_vertices[indices.first].uv, sizeof(NzVertexStruct_XYZ_Color_UV));
|
||||||
|
for (unsigned int i = 0; i < indices.count; ++i)
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < 4; ++j)
|
||||||
|
texCoordPtr[i*4 + j] *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nous enlevons l'ancienne texture et rajoutons la nouvelle à sa place (pour les mêmes indices)
|
||||||
|
m_renderInfos.erase(it);
|
||||||
|
m_renderInfos.insert(std::make_pair(newTexture, std::move(indices)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (m_atlases.find(atlas) == m_atlases.end())
|
||||||
|
{
|
||||||
|
NazaraInternalError("Not listening to " + NzString::Pointer(atlas));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " that was under use has been released");
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::Register()
|
||||||
|
{
|
||||||
|
// Le changement de scène peut affecter les sommets
|
||||||
|
m_verticesUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::Unregister()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::UpdateBoundingVolume() const
|
||||||
|
{
|
||||||
|
if (m_boundingVolume.IsNull())
|
||||||
|
{
|
||||||
|
NzVector3f down = m_scene->GetDown();
|
||||||
|
NzVector3f right = m_scene->GetRight();
|
||||||
|
|
||||||
|
m_boundingVolume.Set(NzVector3f(0.f), static_cast<float>(m_localBounds.width)*right + static_cast<float>(m_localBounds.height)*down);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_transformMatrixUpdated)
|
||||||
|
UpdateTransformMatrix();
|
||||||
|
|
||||||
|
m_boundingVolume.Update(m_transformMatrix);
|
||||||
|
m_boundingVolumeUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzTextSprite::UpdateVertices() const
|
||||||
|
{
|
||||||
|
if (!m_transformMatrixUpdated)
|
||||||
|
UpdateTransformMatrix();
|
||||||
|
|
||||||
|
NzVector3f down = m_scene->GetDown();
|
||||||
|
NzVector3f right = m_scene->GetRight();
|
||||||
|
|
||||||
|
NzSparsePtr<NzColor> colorPtr(&m_vertices[0].color, sizeof(NzVertexStruct_XYZ_Color_UV));
|
||||||
|
NzSparsePtr<NzVector3f> posPtr(&m_vertices[0].position, sizeof(NzVertexStruct_XYZ_Color_UV));
|
||||||
|
|
||||||
|
for (auto& pair : m_renderInfos)
|
||||||
|
{
|
||||||
|
RenderIndices& indices = pair.second;
|
||||||
|
|
||||||
|
NzSparsePtr<NzColor> color = colorPtr + indices.first*4;
|
||||||
|
NzSparsePtr<NzVector3f> pos = posPtr + indices.first*4;
|
||||||
|
NzVertexStruct_XY_Color* localVertex = &m_localVertices[indices.first*4];
|
||||||
|
for (unsigned int i = 0; i < indices.count; ++i)
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < 4; ++j)
|
||||||
|
{
|
||||||
|
*pos++ = m_transformMatrix.Transform(localVertex->position.x*right + localVertex->position.y*down);
|
||||||
|
*color++ = m_color * localVertex->color;
|
||||||
|
|
||||||
|
localVertex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_verticesUpdated = true;
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,7 @@ m_zNear(-1.f)
|
||||||
NzView::NzView(const NzVector2f& size) :
|
NzView::NzView(const NzVector2f& size) :
|
||||||
NzView() // On délègue
|
NzView() // On délègue
|
||||||
{
|
{
|
||||||
m_size = size;
|
SetSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzView::~NzView()
|
NzView::~NzView()
|
||||||
|
|
@ -80,6 +80,21 @@ const NzFrustumf& NzView::GetFrustum() const
|
||||||
return m_frustum;
|
return m_frustum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzVector3f NzView::GetGlobalForward() const
|
||||||
|
{
|
||||||
|
return NzVector3f::UnitZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzView::GetGlobalRight() const
|
||||||
|
{
|
||||||
|
return NzVector3f::UnitX();
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3f NzView::GetGlobalUp() const
|
||||||
|
{
|
||||||
|
return -NzVector3f::UnitY();
|
||||||
|
}
|
||||||
|
|
||||||
const NzMatrix4f& NzView::GetProjectionMatrix() const
|
const NzMatrix4f& NzView::GetProjectionMatrix() const
|
||||||
{
|
{
|
||||||
if (!m_projectionMatrixUpdated)
|
if (!m_projectionMatrixUpdated)
|
||||||
|
|
@ -132,6 +147,17 @@ float NzView::GetZNear() const
|
||||||
return m_zNear;
|
return m_zNear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzView::SetSize(const NzVector2f& size)
|
||||||
|
{
|
||||||
|
SetSize(size.x, size.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzView::SetSize(float width, float height)
|
||||||
|
{
|
||||||
|
m_size.Set(width, height);
|
||||||
|
m_projectionMatrixUpdated = false;
|
||||||
|
}
|
||||||
|
|
||||||
void NzView::SetTarget(const NzRenderTarget* renderTarget)
|
void NzView::SetTarget(const NzRenderTarget* renderTarget)
|
||||||
{
|
{
|
||||||
if (m_target)
|
if (m_target)
|
||||||
|
|
|
||||||
|
|
@ -159,64 +159,64 @@ void NzDebugDrawer::Draw(const NzFrustumf& frustum)
|
||||||
NzBufferMapper<NzVertexBuffer> mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24);
|
NzBufferMapper<NzVertexBuffer> mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24);
|
||||||
NzVertexStruct_XYZ* vertex = reinterpret_cast<NzVertexStruct_XYZ*>(mapper.GetPointer());
|
NzVertexStruct_XYZ* vertex = reinterpret_cast<NzVertexStruct_XYZ*>(mapper.GetPointer());
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearLeftTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarLeftTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightTop));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_NearRightBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_NearRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(frustum.GetCorner(nzCorner_FarRightBottom));
|
vertex->position.Set(frustum.GetCorner(nzBoxCorner_FarRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
mapper.Unmap();
|
mapper.Unmap();
|
||||||
|
|
@ -241,64 +241,64 @@ void NzDebugDrawer::Draw(const NzOrientedBoxf& orientedBox)
|
||||||
NzBufferMapper<NzVertexBuffer> mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24);
|
NzBufferMapper<NzVertexBuffer> mapper(s_vertexBuffer, nzBufferAccess_DiscardAndWrite, 0, 24);
|
||||||
NzVertexStruct_XYZ* vertex = reinterpret_cast<NzVertexStruct_XYZ*>(mapper.GetPointer());
|
NzVertexStruct_XYZ* vertex = reinterpret_cast<NzVertexStruct_XYZ*>(mapper.GetPointer());
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearLeftTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarLeftTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarLeftTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightTop));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightTop));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_NearRightBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_NearRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
vertex->position.Set(orientedBox.GetCorner(nzCorner_FarRightBottom));
|
vertex->position.Set(orientedBox.GetCorner(nzBoxCorner_FarRightBottom));
|
||||||
vertex++;
|
vertex++;
|
||||||
|
|
||||||
mapper.Unmap();
|
mapper.Unmap();
|
||||||
|
|
@ -363,6 +363,11 @@ void NzDebugDrawer::Draw(const NzSkeleton* skeleton)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzDebugDrawer::Draw(const NzVector3f& position, float size)
|
||||||
|
{
|
||||||
|
Draw(NzBoxf(position.x - size*0.5f, position.y - size*0.5f, position.z - size*0.5f, size, size, size));
|
||||||
|
}
|
||||||
|
|
||||||
void NzDebugDrawer::DrawBinormals(const NzStaticMesh* subMesh)
|
void NzDebugDrawer::DrawBinormals(const NzStaticMesh* subMesh)
|
||||||
{
|
{
|
||||||
if (!Initialize())
|
if (!Initialize())
|
||||||
|
|
@ -662,7 +667,7 @@ bool NzDebugDrawer::Initialize()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||||
s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzBufferStorage_Hardware, nzBufferUsage_Dynamic);
|
s_vertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 65365, nzDataStorage_Hardware, nzBufferUsage_Dynamic);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1463,8 +1463,42 @@ void NzOpenGL::SetViewport(const NzRecti& viewport)
|
||||||
|
|
||||||
bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType type)
|
bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType type)
|
||||||
{
|
{
|
||||||
|
// Par défaut
|
||||||
|
format->swizzle[0] = GL_RED;
|
||||||
|
format->swizzle[1] = GL_GREEN;
|
||||||
|
format->swizzle[2] = GL_BLUE;
|
||||||
|
format->swizzle[3] = GL_ALPHA;
|
||||||
|
|
||||||
switch (pixelFormat)
|
switch (pixelFormat)
|
||||||
{
|
{
|
||||||
|
case nzPixelFormat_A8:
|
||||||
|
if (type == FormatType_Texture) // Format supporté uniquement par les textures
|
||||||
|
{
|
||||||
|
if (GetVersion() >= 300)
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_RED;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_R8;
|
||||||
|
|
||||||
|
// Simulation du format
|
||||||
|
format->swizzle[0] = GL_ONE;
|
||||||
|
format->swizzle[1] = GL_ONE;
|
||||||
|
format->swizzle[2] = GL_ONE;
|
||||||
|
format->swizzle[3] = GL_RED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Le bon vieux format GL_ALPHA
|
||||||
|
format->dataFormat = GL_ALPHA;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
case nzPixelFormat_BGR8:
|
case nzPixelFormat_BGR8:
|
||||||
format->dataFormat = GL_BGR;
|
format->dataFormat = GL_BGR;
|
||||||
format->dataType = GL_UNSIGNED_BYTE;
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
|
@ -1496,8 +1530,58 @@ bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, Format
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case nzPixelFormat_L8:
|
case nzPixelFormat_L8:
|
||||||
|
if (type == FormatType_Texture) // Format supporté uniquement par les textures
|
||||||
|
{
|
||||||
|
if (GetVersion() >= 300)
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_RED;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_R8;
|
||||||
|
|
||||||
|
// Simulation du format
|
||||||
|
format->swizzle[0] = GL_RED;
|
||||||
|
format->swizzle[1] = GL_RED;
|
||||||
|
format->swizzle[2] = GL_RED;
|
||||||
|
format->swizzle[3] = GL_ONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format->dataFormat = 0x1909; // GL_LUMINANCE
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = 0x1909; // GL_LUMINANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
case nzPixelFormat_LA8:
|
case nzPixelFormat_LA8:
|
||||||
return false;
|
if (type == FormatType_Texture) // Format supporté uniquement par les textures
|
||||||
|
{
|
||||||
|
if (GetVersion() >= 300)
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_RG;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_RG8;
|
||||||
|
|
||||||
|
// Simulation du format
|
||||||
|
format->swizzle[0] = GL_RED;
|
||||||
|
format->swizzle[1] = GL_RED;
|
||||||
|
format->swizzle[2] = GL_RED;
|
||||||
|
format->swizzle[3] = GL_GREEN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format->dataFormat = 0x190A; // GL_LUMINANCE_ALPHA
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = 0x190A; // GL_LUMINANCE_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
case nzPixelFormat_R8:
|
case nzPixelFormat_R8:
|
||||||
format->dataFormat = GL_RED;
|
format->dataFormat = GL_RED;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <Nazara/Renderer/RenderBuffer.hpp>
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ namespace
|
||||||
bool s_useVertexArrayObjects;
|
bool s_useVertexArrayObjects;
|
||||||
unsigned int s_maxColorAttachments;
|
unsigned int s_maxColorAttachments;
|
||||||
unsigned int s_maxRenderTarget;
|
unsigned int s_maxRenderTarget;
|
||||||
|
unsigned int s_maxTextureSize;
|
||||||
unsigned int s_maxTextureUnit;
|
unsigned int s_maxTextureUnit;
|
||||||
unsigned int s_maxVertexAttribs;
|
unsigned int s_maxVertexAttribs;
|
||||||
|
|
||||||
|
|
@ -612,6 +613,11 @@ unsigned int NzRenderer::GetMaxRenderTargets()
|
||||||
return s_maxRenderTarget;
|
return s_maxRenderTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int NzRenderer::GetMaxTextureSize()
|
||||||
|
{
|
||||||
|
return s_maxTextureSize;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int NzRenderer::GetMaxTextureUnits()
|
unsigned int NzRenderer::GetMaxTextureUnits()
|
||||||
{
|
{
|
||||||
return s_maxTextureUnit;
|
return s_maxTextureUnit;
|
||||||
|
|
@ -692,7 +698,10 @@ bool NzRenderer::Initialize()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer* { return new NzHardwareBuffer(parent, type); } );
|
NzBuffer::SetBufferFactory(nzDataStorage_Hardware, [](NzBuffer* parent, nzBufferType type) -> NzAbstractBuffer*
|
||||||
|
{
|
||||||
|
return new NzHardwareBuffer(parent, type);
|
||||||
|
});
|
||||||
|
|
||||||
for (unsigned int i = 0; i <= nzMatrixType_Max; ++i)
|
for (unsigned int i = 0; i <= nzMatrixType_Max; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -703,19 +712,19 @@ bool NzRenderer::Initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupération des capacités d'OpenGL
|
// Récupération des capacités d'OpenGL
|
||||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||||
s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender);
|
s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender);
|
||||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||||
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
||||||
s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray);
|
s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray);
|
||||||
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr); // Natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation
|
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr); // Natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation
|
||||||
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
||||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
||||||
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
||||||
s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2
|
s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2
|
||||||
s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||||
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||||
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||||
|
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
|
|
@ -759,6 +768,10 @@ bool NzRenderer::Initialize()
|
||||||
else
|
else
|
||||||
s_maxTextureUnit = 1;
|
s_maxTextureUnit = 1;
|
||||||
|
|
||||||
|
GLint maxTextureSize;
|
||||||
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||||
|
s_maxTextureSize = maxTextureSize;
|
||||||
|
|
||||||
GLint maxVertexAttribs;
|
GLint maxVertexAttribs;
|
||||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
|
||||||
s_maxVertexAttribs = static_cast<unsigned int>(maxVertexAttribs);
|
s_maxVertexAttribs = static_cast<unsigned int>(maxVertexAttribs);
|
||||||
|
|
@ -775,7 +788,7 @@ bool NzRenderer::Initialize()
|
||||||
s_updateFlags = Update_Matrices | Update_Shader | Update_VAO;
|
s_updateFlags = Update_Matrices | Update_Shader | Update_VAO;
|
||||||
s_vertexBuffer = nullptr;
|
s_vertexBuffer = nullptr;
|
||||||
|
|
||||||
s_fullscreenQuadBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzBufferStorage_Hardware, nzBufferUsage_Static);
|
s_fullscreenQuadBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzDataStorage_Hardware, nzBufferUsage_Static);
|
||||||
|
|
||||||
float vertices[4*2] =
|
float vertices[4*2] =
|
||||||
{
|
{
|
||||||
|
|
@ -796,7 +809,7 @@ bool NzRenderer::Initialize()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NzErrorFlags errFlags(nzErrorFlag_ThrowException, true);
|
NzErrorFlags errFlags(nzErrorFlag_ThrowException, true);
|
||||||
s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, nzBufferStorage_Hardware, nzBufferUsage_Dynamic);
|
s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, nzDataStorage_Hardware, nzBufferUsage_Dynamic);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -1963,7 +1976,8 @@ void NzRenderer::OnTextureReleased(const NzTexture* texture)
|
||||||
{
|
{
|
||||||
if (unit.texture == texture)
|
if (unit.texture == texture)
|
||||||
unit.texture = nullptr;
|
unit.texture = nullptr;
|
||||||
// Inutile de changer le flag pour une texture désactivée
|
|
||||||
|
// Inutile de changer le flag pour une texture désactivée
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,17 @@
|
||||||
// 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/Renderer/Texture.hpp>
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <Nazara/Renderer/Context.hpp>
|
#include <Nazara/Renderer/Context.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
///TODO: Virer les méthodes faisant référence aux faces et gérer ces dernières comme de simples niveaux de profondeurs (malgré OpenGL)
|
|
||||||
|
|
||||||
struct NzTextureImpl
|
struct NzTextureImpl
|
||||||
{
|
{
|
||||||
GLuint id;
|
GLuint id;
|
||||||
|
|
@ -28,112 +29,10 @@ struct NzTextureImpl
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool CreateTexture(NzTextureImpl* impl, bool proxy)
|
inline unsigned int GetLevelSize(unsigned int size, nzUInt8 level)
|
||||||
{
|
{
|
||||||
NzOpenGL::Format openGLFormat;
|
// Contrairement à la classe Image, un appel à GetLevelSize(0, level) n'est pas possible
|
||||||
if (!NzOpenGL::TranslateFormat(impl->format, &openGLFormat, NzOpenGL::FormatType_Texture))
|
return std::max(size >> level, 1U);
|
||||||
{
|
|
||||||
NazaraError("Format " + NzPixelFormat::ToString(impl->format) + " not supported by OpenGL");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type];
|
|
||||||
switch (impl->type)
|
|
||||||
{
|
|
||||||
case nzImageType_1D:
|
|
||||||
{
|
|
||||||
if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy
|
|
||||||
glTexStorage1D(target, impl->levelCount, openGLFormat.internalFormat, impl->width);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int w = impl->width;
|
|
||||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
|
||||||
{
|
|
||||||
glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
|
||||||
if (w > 1U)
|
|
||||||
w >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case nzImageType_1D_Array:
|
|
||||||
case nzImageType_2D:
|
|
||||||
{
|
|
||||||
if (glTexStorage2D && !proxy)
|
|
||||||
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int w = impl->width;
|
|
||||||
unsigned int h = impl->height;
|
|
||||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
|
||||||
{
|
|
||||||
glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
|
||||||
if (w > 1U)
|
|
||||||
w >>= 1;
|
|
||||||
|
|
||||||
if (h > 1U)
|
|
||||||
h >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case nzImageType_2D_Array:
|
|
||||||
case nzImageType_3D:
|
|
||||||
{
|
|
||||||
if (glTexStorage3D && !proxy)
|
|
||||||
glTexStorage3D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height, impl->depth);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int w = impl->width;
|
|
||||||
unsigned int h = impl->height;
|
|
||||||
unsigned int d = impl->depth;
|
|
||||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
|
||||||
{
|
|
||||||
glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
|
||||||
if (w > 1U)
|
|
||||||
w >>= 1;
|
|
||||||
|
|
||||||
if (h > 1U)
|
|
||||||
h >>= 1;
|
|
||||||
|
|
||||||
if (d > 1U)
|
|
||||||
d >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
|
||||||
{
|
|
||||||
if (glTexStorage2D && !proxy)
|
|
||||||
glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
|
||||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
|
||||||
{
|
|
||||||
for (GLenum face : NzOpenGL::CubemapFace)
|
|
||||||
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
|
||||||
|
|
||||||
if (size > 1U)
|
|
||||||
size >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proxy)
|
|
||||||
{
|
|
||||||
GLint internalFormat = 0;
|
|
||||||
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
|
|
||||||
if (internalFormat == 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetUnpackAlignement(nzUInt8 bpp)
|
inline void SetUnpackAlignement(nzUInt8 bpp)
|
||||||
|
|
@ -149,17 +48,16 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzTexture::NzTexture(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
|
||||||
|
{
|
||||||
|
NzErrorFlags flags(nzErrorFlag_ThrowException);
|
||||||
|
Create(type, format, width, height, depth, levelCount);
|
||||||
|
}
|
||||||
|
|
||||||
NzTexture::NzTexture(const NzImage& image)
|
NzTexture::NzTexture(const NzImage& image)
|
||||||
{
|
{
|
||||||
|
NzErrorFlags flags(nzErrorFlag_ThrowException);
|
||||||
LoadFromImage(image);
|
LoadFromImage(image);
|
||||||
|
|
||||||
#ifdef NAZARA_DEBUG
|
|
||||||
if (!m_impl)
|
|
||||||
{
|
|
||||||
NazaraError("Failed to create texture");
|
|
||||||
throw std::runtime_error("Constructor failed");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzTexture::~NzTexture()
|
NzTexture::~NzTexture()
|
||||||
|
|
@ -220,7 +118,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||||
|
|
||||||
if (depth > 1)
|
if (depth > 1)
|
||||||
{
|
{
|
||||||
NazaraError("1D textures must be 1 depth");
|
NazaraError("1D textures must be 1 deep");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -229,7 +127,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||||
case nzImageType_2D:
|
case nzImageType_2D:
|
||||||
if (depth > 1)
|
if (depth > 1)
|
||||||
{
|
{
|
||||||
NazaraError("2D textures must be 1 depth");
|
NazaraError("2D textures must be 1 deep");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -241,7 +139,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||||
case nzImageType_Cubemap:
|
case nzImageType_Cubemap:
|
||||||
if (depth > 1)
|
if (depth > 1)
|
||||||
{
|
{
|
||||||
NazaraError("Cubemaps must be 1 depth");
|
NazaraError("Cubemaps must be 1 deep");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,40 +162,44 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||||
levelCount = 1;
|
levelCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<NzTextureImpl> impl(new NzTextureImpl);
|
m_impl = new NzTextureImpl;
|
||||||
glGenTextures(1, &impl->id);
|
m_impl->depth = GetValidSize(depth);
|
||||||
|
m_impl->format = format;
|
||||||
|
m_impl->height = GetValidSize(height);
|
||||||
|
m_impl->levelCount = levelCount;
|
||||||
|
m_impl->type = type;
|
||||||
|
m_impl->width = GetValidSize(width);
|
||||||
|
|
||||||
impl->depth = GetValidSize(depth);
|
glGenTextures(1, &m_impl->id);
|
||||||
impl->format = format;
|
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
||||||
impl->height = GetValidSize(height);
|
|
||||||
impl->levelCount = levelCount;
|
|
||||||
impl->type = type;
|
|
||||||
impl->width = GetValidSize(width);
|
|
||||||
|
|
||||||
NzOpenGL::BindTexture(impl->type, impl->id);
|
// En cas d'erreur (sortie prématurée), on détruit la texture
|
||||||
|
NzCallOnExit onExit([this]()
|
||||||
// Vérification du support par la carte graphique
|
|
||||||
if (!CreateTexture(impl.get(), true))
|
|
||||||
{
|
{
|
||||||
NzOpenGL::DeleteTexture(m_impl->id);
|
Destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// On précise le nombre de mipmaps avant la spécification de la texture
|
||||||
|
// https://www.opengl.org/wiki/Hardware_specifics:_NVidia
|
||||||
|
SetMipmapRange(0, m_impl->levelCount-1);
|
||||||
|
if (m_impl->levelCount > 1U)
|
||||||
|
EnableMipmapping(true);
|
||||||
|
|
||||||
|
// Vérification du support par la carte graphique (texture proxy)
|
||||||
|
if (!CreateTexture(true))
|
||||||
|
{
|
||||||
NazaraError("Texture's parameters not supported by driver");
|
NazaraError("Texture's parameters not supported by driver");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Création de la texture
|
// Création de la texture
|
||||||
if (!CreateTexture(impl.get(), false))
|
if (!CreateTexture(false))
|
||||||
{
|
{
|
||||||
NzOpenGL::DeleteTexture(m_impl->id);
|
|
||||||
|
|
||||||
NazaraError("Failed to create texture");
|
NazaraError("Failed to create texture");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_impl = impl.release();
|
onExit.Reset();
|
||||||
|
|
||||||
if (m_impl->levelCount > 1U)
|
|
||||||
EnableMipmapping(true);
|
|
||||||
|
|
||||||
NotifyCreated();
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -346,29 +248,10 @@ bool NzTexture::Download(NzImage* image) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int width = m_impl->width;
|
|
||||||
unsigned int height = m_impl->height;
|
|
||||||
unsigned int depth = m_impl->depth;
|
|
||||||
|
|
||||||
// Téléchargement...
|
// Téléchargement...
|
||||||
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
||||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||||
{
|
glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(0, 0, 0, level));
|
||||||
glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level));
|
|
||||||
|
|
||||||
if (width > 1)
|
|
||||||
width >>= 1;
|
|
||||||
|
|
||||||
if (height > 1)
|
|
||||||
height >>= 1;
|
|
||||||
|
|
||||||
if (depth > 1)
|
|
||||||
depth >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inversion de la texture pour le repère d'OpenGL
|
|
||||||
if (!image->FlipVertically())
|
|
||||||
NazaraWarning("Failed to flip image");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +273,11 @@ bool NzTexture::EnableMipmapping(bool enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_impl->levelCount == 1) // Transformation d'une texture sans mipmaps vers une texture avec mipmaps
|
if (m_impl->levelCount == 1) // Transformation d'une texture sans mipmaps vers une texture avec mipmaps
|
||||||
|
{
|
||||||
|
///FIXME: Est-ce que cette opération est seulement possible ?
|
||||||
m_impl->levelCount = NzImage::GetMaxLevel(m_impl->width, m_impl->height, m_impl->depth);
|
m_impl->levelCount = NzImage::GetMaxLevel(m_impl->width, m_impl->height, m_impl->depth);
|
||||||
|
SetMipmapRange(0, m_impl->levelCount-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_impl->mipmapping && enable)
|
if (!m_impl->mipmapping && enable)
|
||||||
m_impl->mipmapsUpdated = false;
|
m_impl->mipmapsUpdated = false;
|
||||||
|
|
@ -410,7 +297,7 @@ void NzTexture::EnsureMipmapsUpdate() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt8 NzTexture::GetBytesPerPixel() const
|
unsigned int NzTexture::GetDepth(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -420,20 +307,7 @@ nzUInt8 NzTexture::GetBytesPerPixel() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
return GetLevelSize(m_impl->depth, level);
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NzTexture::GetDepth() const
|
|
||||||
{
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (!m_impl)
|
|
||||||
{
|
|
||||||
NazaraError("Texture must be valid");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return m_impl->depth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nzPixelFormat NzTexture::GetFormat() const
|
nzPixelFormat NzTexture::GetFormat() const
|
||||||
|
|
@ -449,7 +323,7 @@ nzPixelFormat NzTexture::GetFormat() const
|
||||||
return m_impl->format;
|
return m_impl->format;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzTexture::GetHeight() const
|
unsigned int NzTexture::GetHeight(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -459,20 +333,103 @@ unsigned int NzTexture::GetHeight() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return m_impl->height;
|
return GetLevelSize(m_impl->height, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzVector2ui NzTexture::GetSize() const
|
nzUInt8 NzTexture::GetLevelCount() const
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Texture must be valid");
|
NazaraError("Texture must be valid");
|
||||||
return NzVector2ui(0, 0);
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NzVector2ui(m_impl->width, m_impl->height);
|
return m_impl->levelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
nzUInt8 NzTexture::GetMaxLevel() const
|
||||||
|
{
|
||||||
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
if (!m_impl)
|
||||||
|
{
|
||||||
|
NazaraError("Texture must be valid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NzImage::GetMaxLevel(m_impl->type, m_impl->width, m_impl->height, m_impl->depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzTexture::GetMemoryUsage() const
|
||||||
|
{
|
||||||
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
if (!m_impl)
|
||||||
|
{
|
||||||
|
NazaraError("Texture must be valid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int width = m_impl->width;
|
||||||
|
unsigned int height = m_impl->height;
|
||||||
|
unsigned int depth = m_impl->depth;
|
||||||
|
|
||||||
|
unsigned int size = 0;
|
||||||
|
for (unsigned int i = 0; i < m_impl->levelCount; ++i)
|
||||||
|
{
|
||||||
|
size += width * height * depth;
|
||||||
|
|
||||||
|
if (width > 1)
|
||||||
|
width >>= 1;
|
||||||
|
|
||||||
|
if (height > 1)
|
||||||
|
height >>= 1;
|
||||||
|
|
||||||
|
if (depth > 1)
|
||||||
|
depth >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_impl->type == nzImageType_Cubemap)
|
||||||
|
size *= 6;
|
||||||
|
|
||||||
|
return size * NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzTexture::GetMemoryUsage(nzUInt8 level) const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!m_impl)
|
||||||
|
{
|
||||||
|
NazaraError("Texture must be valid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level >= m_impl->levelCount)
|
||||||
|
{
|
||||||
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (GetLevelSize(m_impl->width, level)) *
|
||||||
|
(GetLevelSize(m_impl->height, level)) *
|
||||||
|
((m_impl->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level)) *
|
||||||
|
NzPixelFormat::GetBytesPerPixel(m_impl->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzVector3ui NzTexture::GetSize(nzUInt8 level) const
|
||||||
|
{
|
||||||
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
if (!m_impl)
|
||||||
|
{
|
||||||
|
NazaraError("Texture must be valid");
|
||||||
|
return NzVector3ui(0, 0, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NzVector3ui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level));
|
||||||
}
|
}
|
||||||
|
|
||||||
nzImageType NzTexture::GetType() const
|
nzImageType NzTexture::GetType() const
|
||||||
|
|
@ -488,7 +445,7 @@ nzImageType NzTexture::GetType() const
|
||||||
return m_impl->type;
|
return m_impl->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzTexture::GetWidth() const
|
unsigned int NzTexture::GetWidth(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -498,7 +455,7 @@ unsigned int NzTexture::GetWidth() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return m_impl->width;
|
return GetLevelSize(m_impl->width, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::HasMipmaps() const
|
bool NzTexture::HasMipmaps() const
|
||||||
|
|
@ -514,30 +471,17 @@ bool NzTexture::HasMipmaps() const
|
||||||
return m_impl->levelCount > 1;
|
return m_impl->levelCount > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::IsCompressed() const
|
void NzTexture::InvalidateMipmaps()
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Texture must be valid");
|
NazaraInternalError("Texture must be valid");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NzPixelFormat::IsCompressed(m_impl->format);
|
m_impl->mipmapsUpdated = false;
|
||||||
}
|
|
||||||
|
|
||||||
bool NzTexture::IsCubemap() const
|
|
||||||
{
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (!m_impl)
|
|
||||||
{
|
|
||||||
NazaraError("Texture must be valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return m_impl->type == nzImageType_Cubemap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::IsValid() const
|
bool NzTexture::IsValid() const
|
||||||
|
|
@ -573,6 +517,7 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||||
nzPixelFormat format = newImage.GetFormat();
|
nzPixelFormat format = newImage.GetFormat();
|
||||||
if (!IsFormatSupported(format))
|
if (!IsFormatSupported(format))
|
||||||
{
|
{
|
||||||
|
///TODO: Sélectionner le format le plus adapté selon les composantes présentes dans le premier format
|
||||||
nzPixelFormat newFormat = (NzPixelFormat::HasAlpha(format)) ? nzPixelFormat_BGRA8 : nzPixelFormat_BGR8;
|
nzPixelFormat newFormat = (NzPixelFormat::HasAlpha(format)) ? nzPixelFormat_BGRA8 : nzPixelFormat_BGR8;
|
||||||
NazaraWarning("Format " + NzPixelFormat::ToString(format) + " not supported, trying to convert it to " + NzPixelFormat::ToString(newFormat) + "...");
|
NazaraWarning("Format " + NzPixelFormat::ToString(format) + " not supported, trying to convert it to " + NzPixelFormat::ToString(newFormat) + "...");
|
||||||
|
|
||||||
|
|
@ -604,17 +549,20 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzCallOnExit destroyOnExit([this]()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
});
|
||||||
|
|
||||||
if (type == nzImageType_Cubemap)
|
if (type == nzImageType_Cubemap)
|
||||||
{
|
{
|
||||||
for (nzUInt8 level = 0; level < levelCount; ++level)
|
for (nzUInt8 level = 0; level < levelCount; ++level)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i <= nzCubemapFace_Max; ++i)
|
for (unsigned int i = 0; i <= nzCubemapFace_Max; ++i)
|
||||||
{
|
{
|
||||||
if (!UpdateFace(static_cast<nzCubemapFace>(i), newImage.GetConstPixels(0, 0, i, level), level))
|
if (!Update(newImage.GetConstPixels(0, 0, i, level), NzRectui(0, 0, newImage.GetWidth(level), newImage.GetHeight(level)), i, level))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to update texture");
|
NazaraError("Failed to update texture");
|
||||||
Destroy();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -627,13 +575,13 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||||
if (!Update(newImage.GetConstPixels(0, 0, 0, level), level))
|
if (!Update(newImage.GetConstPixels(0, 0, 0, level), level))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to update texture");
|
NazaraError("Failed to update texture");
|
||||||
Destroy();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroyOnExit.Reset();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -793,7 +741,7 @@ bool NzTexture::LoadFaceFromFile(nzCubemapFace face, const NzString& filePath, c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateFace(face, image);
|
return Update(image, NzRectui(0, 0, faceSize, faceSize), face);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::size_t size, const NzImageParams& params)
|
bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::size_t size, const NzImageParams& params)
|
||||||
|
|
@ -832,7 +780,7 @@ bool NzTexture::LoadFaceFromMemory(nzCubemapFace face, const void* data, std::si
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateFace(face, image);
|
return Update(image, NzRectui(0, 0, faceSize, faceSize), face);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, const NzImageParams& params)
|
bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, const NzImageParams& params)
|
||||||
|
|
@ -872,7 +820,7 @@ bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateFace(face, image);
|
return Update(image, NzRectui(0, 0, faceSize, faceSize), face);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
||||||
|
|
@ -992,7 +940,7 @@ bool NzTexture::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned in
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return Update(pixels, NzBoxui(std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), srcWidth, srcHeight, level);
|
return Update(pixels, NzBoxui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)), srcWidth, srcHeight, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
|
|
@ -1004,12 +952,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_impl->type == nzImageType_Cubemap)
|
|
||||||
{
|
|
||||||
NazaraError("Update is not designed for cubemaps, use UpdateFace instead");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pixels)
|
if (!pixels)
|
||||||
{
|
{
|
||||||
NazaraError("Invalid pixel source");
|
NazaraError("Invalid pixel source");
|
||||||
|
|
@ -1023,12 +965,13 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int height = std::max(m_impl->height >> level, 1U);
|
unsigned int height = GetLevelSize(m_impl->height, level);
|
||||||
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (box.x+box.width > std::max(m_impl->width >> level, 1U) ||
|
unsigned int width = GetLevelSize(m_impl->width, level);
|
||||||
box.y+box.height > height ||
|
unsigned int depth = (m_impl->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level);
|
||||||
box.z+box.depth > std::max(m_impl->depth >> level, 1U))
|
if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > depth ||
|
||||||
|
(m_impl->type == nzImageType_Cubemap && box.depth > 1)) // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois
|
||||||
{
|
{
|
||||||
NazaraError("Cube dimensions are out of bounds");
|
NazaraError("Cube dimensions are out of bounds");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1061,16 +1004,16 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int s
|
||||||
|
|
||||||
case nzImageType_1D_Array:
|
case nzImageType_1D_Array:
|
||||||
case nzImageType_2D:
|
case nzImageType_2D:
|
||||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.width, box.height, format.dataFormat, format.dataType, pixels);
|
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzImageType_2D_Array:
|
case nzImageType_2D_Array:
|
||||||
case nzImageType_3D:
|
case nzImageType_3D:
|
||||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, height-box.height-box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels);
|
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
case nzImageType_Cubemap:
|
||||||
NazaraError("Update used on a cubemap texture, please enable safe mode");
|
glTexSubImage2D(NzOpenGL::CubemapFace[box.z], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1082,118 +1025,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
||||||
return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level);
|
return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level)
|
|
||||||
{
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (!image.IsValid())
|
|
||||||
{
|
|
||||||
NazaraError("Image must be valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image.GetFormat() != m_impl->format)
|
|
||||||
{
|
|
||||||
NazaraError("Image format does not match texture format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), NzRectui(0, 0, image.GetWidth(level), image.GetHeight(level)), 0, 0, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level)
|
|
||||||
{
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (!image.IsValid())
|
|
||||||
{
|
|
||||||
NazaraError("Image must be valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image.GetFormat() != m_impl->format)
|
|
||||||
{
|
|
||||||
NazaraError("Image format does not match texture format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return UpdateFace(face, image.GetConstPixels(0, 0, 0, level), rect, image.GetWidth(level), image.GetHeight(level), level);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
|
||||||
{
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (!m_impl)
|
|
||||||
{
|
|
||||||
NazaraError("Texture must be valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return UpdateFace(face, pixels, NzRectui(0, 0, m_impl->width, m_impl->height), srcWidth, srcHeight, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
|
||||||
{
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (!m_impl)
|
|
||||||
{
|
|
||||||
NazaraError("Texture must be valid");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_impl->type != nzImageType_Cubemap)
|
|
||||||
{
|
|
||||||
NazaraError("UpdateFace is designed for cubemaps, use Update instead");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pixels)
|
|
||||||
{
|
|
||||||
NazaraError("Invalid pixel source");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rect.IsValid())
|
|
||||||
{
|
|
||||||
NazaraError("Invalid rectangle");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int height = std::max(m_impl->height >> level, 1U);
|
|
||||||
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (rect.x+rect.width > std::max(m_impl->width >> level, 1U) || rect.y+rect.height > height)
|
|
||||||
{
|
|
||||||
NazaraError("Rectangle dimensions are out of bounds");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level >= m_impl->levelCount)
|
|
||||||
{
|
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_impl->levelCount) + ')');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NzOpenGL::Format format;
|
|
||||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to get OpenGL format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetUnpackAlignement(NzPixelFormat::GetBytesPerPixel(m_impl->format));
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth);
|
|
||||||
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight);
|
|
||||||
|
|
||||||
NzOpenGL::BindTexture(m_impl->type, m_impl->id);
|
|
||||||
glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, pixels);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NzTexture::GetOpenGLID() const
|
unsigned int NzTexture::GetOpenGLID() const
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
|
@ -1226,8 +1057,11 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
// Formats de base
|
// Formats de base
|
||||||
|
case nzPixelFormat_A8:
|
||||||
case nzPixelFormat_BGR8:
|
case nzPixelFormat_BGR8:
|
||||||
case nzPixelFormat_BGRA8:
|
case nzPixelFormat_BGRA8:
|
||||||
|
case nzPixelFormat_L8:
|
||||||
|
case nzPixelFormat_LA8:
|
||||||
case nzPixelFormat_RGB8:
|
case nzPixelFormat_RGB8:
|
||||||
case nzPixelFormat_RGBA8:
|
case nzPixelFormat_RGBA8:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1286,12 +1120,7 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||||
case nzPixelFormat_Stencil16:
|
case nzPixelFormat_Stencil16:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Dépréciés depuis OpenGL 3
|
// Formats compressés
|
||||||
///FIXME: Il doit bien exister des remplaçants (GL_RED ?)
|
|
||||||
case nzPixelFormat_L8:
|
|
||||||
case nzPixelFormat_LA8:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case nzPixelFormat_DXT1:
|
case nzPixelFormat_DXT1:
|
||||||
case nzPixelFormat_DXT3:
|
case nzPixelFormat_DXT3:
|
||||||
case nzPixelFormat_DXT5:
|
case nzPixelFormat_DXT5:
|
||||||
|
|
@ -1302,7 +1131,6 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||||
}
|
}
|
||||||
|
|
||||||
NazaraError("Invalid pixel format");
|
NazaraError("Invalid pixel format");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1330,15 +1158,119 @@ bool NzTexture::IsTypeSupported(nzImageType type)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzTexture::InvalidateMipmaps()
|
bool NzTexture::CreateTexture(bool proxy)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
NzOpenGL::Format openGLFormat;
|
||||||
if (!m_impl)
|
if (!NzOpenGL::TranslateFormat(m_impl->format, &openGLFormat, NzOpenGL::FormatType_Texture))
|
||||||
{
|
{
|
||||||
NazaraInternalError("Texture must be valid");
|
NazaraError("Format " + NzPixelFormat::ToString(m_impl->format) + " not supported by OpenGL");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
m_impl->mipmapsUpdated = false;
|
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[m_impl->type] : NzOpenGL::TextureTarget[m_impl->type];
|
||||||
|
switch (m_impl->type)
|
||||||
|
{
|
||||||
|
case nzImageType_1D:
|
||||||
|
{
|
||||||
|
if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy
|
||||||
|
glTexStorage1D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int w = m_impl->width;
|
||||||
|
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||||
|
{
|
||||||
|
glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||||
|
if (w > 1U)
|
||||||
|
w >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzImageType_1D_Array:
|
||||||
|
case nzImageType_2D:
|
||||||
|
{
|
||||||
|
if (glTexStorage2D && !proxy)
|
||||||
|
glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int w = m_impl->width;
|
||||||
|
unsigned int h = m_impl->height;
|
||||||
|
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||||
|
{
|
||||||
|
glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||||
|
if (w > 1U)
|
||||||
|
w >>= 1;
|
||||||
|
|
||||||
|
if (h > 1U)
|
||||||
|
h >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzImageType_2D_Array:
|
||||||
|
case nzImageType_3D:
|
||||||
|
{
|
||||||
|
if (glTexStorage3D && !proxy)
|
||||||
|
glTexStorage3D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height, m_impl->depth);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int w = m_impl->width;
|
||||||
|
unsigned int h = m_impl->height;
|
||||||
|
unsigned int d = m_impl->depth;
|
||||||
|
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||||
|
{
|
||||||
|
glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||||
|
if (w > 1U)
|
||||||
|
w >>= 1;
|
||||||
|
|
||||||
|
if (h > 1U)
|
||||||
|
h >>= 1;
|
||||||
|
|
||||||
|
if (d > 1U)
|
||||||
|
d >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzImageType_Cubemap:
|
||||||
|
{
|
||||||
|
if (glTexStorage2D && !proxy)
|
||||||
|
glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int size = m_impl->width; // Les cubemaps ont une longueur et largeur identique
|
||||||
|
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||||
|
{
|
||||||
|
for (GLenum face : NzOpenGL::CubemapFace)
|
||||||
|
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||||
|
|
||||||
|
if (size > 1U)
|
||||||
|
size >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxy)
|
||||||
|
{
|
||||||
|
GLint internalFormat = 0;
|
||||||
|
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
|
||||||
|
if (internalFormat == 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Application du swizzle
|
||||||
|
if (!proxy && NzOpenGL::GetVersion() >= 300)
|
||||||
|
{
|
||||||
|
glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, openGLFormat.swizzle[0]);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, openGLFormat.swizzle[1]);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, openGLFormat.swizzle[2]);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, openGLFormat.swizzle[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright (C) 2015 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/AbstractAtlas.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzAbstractAtlas::NzAbstractAtlas() :
|
||||||
|
m_listenersLocked(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NzAbstractAtlas::~NzAbstractAtlas()
|
||||||
|
{
|
||||||
|
m_listenersLocked = true;
|
||||||
|
for (auto& pair : m_listeners)
|
||||||
|
pair.first->OnAtlasReleased(this, pair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractAtlas::AddListener(Listener* listener, void* userdata) const
|
||||||
|
{
|
||||||
|
if (!m_listenersLocked)
|
||||||
|
m_listeners.insert(std::make_pair(listener, userdata));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractAtlas::RemoveListener(Listener* listener) const
|
||||||
|
{
|
||||||
|
if (!m_listenersLocked)
|
||||||
|
m_listeners.erase(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractAtlas::NotifyCleared()
|
||||||
|
{
|
||||||
|
m_listenersLocked = true;
|
||||||
|
|
||||||
|
auto it = m_listeners.begin();
|
||||||
|
while (it != m_listeners.end())
|
||||||
|
{
|
||||||
|
if (!it->first->OnAtlasCleared(this, it->second))
|
||||||
|
m_listeners.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_listenersLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractAtlas::NotifyLayerChange(NzAbstractImage* oldLayer, NzAbstractImage* newLayer)
|
||||||
|
{
|
||||||
|
m_listenersLocked = true;
|
||||||
|
|
||||||
|
auto it = m_listeners.begin();
|
||||||
|
while (it != m_listeners.end())
|
||||||
|
{
|
||||||
|
if (!it->first->OnAtlasLayerChange(this, oldLayer, newLayer, it->second))
|
||||||
|
m_listeners.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_listenersLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NzAbstractAtlas::Listener::~Listener() = default;
|
||||||
|
|
||||||
|
bool NzAbstractAtlas::Listener::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzAbstractAtlas::Listener::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(oldLayer);
|
||||||
|
NazaraUnused(newLayer);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzAbstractAtlas::Listener::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright (C) 2015 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/AbstractImage.hpp>
|
||||||
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzAbstractImage::~NzAbstractImage() = default;
|
||||||
|
|
||||||
|
nzUInt8 NzAbstractImage::GetBytesPerPixel() const
|
||||||
|
{
|
||||||
|
return NzPixelFormat::GetBytesPerPixel(GetFormat());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzAbstractImage::IsCompressed() const
|
||||||
|
{
|
||||||
|
return NzPixelFormat::IsCompressed(GetFormat());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzAbstractImage::IsCubemap() const
|
||||||
|
{
|
||||||
|
return GetType() == nzImageType_Cubemap;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (C) 2015 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/AbstractTextDrawer.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzAbstractTextDrawer::~NzAbstractTextDrawer() = default;
|
||||||
|
|
||||||
|
|
@ -3,6 +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/Buffer.hpp>
|
#include <Nazara/Utility/Buffer.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||||
|
|
@ -16,7 +17,7 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
NzAbstractBuffer* SoftwareBufferFunction(NzBuffer* parent, nzBufferType type)
|
NzAbstractBuffer* SoftwareBufferFactory(NzBuffer* parent, nzBufferType type)
|
||||||
{
|
{
|
||||||
return new NzSoftwareBuffer(parent, type);
|
return new NzSoftwareBuffer(parent, type);
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +30,7 @@ m_size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage, nzBufferUsage usage) :
|
NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzUInt32 storage, nzBufferUsage usage) :
|
||||||
m_type(type),
|
m_type(type),
|
||||||
m_impl(nullptr)
|
m_impl(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -59,22 +60,21 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NzBufferMapper<NzBuffer> mapper(buffer, nzBufferAccess_ReadOnly);
|
NzBufferMapper<NzBuffer> mapper(buffer, nzBufferAccess_ReadOnly);
|
||||||
|
|
||||||
return Fill(mapper.GetPointer(), 0, buffer.GetSize());
|
return Fill(mapper.GetPointer(), 0, buffer.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzBuffer::Create(unsigned int size, nzBufferStorage storage, nzBufferUsage usage)
|
bool NzBuffer::Create(unsigned int size, nzUInt32 storage, nzBufferUsage usage)
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
// Notre buffer est-il supporté ?
|
// Notre buffer est-il supporté ?
|
||||||
if (!s_bufferFunctions[storage])
|
if (!IsStorageSupported(storage))
|
||||||
{
|
{
|
||||||
NazaraError("Buffer storage not supported");
|
NazaraError("Buffer storage not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<NzAbstractBuffer> impl(s_bufferFunctions[storage](this, m_type));
|
std::unique_ptr<NzAbstractBuffer> impl(s_bufferFactories[storage](this, m_type));
|
||||||
if (!impl->Create(size, usage))
|
if (!impl->Create(size, usage))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create buffer");
|
NazaraError("Failed to create buffer");
|
||||||
|
|
@ -131,7 +131,7 @@ unsigned int NzBuffer::GetSize() const
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
nzBufferStorage NzBuffer::GetStorage() const
|
nzUInt32 NzBuffer::GetStorage() const
|
||||||
{
|
{
|
||||||
return m_storage;
|
return m_storage;
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +148,7 @@ nzBufferUsage NzBuffer::GetUsage() const
|
||||||
|
|
||||||
bool NzBuffer::IsHardware() const
|
bool NzBuffer::IsHardware() const
|
||||||
{
|
{
|
||||||
return m_storage == nzBufferStorage_Hardware;
|
return m_storage & nzDataStorage_Hardware;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzBuffer::IsValid() const
|
bool NzBuffer::IsValid() const
|
||||||
|
|
@ -200,7 +200,7 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int siz
|
||||||
return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size);
|
return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzBuffer::SetStorage(nzBufferStorage storage)
|
bool NzBuffer::SetStorage(nzUInt32 storage)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -213,13 +213,11 @@ bool NzBuffer::SetStorage(nzBufferStorage storage)
|
||||||
if (m_storage == storage)
|
if (m_storage == storage)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
if (!IsStorageSupported(storage))
|
||||||
if (!IsSupported(storage))
|
|
||||||
{
|
{
|
||||||
NazaraError("Storage not supported");
|
NazaraError("Storage not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_size);
|
void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_size);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
|
|
@ -228,31 +226,36 @@ bool NzBuffer::SetStorage(nzBufferStorage storage)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type);
|
NzCallOnExit unmapMyImpl([this]()
|
||||||
|
{
|
||||||
|
m_impl->Unmap();
|
||||||
|
});
|
||||||
|
|
||||||
|
std::unique_ptr<NzAbstractBuffer> impl(s_bufferFactories[storage](this, m_type));
|
||||||
if (!impl->Create(m_size, m_usage))
|
if (!impl->Create(m_size, m_usage))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create buffer");
|
NazaraError("Failed to create buffer");
|
||||||
delete impl;
|
|
||||||
m_impl->Unmap();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzCallOnExit destroyImpl([&impl]()
|
||||||
|
{
|
||||||
|
impl->Destroy();
|
||||||
|
});
|
||||||
|
|
||||||
if (!impl->Fill(ptr, 0, m_size))
|
if (!impl->Fill(ptr, 0, m_size))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to fill buffer");
|
NazaraError("Failed to fill buffer");
|
||||||
impl->Destroy();
|
|
||||||
delete impl;
|
|
||||||
m_impl->Unmap();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_impl->Unmap();
|
destroyImpl.Reset();
|
||||||
|
|
||||||
|
unmapMyImpl.CallAndReset();
|
||||||
m_impl->Destroy();
|
m_impl->Destroy();
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
|
|
||||||
m_impl = impl;
|
m_impl = impl.release();
|
||||||
m_storage = storage;
|
m_storage = storage;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -269,29 +272,29 @@ void NzBuffer::Unmap() const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!m_impl->Unmap())
|
if (!m_impl->Unmap())
|
||||||
NazaraWarning("Failed to unmap buffer (it's content is undefined)"); ///TODO: Unexpected ?
|
NazaraWarning("Failed to unmap buffer (it's content may be undefined)"); ///TODO: Unexpected ?
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzBuffer::IsSupported(nzBufferStorage storage)
|
bool NzBuffer::IsStorageSupported(nzUInt32 storage)
|
||||||
{
|
{
|
||||||
return s_bufferFunctions[storage] != nullptr;
|
return s_bufferFactories[storage] != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzBuffer::SetBufferFunction(nzBufferStorage storage, BufferFunction func)
|
void NzBuffer::SetBufferFactory(nzUInt32 storage, BufferFactory func)
|
||||||
{
|
{
|
||||||
s_bufferFunctions[storage] = func;
|
s_bufferFactories[storage] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzBuffer::Initialize()
|
bool NzBuffer::Initialize()
|
||||||
{
|
{
|
||||||
s_bufferFunctions[nzBufferStorage_Software] = SoftwareBufferFunction;
|
s_bufferFactories[nzDataStorage_Software] = SoftwareBufferFactory;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzBuffer::Uninitialize()
|
void NzBuffer::Uninitialize()
|
||||||
{
|
{
|
||||||
std::memset(s_bufferFunctions, 0, (nzBufferStorage_Max+1)*sizeof(NzBuffer::BufferFunction));
|
std::memset(s_bufferFactories, 0, (nzDataStorage_Max+1)*sizeof(NzBuffer::BufferFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBuffer::BufferFunction NzBuffer::s_bufferFunctions[nzBufferStorage_Max+1] = {0};
|
NzBuffer::BufferFactory NzBuffer::s_bufferFactories[nzDataStorage_Max+1] = {0};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,484 @@
|
||||||
|
// Copyright (C) 2014 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/Font.hpp>
|
||||||
|
#include <Nazara/Utility/Config.hpp>
|
||||||
|
#include <Nazara/Utility/FontData.hpp>
|
||||||
|
#include <Nazara/Utility/FontGlyph.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
bool NzFontParams::IsValid() const
|
||||||
|
{
|
||||||
|
return true; // Rien à tester
|
||||||
|
}
|
||||||
|
|
||||||
|
NzFont::NzFont() :
|
||||||
|
m_glyphBorder(1),
|
||||||
|
m_minimumSizeStep(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NzFont::~NzFont()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
SetAtlas(nullptr); // On libère l'atlas par la même occasion
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::ClearGlyphCache()
|
||||||
|
{
|
||||||
|
if (m_atlas)
|
||||||
|
{
|
||||||
|
if (m_atlas.unique())
|
||||||
|
m_atlas->Clear(); // Appellera OnAtlasCleared
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Au moins une autre police utilise cet atlas, on vire nos glyphes un par un
|
||||||
|
for (auto mapIt = m_glyphes.begin(); mapIt != m_glyphes.end(); ++mapIt)
|
||||||
|
{
|
||||||
|
GlyphMap& glyphMap = mapIt->second;
|
||||||
|
for (auto glyphIt = glyphMap.begin(); glyphIt != glyphMap.end(); ++glyphIt)
|
||||||
|
{
|
||||||
|
Glyph& glyph = glyphIt->second;
|
||||||
|
m_atlas->Free(&glyph.atlasRect, &glyph.layerIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destruction des glyphes mémorisés et notification
|
||||||
|
m_glyphes.clear();
|
||||||
|
NotifyModified(ModificationCode_GlyphCacheCleared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::ClearKerningCache()
|
||||||
|
{
|
||||||
|
m_kerningCache.clear();
|
||||||
|
NotifyModified(ModificationCode_KerningCacheCleared);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::ClearSizeInfoCache()
|
||||||
|
{
|
||||||
|
m_sizeInfoCache.clear();
|
||||||
|
NotifyModified(ModificationCode_SizeInfoCacheCleared);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::Create(NzFontData* data)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
NazaraError("Invalid font data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_data.reset(data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::Destroy()
|
||||||
|
{
|
||||||
|
ClearGlyphCache();
|
||||||
|
|
||||||
|
m_data.reset();
|
||||||
|
m_kerningCache.clear();
|
||||||
|
m_sizeInfoCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::ExtractGlyph(unsigned int characterSize, char32_t character, nzUInt32 style, NzFontGlyph* glyph) const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
NazaraError("Invalid font");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_data->ExtractGlyph(characterSize, character, style, glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzAbstractAtlas* NzFont::GetAtlas() const
|
||||||
|
{
|
||||||
|
return m_atlas.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzFont::GetCachedGlyphCount(unsigned int characterSize, nzUInt32 style) const
|
||||||
|
{
|
||||||
|
nzUInt64 key = ComputeKey(characterSize, style);
|
||||||
|
auto it = m_glyphes.find(key);
|
||||||
|
if (it == m_glyphes.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return it->second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzFont::GetCachedGlyphCount() const
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
for (auto& pair : m_glyphes)
|
||||||
|
count += pair.second.size();
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzString NzFont::GetFamilyName() const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
NazaraError("Invalid font");
|
||||||
|
return NzString("Invalid font");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_data->GetFamilyName();
|
||||||
|
}
|
||||||
|
|
||||||
|
int NzFont::GetKerning(unsigned int characterSize, char32_t first, char32_t second) const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
NazaraError("Invalid font");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// On utilise un cache car la méthode interne QueryKerning peut se révéler coûteuse (car pouvant induire un changement de taille)
|
||||||
|
auto& map = m_kerningCache[characterSize];
|
||||||
|
|
||||||
|
nzUInt64 key = (static_cast<nzUInt64>(first) << 32) | second; // Combinaison de deux caractères 32 bits dans un nombre 64 bits
|
||||||
|
|
||||||
|
auto it = map.find(key);
|
||||||
|
if (it == map.end())
|
||||||
|
{
|
||||||
|
// Absent du cache: on va demander l'information à la police
|
||||||
|
int kerning = m_data->QueryKerning(characterSize, first, second);
|
||||||
|
map.insert(std::make_pair(key, kerning));
|
||||||
|
|
||||||
|
return kerning;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return it->second; // Présent dans le cache, tout va bien
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzFont::Glyph& NzFont::GetGlyph(unsigned int characterSize, nzUInt32 style, char32_t character) const
|
||||||
|
{
|
||||||
|
nzUInt64 key = ComputeKey(characterSize, style);
|
||||||
|
return PrecacheGlyph(m_glyphes[key], characterSize, style, character);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzFont::GetGlyphBorder() const
|
||||||
|
{
|
||||||
|
return m_glyphBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzFont::GetMinimumStepSize() const
|
||||||
|
{
|
||||||
|
return m_minimumSizeStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzFont::SizeInfo& NzFont::GetSizeInfo(unsigned int characterSize) const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
NazaraError("Invalid font");
|
||||||
|
|
||||||
|
static SizeInfo dummy;
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto it = m_sizeInfoCache.find(characterSize);
|
||||||
|
if (it == m_sizeInfoCache.end())
|
||||||
|
{
|
||||||
|
SizeInfo sizeInfo;
|
||||||
|
sizeInfo.lineHeight = m_data->QueryLineHeight(characterSize);
|
||||||
|
sizeInfo.underlinePosition = m_data->QueryUnderlinePosition(characterSize);
|
||||||
|
sizeInfo.underlineThickness = m_data->QueryUnderlineThickness(characterSize);
|
||||||
|
|
||||||
|
NzFontGlyph glyph;
|
||||||
|
if (m_data->ExtractGlyph(characterSize, ' ', nzTextStyle_Regular, &glyph))
|
||||||
|
sizeInfo.spaceAdvance = glyph.advance;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraWarning("Failed to extract space character from font, using half the size");
|
||||||
|
sizeInfo.spaceAdvance = characterSize/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = m_sizeInfoCache.insert(std::make_pair(characterSize, sizeInfo)).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzString NzFont::GetStyleName() const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
NazaraError("Invalid font");
|
||||||
|
return NzString("Invalid font");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return m_data->GetStyleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::IsValid() const
|
||||||
|
{
|
||||||
|
return m_data != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, char32_t character) const
|
||||||
|
{
|
||||||
|
nzUInt64 key = ComputeKey(characterSize, style);
|
||||||
|
return PrecacheGlyph(m_glyphes[key], characterSize, style, character).valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, const NzString& characterSet) const
|
||||||
|
{
|
||||||
|
unsigned int size;
|
||||||
|
std::unique_ptr<char32_t[]> characters(characterSet.GetUtf32Buffer(&size));
|
||||||
|
if (!characters)
|
||||||
|
{
|
||||||
|
NazaraError("Invalid character set");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nzUInt64 key = ComputeKey(characterSize, style);
|
||||||
|
auto& glyphMap = m_glyphes[key];
|
||||||
|
for (unsigned int i = 0; i < size; ++i)
|
||||||
|
PrecacheGlyph(glyphMap, characterSize, style, characters[i]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::OpenFromFile(const NzString& filePath, const NzFontParams& params)
|
||||||
|
{
|
||||||
|
return NzFontLoader::LoadFromFile(this, filePath, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::OpenFromMemory(const void* data, std::size_t size, const NzFontParams& params)
|
||||||
|
{
|
||||||
|
return NzFontLoader::LoadFromMemory(this, data, size, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::OpenFromStream(NzInputStream& stream, const NzFontParams& params)
|
||||||
|
{
|
||||||
|
return NzFontLoader::LoadFromStream(this, stream, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::SetAtlas(std::shared_ptr<NzAbstractAtlas> atlas)
|
||||||
|
{
|
||||||
|
if (m_atlas != atlas)
|
||||||
|
{
|
||||||
|
ClearGlyphCache();
|
||||||
|
|
||||||
|
if (m_atlas)
|
||||||
|
m_atlas->RemoveListener(this);
|
||||||
|
|
||||||
|
m_atlas = atlas;
|
||||||
|
if (m_atlas)
|
||||||
|
m_atlas->AddListener(this);
|
||||||
|
|
||||||
|
NotifyModified(ModificationCode_AtlasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::SetGlyphBorder(unsigned int borderSize)
|
||||||
|
{
|
||||||
|
if (m_glyphBorder != borderSize)
|
||||||
|
{
|
||||||
|
m_glyphBorder = borderSize;
|
||||||
|
ClearGlyphCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::SetMinimumStepSize(unsigned int minimumStepSize)
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (minimumStepSize == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Minimum step size cannot be zero as it implies division by zero");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (m_minimumSizeStep != minimumStepSize)
|
||||||
|
{
|
||||||
|
m_minimumSizeStep = minimumStepSize;
|
||||||
|
ClearGlyphCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nzUInt64 NzFont::ComputeKey(unsigned int characterSize, nzUInt32 style) const
|
||||||
|
{
|
||||||
|
// On prend le pas en compte
|
||||||
|
nzUInt64 sizePart = static_cast<nzUInt32>((characterSize/m_minimumSizeStep)*m_minimumSizeStep);
|
||||||
|
|
||||||
|
// Ainsi que le style (uniquement le gras et l'italique, les autres sont gérés par un TextDrawer)
|
||||||
|
nzUInt64 stylePart = 0;
|
||||||
|
|
||||||
|
if (style & nzTextStyle_Bold)
|
||||||
|
stylePart |= nzTextStyle_Bold;
|
||||||
|
|
||||||
|
if (style & nzTextStyle_Italic)
|
||||||
|
stylePart |= nzTextStyle_Italic;
|
||||||
|
|
||||||
|
return (stylePart << 32) | sizePart;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::OnAtlasCleared(const NzAbstractAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
// Est-ce qu'il s'agit bien de notre atlas ?
|
||||||
|
if (m_atlas.get() != atlas)
|
||||||
|
{
|
||||||
|
NazaraInternalError("Notified by a non-listening-to resource");
|
||||||
|
return false; // On ne veut plus être notifié par cette ressource, évidemment
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Notre atlas vient d'être vidé, détruisons le cache de glyphe
|
||||||
|
m_glyphes.clear();
|
||||||
|
NotifyModified(ModificationCode_GlyphCacheCleared);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzFont::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractImage* oldLayer, NzAbstractImage* newLayer, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(oldLayer);
|
||||||
|
NazaraUnused(newLayer);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
// Est-ce qu'il s'agit bien de notre atlas ?
|
||||||
|
if (m_atlas.get() != atlas)
|
||||||
|
{
|
||||||
|
NazaraInternalError("Notified by a non-listening-to resource");
|
||||||
|
return false; // On ne veut plus être notifié par cette ressource, évidemment
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Pour faciliter le travail des ressources qui nous écoutent
|
||||||
|
NotifyModified(ModificationCode_AtlasLayerChanged);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzFont::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata)
|
||||||
|
{
|
||||||
|
NazaraUnused(atlas);
|
||||||
|
NazaraUnused(userdata);
|
||||||
|
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
// Est-ce qu'il s'agit bien de notre atlas ?
|
||||||
|
if (m_atlas.get() != atlas)
|
||||||
|
{
|
||||||
|
NazaraInternalError("Notified by a non-listening-to resource");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Nous ne pouvons pas faire grand chose d'autre que se balancer une erreur à la tête de l'utilisateur avant un potentiel crash...
|
||||||
|
NazaraError("Atlas has been released while in use");
|
||||||
|
}
|
||||||
|
|
||||||
|
const NzFont::Glyph& NzFont::PrecacheGlyph(GlyphMap& glyphMap, unsigned int characterSize, nzUInt32 style, char32_t character) const
|
||||||
|
{
|
||||||
|
auto it = glyphMap.find(character);
|
||||||
|
if (it != glyphMap.end()) // Si le glyphe n'est pas déjà chargé
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
Glyph& glyph = glyphMap[character]; // Insertion du glyphe
|
||||||
|
glyph.requireFauxBold = false;
|
||||||
|
glyph.requireFauxItalic = false;
|
||||||
|
glyph.valid = false;
|
||||||
|
|
||||||
|
// On vérifie que le style demandé est supporté par la police (dans le cas contraire il devra être simulé au rendu)
|
||||||
|
nzUInt32 supportedStyle = style;
|
||||||
|
if (style & nzTextStyle_Bold && !m_data->SupportsStyle(nzTextStyle_Bold))
|
||||||
|
{
|
||||||
|
glyph.requireFauxBold = true;
|
||||||
|
supportedStyle &= ~nzTextStyle_Bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (style & nzTextStyle_Italic && !m_data->SupportsStyle(nzTextStyle_Italic))
|
||||||
|
{
|
||||||
|
glyph.requireFauxItalic = true;
|
||||||
|
supportedStyle &= ~nzTextStyle_Italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Est-ce que la police supporte le style demandé ?
|
||||||
|
if (style == supportedStyle)
|
||||||
|
{
|
||||||
|
// On extrait le glyphe depuis la police
|
||||||
|
NzFontGlyph fontGlyph;
|
||||||
|
if (ExtractGlyph(characterSize, character, style, &fontGlyph))
|
||||||
|
{
|
||||||
|
glyph.atlasRect.width = fontGlyph.image.GetWidth();
|
||||||
|
glyph.atlasRect.height = fontGlyph.image.GetHeight();
|
||||||
|
|
||||||
|
// Insertion du rectangle dans l'un des atlas
|
||||||
|
if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose
|
||||||
|
{
|
||||||
|
// Bordure (pour éviter le débordement lors du filtrage)
|
||||||
|
glyph.atlasRect.width += m_glyphBorder*2;
|
||||||
|
glyph.atlasRect.height += m_glyphBorder*2;
|
||||||
|
|
||||||
|
// Insertion du rectangle dans l'atlas virtuel
|
||||||
|
if (!m_atlas->Insert(fontGlyph.image, &glyph.atlasRect, &glyph.flipped, &glyph.layerIndex))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to insert glyph into atlas");
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compensation de la bordure (centrage du glyphe)
|
||||||
|
glyph.atlasRect.x += m_glyphBorder;
|
||||||
|
glyph.atlasRect.y += m_glyphBorder;
|
||||||
|
glyph.atlasRect.width -= m_glyphBorder*2;
|
||||||
|
glyph.atlasRect.height -= m_glyphBorder*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
glyph.aabb = fontGlyph.aabb;
|
||||||
|
glyph.advance = fontGlyph.advance;
|
||||||
|
glyph.valid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraWarning("Failed to extract glyph \"" + NzString::Unicode(character) + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// La police ne supporte pas le style demandé, nous allons donc précharger le glyphe supportant le style "minimum" supporté
|
||||||
|
// et copier ses données
|
||||||
|
nzUInt64 newKey = ComputeKey(characterSize, supportedStyle);
|
||||||
|
const Glyph& referenceGlyph = PrecacheGlyph(m_glyphes[newKey], characterSize, supportedStyle, character);
|
||||||
|
if (referenceGlyph.valid)
|
||||||
|
{
|
||||||
|
glyph.aabb = referenceGlyph.aabb;
|
||||||
|
glyph.advance = referenceGlyph.advance;
|
||||||
|
glyph.atlasRect = referenceGlyph.atlasRect;
|
||||||
|
glyph.flipped = referenceGlyph.flipped;
|
||||||
|
glyph.layerIndex = referenceGlyph.layerIndex;
|
||||||
|
glyph.valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzFontLoader::LoaderList NzFont::s_loaders;
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright (C) 2014 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/FontData.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
NzFontData::~NzFontData() = default;
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
// Copyright (C) 2015 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/GuillotineImageAtlas.hpp>
|
||||||
|
#include <Nazara/Utility/Config.hpp>
|
||||||
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const unsigned int s_atlasStartSize = 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineImageAtlas::NzGuillotineImageAtlas() :
|
||||||
|
m_rectChoiceHeuristic(NzGuillotineBinPack::RectBestAreaFit),
|
||||||
|
m_rectSplitHeuristic(NzGuillotineBinPack::SplitMinimizeArea)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineImageAtlas::~NzGuillotineImageAtlas() = default;
|
||||||
|
|
||||||
|
void NzGuillotineImageAtlas::Clear()
|
||||||
|
{
|
||||||
|
m_layers.clear();
|
||||||
|
NotifyCleared();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineImageAtlas::Free(NzSparsePtr<const NzRectui> rects, NzSparsePtr<unsigned int> layers, unsigned int count)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (layers[i] >= m_layers.size())
|
||||||
|
{
|
||||||
|
NazaraWarning("Rectangle #" + NzString::Number(i) + " belong to an out-of-bounds layer (" + NzString::Number(i) + " >= " + NzString::Number(m_layers.size()) + ")");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_layers[layers[i]].binPack.FreeRectangle(rects[i]);
|
||||||
|
m_layers[layers[i]].freedRectangles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineBinPack::FreeRectChoiceHeuristic NzGuillotineImageAtlas::GetRectChoiceHeuristic() const
|
||||||
|
{
|
||||||
|
return m_rectChoiceHeuristic;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzGuillotineBinPack::GuillotineSplitHeuristic NzGuillotineImageAtlas::GetRectSplitHeuristic() const
|
||||||
|
{
|
||||||
|
return m_rectSplitHeuristic;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzAbstractImage* NzGuillotineImageAtlas::GetLayer(unsigned int layerIndex) const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (layerIndex >= m_layers.size())
|
||||||
|
{
|
||||||
|
NazaraError("Layer index out of range (" + NzString::Number(layerIndex) + " >= " + NzString::Number(m_layers.size()) + ')');
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Layer& layer = m_layers[layerIndex];
|
||||||
|
ProcessGlyphQueue(layer);
|
||||||
|
|
||||||
|
return layer.image.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzGuillotineImageAtlas::GetLayerCount() const
|
||||||
|
{
|
||||||
|
return m_layers.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzGuillotineImageAtlas::Insert(const NzImage& image, NzRectui* rect, bool* flipped, unsigned int* layerIndex)
|
||||||
|
{
|
||||||
|
if (m_layers.empty())
|
||||||
|
{
|
||||||
|
// On créé une première couche s'il n'y en a pas
|
||||||
|
m_layers.resize(1);
|
||||||
|
Layer& layer = m_layers.back();
|
||||||
|
layer.binPack.Reset(s_atlasStartSize, s_atlasStartSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cette fonction ne fait qu'insérer un rectangle de façon virtuelle, l'insertion des images se fait après
|
||||||
|
for (unsigned int i = 0; i < m_layers.size(); ++i)
|
||||||
|
{
|
||||||
|
Layer& layer = m_layers[i];
|
||||||
|
|
||||||
|
// Une fois qu'un certain nombre de rectangles ont étés libérés d'une couche, on fusionne les rectangles libres
|
||||||
|
if (layer.freedRectangles > 10) // Valeur totalement arbitraire
|
||||||
|
{
|
||||||
|
while (layer.binPack.MergeFreeRectangles()); // Tant qu'une fusion est possible
|
||||||
|
layer.freedRectangles = 0; // Et on repart de zéro
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer.binPack.Insert(rect, flipped, 1, false, m_rectChoiceHeuristic, m_rectSplitHeuristic))
|
||||||
|
{
|
||||||
|
// Insertion réussie dans l'une des couches, on place le glyphe en file d'attente
|
||||||
|
layer.queuedGlyphs.resize(layer.queuedGlyphs.size()+1);
|
||||||
|
QueuedGlyph& glyph = layer.queuedGlyphs.back();
|
||||||
|
glyph.flipped = *flipped;
|
||||||
|
glyph.image = image; // Merci le Copy-On-Write
|
||||||
|
glyph.rect = *rect;
|
||||||
|
|
||||||
|
*layerIndex = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (i == m_layers.size() - 1) // Dernière itération ?
|
||||||
|
{
|
||||||
|
// Dernière couche, et le glyphe ne rentre pas, peut-on agrandir la taille de l'image ?
|
||||||
|
NzVector2ui newSize = layer.binPack.GetSize()*2;
|
||||||
|
if (ResizeLayer(layer, newSize))
|
||||||
|
{
|
||||||
|
// Oui on peut !
|
||||||
|
layer.binPack.Expand(newSize); // On ajuste l'atlas virtuel
|
||||||
|
|
||||||
|
// Et on relance la boucle sur la nouvelle dernière couche
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// On ne peut plus agrandir la dernière couche, il est temps d'en créer une nouvelle
|
||||||
|
newSize.Set(s_atlasStartSize);
|
||||||
|
|
||||||
|
Layer newLayer;
|
||||||
|
if (!ResizeLayer(newLayer, newSize))
|
||||||
|
{
|
||||||
|
// Impossible d'allouer une nouvelle couche, nous manquons probablement de mémoire (ou le glyphe est trop grand)
|
||||||
|
NazaraError("Failed to allocate new layer, we are probably out of memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
newLayer.binPack.Reset(newSize);
|
||||||
|
|
||||||
|
m_layers.emplace_back(std::move(newLayer)); // Insertion du layer
|
||||||
|
|
||||||
|
// On laisse la boucle insérer toute seule le rectangle à la prochaine itération
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraInternalError("Unknown error"); // Normalement on ne peut pas arriver ici
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineImageAtlas::SetRectChoiceHeuristic(NzGuillotineBinPack::FreeRectChoiceHeuristic heuristic)
|
||||||
|
{
|
||||||
|
m_rectChoiceHeuristic = heuristic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineImageAtlas::SetRectSplitHeuristic(NzGuillotineBinPack::GuillotineSplitHeuristic heuristic)
|
||||||
|
{
|
||||||
|
m_rectSplitHeuristic = heuristic;
|
||||||
|
}
|
||||||
|
|
||||||
|
NzAbstractImage* NzGuillotineImageAtlas::ResizeImage(NzAbstractImage* oldImage, const NzVector2ui& size) const
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzImage> newImage(new NzImage(nzImageType_2D, nzPixelFormat_A8, size.x, size.y));
|
||||||
|
if (oldImage)
|
||||||
|
{
|
||||||
|
NzImage& image = *static_cast<NzImage*>(oldImage);
|
||||||
|
newImage->Copy(image, NzRectui(size), NzVector2ui(0, 0)); // Copie des anciennes données
|
||||||
|
}
|
||||||
|
|
||||||
|
return newImage.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NzGuillotineImageAtlas::ResizeLayer(Layer& layer, const NzVector2ui& size)
|
||||||
|
{
|
||||||
|
NzAbstractImage* oldLayer = layer.image.get();
|
||||||
|
|
||||||
|
std::unique_ptr<NzAbstractImage> newImage(ResizeImage(layer.image.get(), size));
|
||||||
|
if (!newImage)
|
||||||
|
return false; // Nous n'avons pas pu allouer
|
||||||
|
|
||||||
|
if (newImage.get() == oldLayer) // Le layer a été agrandi dans le même objet, pas de souci
|
||||||
|
{
|
||||||
|
newImage.release(); // On possède déjà un unique_ptr sur cette ressource
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On indique à ceux que ça intéresse qu'on a changé de pointeur
|
||||||
|
// (chose très importante pour ceux qui le stockent)
|
||||||
|
NotifyLayerChange(layer.image.get(), newImage.get());
|
||||||
|
|
||||||
|
// Et on ne met à jour le pointeur qu'après (car cette ligne libère également l'ancienne image)
|
||||||
|
layer.image = std::move(newImage);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzGuillotineImageAtlas::ProcessGlyphQueue(Layer& layer) const
|
||||||
|
{
|
||||||
|
std::vector<nzUInt8> pixelBuffer;
|
||||||
|
|
||||||
|
for (QueuedGlyph& glyph : layer.queuedGlyphs)
|
||||||
|
{
|
||||||
|
unsigned int glyphWidth = glyph.image.GetWidth();
|
||||||
|
unsigned int glyphHeight = glyph.image.GetHeight();
|
||||||
|
|
||||||
|
// Calcul de l'éventuel padding (pixels de contour)
|
||||||
|
unsigned int paddingX;
|
||||||
|
unsigned int paddingY;
|
||||||
|
if (glyph.flipped)
|
||||||
|
{
|
||||||
|
paddingX = (glyph.rect.height - glyphWidth)/2;
|
||||||
|
paddingY = (glyph.rect.width - glyphHeight)/2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paddingX = (glyph.rect.width - glyphWidth)/2;
|
||||||
|
paddingY = (glyph.rect.height - glyphHeight)/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paddingX > 0 || paddingY > 0)
|
||||||
|
{
|
||||||
|
// On remplit les contours
|
||||||
|
pixelBuffer.resize(glyph.rect.width * glyph.rect.height);
|
||||||
|
std::memset(pixelBuffer.data(), 0, glyph.rect.width*glyph.rect.height*sizeof(nzUInt8));
|
||||||
|
|
||||||
|
layer.image->Update(pixelBuffer.data(), glyph.rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nzUInt8* pixels;
|
||||||
|
// On copie le glyphe dans l'atlas
|
||||||
|
if (glyph.flipped)
|
||||||
|
{
|
||||||
|
pixelBuffer.resize(glyphHeight * glyphWidth);
|
||||||
|
|
||||||
|
// On tourne le glyphe pour qu'il rentre dans le rectangle
|
||||||
|
const nzUInt8* src = glyph.image.GetConstPixels();
|
||||||
|
nzUInt8* ptr = pixelBuffer.data();
|
||||||
|
|
||||||
|
unsigned int lineStride = glyphWidth*sizeof(nzUInt8); // BPP = 1
|
||||||
|
src += lineStride-1; // Départ en haut à droite
|
||||||
|
for (unsigned int x = 0; x < glyphWidth; ++x)
|
||||||
|
{
|
||||||
|
for (unsigned int y = 0; y < glyphHeight; ++y)
|
||||||
|
{
|
||||||
|
*ptr++ = *src;
|
||||||
|
src += lineStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
src -= glyphHeight*lineStride + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels = pixelBuffer.data();
|
||||||
|
std::swap(glyphWidth, glyphHeight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pixels = glyph.image.GetConstPixels();
|
||||||
|
|
||||||
|
layer.image->Update(pixels, NzRectui(glyph.rect.x + paddingX, glyph.rect.y + paddingY, glyphWidth, glyphHeight), 0, glyphWidth, glyphHeight);
|
||||||
|
glyph.image.Destroy(); // On libère l'image dès que possible (pour réduire la consommation)
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.queuedGlyphs.clear();
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
#include <Nazara/Utility/Image.hpp>
|
#include <Nazara/Utility/Image.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <Nazara/Utility/Config.hpp>
|
#include <Nazara/Utility/Config.hpp>
|
||||||
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
@ -43,15 +45,8 @@ m_sharedImage(&emptyImage)
|
||||||
NzImage::NzImage(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount) :
|
NzImage::NzImage(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount) :
|
||||||
m_sharedImage(&emptyImage)
|
m_sharedImage(&emptyImage)
|
||||||
{
|
{
|
||||||
|
NzErrorFlags flags(nzErrorFlag_ThrowException);
|
||||||
Create(type, format, width, height, depth, levelCount);
|
Create(type, format, width, height, depth, levelCount);
|
||||||
|
|
||||||
#ifdef NAZARA_DEBUG
|
|
||||||
if (!m_sharedImage)
|
|
||||||
{
|
|
||||||
NazaraError("Failed to create image");
|
|
||||||
throw std::runtime_error("Constructor failed");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzImage::NzImage(const NzImage& image) :
|
NzImage::NzImage(const NzImage& image) :
|
||||||
|
|
@ -62,12 +57,6 @@ m_sharedImage(image.m_sharedImage)
|
||||||
m_sharedImage->refCount++;
|
m_sharedImage->refCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzImage::NzImage(NzImage&& image) noexcept :
|
|
||||||
m_sharedImage(image.m_sharedImage)
|
|
||||||
{
|
|
||||||
image.m_sharedImage = &emptyImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzImage::NzImage(SharedImage* sharedImage) :
|
NzImage::NzImage(SharedImage* sharedImage) :
|
||||||
m_sharedImage(sharedImage)
|
m_sharedImage(sharedImage)
|
||||||
{
|
{
|
||||||
|
|
@ -590,11 +579,6 @@ bool NzImage::FlipVertically()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt8 NzImage::GetBytesPerPixel() const
|
|
||||||
{
|
|
||||||
return NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level) const
|
const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned int z, nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
|
@ -680,6 +664,49 @@ nzUInt8 NzImage::GetMaxLevel() const
|
||||||
return GetMaxLevel(m_sharedImage->type, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
return GetMaxLevel(m_sharedImage->type, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int NzImage::GetMemoryUsage() const
|
||||||
|
{
|
||||||
|
unsigned int width = m_sharedImage->width;
|
||||||
|
unsigned int height = m_sharedImage->height;
|
||||||
|
unsigned int depth = m_sharedImage->depth;
|
||||||
|
|
||||||
|
unsigned int size = 0;
|
||||||
|
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
||||||
|
{
|
||||||
|
size += width * height * depth;
|
||||||
|
|
||||||
|
if (width > 1)
|
||||||
|
width >>= 1;
|
||||||
|
|
||||||
|
if (height > 1)
|
||||||
|
height >>= 1;
|
||||||
|
|
||||||
|
if (depth > 1)
|
||||||
|
depth >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_sharedImage->type == nzImageType_Cubemap)
|
||||||
|
size *= 6;
|
||||||
|
|
||||||
|
return size * NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzImage::GetMemoryUsage(nzUInt8 level) const
|
||||||
|
{
|
||||||
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
if (level >= m_sharedImage->levelCount)
|
||||||
|
{
|
||||||
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (GetLevelSize(m_sharedImage->width, level)) *
|
||||||
|
(GetLevelSize(m_sharedImage->height, level)) *
|
||||||
|
((m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) *
|
||||||
|
NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
|
}
|
||||||
|
|
||||||
NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) const
|
NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
|
@ -776,34 +803,7 @@ nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUI
|
||||||
return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzImage::GetSize() const
|
NzVector3ui NzImage::GetSize(nzUInt8 level) const
|
||||||
{
|
|
||||||
unsigned int width = m_sharedImage->width;
|
|
||||||
unsigned int height = m_sharedImage->height;
|
|
||||||
unsigned int depth = m_sharedImage->depth;
|
|
||||||
|
|
||||||
unsigned int size = 0;
|
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
|
||||||
{
|
|
||||||
size += width * height * depth;
|
|
||||||
|
|
||||||
if (width > 1)
|
|
||||||
width >>= 1;
|
|
||||||
|
|
||||||
if (height > 1)
|
|
||||||
height >>= 1;
|
|
||||||
|
|
||||||
if (depth > 1)
|
|
||||||
depth >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_sharedImage->type == nzImageType_Cubemap)
|
|
||||||
size *= 6;
|
|
||||||
|
|
||||||
return size * NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int NzImage::GetSize(nzUInt8 level) const
|
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levelCount)
|
||||||
|
|
@ -813,10 +813,7 @@ unsigned int NzImage::GetSize(nzUInt8 level) const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (GetLevelSize(m_sharedImage->width, level)) *
|
return NzVector3ui(GetLevelSize(m_sharedImage->width, level), GetLevelSize(m_sharedImage->height, level), GetLevelSize(m_sharedImage->depth, level));
|
||||||
(GetLevelSize(m_sharedImage->height, level)) *
|
|
||||||
((m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) *
|
|
||||||
NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nzImageType NzImage::GetType() const
|
nzImageType NzImage::GetType() const
|
||||||
|
|
@ -837,16 +834,6 @@ unsigned int NzImage::GetWidth(nzUInt8 level) const
|
||||||
return GetLevelSize(m_sharedImage->width, level);
|
return GetLevelSize(m_sharedImage->width, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::IsCompressed() const
|
|
||||||
{
|
|
||||||
return NzPixelFormat::IsCompressed(m_sharedImage->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzImage::IsCubemap() const
|
|
||||||
{
|
|
||||||
return m_sharedImage->type == nzImageType_Cubemap;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzImage::IsValid() const
|
bool NzImage::IsValid() const
|
||||||
{
|
{
|
||||||
return m_sharedImage != &emptyImage;
|
return m_sharedImage != &emptyImage;
|
||||||
|
|
@ -1122,7 +1109,7 @@ void NzImage::SetLevelCount(nzUInt8 levelCount)
|
||||||
|
|
||||||
nzUInt8 oldLevelCount = m_sharedImage->levelCount;
|
nzUInt8 oldLevelCount = m_sharedImage->levelCount;
|
||||||
nzUInt8 maxLevelCount = std::max(levelCount, oldLevelCount);
|
nzUInt8 maxLevelCount = std::max(levelCount, oldLevelCount);
|
||||||
m_sharedImage->levelCount = levelCount; // Pour faire fonctionner GetSize
|
m_sharedImage->levelCount = levelCount; // Pour faire fonctionner GetMemoryUsage
|
||||||
|
|
||||||
nzUInt8** pixels = new nzUInt8*[levelCount];
|
nzUInt8** pixels = new nzUInt8*[levelCount];
|
||||||
for (unsigned int i = 0; i < maxLevelCount; ++i)
|
for (unsigned int i = 0; i < maxLevelCount; ++i)
|
||||||
|
|
@ -1130,7 +1117,7 @@ void NzImage::SetLevelCount(nzUInt8 levelCount)
|
||||||
if (i < oldLevelCount)
|
if (i < oldLevelCount)
|
||||||
pixels[i] = m_sharedImage->pixels[i];
|
pixels[i] = m_sharedImage->pixels[i];
|
||||||
else if (i < levelCount)
|
else if (i < levelCount)
|
||||||
pixels[i] = new nzUInt8[GetSize(i)];
|
pixels[i] = new nzUInt8[GetMemoryUsage(i)];
|
||||||
else
|
else
|
||||||
delete[] m_sharedImage->pixels[i];
|
delete[] m_sharedImage->pixels[i];
|
||||||
}
|
}
|
||||||
|
|
@ -1186,25 +1173,25 @@ bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
bool NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (m_sharedImage == &emptyImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pixels)
|
if (!pixels)
|
||||||
{
|
{
|
||||||
NazaraError("Invalid pixel source");
|
NazaraError("Invalid pixel source");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levelCount)
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1216,27 +1203,29 @@ void NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int
|
||||||
GetLevelSize(m_sharedImage->depth, level),
|
GetLevelSize(m_sharedImage->depth, level),
|
||||||
0, 0,
|
0, 0,
|
||||||
srcWidth, srcHeight);
|
srcWidth, srcHeight);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
bool NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (m_sharedImage == &emptyImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
NazaraError("Image must be valid");
|
NazaraError("Image must be valid");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pixels)
|
if (!pixels)
|
||||||
{
|
{
|
||||||
NazaraError("Invalid pixel source");
|
NazaraError("Invalid pixel source");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levelCount)
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1247,15 +1236,15 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src
|
||||||
if (!box.IsValid())
|
if (!box.IsValid())
|
||||||
{
|
{
|
||||||
NazaraError("Invalid box");
|
NazaraError("Invalid box");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois (Nous prenons donc la profondeur de base)
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level);
|
||||||
///FIXME: Ce code n'autorise même pas la modification d'une autre face du cubemap Oo
|
if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > depth ||
|
||||||
if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > GetLevelSize(m_sharedImage->depth, level))
|
(m_sharedImage->type == nzImageType_Cubemap && box.depth > 1)) // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois
|
||||||
{
|
{
|
||||||
NazaraError("Box dimensions are out of bounds");
|
NazaraError("Box dimensions are out of bounds");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1268,64 +1257,13 @@ void NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src
|
||||||
box.width, box.height, box.depth,
|
box.width, box.height, box.depth,
|
||||||
width, height,
|
width, height,
|
||||||
srcWidth, srcHeight);
|
srcWidth, srcHeight);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, nzUInt8 level)
|
||||||
{
|
{
|
||||||
///FIXME: Cette surcharge possède-t-elle la moindre utilité ? (Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, ..) devrait donner le même résultat
|
return Update(pixels, NzBoxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level);
|
||||||
#if NAZARA_UTILITY_SAFE
|
|
||||||
if (m_sharedImage == &emptyImage)
|
|
||||||
{
|
|
||||||
NazaraError("Image must be valid");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pixels)
|
|
||||||
{
|
|
||||||
NazaraError("Invalid pixel source");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rect.IsValid())
|
|
||||||
{
|
|
||||||
NazaraError("Invalid rectangle");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
|
||||||
{
|
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int width = GetLevelSize(m_sharedImage->width, level);
|
|
||||||
unsigned int height = GetLevelSize(m_sharedImage->height, level);
|
|
||||||
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
|
||||||
if (rect.x+rect.width > width || rect.y+rect.height > height)
|
|
||||||
{
|
|
||||||
NazaraError("Rectangle dimensions are out of bounds");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level);
|
|
||||||
if (z >= depth)
|
|
||||||
{
|
|
||||||
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= " + NzString::Number(depth) + ')');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EnsureOwnership();
|
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
|
||||||
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, rect.x, rect.y, z, width, height);
|
|
||||||
|
|
||||||
Copy(dstPixels, pixels, bpp,
|
|
||||||
rect.width, rect.height, 1,
|
|
||||||
width, height,
|
|
||||||
srcWidth, srcHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzImage& NzImage::operator=(const NzImage& image)
|
NzImage& NzImage::operator=(const NzImage& image)
|
||||||
|
|
@ -1339,13 +1277,6 @@ NzImage& NzImage::operator=(const NzImage& image)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzImage& NzImage::operator=(NzImage&& image) noexcept
|
|
||||||
{
|
|
||||||
std::swap(m_sharedImage, image.m_sharedImage);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzImage::Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth, unsigned int dstWidth, unsigned int dstHeight, unsigned int srcWidth, unsigned int srcHeight)
|
void NzImage::Copy(nzUInt8* destination, const nzUInt8* source, nzUInt8 bpp, unsigned int width, unsigned int height, unsigned int depth, unsigned int dstWidth, unsigned int dstHeight, unsigned int srcWidth, unsigned int srcHeight)
|
||||||
{
|
{
|
||||||
if (dstWidth == 0)
|
if (dstWidth == 0)
|
||||||
|
|
@ -1434,7 +1365,7 @@ void NzImage::EnsureOwnership()
|
||||||
nzUInt8** pixels = new nzUInt8*[m_sharedImage->levelCount];
|
nzUInt8** pixels = new nzUInt8*[m_sharedImage->levelCount];
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
||||||
{
|
{
|
||||||
unsigned int size = GetSize(i);
|
unsigned int size = GetMemoryUsage(i);
|
||||||
pixels[i] = new nzUInt8[size];
|
pixels[i] = new nzUInt8[size];
|
||||||
std::memcpy(pixels[i], m_sharedImage->pixels[i], size);
|
std::memcpy(pixels[i], m_sharedImage->pixels[i], size);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int s
|
||||||
Reset(largeIndices, buffer, startOffset, endOffset);
|
Reset(largeIndices, buffer, startOffset, endOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage)
|
NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzUInt32 storage, nzBufferUsage usage)
|
||||||
{
|
{
|
||||||
NzErrorFlags(nzErrorFlag_ThrowException, true);
|
NzErrorFlags(nzErrorFlag_ThrowException, true);
|
||||||
Reset(largeIndices, length, storage, usage);
|
Reset(largeIndices, length, storage, usage);
|
||||||
|
|
@ -220,7 +220,7 @@ void NzIndexBuffer::Reset(bool largeIndices, NzBuffer* buffer, unsigned int star
|
||||||
m_startOffset = startOffset;
|
m_startOffset = startOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzIndexBuffer::Reset(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage)
|
void NzIndexBuffer::Reset(bool largeIndices, unsigned int length, nzUInt32 storage, nzBufferUsage usage)
|
||||||
{
|
{
|
||||||
unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16);
|
unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16);
|
||||||
|
|
||||||
|
|
@ -251,7 +251,7 @@ void NzIndexBuffer::Reset(NzIndexBuffer&& indexBuffer) noexcept
|
||||||
m_startOffset = indexBuffer.m_startOffset;
|
m_startOffset = indexBuffer.m_startOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzIndexBuffer::SetStorage(nzBufferStorage storage)
|
bool NzIndexBuffer::SetStorage(nzUInt32 storage)
|
||||||
{
|
{
|
||||||
return m_buffer->SetStorage(storage);
|
return m_buffer->SetStorage(storage);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (C) 2014 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_LOADERS_FREETYPE_HPP
|
||||||
|
#define NAZARA_LOADERS_FREETYPE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
|
||||||
|
void NzLoaders_FreeType_Register();
|
||||||
|
void NzLoaders_FreeType_Unregister();
|
||||||
|
|
||||||
|
#endif // NAZARA_LOADERS_FREETYPE_HPP
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue