Added RenderTextures (And many others things)

-Added Forward, left and up vector (Vector3)
-Added Matrix4::ConcatenateAffine shortcut
-Added Quaternion::GetInverse() and Quaternion::Inverse()
-Added Resource listeners
-Added Depth and stencil pixel formats
-All enums now have an ending "max" entry
-Animation/Mesh::Add[Sequence/Skin/SubMesh] now returns a boolean
-Contexts are now resources
-Enhanced AnimatedMesh demo
-Fixed MD2 facing
-Fixed Vector3::CrossProduct
-Made Resource thread-safe
-Made OpenGL translation table global
-Many bugfixes
-MLT will now write malloc failure to the log
-Most of the strcpy were replaced with faster memcpy
-Occlusion queries availability is now always tested
-OpenGL-related includes now requires NAZARA_RENDERER_OPENGL to be
defined to have any effect
-Pixel formats now have a type
-Renamed RenderTarget::IsValid to IsRenderable
-Renamed Quaternion::GetNormalized() to GetNormal()
-Renamed Texture::Bind() to Prepare()
-Renamed VectorX::Make[Ceil|Floor] to Maximize/Minimize
-Removed MATH_MATRIX_COLUMN_MAJOR option (all matrices are column-major)
-Removed RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION option (Render
windows are active upon their creation)


Former-commit-id: 0d1da1e32c156a958221edf04a5315c75b354450
This commit is contained in:
Jérôme Leclercq 2012-09-20 22:07:30 +02:00
parent a6ed70123b
commit cd5a1b7a5e
65 changed files with 24385 additions and 22703 deletions

View File

@ -2,6 +2,8 @@ if (not _OPTIONS["one-library"]) then
project "NazaraRenderer"
end
defines "NAZARA_RENDERER_OPENGL"
files
{
"../include/Nazara/Renderer/**.hpp",

View File

@ -38,9 +38,10 @@ void SetSequence(AnimatedModel& model, const NzString& name);
int main()
{
// Tout d'abord on affiche les instructions
std::cout << "Camera controls: ZQSD" << std::endl;
std::cout << "Dr. Freak controls: Up, down, left and right" << std::endl;
std::cout << "Controls: ZQSD" << std::endl;
std::cout << "Escape to quit" << std::endl;
std::cout << "Left click to capture/free the mouse" << std::endl;
std::cout << "Right click to control Dr. Freak" << std::endl;
// Cette ligne active le mode de compatibilité d'OpenGL lors de l'initialisation de Nazara (Nécessaire pour le shader)
NzContextParameters::defaultCompatibilityProfile = true;
@ -135,8 +136,8 @@ int main()
// Le sol ne subit aucune transformation
floor.matrix.MakeIdentity();
// Pour effectuer un rendu, il faut que la carte graphique sache quoi faire.
// Les shaders sont de petits programmes qui donnent des instructions à la carte graphique lors du pipeline.
// Pour effectuer un rendu, il faut que la carte graphique sache comment le faire.
// Les shaders sont de petits programmes qui donnent des instructions à la carte graphique lors de son pipeline.
// Ils sont aujourd'hui indispensables pour un rendu 3D, mais sont très utiles pour divers effets !
// Il existe plusieurs langages de shaders, GLSL pour OpenGL, HLSL pour Direct3D et Cg qui peut être utilisé pour les deux.
// Le Renderer de Nazara utilise OpenGL, par conséquent nous utiliserons le GLSL
@ -152,6 +153,8 @@ int main()
// Une fois le shader créé, nous devons lui spécifier les codes sources de nos shaders
// Pour notre exemple nous prendrons un shader très simple
// Un shader doit obligatoirement posséder au moins deux codes, un pour le fragment shader et un pour le vertex shader
// Le fragment shader traite la couleur de nos pixels
if (!shader.LoadFromFile(nzShaderType_Fragment, "shaders/basic.frag"))
{
std::cout << "Failed to load fragment shader from file" << std::endl;
@ -161,7 +164,7 @@ int main()
return EXIT_FAILURE;
}
// Maintenant le vertex shader
// Le vertex shader (Transformation des vertices de l'espace 3D vers l'espace écran)
if (!shader.LoadFromFile(nzShaderType_Vertex, "shaders/basic.vert"))
{
std::cout << "Failed to load vertex shader from file" << std::endl;
@ -170,7 +173,7 @@ int main()
return EXIT_FAILURE;
}
// Une fois le code source de nos shaders chargé, nous pouvons le compiler, afin de le rendre utilisable
// Une fois les codes sources de notre shader chargé, nous pouvons le compiler, afin de le rendre utilisable
if (!shader.Compile())
{
std::cout << "Failed to compile shader" << std::endl;
@ -182,25 +185,34 @@ int main()
// Nos ressources sont chargées, et c'est bien beau, mais il nous faudrait une fenêtre pour afficher tout ça
// Window représente une fenêtre singulière, pour y effectuer un rendu il nous faut une RenderWindow
// Tout d'abord, sa taille, disons celle du bureau divisé par deux
NzVideoMode mode = NzVideoMode::GetDesktopMode();
// Un VideoMode est une structure contenant une longueur (width), une largeur (height) et le nombre de bits par pixels (bitsPerPixel)
NzVideoMode mode = NzVideoMode::GetDesktopMode(); // Nous récupérons le mode actuellement utilisé par le bureau
// Nous divisons sa longueur et sa largeur par deux
mode.width /= 2;
mode.height /= 2;
NzString title = "Nazara Demo - AnimatedMesh";
// Maintenant le titre, rien de plus simple...
NzString windowTitle = "Nazara Demo - AnimatedMesh";
// Nous pouvons créer notre fenêtre ! (Via le constructeur directement ou par la méthode Create)
NzRenderWindow window;
// Le premier argument définit la taille de rendu de la fenêtre (Si elle possède une bordure elle sera légèrement plus grande)
// Le deuxième argument est le titre de la fenêtre lors de sa création, vous pouvez le modifier à tout moment via window.SetTitle
// Le premier argument définit la taille de rendu de la fenêtre (Si elle possède une bordure elle sera légèrement plus grande).
// Le deuxième argument est le titre de la fenêtre lors de sa création, vous pouvez le modifier à tout moment via window.SetTitle.
// Le troisième argument représente la décoration de la fenêtre, sa bordure, ses boutons.
// Attention que cela permet à la fenêtre d'envoyer des évènements, et de changer sa taille
// Attention que cela permet à la fenêtre de changer sa taille et qu'il faudra donc traiter l'évènement.
// Par défaut le troisième argument vaut nzWindowStyle_Default (Bordure + Bouton de fermeture + Redimensionnement)
if (!window.Create(mode, title, nzWindowStyle_Default))
if (!window.Create(mode, windowTitle, nzWindowStyle_Default))
{
std::cout << "Failed to create window" << std::endl;
std::getchar();
return EXIT_FAILURE;
}
// Notre belle fenêtre est créée, nous pouvons la configurer
// On cache le curseur
window.SetCursor(nzWindowCursor_None);
@ -215,40 +227,27 @@ int main()
unsigned int fps = 0; // Compteur de FPS
// Quelques variables pour notre improvisation de physique
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Pas très exact
NzVector3f modelPos(0.f, groundPos, -50.f);
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Les coordonnées locales du "bas" du modèle
NzVector3f modelPos(0.f, -groundPos, -50.f);
NzVector3f modelVel(0.f, 0.f, 0.f);
NzQuaternionf modelRot(NzEulerAnglesf(0.f, 0.f, 0.f)); // Les angles d'eulers sont bien plus facile à se représenter
float speed = 60.f;
NzQuaternionf modelOrient(NzQuaternionf::Identity());
NzEulerAnglesf modelRot(0.f, 0.f, 0.f);
float modelSpeed = 150.f;
// Nous initialisons la matrice
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
drfreak.matrix = NzMatrix4f::Rotate(modelOrient) * NzMatrix4f::Translate(modelPos);
// Notre caméra
NzVector3f camPos(0.f, 25.f, -20.f);
NzEulerAnglesf camRot(0.f, 0.f, 0.f);
NzQuaternionf camOrient(NzQuaternionf::Identity());
NzEulerAnglesf camRot(0.f, 0.f, 0.f); // Les angles d'eulers sont bien plus facile à utiliser
NzMatrix4f camMatrix = NzMatrix4f::Translate(camPos);
float camSpeed = 2.f;
float sensitivity = 0.5;
float camSpeed = 100.f;
float sensitivity = 0.8f;
// Dernière étape, nos touches
// Chaque touche fera bouger
struct Movement
{
NzVector3f direction; // La direction
NzQuaternionf rotation; // La rotation du modèle
};
std::map<NzKeyboard::Key, Movement> movements;
movements[NzKeyboard::Up] = Movement{NzVector3f(0.f, 0.f, -1.f), NzQuaternionf(NzEulerAnglesf(0.f, 180.f, 0.f))};
movements[NzKeyboard::Down] = Movement{NzVector3f(0.f, 0.f, 1.f), NzQuaternionf(NzEulerAnglesf(0.f, 0.f, 0.f))};
movements[NzKeyboard::Left] = Movement{NzVector3f(-1.f, 0.f, 0.f), NzQuaternionf(NzEulerAnglesf(0.f, 90.f, 0.f))};
movements[NzKeyboard::Right] = Movement{NzVector3f(1.f, 0.f, 0.f), NzQuaternionf(NzEulerAnglesf(0.f, -90.f, 0.f))};
NzKeyboard::Key currentKey = NzKeyboard::Undefined;
// Quelques booléens
// Quelques variables
bool camMode = true;
bool thirdPerson = false;
bool windowOpen = true;
// On peut commencer la boucle du programme
@ -258,36 +257,38 @@ int main()
NzEvent event;
while (window.PollEvent(&event)) // Avons-nous un évènement dans la file ?
{
// Nous avons un évènement
// Nous avons un évènement !
switch (event.type) // De quel type est cet évènement ?
{
case nzEventType_Quit: // L'utilisateur/L'OS nous a demandé de terminer notre exécution
windowOpen = false; // Nous terminons alors la boucle
break;
case nzEventType_MouseMoved:
case nzEventType_MouseMoved: // La souris a bougé
{
// Si nous ne sommes pas en mode caméra, on ne traite pas l'évènement
if (!camMode)
// Si nous ne sommes pas en mode free-fly, on ne traite pas l'évènement
if (!camMode || thirdPerson)
break;
// On modifie l'angle de la caméra grâce au déplacement relatif de la souris
camRot.yaw = NzNormalizeAngle(camRot.yaw - event.mouseMove.deltaX*sensitivity);
// Pour éviter les loopings, on restreint les angles
camRot.pitch = NzClamp(camRot.pitch + event.mouseMove.deltaY*sensitivity, -90.f, 90.f);
// Pour éviter les loopings mais surtout les problèmes de calculation de la matrice de vue, on restreint les angles
camRot.pitch = NzClamp(camRot.pitch - event.mouseMove.deltaY*sensitivity, -89.f, 89.f);
// La matrice vue représente les transformations effectuées par la caméra
// On recalcule la matrice de la caméra et on l'envoie au renderer
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot));
camOrient = camRot; // Conversion des angles d'euler en quaternion
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::LookAt(camPos, camPos + camOrient * NzVector3f::Forward()));
// Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre
NzMouse::SetPosition(window.GetWidth()/2, window.GetHeight()/2, window);
break;
}
case nzEventType_MouseButtonPressed:
if (event.mouseButton.button == NzMouse::Left)
case nzEventType_MouseButtonPressed: // L'utilisateur (ou son chat) vient de cliquer sur la souris
if (event.mouseButton.button == NzMouse::Left) // Est-ce le clic gauche ?
{
// L'utilisateur vient d'appuyer sur le bouton left de la souris
// Nous allons inverser le mode caméra et montrer/cacher le curseur en conséquence
@ -301,44 +302,54 @@ int main()
camMode = true;
window.SetCursor(nzWindowCursor_None);
}
}
else if (event.mouseButton.button == NzMouse::Right) // Est-ce le clic droit ?
{
if (thirdPerson)
{
// On arrête le mouvement
SetSequence(drfreak, "stand");
// Afin de synchroniser le quaternion avec les angles d'euler
camRot = camOrient.ToEulerAngles();
thirdPerson = false;
}
else
thirdPerson = true;
}
break;
case nzEventType_Resized: // L'utilisateur a changé notre taille, le coquin !
case nzEventType_Resized: // L'utilisateur a changé la taille de la fenêtre, le coquin !
NzRenderer::SetViewport(NzRectui(0, 0, event.size.width, event.size.height)); // Adaptons l'affichage
// Il nous faut aussi mettre à jour notre matrice de projection
NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(event.size.width)/event.size.height, 1.f, 1000.f));
break;
case nzEventType_KeyPressed:
if (!event.key.repeated) // Si la touche n'est pas répétée
case nzEventType_KeyPressed: // Une touche du clavier vient d'être enfoncée
if (thirdPerson &&
(event.key.code == NzKeyboard::Z || // Est-ce la touche Z ?
event.key.code == NzKeyboard::S || // Ou bien la touche S ?
event.key.code == NzKeyboard::Q || // Ou encore la touche Q ?
event.key.code == NzKeyboard::D)) // Et pourquoi pas la touche D ?
{
auto it = movements.find(event.key.code);
if (it != movements.end())
{
// Si la touche est une touche de mouvement
SetSequence(drfreak, "run"); // On anime le personnage pour qu'il ait une animation de déplacement
modelRot = it->second.rotation; // On change la rotation du modèle
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos); // On recalcule sa matrice
modelVel = it->second.direction * speed; // On change la vitesse de déplacement
currentKey = event.key.code;
}
// Si une touche concernant le déplacement est appuyée
SetSequence(drfreak, "run"); // On anime le personnage pour qu'il ait une animation de déplacement
}
if (event.key.code == NzKeyboard::Escape)
else if (event.key.code == NzKeyboard::Escape)
windowOpen = false;
break;
case nzEventType_KeyReleased:
if (event.key.code == currentKey)
case nzEventType_KeyReleased: // Une touche du clavier vient d'être relachée
if (thirdPerson &&
!NzKeyboard::IsKeyPressed(NzKeyboard::Z) && // Est-ce que la touche Z est enfoncée en ce moment ?
!NzKeyboard::IsKeyPressed(NzKeyboard::S) && // Ou bien la touche S ?
!NzKeyboard::IsKeyPressed(NzKeyboard::Q) && // Etc..
!NzKeyboard::IsKeyPressed(NzKeyboard::D)) // Etc..
{
// Si plus aucune touche de déplacement n'est enfoncée
SetSequence(drfreak, "stand");
modelVel = NzVector3f(0.f); // On arrête le déplacement
break;
}
break;
@ -348,81 +359,115 @@ int main()
}
}
// On active le shader et paramètrons le rendu
NzRenderer::SetShader(&shader);
NzRenderer::Enable(nzRendererParameter_DepthTest, true);
NzRenderer::SetClearColor(128, 128, 128);
NzRenderer::Clear(nzRendererClear_Color | nzRendererClear_Depth);
// Mise à jour de la partie logique
if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde
{
float elapsedTime = updateClock.GetSeconds(); // Le temps depuis la dernière mise à jour
// Déplacement de la caméra
static const NzVector3f forward(NzVector3f::UnitZ());
static const NzVector3f left(NzVector3f::UnitX());
static const NzVector3f up(NzVector3f::UnitY());
static const NzVector3f forward(NzVector3f::Forward());
static const NzVector3f left(NzVector3f::Left());
static const NzVector3f up(NzVector3f::Up());
// Notre rotation sous forme de quaternion nous permet de tourner un vecteur
NzQuaternionf quaternion(camRot);
// Par exemple ici, quaternion * forward nous permet de récupérer le vecteur de la direction "avant"
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
camPos += quaternion * forward * camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
camPos -= quaternion * forward * camSpeed;
if (thirdPerson)
{
// Nous déplaçons le personnage en fonction des touches pressées
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
camPos += quaternion * left * camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
modelPos += modelOrient * forward * modelSpeed * elapsedTime;
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
camPos -= quaternion * left * camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
modelPos -= modelOrient * forward * modelSpeed * elapsedTime;
// En revanche, ici la hauteur est toujours la même, peu importe notre orientation
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
camPos += up * camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
modelRot.yaw += camSpeed * elapsedTime;
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
camPos -= up * camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
modelRot.yaw -= camSpeed * elapsedTime;
// Oui le quaternion et la matrice sont calculés même si la caméra ne bouge pas
modelOrient = modelRot;
}
else
{
// Sinon, c'est la caméra qui se déplace (en fonction des mêmes touches)
// Un boost en maintenant le shift gauche
float speed = (NzKeyboard::IsKeyPressed(NzKeyboard::Key::LShift)) ? camSpeed*5 : camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
camPos += camOrient * forward * speed * elapsedTime;
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
camPos -= camOrient * forward * speed * elapsedTime;
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
camPos += camOrient * left * speed * elapsedTime;
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
camPos -= camOrient * left * speed * elapsedTime;
// En revanche, ici la hauteur est toujours la même, peu importe notre orientation
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
camPos += up * speed * elapsedTime;
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
camPos -= up * speed * elapsedTime;
}
// Oui les quaternions et les matrices sont calculés même si la caméra ne bouge pas
// C'est une limitation de mon implémentation, qui ne sera pas présente une fois les NzSceneNode intégrés
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot));
if (thirdPerson)
{
static NzQuaternionf rotDown(NzEulerAnglesf(-15.f, 0.f, 0.f)); // Une rotation pour regarder vers le bas
camOrient = modelOrient * rotDown;
camPos = modelPos + camOrient * NzVector3f(0.f, 25.f, 60.f);
}
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::LookAt(camPos, camPos + camOrient * NzVector3f::Forward()));
// Mise à jour de la matrice du personnage
drfreak.matrix = NzMatrix4f::Rotate(modelOrient) * NzMatrix4f::Translate(modelPos);
// Animation
AnimateModel(drfreak, elapsedTime);
updateClock.Restart();
// "Physique"
if (modelVel != NzVector3f::Zero())
{
modelPos += modelVel * elapsedTime;
// Mise à jour de la matrice
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
}
}
// On active le shader et paramètrons le rendu
NzRenderer::SetShader(&shader);
// Notre scène 3D requiert un test de profondeur
NzRenderer::Enable(nzRendererParameter_DepthTest, true);
// Nous voulons avoir un fond bien gris
NzRenderer::SetClearColor(128, 128, 128);
// Et nous effaçons les buffers de couleur et de profondeur
NzRenderer::Clear(nzRendererClear_Color | nzRendererClear_Depth);
// Affichage des meshs
DrawModel(floor);
// Notre Dr. Freak possède des normales, nous pouvons alors culler les faces qu'on ne voit pas
// Notre Dr. Freak possède des normales, nous pouvons alors éliminer les faces qu'on ne voit pas
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
DrawModel(drfreak);
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
window.Display(); // Nous mettons à jour l'écran
// Nous mettons à jour l'écran
window.Display();
fps++;
// Toutes les secondes
if (secondClock.GetMilliseconds() >= 1000)
{
window.SetTitle(title + " (FPS: " + NzString::Number(fps) + ')');
window.SetTitle(windowTitle + " (FPS: " + NzString::Number(fps) + ')');
fps = 0;
secondClock.Restart();
}
@ -567,10 +612,10 @@ bool CreateFloorMesh(NzMesh* mesh)
mesh->AddSubMesh(subMesh);
// Nos ressources sont notifiées utilisées par le mesh et le submesh, nous pouvons les rendre éphèmères.
// Les ressources seront donc automatiquement libérées lorsque plus aucune classe n'en aura besoin
// Les ressources seront donc automatiquement libérées lorsqu'elles ne seront plus référencées par une classe
buffer->SetPersistent(false);
declaration->SetPersistent(false);
subMesh->SetPersistent(false); // Pour le submesh, c'est déjà à false à la base
subMesh->SetPersistent(false); // Pour le submesh, c'est déjà le comportement par défaut
return true;
}
@ -606,8 +651,12 @@ void SetSequence(AnimatedModel& model, const NzString& sequenceName)
const NzAnimation* animation = model.mesh.GetAnimation();
// Nous nous basons sur l'assertion que la séquence existe (Chose que nous pouvons tester avec HasSequence())
model.currentSequence = animation->GetSequence(sequenceName);
const NzSequence* sequence = animation->GetSequence(sequenceName);
if (model.currentSequence != sequence)
{
model.currentSequence = sequence;
// Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame
model.nextFrame = model.currentSequence->firstFrame;
// Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame
model.nextFrame = model.currentSequence->firstFrame;
}
}

View File

@ -52,6 +52,7 @@
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/String.hpp>

View File

@ -67,6 +67,7 @@
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
#define NAZARA_THREADSAFETY_RESOURCE 1 // NzResource
#define NAZARA_THREADSAFETY_STRING 1 // NzString (COW)
#define NAZARA_THREADSAFETY_STRINGSTREAM 0 // NzStringStream

View File

@ -12,7 +12,9 @@ enum nzEndianness
nzEndianness_Unknown = -1,
nzEndianness_BigEndian,
nzEndianness_LittleEndian
nzEndianness_LittleEndian,
nzEndianness_Max = nzEndianness_LittleEndian
};
enum nzErrorType
@ -20,7 +22,9 @@ enum nzErrorType
nzErrorType_AssertFailed,
nzErrorType_Internal,
nzErrorType_Normal,
nzErrorType_Warning
nzErrorType_Warning,
nzErrorType_Max = nzErrorType_Warning
};
#endif // NAZARA_ENUMS_CORE_HPP

View File

@ -8,6 +8,32 @@
#define NAZARA_RESOURCE_HPP
#include <Nazara/Prerequesites.hpp>
#include <set>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
class NzResourceListener;
struct NzResourceEntry
{
NzResourceEntry(NzResourceListener* resourceListener, int i = 0) :
listener(resourceListener),
index(i)
{
}
bool operator<(const NzResourceEntry& rhs) const
{
return listener < rhs.listener;
}
NzResourceListener* listener;
int index;
};
class NAZARA_API NzResource
{
@ -16,14 +42,30 @@ class NAZARA_API NzResource
NzResource(const NzResource& resource);
virtual ~NzResource();
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
void AddResourceReference() const;
bool IsPersistent() const;
void RemoveResourceListener(NzResourceListener* listener) const;
void RemoveResourceReference() const;
void SetPersistent(bool persistent = true);
protected:
void NotifyCreated();
void NotifyDestroy();
private:
void EnsureResourceListenerUpdate() const;
NazaraMutexAttrib(m_mutex, mutable)
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
mutable bool m_resourcePersistent;
mutable std::set<NzResourceEntry> m_resourceListeners;
mutable std::set<NzResourceEntry> m_resourceListenersCache;
mutable bool m_resourceListenerUpdated;
bool m_resourcePersistent;
mutable unsigned int m_resourceReferenceCount;
};

View File

@ -0,0 +1,25 @@
// Copyright (C) 2012 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
#pragma once
#ifndef NAZARA_RESOURCELISTENER_HPP
#define NAZARA_RESOURCELISTENER_HPP
#include <Nazara/Prerequesites.hpp>
class NzResource;
class NAZARA_API NzResourceListener
{
public:
NzResourceListener() = default;
virtual ~NzResourceListener();
virtual void OnResourceCreated(const NzResource* resource, int index);
virtual void OnResourceDestroy(const NzResource* resource, int index);
virtual void OnResourceReleased(const NzResource* resource, int index);
};
#endif // NAZARA_RESOURCELISTENER_HPP

View File

@ -15,7 +15,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzSt
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid Parameters");
NazaraError("Invalid parameters");
return false;
}
#endif
@ -81,7 +81,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid Parameters");
NazaraError("Invalid parameters");
return false;
}
@ -117,7 +117,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
template<typename Type, typename Parameters>
void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
{
/// Trouver une alternative à ce code monstrueux
///FIXME: Trouver une alternative à ce code monstrueux
std::vector<NzString> exts;
fileExtensions.SplitAny(exts, " /\\.,;|-_");

View File

@ -301,7 +301,7 @@ class NAZARA_API NzString : public NzHashable
};
static SharedString emptyString;
static unsigned int npos;
static const unsigned int npos;
private:
void EnsureOwnership();

View File

@ -33,9 +33,6 @@
// Définit le radian comme l'unité utilisée pour les angles
#define NAZARA_MATH_ANGLE_RADIAN 0
// Définit la disposition des matrices en colonnes (Façon OpenGL)
#define NAZARA_MATH_MATRIX_COLUMN_MAJOR 1
// Optimise les opérations entre matrices affines (Demande plusieurs comparaisons pour déterminer si une matrice est affine)
#define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0

View File

@ -38,6 +38,7 @@ template<typename T> class NzMatrix4
~NzMatrix4();
NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
NzMatrix4 ConcatenateAffine(const NzMatrix4& matrix) const;
T GetDeterminant() const;
NzMatrix4 GetInverse() const;
@ -54,7 +55,7 @@ template<typename T> class NzMatrix4
bool IsDefined() const;
void MakeIdentity();
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up);
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
void MakePerspective(T angle, T ratio, T zNear, T zFar);
void MakeRotation(const NzQuaternion<T>& rotation);
@ -106,7 +107,7 @@ template<typename T> class NzMatrix4
static NzMatrix4 Concatenate(const NzMatrix4& m1, const NzMatrix4& m2);
static NzMatrix4 ConcatenateAffine(const NzMatrix4& m1, const NzMatrix4& m2);
static NzMatrix4 Identity();
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up);
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
static NzMatrix4 Ortho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar);
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);

View File

@ -74,6 +74,12 @@ NzMatrix4<T> NzMatrix4<T>::Concatenate(const NzMatrix4& matrix) const
return Concatenate(*this, matrix);
}
template<typename T>
NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& matrix) const
{
return ConcatenateAffine(*this, matrix);
}
template<typename T>
T NzMatrix4<T>::GetDeterminant() const
{
@ -162,11 +168,7 @@ NzVector3<T> NzMatrix4<T>::GetTranslation() const
}
#endif
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
return NzVector3<T>(m_sharedMatrix->m41, m_sharedMatrix->m42, m_sharedMatrix->m43);
#else
return NzVector3<T>(m_sharedMatrix->m14, m_sharedMatrix->m24, m_sharedMatrix->m34);
#endif
}
template<typename T>
@ -229,17 +231,10 @@ bool NzMatrix4<T>::IsAffine() const
}
#endif
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
return NzNumberEquals(m_sharedMatrix->m14, F(0.0)) &&
NzNumberEquals(m_sharedMatrix->m24, F(0.0)) &&
NzNumberEquals(m_sharedMatrix->m34, F(0.0)) &&
NzNumberEquals(m_sharedMatrix->m44, F(1.0));
#else
return NzNumberEquals(m_sharedMatrix->m41, F(0.0)) &&
NzNumberEquals(m_sharedMatrix->m42, F(0.0)) &&
NzNumberEquals(m_sharedMatrix->m43, F(0.0)) &&
NzNumberEquals(m_sharedMatrix->m44, F(1.0));
#endif
}
template<typename T>
@ -260,86 +255,80 @@ void NzMatrix4<T>::MakeIdentity()
template<typename T>
void NzMatrix4<T>::MakeOrtho(T left, T top, T width, T height, T zNear, T zFar)
{
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb204941(v=vs.85).aspx
Set(F(2.0)/(width-left), F(0.0), F(0.0), -(width+left)/(width-left),
F(0.0), F(2.0)/(top-height), F(0.0), -(top+height)/(top-height),
F(0.0), F(0.0), F(-2.0)/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
F(0.0), F(0.0), F(0.0), F(1.0));
#else
Set(F(2.0)/(width-left), F(0.0), F(0.0), F(0.0),
F(0.0), F(2.0)/(top-height), F(0.0), F(0.0),
F(0.0), F(0.0), F(-2.0)/(zFar-zNear), F(0.0),
-(width+left)/(width-left), -(top+height)/(top-height), -(zFar+zNear)/(zFar-zNear), F(1.0));
#endif
}
template<typename T>
void NzMatrix4<T>::MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up)
void NzMatrix4<T>::MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
{
// http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml
NzVector3<T> f = center - eye;
f.Normalize();
NzVector3<T> u = up;
u.Normalize();
NzVector3<T> s = f.CrossProduct(u);
NzVector3<T> f = NzVector3<T>::Normalize(target - eye);
NzVector3<T> u(up.GetNormal());
NzVector3<T> s = NzVector3<T>::Normalize(f.CrossProduct(u));
u = s.CrossProduct(f);
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
Set(s.x, s.y, s.z, F(0.0),
u.x, u.y, u.z, F(0.0),
-f.x, -f.y, -f.z, F(0.0),
F(0.0), F(0.0), F(0.0), F(1.0));
#else
Set(s.x, u.x, -f.x, F(0.0),
s.y, u.y, -f.y, F(0.0),
s.z, u.z, -f.z, F(0.0),
F(0.0), F(0.0), F(0.0), F(1.0));
#endif
Concatenate(Translate(-eye));
Set(s.x, u.x, -f.x, T(0.0),
s.y, u.y, -f.y, T(0.0),
s.z, u.z, -f.z, T(0.0),
-s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0));
}
template<typename T>
void NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb204944(v=vs.85).aspx
#if NAZARA_MATH_ANGLE_RADIAN
angle /= F(2.0);
#else
angle = NzDegreeToRadian(angle/2);
angle = NzDegreeToRadian(angle/F(2.0));
#endif
T f = F(1.0) / std::tan(angle);
T yScale = F(1.0) / std::tan(angle);
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
Set(f / ratio, F(0.0), F(0.0), F(0.0),
F(0.0), f, F(0.0), F(0.0),
F(0.0), F(0.0), (zNear+zFar) / (zNear-zFar), F(-1.0),
F(0.0), F(0.0), (F(2.0)*zNear*zFar) / (zNear-zFar), F(1.0));
#else
Set(f / ratio, F(0.0), F(0.0), F(0.0),
F(0.0), f, F(0.0), F(0.0),
F(0.0), F(0.0), (zNear+zFar) / (zNear-zFar), (F(2.0)*zNear*zFar) / (zNear-zFar),
F(0.0), F(0.0), F(-1.0), F(1.0));
#endif
Set(yScale / ratio, F(0.0), F(0.0), F(0.0),
F(0.0), yScale, F(0.0), F(0.0),
F(0.0), F(0.0), zFar / (zNear-zFar), F(-1.0),
F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.0));
}
template<typename T>
void NzMatrix4<T>::MakeRotation(const NzQuaternion<T>& rotation)
{
// http://stackoverflow.com/questions/1556260/convert-quaternion-rotation-to-rotation-matrix
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
Set(F(1.0) - F(2.0)*rotation.y*rotation.y - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w, F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w, F(0.0),
F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w, F(0.0),
F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w, F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y, F(0.0),
F(0.0), F(0.0), F(0.0), F(1.0));
#else
Set(F(1.0) - F(2.0)*rotation.y*rotation.y - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w, F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w, F(0.0),
F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w, F(0.0),
F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w, F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y, F(0.0),
F(0.0), F(0.0), F(0.0), F(1.0));
#endif
// http://www.flipcode.com/documents/matrfaq.html#Q54
/*
| 2 2 |
| 1 - 2Y - 2Z 2XY + 2ZW 2XZ - 2YW |
| |
| 2 2 |
M = | 2XY - 2ZW 1 - 2X - 2Z 2YZ + 2XW |
| |
| 2 2 |
| 2XZ + 2YW 2YZ - 2XW 1 - 2X - 2Y |
| |
*/
///FIXME: À corriger (Rotation quaternino != rotation matricielle)
Set(F(1.0) - F(2.0)*rotation.y*rotation.y - F(2.0)*rotation.z*rotation.z,
F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w,
F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w,
F(0.0),
F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w,
F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z,
F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w,
F(0.0),
F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w,
F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w,
F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y,
F(0.0),
F(0.0),
F(0.0),
F(0.0),
F(1.0));
}
template<typename T>
@ -354,17 +343,10 @@ void NzMatrix4<T>::MakeScale(const NzVector3<T>& scale)
template<typename T>
void NzMatrix4<T>::MakeTranslation(const NzVector3<T>& translation)
{
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
Set(F(1.0), F(0.0), F(0.0), F(0.0),
F(0.0), F(1.0), F(0.0), F(0.0),
F(0.0), F(0.0), F(1.0), F(0.0),
translation.x, translation.y, translation.z, F(1.0));
#else
Set(F(1.0), F(0.0), F(0.0), translation.x,
F(0.0), F(1.0), F(0.0), translation.y,
F(0.0), F(0.0), F(1.0), translation.z,
F(0.0), F(0.0), F(0.0), F(1.0));
#endif
}
template<typename T>
@ -451,21 +433,12 @@ void NzMatrix4<T>::SetRotation(const NzQuaternion<T>& rotation)
m_sharedMatrix->m22 = F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z;
m_sharedMatrix->m33 = F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y;
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
m_sharedMatrix->m12 = F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w;
m_sharedMatrix->m13 = F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w;
m_sharedMatrix->m21 = F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w;
m_sharedMatrix->m23 = F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w;
m_sharedMatrix->m31 = F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w;
m_sharedMatrix->m32 = F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w;
#else
m_sharedMatrix->m12 = F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w;
m_sharedMatrix->m13 = F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w;
m_sharedMatrix->m21 = F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w;
m_sharedMatrix->m23 = F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w;
m_sharedMatrix->m31 = F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w;
m_sharedMatrix->m32 = F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w;
#endif
}
template<typename T>
@ -483,17 +456,10 @@ void NzMatrix4<T>::SetTranslation(const NzVector3<T>& translation)
{
EnsureOwnership();
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
m_sharedMatrix->m41 = translation.x;
m_sharedMatrix->m42 = translation.y;
m_sharedMatrix->m43 = translation.z;
m_sharedMatrix->m44 = F(1.0);
#else
m_sharedMatrix->m14 = translation.x;
m_sharedMatrix->m24 = translation.y;
m_sharedMatrix->m34 = translation.z;
m_sharedMatrix->m44 = F(1.0);
#endif
}
template<typename T>
@ -832,7 +798,6 @@ NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& m1, const NzMatrix
}
#endif
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
return NzMatrix4(m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m31,
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m32,
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m33,
@ -852,27 +817,6 @@ NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& m1, const NzMatrix
m1.m_sharedMatrix->m41*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m42*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m43*m2.m_sharedMatrix->m32 + m2.m_sharedMatrix->m42,
m1.m_sharedMatrix->m41*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m42*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m43*m2.m_sharedMatrix->m33 + m2.m_sharedMatrix->m43,
F(1.0));
#else
return NzMatrix4(m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m31,
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m32,
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m33,
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m14 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m24 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m34 + m1.m_sharedMatrix->m14,
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m31,
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m32,
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m33,
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m14 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m24 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m34 + m1.m_sharedMatrix->m24,
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m31,
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m32,
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m33,
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m14 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m24 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m34 + m1.m_sharedMatrix->m34,
F(0.0),
F(0.0),
F(0.0),
F(1.0));
#endif
}
template<typename T>
@ -885,10 +829,10 @@ NzMatrix4<T> NzMatrix4<T>::Identity()
}
template<typename T>
NzMatrix4<T> NzMatrix4<T>::LookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up)
NzMatrix4<T> NzMatrix4<T>::LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
{
NzMatrix4 matrix;
matrix.MakeLookAt(eye, center, up);
matrix.MakeLookAt(eye, target, up);
return matrix;
}

View File

@ -28,7 +28,10 @@ template<typename T> class NzQuaternion
T DotProduct(const NzQuaternion& vec) const;
NzQuaternion GetConjugate() const;
NzQuaternion GetNormalized() const;
NzQuaternion GetInverse() const;
NzQuaternion GetNormal() const;
void Inverse();
void MakeIdentity();
void MakeZero();

View File

@ -67,7 +67,16 @@ NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetNormalized() const
NzQuaternion<T> NzQuaternion<T>::GetInverse() const
{
NzQuaternion<T> quat(*this);
quat.Inverse();
return quat;
}
template<typename T>
NzQuaternion<T> NzQuaternion<T>::GetNormal() const
{
NzQuaternion<T> quat(*this);
quat.Normalize();
@ -75,16 +84,31 @@ NzQuaternion<T> NzQuaternion<T>::GetNormalized() const
return quat;
}
template<typename T>
void NzQuaternion<T>::Inverse()
{
T norm = SquaredMagnitude();
if (norm > F(0.0))
{
T invNorm = F(1.0) / norm;
w *= invNorm;
x *= -invNorm;
y *= -invNorm;
z *= -invNorm;
}
}
template<typename T>
void NzQuaternion<T>::MakeIdentity()
{
Set(1.0, 0.0, 0.0, 0.0);
Set(F(1.0), F(0.0), F(0.0), F(0.0));
}
template<typename T>
void NzQuaternion<T>::MakeZero()
{
Set(0.0, 0.0, 0.0, 0.0);
Set(F(0.0), F(0.0), F(0.0), F(0.0));
}
template<typename T>
@ -98,16 +122,18 @@ T NzQuaternion<T>::Normalize()
{
T squaredMagnitude = SquaredMagnitude();
if (squaredMagnitude-F(1.0) > std::numeric_limits<T>::epsilon())
// Inutile de vérifier si la magnitude au carrée est négative (Elle ne peut pas l'être)
if (!NzNumberEquals(squaredMagnitude, F(1.0)))
{
T magnitude = std::sqrt(squaredMagnitude);
T norm = std::sqrt(squaredMagnitude);
T invNorm = F(1.0) / norm;
w /= magnitude;
x /= magnitude;
y /= magnitude;
z /= magnitude;
w *= invNorm;
x *= invNorm;
y *= invNorm;
z *= invNorm;
return magnitude;
return norm;
}
else
return F(1.0); // Le quaternion est déjà normalisé
@ -132,20 +158,24 @@ void NzQuaternion<T>::Set(T quat[4])
}
template<typename T>
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& normalizedAxis)
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& axis)
{
angle /= F(2.0);
#if !NAZARA_MATH_ANGLE_RADIAN
angle = NzDegreeToRadian(angle);
#endif
angle /= 2;
NzVector3<T> normalizedAxis = axis.GetNormal();
auto sinAngle = std::sin(angle);
T sinAngle = std::sin(angle);
w = std::cos(angle);
x = normalizedAxis.x * sinAngle;
y = normalizedAxis.y * sinAngle;
z = normalizedAxis.z * sinAngle;
Normalize();
}
template<typename T>
@ -190,12 +220,8 @@ NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
if (test < F(-0.499))
return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
T xx = x*x;
T yy = y*y;
T zz = z*z;
return NzEulerAngles<T>(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*xx - F(2.0)*zz)),
NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*yy - F(2.0)*zz)),
return NzEulerAngles<T>(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x* - F(2.0)*z*z)),
NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)),
NzRadians(std::asin(F(2.0)*test)));
}
@ -242,14 +268,13 @@ NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
template<typename T>
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
{
NzVector3<T> normal(vec);
normal.Normalize();
NzQuaternion qvec(0.0, normal.x, normal.y, normal.z);
NzQuaternion result(operator*(qvec * GetConjugate()));
return NzVector3<T>(result.x, result.y, result.z);
NzVector3f quatVec(x, y, z);
NzVector3f uv = quatVec.CrossProduct(vec);
NzVector3f uuv = quatVec.CrossProduct(uv);
uv *= F(2.0) * w;
uuv *= F(2.0);
return vec + uv + uuv;
}
template<typename T>

View File

@ -29,14 +29,15 @@ template<typename T> class NzVector2
NzVector2 GetNormal() const;
void MakeCeil(const NzVector2& vec);
void MakeFloor(const NzVector2& vec);
T Length() const;
float Lengthf() const;
void MakeUnitX();
void MakeUnitY();
void MakeZero();
T Length() const;
float Lengthf() const;
void Maximize(const NzVector2& vec);
void Minimize(const NzVector2& vec);
void Normalize();

View File

@ -99,26 +99,6 @@ float NzVector2<T>::Lengthf() const
return std::sqrt(static_cast<float>(SquaredLength()));
}
template<typename T>
void NzVector2<T>::MakeCeil(const NzVector2& vec)
{
if (vec.x > x)
x = vec.x;
if (vec.y > y)
y = vec.y;
}
template<typename T>
void NzVector2<T>::MakeFloor(const NzVector2& vec)
{
if (vec.x < x)
x = vec.x;
if (vec.y < y)
y = vec.y;
}
template<typename T>
void NzVector2<T>::MakeUnitX()
{
@ -137,6 +117,26 @@ void NzVector2<T>::MakeZero()
Set(F(0.0), F(0.0));
}
template<typename T>
void NzVector2<T>::Maximize(const NzVector2& vec)
{
if (vec.x > x)
x = vec.x;
if (vec.y > y)
y = vec.y;
}
template<typename T>
void NzVector2<T>::Minimize(const NzVector2& vec)
{
if (vec.x < x)
x = vec.x;
if (vec.y < y)
y = vec.y;
}
template<typename T>
void NzVector2<T>::Normalize()
{

View File

@ -36,13 +36,17 @@ template<typename T> class NzVector3
T Length() const;
float Lengthf() const;
void MakeCeil(const NzVector3& vec);
void MakeFloor(const NzVector3& vec);
void MakeForward();
void MakeLeft();
void MakeUnitX();
void MakeUnitY();
void MakeUnitZ();
void MakeUp();
void MakeZero();
void Maximize(const NzVector3& vec);
void Minimize(const NzVector3& vec);
void Normalize();
void Set(T X, T Y, T Z);
@ -88,9 +92,15 @@ template<typename T> class NzVector3
bool operator>(const NzVector3& vec) const;
bool operator>=(const NzVector3& vec) const;
static NzVector3 CrossProduct(const NzVector3& vec1, const NzVector3& vec2);
static T DotProduct(const NzVector3& vec1, const NzVector3& vec2);
static NzVector3 Forward();
static NzVector3 Left();
static NzVector3 Normalize(const NzVector3& vec);
static NzVector3 UnitX();
static NzVector3 UnitY();
static NzVector3 UnitZ();
static NzVector3 Up();
static NzVector3 Zero();
T x, y, z;

View File

@ -69,7 +69,7 @@ inline unsigned int NzVector3<unsigned int>::AbsDotProduct(const NzVector3<unsig
template<typename T>
NzVector3<T> NzVector3<T>::CrossProduct(const NzVector3& vec) const
{
return NzVector3(y * vec.z - z * vec.y, z * vec.x - x * vec.y, x * vec.y - y * vec.x);
return NzVector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
}
template<typename T>
@ -100,29 +100,27 @@ NzVector3<T> NzVector3<T>::GetNormal() const
}
template<typename T>
void NzVector3<T>::MakeCeil(const NzVector3& vec)
T NzVector3<T>::Length() const
{
if (vec.x > x)
x = vec.x;
if (vec.y > y)
y = vec.y;
if (vec.z > z)
z = vec.z;
return std::sqrt(SquaredLength());
}
template<typename T>
void NzVector3<T>::MakeFloor(const NzVector3& vec)
float NzVector3<T>::Lengthf() const
{
if (vec.x < x)
x = vec.x;
return std::sqrt(static_cast<float>(SquaredLength()));
}
if (vec.y < y)
y = vec.y;
template<typename T>
void NzVector3<T>::MakeForward()
{
Set(F(0.0), F(0.0), F(-1.0));
}
if (vec.z < z)
z = vec.z;
template<typename T>
void NzVector3<T>::MakeLeft()
{
Set(F(-1.0), F(0.0), F(0.0));
}
template<typename T>
@ -143,6 +141,12 @@ void NzVector3<T>::MakeUnitZ()
Set(F(0.0), F(0.0), F(1.0));
}
template<typename T>
void NzVector3<T>::MakeUp()
{
Set(F(0.0), F(1.0), F(0.0));
}
template<typename T>
void NzVector3<T>::MakeZero()
{
@ -150,15 +154,29 @@ void NzVector3<T>::MakeZero()
}
template<typename T>
T NzVector3<T>::Length() const
void NzVector3<T>::Maximize(const NzVector3& vec)
{
return std::sqrt(SquaredLength());
if (vec.x > x)
x = vec.x;
if (vec.y > y)
y = vec.y;
if (vec.z > z)
z = vec.z;
}
template<typename T>
float NzVector3<T>::Lengthf() const
void NzVector3<T>::Minimize(const NzVector3& vec)
{
return std::sqrt(static_cast<float>(SquaredLength()));
if (vec.x < x)
x = vec.x;
if (vec.y < y)
y = vec.y;
if (vec.z < z)
z = vec.z;
}
template<typename T>
@ -166,13 +184,13 @@ void NzVector3<T>::Normalize()
{
T squaredLength = SquaredLength();
if (squaredLength-F(1.0) > std::numeric_limits<T>::epsilon())
if (!NzNumberEquals(squaredLength, F(1.0)))
{
T length = std::sqrt(squaredLength);
T invLength = F(1.0) / std::sqrt(squaredLength);
x /= length;
y /= length;
z /= length;
x *= invLength;
y *= invLength;
z *= invLength;
}
}
@ -467,6 +485,42 @@ bool NzVector3<T>::operator>=(const NzVector3& vec) const
return !operator<(vec);
}
template<typename T>
NzVector3<T> NzVector3<T>::CrossProduct(const NzVector3& vec1, const NzVector3& vec2)
{
return vec1.CrossProduct(vec2);
}
template<typename T>
T NzVector3<T>::DotProduct(const NzVector3& vec1, const NzVector3& vec2)
{
return vec1.DotProduct(vec2);
}
template<typename T>
NzVector3<T> NzVector3<T>::Forward()
{
NzVector3 vector;
vector.MakeForward();
return vector;
}
template<typename T>
NzVector3<T> NzVector3<T>::Left()
{
NzVector3 vector;
vector.MakeLeft();
return vector;
}
template<typename T>
NzVector3<T> NzVector3<T>::Normalize(const NzVector3& vec)
{
return vec.GetNormal();
}
template<typename T>
NzVector3<T> NzVector3<T>::UnitX()
{
@ -494,6 +548,15 @@ NzVector3<T> NzVector3<T>::UnitZ()
return vector;
}
template<typename T>
NzVector3<T> NzVector3<T>::Up()
{
NzVector3 vector;
vector.MakeUp();
return vector;
}
template<typename T>
NzVector3<T> NzVector3<T>::Zero()
{

View File

@ -26,13 +26,14 @@ template<typename T> class NzVector4
T DotProduct(const NzVector4& vec) const;
void MakeCeil(const NzVector4& vec);
void MakeFloor(const NzVector4& vec);
void MakeUnitX();
void MakeUnitY();
void MakeUnitZ();
void MakeZero();
void Maximize(const NzVector4& vec);
void Minimize(const NzVector4& vec);
void Normalize();
void Set(T X, T Y, T Z, T W = 1.0);

View File

@ -73,38 +73,6 @@ T NzVector4<T>::DotProduct(const NzVector4& vec) const
return x*vec.x + y*vec.y + z*vec.z + w*vec.w;
}
template<typename T>
void NzVector4<T>::MakeCeil(const NzVector4& vec)
{
if (vec.x > x)
x = vec.x;
if (vec.y > y)
y = vec.y;
if (vec.z > z)
z = vec.z;
if (vec.w > w)
w = vec.w;
}
template<typename T>
void NzVector4<T>::MakeFloor(const NzVector4& vec)
{
if (vec.x < x)
x = vec.x;
if (vec.y < y)
y = vec.y;
if (vec.z < z)
z = vec.z;
if (vec.w < w)
w = vec.w;
}
template<typename T>
void NzVector4<T>::MakeUnitX()
{
@ -129,6 +97,38 @@ void NzVector4<T>::MakeZero()
Set(F(0.0), F(0.0), F(0.0), F(0.0));
}
template<typename T>
void NzVector4<T>::Maximize(const NzVector4& vec)
{
if (vec.x > x)
x = vec.x;
if (vec.y > y)
y = vec.y;
if (vec.z > z)
z = vec.z;
if (vec.w > w)
w = vec.w;
}
template<typename T>
void NzVector4<T>::Minimize(const NzVector4& vec)
{
if (vec.x < x)
x = vec.x;
if (vec.y < y)
y = vec.y;
if (vec.z < z)
z = vec.z;
if (vec.w < w)
w = vec.w;
}
template<typename T>
void NzVector4<T>::Normalize()
{

View File

@ -35,6 +35,7 @@
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/RenderTargetParameters.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Renderer/RenderWindow.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/Texture.hpp>

View File

@ -29,9 +29,6 @@
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Active une fenêtre de rendu (NzRenderWindow) lors de sa création
#define NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION 1
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 0

View File

@ -2,20 +2,19 @@
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#ifdef NAZARA_RENDERER_COMMON
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
#endif
#pragma once
#ifndef NAZARA_CONTEXT_HPP
#define NAZARA_CONTEXT_HPP
#ifdef NAZARA_RENDERER_OPENGL
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Renderer/ContextParameters.hpp>
class NzContextImpl;
class NAZARA_API NzContext
class NAZARA_API NzContext : public NzResource
{
friend NzContextImpl;
@ -25,6 +24,7 @@ class NAZARA_API NzContext
bool Create(const NzContextParameters& parameters = NzContextParameters());
void Destroy();
const NzContextParameters& GetParameters() const;
bool IsActive() const;
bool SetActive(bool active);
@ -44,4 +44,6 @@ class NAZARA_API NzContext
static NzContext* s_reference;
};
#endif // NAZARA_RENDERER_OPENGL
#endif // NAZARA_CONTEXT_HPP

View File

@ -7,6 +7,16 @@
#ifndef NAZARA_ENUMS_RENDERER_HPP
#define NAZARA_ENUMS_RENDERER_HPP
enum nzAttachmentPoint
{
nzAttachmentPoint_Color,
nzAttachmentPoint_Depth,
nzAttachmentPoint_DepthStencil,
nzAttachmentPoint_Stencil,
nzAttachmentPoint_Max = nzAttachmentPoint_Stencil
};
enum nzBlendFunc
{
nzBlendFunc_DestAlpha,
@ -18,21 +28,27 @@ enum nzBlendFunc
nzBlendFunc_InvSrcAlpha,
nzBlendFunc_InvSrcColor,
nzBlendFunc_One,
nzBlendFunc_Zero
nzBlendFunc_Zero,
nzBlendFunc_Max = nzBlendFunc_Zero
};
enum nzFaceCulling
{
nzFaceCulling_Back,
nzFaceCulling_Front,
nzFaceCulling_FrontAndBack
nzFaceCulling_FrontAndBack,
nzFaceCulling_Max = nzFaceCulling_FrontAndBack
};
enum nzFaceFilling
{
nzFaceFilling_Point,
nzFaceFilling_Line,
nzFaceFilling_Fill
nzFaceFilling_Fill,
nzFaceFilling_Max = nzFaceFilling_Fill
};
enum nzMatrixType
@ -47,7 +63,9 @@ enum nzMatrixType
enum nzPixelBufferType
{
nzPixelBufferType_Pack,
nzPixelBufferType_Unpack
nzPixelBufferType_Unpack,
nzPixelBufferType_Max = nzPixelBufferType_Unpack
};
enum nzRendererCap
@ -58,6 +76,7 @@ enum nzRendererCap
nzRendererCap_MultipleRenderTargets,
nzRendererCap_OcclusionQuery,
nzRendererCap_PixelBufferObject,
nzRendererCap_RenderTexture,
nzRendererCap_Texture3D,
nzRendererCap_TextureCubemap,
nzRendererCap_TextureMulti,
@ -66,7 +85,7 @@ enum nzRendererCap
nzRendererCap_Max = nzRendererCap_TextureNPOT
};
enum nzRendererClear
enum nzRendererClearFlags
{
nzRendererClear_Color = 0x01,
nzRendererClear_Depth = 0x02,
@ -81,7 +100,9 @@ enum nzRendererComparison
nzRendererComparison_GreaterOrEqual,
nzRendererComparison_Less,
nzRendererComparison_LessOrEqual,
nzRendererComparison_Never
nzRendererComparison_Never,
nzRendererComparison_Max = nzRendererComparison_Never
};
enum nzRendererParameter
@ -91,15 +112,19 @@ enum nzRendererParameter
nzRendererParameter_DepthTest,
nzRendererParameter_DepthWrite,
nzRendererParameter_FaceCulling,
nzRendererParameter_Stencil
nzRendererParameter_Stencil,
nzRendererParameter_Max = nzRendererParameter_Stencil
};
enum nzShaderLanguage
{
nzShaderLanguage_Unknown,
nzShaderLanguage_Unknown = -1,
nzShaderLanguage_Cg,
nzShaderLanguage_GLSL
nzShaderLanguage_GLSL,
nzShaderLanguage_Max = nzShaderLanguage_GLSL
};
enum nzShaderType
@ -120,22 +145,30 @@ enum nzStencilOperation
nzStencilOperation_Invert,
nzStencilOperation_Keep,
nzStencilOperation_Replace,
nzStencilOperation_Zero
nzStencilOperation_Zero,
nzStencilOperation_Max = nzStencilOperation_Zero
};
enum nzTextureFilter
{
nzTextureFilter_Unknown = -1,
nzTextureFilter_Bilinear,
nzTextureFilter_Nearest,
nzTextureFilter_Trilinear,
nzTextureFilter_Unknown
nzTextureFilter_Max = nzTextureFilter_Trilinear
};
enum nzTextureWrap
{
nzTextureWrap_Unknown = -1,
nzTextureWrap_Clamp,
nzTextureWrap_Repeat,
nzTextureWrap_Unknown
nzTextureWrap_Max = nzTextureWrap_Repeat
};
#endif // NAZARA_ENUMS_RENDERER_HPP

View File

@ -2,19 +2,19 @@
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#ifdef NAZARA_RENDERER_COMMON
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
#endif
#pragma once
#ifndef NAZARA_OPENGL_HPP
#define NAZARA_OPENGL_HPP
#ifdef NAZARA_RENDERER_OPENGL
// gl3.h définit WIN32_LEAN_AND_MEAN qui entre en conflit avec la définition de Nazara et doit donc être inclut en premier
#include <GL3/glcorearb.h>
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Enums.hpp>
#include <Nazara/Renderer/Enums.hpp>
// Inclusion des extensions
#include <GL3/glext.h>
@ -24,35 +24,69 @@
#include <GL3/glxext.h>
#endif
enum nzOpenGLExtension
{
nzOpenGLExtension_AnisotropicFilter,
nzOpenGLExtension_DebugOutput,
nzOpenGLExtension_FP64,
nzOpenGLExtension_FrameBufferObject,
nzOpenGLExtension_PixelBufferObject,
nzOpenGLExtension_SeparateShaderObjects,
nzOpenGLExtension_TextureArray,
nzOpenGLExtension_TextureCompression_s3tc,
nzOpenGLExtension_TextureStorage,
nzOpenGLExtension_VertexArrayObject,
nzOpenGLExtension_Max = nzOpenGLExtension_VertexArrayObject
};
using NzOpenGLFunc = void (*)();
class NAZARA_API NzOpenGL
namespace NzOpenGL
{
public:
enum Extension
{
AnisotropicFilter,
DebugOutput,
FP64,
FrameBufferObject,
PixelBufferObject,
SeparateShaderObjects,
Texture3D,
TextureArray,
TextureCompression_s3tc,
TextureStorage,
VertexArrayObject,
enum FormatType
{
FormatType_RenderBuffer,
// FormatType_MultisampleTexture,
FormatType_Texture
};
Max = VertexArrayObject
};
struct Format
{
GLenum dataFormat;
GLenum dataType;
GLint internalFormat;
};
static NzOpenGLFunc GetEntry(const NzString& entryPoint);
static unsigned int GetVersion();
static bool Initialize();
static bool IsSupported(Extension extension);
static bool IsSupported(const NzString& string);
static void Uninitialize();
};
NzOpenGLFunc GetEntry(const NzString& entryPoint);
unsigned int GetVersion();
bool Initialize();
bool IsSupported(nzOpenGLExtension extension);
bool IsSupported(const NzString& string);
bool TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType target);
void Uninitialize();
extern GLenum Attachment[nzAttachmentPoint_Max+1];
extern nzUInt8 AttributeIndex[nzElementUsage_Max+1];
extern GLenum BlendFunc[nzBlendFunc_Max+1];
extern GLenum BufferLock[nzBufferAccess_Max+1];
extern GLenum BufferLockRange[nzBufferAccess_Max+1];
extern GLenum BufferTarget[nzBufferType_Max+1];
extern GLenum BufferTargetBinding[nzBufferType_Max+1];
extern GLenum BufferUsage[nzBufferUsage_Max+1];
extern GLenum CubemapFace[6]; // Un cube possède six faces et ça n'est pas prêt de changer
extern GLenum ElementType[nzElementType_Max+1];
extern GLenum FaceCulling[nzFaceCulling_Max+1];
extern GLenum FaceFilling[nzFaceFilling_Max+1];
extern GLenum PrimitiveType[nzPrimitiveType_Max+1];
extern GLenum RendererComparison[nzRendererComparison_Max+1];
extern GLenum RendererParameter[nzRendererParameter_Max+1];
extern GLenum ShaderType[nzShaderType_Max+1];
extern GLenum StencilOperation[nzStencilOperation_Max+1];
extern GLenum TextureTarget[nzImageType_Max+1];
extern GLenum TextureTargetBinding[nzImageType_Max+1];
extern GLenum TextureTargetProxy[nzImageType_Max+1];
}
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
@ -60,6 +94,7 @@ NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery;
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
NAZARA_API extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
@ -99,7 +134,11 @@ NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
NAZARA_API extern PFNGLFLUSHPROC glFlush;
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
NAZARA_API extern PFNGLENABLEPROC glEnable;
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
@ -189,4 +228,6 @@ NAZARA_API extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
NAZARA_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval;
#endif
#endif // NAZARA_RENDERER_OPENGL
#endif // NAZARA_OPENGL_HPP

View File

@ -21,19 +21,18 @@ class NAZARA_API NzRenderTarget
NzRenderTarget() = default;
virtual ~NzRenderTarget();
#ifndef NAZARA_RENDERER_COMMON
virtual bool HasContext() const = 0;
#endif
virtual unsigned int GetHeight() const = 0;
virtual NzRenderTargetParameters GetParameters() const = 0;
virtual unsigned int GetWidth() const = 0;
bool IsActive() const;
virtual bool IsValid() const = 0;
virtual bool IsRenderable() const = 0;
bool SetActive(bool active);
// Fonctions OpenGL
virtual bool HasContext() const = 0;
protected:
virtual bool Activate() = 0;
virtual void Desactivate();

View File

@ -0,0 +1,60 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RENDERTEXTURE_HPP
#define NAZARA_RENDERTEXTURE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/Texture.hpp>
struct NzRenderTextureImpl;
class NAZARA_API NzRenderTexture : public NzRenderTarget, NzResourceListener, NzNonCopyable
{
public:
NzRenderTexture() = default;
~NzRenderTexture();
bool AttachBuffer(nzAttachmentPoint attachmentPoint, nzUInt8 index, nzPixelFormat format);
bool AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture);
bool AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture, unsigned int z);
bool Create(unsigned int width, unsigned int height, bool lock = false);
void Destroy();
void Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index);
unsigned int GetHeight() const;
NzRenderTargetParameters GetParameters() const;
unsigned int GetWidth() const;
bool IsComplete() const;
bool IsRenderable() const;
bool IsValid() const;
bool Lock() const;
void Unlock() const;
// Fonctions OpenGL
bool HasContext() const;
static bool IsSupported();
protected:
bool Activate() override;
void Desactivate() override;
private:
void OnResourceDestroy(const NzResource* resource, int index) override;
NzRenderTextureImpl* m_impl = nullptr;
};
#endif // NAZARA_RENDERTEXTURE_HPP

View File

@ -39,28 +39,25 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
void EnableVerticalSync(bool enabled);
#ifndef NAZARA_RENDERER_COMMON
NzContextParameters GetContextParameters() const;
#endif
unsigned int GetHeight() const;
NzRenderTargetParameters GetParameters() const;
unsigned int GetWidth() const;
#ifndef NAZARA_RENDERER_COMMON
bool HasContext() const;
#endif
bool IsRenderable() const;
bool IsValid() const;
void SetFramerateLimit(unsigned int limit);
// Fonctions OpenGL
NzContextParameters GetContextParameters() const;
bool HasContext() const;
protected:
virtual bool Activate() override;
bool Activate() override;
private:
virtual void OnWindowDestroying() override;
virtual bool OnWindowCreated() override;
bool OnWindowCreated() override;
void OnWindowDestroy() override;
NzClock m_clock;
NzContextParameters m_parameters;

View File

@ -13,10 +13,12 @@
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
class NzRenderTexture;
struct NzTextureImpl;
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
{
friend NzRenderTexture;
friend class NzShader;
public:
@ -24,10 +26,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
explicit NzTexture(const NzImage& image);
~NzTexture();
#ifndef NAZARA_RENDERER_COMMON
bool Bind() const;
#endif
bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false);
void Destroy();
@ -75,13 +73,18 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
void Unlock();
// Fonctions OpenGL
unsigned int GetOpenGLID() const;
bool Prepare() const;
static unsigned int GetValidSize(unsigned int size);
static bool IsFormatSupported(nzPixelFormat format);
static bool IsMipmappingSupported();
static bool IsTypeSupported(nzImageType type);
private:
void SetTarget(bool isTarget);
NzRenderTexture* GetRenderTexture() const;
void SetRenderTexture(NzRenderTexture* renderTexture);
NzTextureImpl* m_impl;
};

View File

@ -43,7 +43,7 @@ class NAZARA_API NzAnimation : public NzResource
NzAnimation() = default;
~NzAnimation();
unsigned int AddSequence(const NzSequence& sequence);
bool AddSequence(const NzSequence& sequence);
bool Create(nzAnimationType type, unsigned int frameCount);
void Destroy();
@ -54,6 +54,7 @@ class NAZARA_API NzAnimation : public NzResource
const NzSequence* GetSequence(const NzString& sequenceName) const;
const NzSequence* GetSequence(unsigned int index) const;
unsigned int GetSequenceCount() const;
int GetSequenceIndex(const NzString& sequenceName) const;
nzAnimationType GetType() const;
bool HasSequence(const NzString& sequenceName) const;

View File

@ -11,7 +11,9 @@ enum nzAnimationType
{
nzAnimationType_Keyframe,
nzAnimationType_Skeletal,
nzAnimationType_Static
nzAnimationType_Static,
nzAnimationType_Max = nzAnimationType_Static
};
enum nzBufferAccess
@ -19,7 +21,9 @@ enum nzBufferAccess
nzBufferAccess_DiscardAndWrite,
nzBufferAccess_ReadOnly,
nzBufferAccess_ReadWrite,
nzBufferAccess_WriteOnly
nzBufferAccess_WriteOnly,
nzBufferAccess_Max = nzBufferAccess_WriteOnly
};
enum nzBufferStorage
@ -34,13 +38,17 @@ enum nzBufferStorage
enum nzBufferType
{
nzBufferType_Index,
nzBufferType_Vertex
nzBufferType_Vertex,
nzBufferType_Max = nzBufferType_Vertex
};
enum nzBufferUsage
{
nzBufferUsage_Dynamic,
nzBufferUsage_Static
nzBufferUsage_Static,
nzBufferUsage_Max = nzBufferUsage_Static
};
enum nzCubemapFace
@ -52,7 +60,9 @@ enum nzCubemapFace
nzCubemapFace_PositiveZ = 4,
nzCubemapFace_NegativeX = 1,
nzCubemapFace_NegativeY = 3,
nzCubemapFace_NegativeZ = 5
nzCubemapFace_NegativeZ = 5,
nzCubemapFace_Max = nzCubemapFace_NegativeZ
};
enum nzElementStream
@ -73,7 +83,9 @@ enum nzElementType
nzElementType_Float1,
nzElementType_Float2,
nzElementType_Float3,
nzElementType_Float4
nzElementType_Float4,
nzElementType_Max = nzElementType_Float4
};
enum nzElementUsage
@ -103,14 +115,18 @@ enum nzEventType
nzEventType_Moved,
nzEventType_Quit,
nzEventType_Resized,
nzEventType_TextEntered
nzEventType_TextEntered,
nzEventType_Max = nzEventType_TextEntered
};
enum nzExtend
{
nzExtend_Finite,
nzExtend_Infinite,
nzExtend_Null
nzExtend_Null,
nzExtend_Max = nzExtend_Null
};
enum nzImageType
@ -129,28 +145,27 @@ enum nzPixelFormat
{
nzPixelFormat_Undefined = -1,
nzPixelFormat_BGR8, // 3*nzUInt8
nzPixelFormat_BGRA8, // 4*nzUInt8
nzPixelFormat_BGR8, // 3*nzUInt8
nzPixelFormat_BGRA8, // 4*nzUInt8
nzPixelFormat_DXT1,
nzPixelFormat_DXT3,
nzPixelFormat_DXT5,
nzPixelFormat_L8, // 1*nzUInt8
nzPixelFormat_LA8, // 2*nzUInt8
nzPixelFormat_L8, // 1*nzUInt8
nzPixelFormat_LA8, // 2*nzUInt8
/*
nzPixelFormat_RGB16F,
nzPixelFormat_RGB16I, // 4*nzUInt16
nzPixelFormat_RGB16I, // 4*nzUInt16
nzPixelFormat_RGB32F,
nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_RGBA16F,
nzPixelFormat_RGBA16I, // 4*nzUInt16
nzPixelFormat_RGBA16I, // 4*nzUInt16
nzPixelFormat_RGBA32F,
nzPixelFormat_RGBA32I, // 4*nzUInt32
nzPixelFormat_RGBA32I, // 4*nzUInt32
*/
nzPixelFormat_RGBA4, // 1*nzUInt16
nzPixelFormat_RGB5A1, // 1*nzUInt16
nzPixelFormat_RGB8, // 3*nzUInt8
nzPixelFormat_RGBA8, // 4*nzUInt8
/*
nzPixelFormat_RGBA4, // 1*nzUInt16
nzPixelFormat_RGB5A1, // 1*nzUInt16
nzPixelFormat_RGB8, // 3*nzUInt8
nzPixelFormat_RGBA8, // 4*nzUInt8
nzPixelFormat_Depth16,
nzPixelFormat_Depth24,
nzPixelFormat_Depth24Stencil8,
@ -159,9 +174,20 @@ enum nzPixelFormat
nzPixelFormat_Stencil4,
nzPixelFormat_Stencil8,
nzPixelFormat_Stencil16,
*/
nzPixelFormat_Max = nzPixelFormat_RGBA8
nzPixelFormat_Max = nzPixelFormat_Stencil16
};
enum nzPixelFormatType
{
nzPixelFormatType_Undefined = -1,
nzPixelFormatType_Color,
nzPixelFormatType_Depth,
nzPixelFormatType_DepthStencil,
nzPixelFormatType_Stencil,
nzPixelFormatType_Max = nzPixelFormatType_Stencil
};
enum nzPixelFlipping
@ -179,7 +205,9 @@ enum nzPrimitiveType
nzPrimitiveType_PointList,
nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip,
nzPrimitiveType_TriangleFan
nzPrimitiveType_TriangleFan,
nzPrimitiveType_Max = nzPrimitiveType_TriangleFan
};
enum nzWindowCursor
@ -202,10 +230,12 @@ enum nzWindowCursor
nzWindowCursor_ResizeSW,
nzWindowCursor_ResizeW,
nzWindowCursor_Text,
nzWindowCursor_Wait
nzWindowCursor_Wait,
nzWindowCursor_Max = nzWindowCursor_Wait
};
enum nzWindowStyle
enum nzWindowStyleFlags
{
nzWindowStyle_None = 0x0,
nzWindowStyle_Fullscreen = 0x1,

View File

@ -10,6 +10,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Utility/Animation.hpp>
@ -34,7 +35,7 @@ using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
struct NzMeshImpl;
class NAZARA_API NzMesh : public NzResource
class NAZARA_API NzMesh : public NzResource, NzResourceListener
{
friend NzMeshLoader;
@ -42,9 +43,9 @@ class NAZARA_API NzMesh : public NzResource
NzMesh() = default;
~NzMesh();
unsigned int AddSkin(const NzString& skin, bool setDefault = false);
nzUInt8 AddSubMesh(NzSubMesh* subMesh);
nzUInt8 AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
bool AddSkin(const NzString& skin, bool setDefault = false);
bool AddSubMesh(NzSubMesh* subMesh);
bool AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
@ -58,16 +59,17 @@ class NAZARA_API NzMesh : public NzResource
NzString GetSkin(unsigned int index = 0) const;
unsigned int GetSkinCount() const;
NzSubMesh* GetSubMesh(const NzString& identifier);
NzSubMesh* GetSubMesh(nzUInt8 index);
NzSubMesh* GetSubMesh(unsigned int index);
const NzSubMesh* GetSubMesh(const NzString& identifier) const;
const NzSubMesh* GetSubMesh(nzUInt8 index) const;
nzUInt8 GetSubMeshCount() const;
const NzSubMesh* GetSubMesh(unsigned int index) const;
unsigned int GetSubMeshCount() const;
int GetSubMeshIndex(const NzString& identifier) const;
unsigned int GetVertexCount() const;
bool HasAnimation() const;
bool HasSkin(unsigned int index = 0) const;
bool HasSubMesh(const NzString& identifier) const;
bool HasSubMesh(nzUInt8 index = 0) const;
bool HasSubMesh(unsigned int index = 0) const;
void InvalidateAABB() const;
@ -80,11 +82,14 @@ class NAZARA_API NzMesh : public NzResource
void RemoveSkin(unsigned int index = 0);
void RemoveSubMesh(const NzString& identifier);
void RemoveSubMesh(nzUInt8 index = 0);
void RemoveSubMesh(unsigned int index = 0);
bool SetAnimation(const NzAnimation* animation);
private:
void OnResourceCreated(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
NzMeshImpl* m_impl = nullptr;
static NzMeshLoader::LoaderList s_loaders;

View File

@ -28,6 +28,7 @@ class NzPixelFormat
static bool Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
static nzUInt8 GetBPP(nzPixelFormat format);
static nzPixelFormatType GetType(nzPixelFormat format);
static bool HasAlpha(nzPixelFormat format);

View File

@ -225,16 +225,79 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
case nzPixelFormat_RGBA8:
return 4;
case nzPixelFormat_Undefined:
NazaraError("Invalid pixel format");
case nzPixelFormat_Depth16:
return 2;
case nzPixelFormat_Depth24:
return 3;
case nzPixelFormat_Depth24Stencil8:
return 4;
case nzPixelFormat_Depth32:
return 4;
case nzPixelFormat_Stencil1:
NazaraWarning("This format uses less than one byte per pixel");
return 0;
case nzPixelFormat_Stencil4:
NazaraWarning("This format uses less than one byte per pixel");
return 0;
case nzPixelFormat_Stencil8:
return 1;
case nzPixelFormat_Stencil16:
return 2;
case nzPixelFormat_Undefined:
break;
}
NazaraInternalError("Invalid pixel format");
NazaraError("Invalid pixel format");
return 0;
}
inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format)
{
switch (format)
{
case nzPixelFormat_BGR8:
case nzPixelFormat_BGRA8:
case nzPixelFormat_DXT1:
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
case nzPixelFormat_L8:
case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGB8:
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
return nzPixelFormatType_Color;
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth32:
return nzPixelFormatType_Depth;
case nzPixelFormat_Depth24Stencil8:
return nzPixelFormatType_DepthStencil;
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return nzPixelFormatType_Stencil;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return nzPixelFormatType_Undefined;
}
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
{
switch (format)
@ -252,6 +315,14 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
case nzPixelFormat_DXT1:
case nzPixelFormat_L8:
case nzPixelFormat_RGB8:
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth24Stencil8:
case nzPixelFormat_Depth32:
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return false;
case nzPixelFormat_Undefined:
@ -271,9 +342,30 @@ inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
case nzPixelFormat_DXT5:
return true;
default:
case nzPixelFormat_BGRA8:
case nzPixelFormat_LA8:
case nzPixelFormat_RGB5A1:
case nzPixelFormat_RGBA4:
case nzPixelFormat_RGBA8:
case nzPixelFormat_BGR8:
case nzPixelFormat_L8:
case nzPixelFormat_RGB8:
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth24Stencil8:
case nzPixelFormat_Depth32:
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return false;
case nzPixelFormat_Undefined:
break;
}
NazaraError("Invalid pixel format");
return false;
}
inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat)
@ -360,6 +452,30 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format)
case nzPixelFormat_RGBA8:
return "RGBA8";
case nzPixelFormat_Depth16:
return "Depth16";
case nzPixelFormat_Depth24:
return "Depth24";
case nzPixelFormat_Depth24Stencil8:
return "Depth24Stencil8";
case nzPixelFormat_Depth32:
return "Depth32";
case nzPixelFormat_Stencil1:
return "Stencil1";
case nzPixelFormat_Stencil4:
return "Stencil4";
case nzPixelFormat_Stencil8:
return "Stencil8";
case nzPixelFormat_Stencil16:
return "Stencil16";
case nzPixelFormat_Undefined:
return "Undefined";
}

View File

@ -8,9 +8,10 @@
#define NAZARA_STATICMESH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Utility/SubMesh.hpp>
class NAZARA_API NzStaticMesh final : public NzSubMesh
class NAZARA_API NzStaticMesh final : public NzSubMesh, NzResourceListener
{
public:
NzStaticMesh(const NzMesh* parent);
@ -38,6 +39,7 @@ class NAZARA_API NzStaticMesh final : public NzSubMesh
private:
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
void OnResourceReleased(const NzResource* resource, int index) override;
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
NzAxisAlignedBox m_aabb;

View File

@ -46,6 +46,9 @@ class NAZARA_API NzVertexDeclaration : public NzResource
NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration);
NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept;
static unsigned int GetElementCount(nzElementType type);
static unsigned int GetElementSize(nzElementType type);
private:
NzVertexDeclarationImpl* m_sharedImpl = nullptr;
};

View File

@ -21,8 +21,8 @@
#include <queue>
#if NAZARA_UTILITY_THREADED_WINDOW
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/ThreadCondition.hpp>
#endif
class NzCursor;
@ -61,6 +61,7 @@ class NAZARA_API NzWindow : NzNonCopyable
bool IsMinimized() const;
bool IsOpen() const;
bool IsValid() const;
bool IsVisible() const;
bool PollEvent(NzEvent* event);
@ -85,8 +86,8 @@ class NAZARA_API NzWindow : NzNonCopyable
bool WaitEvent(NzEvent* event);
protected:
virtual void OnWindowDestroying();
virtual bool OnWindowCreated();
virtual void OnWindowDestroy();
NzWindowImpl* m_impl;

View File

@ -50,9 +50,6 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
{
Destroy();
if (sampleCount == 0)
return true;
#if NAZARA_AUDIO_SAFE
if (!IsFormatSupported(format))
{
@ -60,6 +57,12 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
return false;
}
if (sampleCount == 0)
{
NazaraError("Sample rate must be different from zero");
return false;
}
if (sampleRate == 0)
{
NazaraError("Sample rate must be different from zero");
@ -104,6 +107,7 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
m_impl->samples = new nzInt16[sampleCount];
std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16));
NotifyCreated();
return true;
}
@ -111,6 +115,8 @@ void NzSoundBuffer::Destroy()
{
if (m_impl)
{
NotifyDestroy();
delete[] m_impl->samples;
delete m_impl;
m_impl = nullptr;

View File

@ -1,8 +1,8 @@
/*
// Copyright (C) 2012 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
/*
#include <Nazara/Core/ByteArray.hpp>
#include <algorithm>
#include <cstring>
@ -61,7 +61,7 @@ m_sharedArray(buffer.m_sharedArray)
}
}
NzByteArray::NzByteArray(NzByteArray&& buffer) :
NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept :
m_sharedArray(buffer.m_sharedArray)
{
buffer.m_sharedArray = &emptyArray;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2012 Jérôme Leclercq
// Copyright (C) 2012 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
@ -73,7 +73,14 @@ void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file,
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
if (!ptr)
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
{
// Pas d'information de temps (Car nécessitant une allocation)
FILE* log = std::fopen(MLTFileName, "a");
std::fprintf(log, "Failed to allocate memory (%d bytes)\n", size);
std::fclose(log);
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
}
ptr->array = multi;
ptr->file = file;

View File

@ -5,6 +5,7 @@
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/Debug.hpp>
NzResource::NzResource(bool persistent) :
@ -19,20 +20,57 @@ m_resourceReferenceCount(0)
{
}
NzResource::~NzResource() = default;
NzResource::~NzResource()
{
EnsureResourceListenerUpdate();
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceReleased(this, (*it).index);
}
void NzResource::AddResourceListener(NzResourceListener* listener, int index) const
{
NazaraLock(m_mutex)
if (m_resourceListeners.insert(NzResourceEntry(listener, index)).second)
{
m_resourceListenerUpdated = false;
// AddResourceReference()
m_resourceReferenceCount++;
}
}
void NzResource::AddResourceReference() const
{
NazaraLock(m_mutex)
m_resourceReferenceCount++;
}
bool NzResource::IsPersistent() const
{
NazaraLock(m_mutex)
return m_resourcePersistent;
}
void NzResource::RemoveResourceListener(NzResourceListener* listener) const
{
NazaraLock(m_mutex)
if (m_resourceListeners.erase(listener) != 0)
m_resourceListenerUpdated = false;
else
NazaraError(NzString::Pointer(listener) + " is not listening to " + NzString::Pointer(this));
RemoveResourceReference();
}
void NzResource::RemoveResourceReference() const
{
NazaraMutexLock(m_mutex);
#if NAZARA_CORE_SAFE
if (m_resourceReferenceCount == 0)
{
@ -42,13 +80,59 @@ void NzResource::RemoveResourceReference() const
#endif
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent)
{
NazaraMutexUnlock(m_mutex);
delete this;
}
else
{
NazaraMutexUnlock(m_mutex);
}
}
void NzResource::SetPersistent(bool persistent)
{
NazaraMutexLock(m_mutex);
m_resourcePersistent = persistent;
if (!persistent && m_resourceReferenceCount == 0)
{
NazaraMutexUnlock(m_mutex);
delete this;
}
else
{
NazaraMutexUnlock(m_mutex);
}
}
void NzResource::NotifyCreated()
{
NazaraLock(m_mutex)
EnsureResourceListenerUpdate();
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceCreated(this, (*it).index);
}
void NzResource::NotifyDestroy()
{
NazaraLock(m_mutex)
EnsureResourceListenerUpdate();
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
(*it).listener->OnResourceDestroy(this, (*it).index);
}
void NzResource::EnsureResourceListenerUpdate() const
{
// Déjà bloqué par une mutex
if (!m_resourceListenerUpdated)
{
m_resourceListenersCache = m_resourceListeners;
m_resourceListenerUpdated = true;
}
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2012 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
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/Debug.hpp>
NzResourceListener::~NzResourceListener() = default;
void NzResourceListener::OnResourceCreated(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
}
void NzResourceListener::OnResourceDestroy(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
}
void NzResourceListener::OnResourceReleased(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
}

View File

@ -11,6 +11,7 @@
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <limits>
#include <sstream>
#include <Utfcpp/utf8.h>
#include <Nazara/Core/Debug.hpp>
@ -108,7 +109,7 @@ NzString::NzString(const char* string)
m_sharedString->capacity = size;
m_sharedString->size = size;
m_sharedString->string = new char[size+1];
std::strcpy(m_sharedString->string, string);
std::memcpy(m_sharedString->string, string, size+1);
}
else
m_sharedString = &emptyString;
@ -125,7 +126,7 @@ NzString::NzString(const std::string& string)
m_sharedString->capacity = string.capacity();
m_sharedString->size = string.size();
m_sharedString->string = new char[string.capacity()+1];
std::strcpy(m_sharedString->string, string.c_str());
std::memcpy(m_sharedString->string, string.c_str(), string.size()+1);
}
else
m_sharedString = &emptyString;
@ -180,7 +181,7 @@ NzString& NzString::Append(char character)
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::memcpy(str, m_sharedString->string, m_sharedString->size);
str[m_sharedString->size] = character;
str[newSize] = '\0';
@ -207,7 +208,7 @@ NzString& NzString::Append(const char* string)
{
EnsureOwnership();
std::strcpy(&m_sharedString->string[m_sharedString->size], string);
std::memcpy(&m_sharedString->string[m_sharedString->size], string, length+1);
m_sharedString->size += length;
}
else
@ -216,8 +217,8 @@ NzString& NzString::Append(const char* string)
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string);
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string, length+1);
ReleaseString();
m_sharedString = new SharedString;
@ -241,7 +242,7 @@ NzString& NzString::Append(const NzString& string)
{
EnsureOwnership();
std::strcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string);
std::memcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
m_sharedString->size += string.m_sharedString->size;
}
else
@ -250,8 +251,8 @@ NzString& NzString::Append(const NzString& string)
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
ReleaseString();
m_sharedString = new SharedString;
@ -2270,7 +2271,7 @@ char* NzString::GetUtf8Buffer(unsigned int* size) const
return nullptr;
char* buffer = new char[m_sharedString->size+1];
std::strcpy(buffer, m_sharedString->string);
std::memcpy(buffer, m_sharedString->string, m_sharedString->size+1);
if (size)
*size = m_sharedString->size;
@ -2372,7 +2373,7 @@ wchar_t* NzString::GetWideBuffer(unsigned int* size) const
if (cp <= 0xFFFF && (cp < 0xD800 || cp > 0xDFFF)) // @Laurent Gomila
*ptr++ = static_cast<wchar_t>(cp);
else
*ptr++ = static_cast<wchar_t>('?');
*ptr++ = L'?';
}
while (*it++);
}
@ -2480,7 +2481,7 @@ NzString& NzString::Insert(int pos, char character)
{
EnsureOwnership();
std::memmove(&m_sharedString->string[start+1], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
std::memmove(&m_sharedString->string[start+1], &m_sharedString->string[start], m_sharedString->size);
m_sharedString->string[start] = character;
m_sharedString->size += 1;
@ -2526,8 +2527,8 @@ NzString& NzString::Insert(int pos, const char* string)
{
EnsureOwnership();
std::memmove(&m_sharedString->string[start+len], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
std::memcpy(&m_sharedString->string[start], string, len*sizeof(char));
std::memmove(&m_sharedString->string[start+len], &m_sharedString->string[start], m_sharedString->size);
std::memcpy(&m_sharedString->string[start], string, len+1);
m_sharedString->size += len;
}
@ -2576,8 +2577,8 @@ NzString& NzString::Insert(int pos, const NzString& string)
{
EnsureOwnership();
std::memmove(&m_sharedString->string[start+string.m_sharedString->size], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
std::memcpy(&m_sharedString->string[start], string.m_sharedString->string, string.m_sharedString->size*sizeof(char));
std::memmove(&m_sharedString->string[start+string.m_sharedString->size], &m_sharedString->string[start], m_sharedString->size);
std::memcpy(&m_sharedString->string[start], string.m_sharedString->string, string.m_sharedString->size+1);
m_sharedString->size += string.m_sharedString->size;
}
@ -2837,7 +2838,7 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
found = true;
}
std::memcpy(&m_sharedString->string[pos], replaceString, oSize*sizeof(char));
std::memcpy(&m_sharedString->string[pos], replaceString, oSize);
pos += oSize;
++count;
@ -2859,9 +2860,9 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
{
const char* r = &m_sharedString->string[pos];
std::memcpy(ptr, p, (r-p)*sizeof(char));
std::memcpy(ptr, p, r-p);
ptr += r-p;
std::memcpy(ptr, replaceString, rSize*sizeof(char));
std::memcpy(ptr, replaceString, rSize);
ptr += rSize;
p = r+oSize;
pos += oSize;
@ -2907,7 +2908,7 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
found = true;
}
std::memcpy(&m_sharedString->string[pos], replaceString.m_sharedString->string, oldString.m_sharedString->size*sizeof(char));
std::memcpy(&m_sharedString->string[pos], replaceString.m_sharedString->string, oldString.m_sharedString->size);
pos += oldString.m_sharedString->size;
++count;
@ -2929,9 +2930,9 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
{
const char* r = &m_sharedString->string[pos];
std::memcpy(ptr, p, (r-p)*sizeof(char));
std::memcpy(ptr, p, r-p);
ptr += r-p;
std::memcpy(ptr, replaceString.m_sharedString->string, replaceString.m_sharedString->size*sizeof(char));
std::memcpy(ptr, replaceString.m_sharedString->string, replaceString.m_sharedString->size);
ptr += replaceString.m_sharedString->size;
p = r+oldString.m_sharedString->size;
pos += oldString.m_sharedString->size;
@ -3189,7 +3190,7 @@ void NzString::Reserve(unsigned int bufferSize)
char* ptr = new char[bufferSize+1];
if (m_sharedString->size > 0)
std::strcpy(ptr, m_sharedString->string);
std::memcpy(ptr, m_sharedString->string, m_sharedString->size+1);
unsigned int size = m_sharedString->size;
@ -3233,7 +3234,7 @@ NzString& NzString::Resize(int size, char character)
{
char* newString = new char[newSize+1];
if (m_sharedString->size != 0)
std::memcpy(newString, m_sharedString->string, newSize*sizeof(char));
std::memcpy(newString, m_sharedString->string, newSize);
char* ptr = &newString[m_sharedString->size];
char* limit = &newString[newSize];
@ -3673,7 +3674,7 @@ bool NzString::StartsWith(const NzString& string, nzUInt32 flags) const
}
}
else
return std::memcmp(m_sharedString->string, string.m_sharedString->string, string.m_sharedString->size*sizeof(char)) == 0;
return std::memcmp(m_sharedString->string, string.m_sharedString->string, string.m_sharedString->size) == 0;
return false;
}
@ -3699,7 +3700,7 @@ NzString NzString::Substr(int startPos, int endPos) const
unsigned int size = minEnd-start+1;
char* str = new char[size+1];
std::memcpy(str, &m_sharedString->string[start], size*sizeof(char));
std::memcpy(str, &m_sharedString->string[start], size);
str[size] = '\0';
return NzString(new SharedString(1, size, size, str));
@ -4185,7 +4186,7 @@ NzString& NzString::operator=(const char* string)
}
m_sharedString->size = size;
std::strcpy(m_sharedString->string, string);
std::memcpy(m_sharedString->string, string, size+1);
}
else
ReleaseString();
@ -4209,7 +4210,7 @@ NzString& NzString::operator=(const std::string& string)
}
m_sharedString->size = string.size();
std::strcpy(m_sharedString->string, string.c_str());
std::memcpy(m_sharedString->string, string.c_str(), string.size()+1);
}
else
ReleaseString();
@ -4246,7 +4247,7 @@ NzString NzString::operator+(char character) const
unsigned int totalSize = m_sharedString->size+1;
char* str = new char[totalSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::memcpy(str, m_sharedString->string, m_sharedString->size);
str[m_sharedString->size] = character;
str[totalSize] = '\0';
@ -4268,8 +4269,8 @@ NzString NzString::operator+(const char* string) const
unsigned int totalSize = m_sharedString->size + length;
char* str = new char[totalSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string);
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string, length+1);
return NzString(new SharedString(1, totalSize, totalSize, str));
}
@ -4284,8 +4285,8 @@ NzString NzString::operator+(const std::string& string) const
unsigned int totalSize = m_sharedString->size + string.size();
char* str = new char[totalSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string.c_str());
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string.c_str(), string.size()+1);
return NzString(new SharedString(1, totalSize, totalSize, str));
}
@ -4300,8 +4301,8 @@ NzString NzString::operator+(const NzString& string) const
unsigned int totalSize = m_sharedString->size + string.m_sharedString->size;
char* str = new char[totalSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
return NzString(new SharedString(1, totalSize, totalSize, str));
}
@ -4328,7 +4329,7 @@ NzString& NzString::operator+=(char character)
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::memcpy(str, m_sharedString->string, m_sharedString->size);
str[m_sharedString->size] = character;
str[newSize] = '\0';
@ -4350,25 +4351,25 @@ NzString& NzString::operator+=(const char* string)
if (m_sharedString->size == 0)
return operator=(string);
unsigned int length = std::strlen(string);
if (length == 0)
unsigned int size = std::strlen(string);
if (size == 0)
return *this;
if (m_sharedString->capacity >= m_sharedString->size + length)
if (m_sharedString->capacity >= m_sharedString->size + size)
{
EnsureOwnership();
std::strcpy(&m_sharedString->string[m_sharedString->size], string);
m_sharedString->size += length;
std::memcpy(&m_sharedString->string[m_sharedString->size], string, size+1);
m_sharedString->size += size;
}
else
{
unsigned int newSize = m_sharedString->size + length;
unsigned int newSize = m_sharedString->size + size;
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string);
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string, size+1);
ReleaseString();
m_sharedString = new SharedString;
@ -4392,7 +4393,7 @@ NzString& NzString::operator+=(const std::string& string)
{
EnsureOwnership();
std::strcpy(&m_sharedString->string[m_sharedString->size], string.c_str());
std::memcpy(&m_sharedString->string[m_sharedString->size], string.c_str(), string.size()+1);
m_sharedString->size += string.size();
}
else
@ -4401,8 +4402,8 @@ NzString& NzString::operator+=(const std::string& string)
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string.c_str());
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string.c_str(), string.size()+1);
ReleaseString();
m_sharedString = new SharedString;
@ -4426,7 +4427,7 @@ NzString& NzString::operator+=(const NzString& string)
{
EnsureOwnership();
std::strcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string);
std::memcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
m_sharedString->size += string.m_sharedString->size;
}
else
@ -4435,8 +4436,8 @@ NzString& NzString::operator+=(const NzString& string)
unsigned int bufferSize = nzGetNewSize(newSize);
char* str = new char[bufferSize+1];
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
std::memcpy(str, m_sharedString->string, m_sharedString->size);
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
ReleaseString();
m_sharedString = new SharedString;
@ -4902,7 +4903,7 @@ NzString operator+(char character, const NzString& string)
unsigned int totalSize = string.m_sharedString->size+1;
char* str = new char[totalSize+1];
str[0] = character;
std::strcpy(str, string.m_sharedString->string);
std::memcpy(str, string.m_sharedString->string, string.m_sharedString->size+1);
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
}
@ -4918,8 +4919,8 @@ NzString operator+(const char* string, const NzString& nstring)
unsigned int size = std::strlen(string);
unsigned int totalSize = size + nstring.m_sharedString->size;
char* str = new char[totalSize+1];
std::memcpy(str, string, size*sizeof(char));
std::strcpy(&str[size], nstring.m_sharedString->string);
std::memcpy(str, string, size);
std::memcpy(&str[size], nstring.m_sharedString->string, nstring.m_sharedString->size+1);
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
}
@ -4934,8 +4935,8 @@ NzString operator+(const std::string& string, const NzString& nstring)
unsigned int totalSize = string.size() + nstring.m_sharedString->size;
char* str = new char[totalSize+1];
std::memcpy(str, string.c_str(), string.size()*sizeof(char));
std::strcpy(&str[string.size()], nstring.m_sharedString->string);
std::memcpy(str, string.c_str(), string.size());
std::memcpy(&str[string.size()], nstring.m_sharedString->string, nstring.m_sharedString->size+1);
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
}
@ -5083,7 +5084,7 @@ void NzString::EnsureOwnership()
m_sharedString->refCount--;
char* string = new char[m_sharedString->capacity+1];
std::strcpy(string, m_sharedString->string);
std::memcpy(string, m_sharedString->string, m_sharedString->size+1);
m_sharedString = new SharedString(1, m_sharedString->capacity, m_sharedString->size, string);
}
@ -5115,7 +5116,7 @@ void NzString::ReleaseString()
}
NzString::SharedString NzString::emptyString(0, 0, 0, nullptr);
unsigned int NzString::npos(static_cast<unsigned int>(-1));
const unsigned int NzString::npos(std::numeric_limits<unsigned int>::max());
namespace std
{

View File

@ -172,15 +172,17 @@ bool NzContext::Create(const NzContextParameters& parameters)
if (m_parameters.antialiasingLevel > 0)
glEnable(GL_MULTISAMPLE);
if (NzOpenGL::IsSupported(NzOpenGL::DebugOutput) && m_parameters.debugMode)
if (NzOpenGL::IsSupported(nzOpenGLExtension_DebugOutput) && m_parameters.debugMode)
{
glDebugMessageCallback(&DebugCallback, this);
#ifdef NAZARA_DEBUG
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
#endif
}
NotifyCreated();
return true;
}
@ -188,6 +190,8 @@ void NzContext::Destroy()
{
if (m_impl)
{
NotifyDestroy();
if (currentContext == this)
NzContextImpl::Desactivate();

View File

@ -14,22 +14,6 @@
namespace
{
///FIXME: Déclaré deux fois (ici et dans Renderer.cpp)
const nzUInt8 attribIndex[] =
{
2, // nzElementUsage_Diffuse
1, // nzElementUsage_Normal
0, // nzElementUsage_Position
3, // nzElementUsage_Tangent
4 // nzElementUsage_TexCoord
};
const GLenum shaderType[nzShaderType_Max+1] = {
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
GL_GEOMETRY_SHADER, // nzShaderType_Geometry
GL_VERTEX_SHADER // nzShaderType_Vertex
};
GLuint lockedPrevious = 0;
nzUInt8 lockedLevel = 0;
}
@ -41,6 +25,8 @@ m_parent(parent)
NzGLSLShader::~NzGLSLShader()
{
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
it->second.texture->RemoveResourceListener(this);
}
bool NzGLSLShader::Bind()
@ -71,11 +57,11 @@ bool NzGLSLShader::BindTextures()
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
{
TextureSlot& slot = it->second;
if (!slot.updated)
if (slot.enabled && !slot.updated)
{
glActiveTexture(GL_TEXTURE0 + slot.unit);
if (!slot.texture->Bind())
NazaraWarning("Failed to bind texture");
if (!slot.texture->Prepare())
NazaraWarning("Failed to prepare texture");
slot.updated = true;
}
@ -137,17 +123,35 @@ bool NzGLSLShader::Create()
return false;
}
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Position], "Position");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Normal], "Normal");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Position], "Position");
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Normal], "Normal");
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Diffuse], "Diffuse");
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Tangent], "Tangent");
NzString uniform = "TexCoord";
unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
NzString uniform;
static const unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
uniform.Reserve(10); // 8 + 2
uniform = "TexCoord";
for (unsigned int i = 0; i < maxTexCoords; ++i)
{
NzString uniformName = uniform + NzString::Number(i);
glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
}
static const bool mrtSupported = NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets);
if (mrtSupported)
{
static const unsigned int maxRenderTargets = NzRenderer::GetMaxRenderTargets();
uniform.Reserve(14); // 12 + 2
uniform = "RenderTarget";
for (unsigned int i = 0; i < maxRenderTargets; ++i)
{
NzString uniformName = uniform + NzString::Number(i);
glBindFragDataLocation(m_program, i, uniformName.GetConstBuffer());
}
}
for (int i = 0; i <= nzShaderType_Max; ++i)
@ -224,7 +228,7 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source)
{
NzContext::EnsureContext();
GLuint shader = glCreateShader(shaderType[type]);
GLuint shader = glCreateShader(NzOpenGL::ShaderType[type]);
if (!shader)
{
m_log = "Failed to create shader object";
@ -301,7 +305,12 @@ bool NzGLSLShader::SendBoolean(int location, bool value)
glProgramUniform1i(m_program, location, value);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform1i(location, value);
Unlock();
}
@ -315,7 +324,12 @@ bool NzGLSLShader::SendDouble(int location, double value)
glProgramUniform1d(m_program, location, value);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform1d(location, value);
Unlock();
}
@ -329,7 +343,12 @@ bool NzGLSLShader::SendFloat(int location, float value)
glProgramUniform1f(m_program, location, value);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform1f(location, value);
Unlock();
}
@ -343,7 +362,12 @@ bool NzGLSLShader::SendInteger(int location, int value)
glProgramUniform1i(m_program, location, value);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform1i(location, value);
Unlock();
}
@ -357,7 +381,12 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4d& matrix)
glProgramUniformMatrix4dv(m_program, location, 1, GL_FALSE, matrix);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniformMatrix4dv(location, 1, GL_FALSE, matrix);
Unlock();
}
@ -371,7 +400,12 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4f& matrix)
glProgramUniformMatrix4fv(m_program, location, 1, GL_FALSE, matrix);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniformMatrix4fv(location, 1, GL_FALSE, matrix);
Unlock();
}
@ -388,12 +422,12 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture)
TextureSlot& slot = it->second;
if (slot.texture != texture)
{
slot.texture->RemoveResourceReference();
slot.texture->RemoveResourceListener(this);
if (texture)
{
slot.texture = texture;
slot.texture->AddResourceReference();
slot.texture->AddResourceListener(this, location);
slot.updated = false;
}
@ -439,19 +473,28 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture)
}
TextureSlot slot;
slot.enabled = texture->IsValid();
slot.unit = unit;
slot.texture = texture;
texture->AddResourceReference();
texture->AddResourceListener(this, location);
m_textures[location] = slot;
if (glProgramUniform1i)
glProgramUniform1i(m_program, location, unit);
else
if (slot.enabled)
{
Lock();
glUniform1i(location, unit);
Unlock();
if (glProgramUniform1i)
glProgramUniform1i(m_program, location, unit);
else
{
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform1i(location, unit);
Unlock();
}
}
}
@ -464,7 +507,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector2d& vector)
glProgramUniform2dv(m_program, location, 1, vector);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform2dv(location, 1, vector);
Unlock();
}
@ -478,7 +526,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector2f& vector)
glProgramUniform2fv(m_program, location, 1, vector);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform2fv(location, 1, vector);
Unlock();
}
@ -492,7 +545,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector3d& vector)
glProgramUniform3dv(m_program, location, 1, vector);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform3dv(location, 1, vector);
Unlock();
}
@ -506,7 +564,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector3f& vector)
glProgramUniform3fv(m_program, location, 1, vector);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform3fv(location, 1, vector);
Unlock();
}
@ -520,7 +583,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector4d& vector)
glProgramUniform4dv(m_program, location, 1, vector);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform4dv(location, 1, vector);
Unlock();
}
@ -534,7 +602,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector4f& vector)
glProgramUniform4fv(m_program, location, 1, vector);
else
{
Lock();
if (!Lock())
{
NazaraError("Failed to lock shader");
return false;
}
glUniform4fv(location, 1, vector);
Unlock();
}
@ -576,3 +649,64 @@ void NzGLSLShader::Unlock()
if (--lockedLevel == 0 && lockedPrevious != m_program)
glUseProgram(lockedPrevious);
}
void NzGLSLShader::OnResourceCreated(const NzResource* resource, int index)
{
NazaraUnused(resource);
auto it = m_textures.find(index);
#ifdef NAZARA_DEBUG
if (it == m_textures.end())
{
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
return;
}
#endif
TextureSlot& slot = it->second;
#ifdef NAZARA_DEBUG
if (slot.texture != resource)
{
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
return;
}
#endif
slot.enabled = true;
slot.updated = false;
}
void NzGLSLShader::OnResourceDestroy(const NzResource* resource, int index)
{
NazaraUnused(resource);
auto it = m_textures.find(index);
#ifdef NAZARA_DEBUG
if (it == m_textures.end())
{
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
return;
}
#endif
TextureSlot& slot = it->second;
#ifdef NAZARA_DEBUG
if (slot.texture != resource)
{
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
return;
}
#endif
slot.enabled = false;
}
void NzGLSLShader::OnResourceReleased(const NzResource* resource, int index)
{
if (m_textures.erase(index) == 0)
NazaraInternalError("Texture " + NzString::Pointer(resource) + " not found");
}

View File

@ -7,13 +7,16 @@
#ifndef NAZARA_GLSLSHADER_HPP
#define NAZARA_GLSLSHADER_HPP
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp>
#include <map>
class NzGLSLShader : public NzShaderImpl
class NzResource;
class NzGLSLShader : public NzShaderImpl, NzResourceListener
{
public:
NzGLSLShader(NzShader* parent);
@ -55,8 +58,13 @@ class NzGLSLShader : public NzShaderImpl
void Unlock();
private:
void OnResourceCreated(const NzResource* resource, int index) override;
void OnResourceDestroy(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
struct TextureSlot
{
bool enabled;
bool updated = false;
nzUInt8 unit;
const NzTexture* texture;

View File

@ -12,38 +12,6 @@
namespace
{
GLenum bufferLock[] = {
GL_WRITE_ONLY, // nzBufferAccess_DiscardAndWrite
GL_READ_ONLY, // nzBufferAccess_ReadOnly
GL_READ_WRITE, // nzBufferAccess_ReadWrite
GL_WRITE_ONLY // nzBufferAccess_WriteOnly
};
GLenum bufferLockRange[] = {
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_DiscardAndWrite
GL_MAP_READ_BIT, // nzBufferAccess_ReadOnly
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_ReadWrite
GL_MAP_WRITE_BIT // nzBufferAccess_WriteOnly
};
GLenum bufferTarget[] = {
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
GL_ARRAY_BUFFER, // nzBufferType_Vertex
};
GLenum bufferTargetBinding[] = {
GL_ELEMENT_ARRAY_BUFFER_BINDING, // nzBufferType_Index,
GL_ARRAY_BUFFER_BINDING, // nzBufferType_Vertex
};
GLenum bufferUsage[] = {
// J'ai choisi DYNAMIC à la place de STREAM car DYNAMIC semble plus adapté au profil "une mise à jour pour quelques rendus"
// Ce qui est je pense le scénario qui arrivera le plus souvent (Prévoir une option pour permettre d'utiliser le STREAM_DRAW ?)
// Source: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=160839
GL_DYNAMIC_DRAW, // nzBufferUsage_Dynamic
GL_STATIC_DRAW // nzBufferUsage_Static
};
using LockRoutine = nzUInt8* (*)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
@ -53,16 +21,16 @@ namespace
if (access == nzBufferAccess_DiscardAndWrite)
{
GLint bufSize;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
GLint bufUsage;
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
// On discard le buffer
glBufferData(bufferTargetBinding[type], bufSize, nullptr, bufUsage);
glBufferData(NzOpenGL::BufferTargetBinding[type], bufSize, nullptr, bufUsage);
}
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]);
void* ptr = glMapBuffer(NzOpenGL::BufferTarget[type], NzOpenGL::BufferLock[access]);
if (ptr)
return reinterpret_cast<nzUInt8*>(ptr) + offset;
else
@ -71,7 +39,7 @@ namespace
nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
{
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[access]));
return reinterpret_cast<nzUInt8*>(glMapBufferRange(NzOpenGL::BufferTarget[type], offset, size, NzOpenGL::BufferLockRange[access]));
}
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
@ -109,7 +77,7 @@ void NzHardwareBuffer::Bind()
}
#endif
glBindBuffer(bufferTarget[m_type], m_buffer);
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
}
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
@ -120,14 +88,14 @@ bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
glGenBuffers(1, &m_buffer);
GLint previous;
glGetIntegerv(bufferTargetBinding[m_type], &previous);
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], &previous);
glBindBuffer(bufferTarget[m_type], m_buffer);
glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]);
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
glBufferData(NzOpenGL::BufferTarget[m_type], size, nullptr, NzOpenGL::BufferUsage[usage]);
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
if (previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return true;
}
@ -144,10 +112,10 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
NzContext::EnsureContext();
GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer);
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
// Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
@ -155,9 +123,9 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
{
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
if (size == m_parent->GetSize())
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
glBufferSubData(bufferTarget[m_type], offset, size, data);
glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data);
}
else
{
@ -170,12 +138,12 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
std::memcpy(ptr, data, size);
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
{
// Une erreur rare est survenue, nous devons réinitialiser le buffer
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
return false;
}
@ -183,7 +151,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return true;
}
@ -204,16 +172,16 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer);
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
void* ptr = mapBuffer(m_type, access, offset, size);
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return ptr;
}
@ -223,28 +191,28 @@ bool NzHardwareBuffer::Unmap()
NzContext::EnsureContext();
GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
if (previous != m_buffer)
glBindBuffer(bufferTarget[m_type], m_buffer);
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
{
// Une erreur rare est survenue, nous devons réinitialiser le buffer
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return false;
}
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
if (previous != m_buffer && previous != 0)
glBindBuffer(bufferTarget[m_type], previous);
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
return true;
}

View File

@ -14,21 +14,17 @@
NzOcclusionQuery::NzOcclusionQuery() :
m_id(0)
{
#if NAZARA_RENDERER_SAFE
if (IsSupported())
{
#endif
NzContext::EnsureContext();
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
#if NAZARA_RENDERER_SAFE
}
else
{
NazaraError("Occlusion queries not supported");
return;
}
#endif
#ifdef NAZARA_DEBUG
if (!m_id)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,728 @@
// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/RenderTexture.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <vector>
#include <Nazara/Renderer/Debug.hpp>
namespace
{
struct Attachment
{
union
{
GLuint buffer;
NzTexture* texture;
};
bool isBuffer;
bool isUsed = false;
};
unsigned int attachmentIndex[nzAttachmentPoint_Max+1] =
{
2, // nzAttachmentPoint_Color
0, // nzAttachmentPoint_Depth
0, // nzAttachmentPoint_DepthStencil
1 // nzAttachmentPoint_Stencil
};
nzAttachmentPoint formatTypeToAttachment[nzPixelFormatType_Max+1] =
{
nzAttachmentPoint_Color, // nzPixelFormatType_Color
nzAttachmentPoint_Depth, // nzPixelFormatType_Depth
nzAttachmentPoint_DepthStencil, // nzPixelFormatType_DepthStencil
nzAttachmentPoint_Stencil // nzPixelFormatType_Stencil
};
GLuint lockedPrevious = 0;
nzUInt8 lockedLevel = 0;
}
struct NzRenderTextureImpl
{
GLuint fbo;
std::vector<Attachment> attachements;
std::vector<GLenum> drawBuffers;
NzContext* context;
bool checked = false;
bool complete = false;
bool drawBuffersUpdated = true;
unsigned int height;
unsigned int width;
};
NzRenderTexture::~NzRenderTexture()
{
Destroy();
}
bool NzRenderTexture::AttachBuffer(nzAttachmentPoint attachmentPoint, nzUInt8 index, nzPixelFormat format)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return false;
}
unsigned int depthStencilIndex = attachmentIndex[nzAttachmentPoint_DepthStencil];
if (attachmentPoint == nzAttachmentPoint_Stencil && m_impl->attachements.size() > depthStencilIndex &&
m_impl->attachements[depthStencilIndex].isUsed)
{
NazaraError("Stencil target already attached by DepthStencil attachment");
return false;
}
if (formatTypeToAttachment[NzPixelFormat::GetType(format)] != attachmentPoint)
{
NazaraError("Pixel format type does not match attachment point type");
return false;
}
#endif
NzOpenGL::Format openglFormat;
if (!NzOpenGL::TranslateFormat(format, &openglFormat, NzOpenGL::FormatType_RenderBuffer))
{
NazaraError("Failed to translate pixel format into OpenGL format");
return false;
}
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
// Détachement de l'attache précédente (Si il y a)
Detach(attachmentPoint, index);
GLuint renderBuffer = 0;
glGenRenderbuffers(1, &renderBuffer);
if (!renderBuffer)
{
NazaraError("Failed to create renderbuffer");
return false;
}
GLint previous;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &previous);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, openglFormat.internalFormat, m_impl->width, m_impl->height);
if (previous != 0)
glBindRenderbuffer(GL_RENDERBUFFER, previous);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, renderBuffer);
Unlock();
unsigned int minSize = attachmentIndex[attachmentPoint]+index+1;
if (m_impl->attachements.size() < minSize)
m_impl->attachements.resize(minSize);
Attachment& attachment = m_impl->attachements[minSize-1];
attachment.isBuffer = true;
attachment.isUsed = true;
attachment.buffer = renderBuffer;
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
bool NzRenderTexture::AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return false;
}
unsigned int depthStencilIndex = attachmentIndex[nzAttachmentPoint_DepthStencil];
if (attachmentPoint == nzAttachmentPoint_Stencil && m_impl->attachements.size() > depthStencilIndex &&
m_impl->attachements[depthStencilIndex].isUsed)
{
NazaraError("Stencil target already attached by DepthStencil attachment");
return false;
}
if (!texture || !texture->IsValid())
{
NazaraError("Invalid texture");
return false;
}
if (texture->GetWidth() < m_impl->width || texture->GetHeight() < m_impl->height)
{
NazaraError("Texture cannot be smaller than render texture");
return false;
}
if (texture->GetRenderTexture() != nullptr)
{
NazaraError("Texture already used by another render texture");
return false;
}
if (formatTypeToAttachment[NzPixelFormat::GetType(texture->GetFormat())] != attachmentPoint)
{
NazaraError("Pixel format type does not match attachment point type");
return false;
}
#endif
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
// Détachement de l'attache précédente (Si il y a)
Detach(attachmentPoint, index);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, texture->GetOpenGLID(), 0);
Unlock();
unsigned int minSize = attachmentIndex[attachmentPoint]+index+1;
if (m_impl->attachements.size() < minSize)
m_impl->attachements.resize(minSize);
Attachment& attachment = m_impl->attachements[minSize-1];
attachment.isBuffer = true;
attachment.isUsed = true;
attachment.texture = texture;
texture->AddResourceListener(this, minSize-1);
texture->SetRenderTexture(this);
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
bool NzRenderTexture::AttachTexture(nzAttachmentPoint attachmentPoint, nzUInt8 index, NzTexture* texture, unsigned int z)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return false;
}
if (attachmentPoint == nzAttachmentPoint_Stencil)
{
NazaraError("Targeting stencil-only textures is not supported");
return false;
}
unsigned int depthStencilIndex = attachmentIndex[nzAttachmentPoint_DepthStencil];
if (attachmentPoint == nzAttachmentPoint_Stencil && m_impl->attachements.size() > depthStencilIndex &&
m_impl->attachements[depthStencilIndex].isUsed)
{
NazaraError("Stencil target already attached by DepthStencil attachment");
return false;
}
if (!texture || !texture->IsValid())
{
NazaraError("Invalid texture");
return false;
}
if (texture->GetWidth() < m_impl->width || texture->GetHeight() < m_impl->height)
{
NazaraError("Texture cannot be smaller than render texture");
return false;
}
unsigned int depth = (texture->GetType() == nzImageType_Cubemap) ? 6 : texture->GetDepth();
if (z >= depth)
{
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')');
return false;
}
if (texture->GetRenderTexture() != nullptr)
{
NazaraError("Texture already used by another render texture");
return false;
}
if (formatTypeToAttachment[NzPixelFormat::GetType(texture->GetFormat())] != attachmentPoint)
{
NazaraError("Pixel format type does not match attachment point type");
return false;
}
#endif
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
// Détachement de l'attache précédente (Si il y a)
Detach(attachmentPoint, index);
switch (texture->GetType())
{
case nzImageType_1D:
glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_1D, texture->GetOpenGLID(), 0);
break;
case nzImageType_1D_Array:
case nzImageType_2D_Array:
glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, texture->GetOpenGLID(), 0, z);
break;
case nzImageType_2D:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, NzOpenGL::TextureTarget[texture->GetType()], texture->GetOpenGLID(), 0);
break;
case nzImageType_3D:
glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_3D, texture->GetOpenGLID(), 0, z);
break;
case nzImageType_Cubemap:
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, NzOpenGL::CubemapFace[z], texture->GetOpenGLID(), 0);
break;
}
Unlock();
unsigned int minSize = attachmentIndex[attachmentPoint]+index+1;
if (m_impl->attachements.size() < minSize)
m_impl->attachements.resize(minSize);
Attachment& attachment = m_impl->attachements[minSize-1];
attachment.isBuffer = true;
attachment.isUsed = true;
attachment.texture = texture;
texture->AddResourceListener(this);
texture->SetRenderTexture(this);
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
bool NzRenderTexture::Create(unsigned int width, unsigned int height, bool lock)
{
if (!IsSupported())
{
NazaraError("Render textures not supported");
return false;
}
Destroy();
#if NAZARA_RENDERER_SAFE
if (width == 0)
{
NazaraError("Width must be at least 1 (0)");
return false;
}
if (height == 0)
{
NazaraError("Height must be at least 1 (0)");
return false;
}
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return false;
}
#endif
NzRenderTextureImpl* impl = new NzRenderTextureImpl;
impl->width = width;
impl->height = height;
impl->context = NzContext::GetCurrent();
impl->context->AddResourceListener(this);
impl->fbo = 0;
glGenFramebuffers(1, &impl->fbo);
if (!impl->fbo)
{
NazaraError("Failed to create framebuffer");
delete impl;
return false;
}
m_impl = impl;
if (lock && !Lock())
{
NazaraError("Failed to lock render texture");
delete impl;
m_impl = nullptr;
return false;
}
return true;
}
void NzRenderTexture::Destroy()
{
if (m_impl)
{
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture can only be used with it's creation context");
return;
}
#endif
m_impl->context->RemoveResourceListener(this);
for (Attachment& attachment : m_impl->attachements)
{
if (attachment.isUsed)
{
if (attachment.isBuffer)
glDeleteRenderbuffers(1, &attachment.buffer);
else
{
attachment.texture->RemoveResourceListener(this);
attachment.texture->SetRenderTexture(nullptr);
}
}
}
glDeleteFramebuffers(1, &m_impl->fbo);
delete m_impl;
m_impl = nullptr;
}
}
void NzRenderTexture::Detach(nzAttachmentPoint attachmentPoint, nzUInt8 index)
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return;
}
if (attachmentPoint != nzAttachmentPoint_Color && index > 0)
{
NazaraError("Index must be 0 for non-color attachments");
return;
}
#endif
unsigned int attachIndex = attachmentIndex[attachmentPoint]+index;
if (attachIndex >= m_impl->attachements.size())
return;
Attachment& attachement = m_impl->attachements[attachIndex];
if (!attachement.isUsed)
return;
if (!Lock())
{
NazaraError("Failed to lock render texture");
return;
}
attachement.isUsed = false;
if (attachement.isBuffer)
{
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, 0);
glDeleteRenderbuffers(1, &attachement.buffer);
}
else
{
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, NzOpenGL::Attachment[attachmentPoint]+index, 0, 0);
attachement.texture->RemoveResourceListener(this);
attachement.texture->SetRenderTexture(nullptr);
}
Unlock();
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
}
unsigned int NzRenderTexture::GetHeight() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return 0;
}
#endif
return m_impl->height;
}
NzRenderTargetParameters NzRenderTexture::GetParameters() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return NzRenderTargetParameters();
}
#endif
return NzRenderTargetParameters();
}
unsigned int NzRenderTexture::GetWidth() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return 0;
}
#endif
return m_impl->width;
}
bool NzRenderTexture::IsComplete() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
#endif
if (!m_impl->checked)
{
if (!Lock())
{
NazaraError("Failed to lock render texture");
return false;
}
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
Unlock();
m_impl->complete = false;
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE:
m_impl->complete = true;
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
NazaraError("Incomplete attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
NazaraInternalError("Incomplete draw buffer");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
NazaraInternalError("Incomplete read buffer");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
NazaraError("Incomplete missing attachment");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
NazaraError("Incomplete multisample");
break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
NazaraError("Incomplete layer targets");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
NazaraError("Render texture has unsupported attachments");
break;
default:
NazaraInternalError("Unknown error");
}
m_impl->checked = true;
}
return m_impl->complete;
}
bool NzRenderTexture::IsRenderable() const
{
return IsComplete();
}
bool NzRenderTexture::IsValid() const
{
return m_impl != nullptr;
}
bool NzRenderTexture::Lock() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return false;
}
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return false;
}
#endif
if (lockedLevel++ == 0)
{
GLint previous;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previous);
lockedPrevious = previous;
if (lockedPrevious != m_impl->fbo)
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo);
}
return true;
}
void NzRenderTexture::Unlock() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Render texture not created");
return;
}
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return;
}
if (lockedLevel == 0)
{
NazaraWarning("Unlock called on non-locked texture");
return;
}
#endif
if (--lockedLevel == 0 && lockedPrevious != m_impl->fbo) // Ici, il est important qu'un FBO soit débindé si l'ancien était 0
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lockedPrevious);
}
bool NzRenderTexture::HasContext() const
{
return false;
}
bool NzRenderTexture::IsSupported()
{
return NzRenderer::HasCapability(nzRendererCap_RenderTexture);
}
bool NzRenderTexture::Activate()
{
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return false;
}
#endif
if (!m_impl->drawBuffersUpdated)
{
m_impl->drawBuffers.clear();
m_impl->drawBuffers.reserve(m_impl->attachements.size());
for (unsigned int i = attachmentIndex[nzAttachmentPoint_Color]; i < m_impl->attachements.size(); ++i)
{
if (m_impl->attachements[i].isUsed)
m_impl->drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + i - attachmentIndex[nzAttachmentPoint_Color]);
}
m_impl->drawBuffersUpdated = true;
}
glDrawBuffers(m_impl->drawBuffers.size(), &m_impl->drawBuffers[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo);
return true;
}
void NzRenderTexture::Desactivate()
{
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture cannot be used with this context");
return;
}
#endif
glFlush();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
{
if (resource == m_impl->context)
// Notre context a été détruit, libérons la RenderTexture pour éviter un leak
Destroy();
else
{
// Sinon, c'est une texture
// La ressource n'est plus, du coup nous mettons à jour
Attachment& attachement = m_impl->attachements[index];
attachement.isUsed = false;
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
}
}

View File

@ -40,7 +40,7 @@ NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters&
NzRenderWindow::~NzRenderWindow()
{
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
OnWindowDestroying();
OnWindowDestroy();
}
bool NzRenderWindow::CopyToImage(NzImage* image)
@ -178,17 +178,6 @@ void NzRenderWindow::EnableVerticalSync(bool enabled)
NazaraError("No context");
}
NzContextParameters NzRenderWindow::GetContextParameters() const
{
if (m_context)
return m_context->GetParameters();
else
{
NazaraError("Window not created/context not initialized");
return NzContextParameters();
}
}
unsigned int NzRenderWindow::GetHeight() const
{
return NzWindow::GetHeight();
@ -213,14 +202,9 @@ unsigned int NzRenderWindow::GetWidth() const
return NzWindow::GetWidth();
}
bool NzRenderWindow::HasContext() const
bool NzRenderWindow::IsRenderable() const
{
return true;
}
bool NzRenderWindow::IsValid() const
{
return m_impl != nullptr && m_context != nullptr;
return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
}
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
@ -228,6 +212,22 @@ void NzRenderWindow::SetFramerateLimit(unsigned int limit)
m_framerateLimit = limit;
}
NzContextParameters NzRenderWindow::GetContextParameters() const
{
if (m_context)
return m_context->GetParameters();
else
{
NazaraError("Window not created/context not initialized");
return NzContextParameters();
}
}
bool NzRenderWindow::HasContext() const
{
return true;
}
bool NzRenderWindow::Activate()
{
if (m_context->SetActive(true))
@ -242,15 +242,6 @@ bool NzRenderWindow::Activate()
}
}
void NzRenderWindow::OnWindowDestroying()
{
if (m_context)
{
delete m_context;
m_context = nullptr;
}
}
bool NzRenderWindow::OnWindowCreated()
{
m_parameters.doubleBuffered = true;
@ -267,12 +258,19 @@ bool NzRenderWindow::OnWindowCreated()
EnableVerticalSync(false);
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION
if (!SetActive(true)) // Les fenêtres s'activent à la création
NazaraWarning("Failed to activate window");
#endif
m_clock.Restart();
return true;
}
void NzRenderWindow::OnWindowDestroy()
{
if (m_context)
{
delete m_context;
m_context = nullptr;
}
}

View File

@ -24,114 +24,6 @@
namespace
{
const nzUInt8 attribIndex[] =
{
2, // nzElementUsage_Diffuse
1, // nzElementUsage_Normal
0, // nzElementUsage_Position
3, // nzElementUsage_Tangent
4 // nzElementUsage_TexCoord (Doit être le dernier de la liste car extensible)
};
const GLenum blendFunc[] =
{
GL_DST_ALPHA, // nzBlendFunc_DestAlpha
GL_DST_COLOR, // nzBlendFunc_DestColor
GL_SRC_ALPHA, // nzBlendFunc_SrcAlpha
GL_SRC_COLOR, // nzBlendFunc_SrcColor
GL_ONE_MINUS_DST_ALPHA, // nzBlendFunc_InvDestAlpha
GL_ONE_MINUS_DST_COLOR, // nzBlendFunc_InvDestColor
GL_ONE_MINUS_SRC_ALPHA, // nzBlendFunc_InvSrcAlpha
GL_ONE_MINUS_SRC_COLOR, // nzBlendFunc_InvSrcColor
GL_ONE, // nzBlendFunc_One
GL_ZERO // nzBlendFunc_Zero
};
const GLenum faceCullingMode[] =
{
GL_BACK, // nzFaceCulling_Back
GL_FRONT, // nzFaceCulling_Front
GL_FRONT_AND_BACK // nzFaceCulling_FrontAndBack
};
const GLenum faceFillingMode[] =
{
GL_POINT, // nzFaceFilling_Point
GL_LINE, // nzFaceFilling_Line
GL_FILL // nzFaceFilling_Fill
};
const GLenum openglPrimitive[] =
{
GL_LINES, // nzPrimitiveType_LineList,
GL_LINE_STRIP, // nzPrimitiveType_LineStrip,
GL_POINTS, // nzPrimitiveType_PointList,
GL_TRIANGLES, // nzPrimitiveType_TriangleList,
GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip,
GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan
};
const nzUInt8 openglSize[] =
{
4, // nzElementType_Color
1, // nzElementType_Double1
2, // nzElementType_Double2
3, // nzElementType_Double3
4, // nzElementType_Double4
1, // nzElementType_Float1
2, // nzElementType_Float2
3, // nzElementType_Float3
4 // nzElementType_Float4
};
const GLenum openglType[] =
{
GL_UNSIGNED_BYTE, // nzElementType_Color
GL_DOUBLE, // nzElementType_Double1
GL_DOUBLE, // nzElementType_Double2
GL_DOUBLE, // nzElementType_Double3
GL_DOUBLE, // nzElementType_Double4
GL_FLOAT, // nzElementType_Float1
GL_FLOAT, // nzElementType_Float2
GL_FLOAT, // nzElementType_Float3
GL_FLOAT // nzElementType_Float4
};
const GLenum rendererComparison[] =
{
GL_ALWAYS, // nzRendererComparison_Always
GL_EQUAL, // nzRendererComparison_Equal
GL_GREATER, // nzRendererComparison_Greater
GL_GEQUAL, // nzRendererComparison_GreaterOrEqual
GL_LESS, // nzRendererComparison_Less
GL_LEQUAL, // nzRendererComparison_LessOrEqual
GL_NEVER // nzRendererComparison_Never
};
const GLenum rendererParameter[] =
{
GL_BLEND, // nzRendererParameter_Blend
GL_NONE, // nzRendererParameter_ColorWrite
GL_DEPTH_TEST, // nzRendererParameter_DepthTest
GL_NONE, // nzRendererParameter_DepthWrite
GL_CULL_FACE, // nzRendererParameter_FaceCulling
GL_STENCIL_TEST // nzRendererParameter_Stencil
};
const GLenum stencilOperation[] =
{
GL_DECR, // nzStencilOperation_Decrement
GL_DECR_WRAP, // nzStencilOperation_DecrementToSaturation
GL_INCR, // nzStencilOperation_Increment
GL_INCR_WRAP, // nzStencilOperation_IncrementToSaturation
GL_INVERT, // nzStencilOperation_Invert
GL_KEEP, // nzStencilOperation_Keep
GL_REPLACE, // nzStencilOperation_Replace
GL_ZERO // nzStencilOperation_Zero
};
///FIXME: Solution temporaire pour plus de facilité
enum nzMatrixCombination
{
@ -227,7 +119,7 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
}
if (s_indexBuffer->IsSequential())
glDrawArrays(openglPrimitive[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
glDrawArrays(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
else
{
nzUInt8 indexSize = s_indexBuffer->GetIndexSize();
@ -252,7 +144,7 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
return;
}
glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer()) + firstIndex*indexSize);
glDrawElements(NzOpenGL::PrimitiveType[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer()) + firstIndex*indexSize);
}
}
@ -272,7 +164,7 @@ void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVer
return;
}
glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount);
glDrawArrays(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount);
}
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
@ -297,9 +189,9 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
default:
if (enable)
glEnable(rendererParameter[parameter]);
glEnable(NzOpenGL::RendererParameter[parameter]);
else
glDisable(rendererParameter[parameter]);
glDisable(NzOpenGL::RendererParameter[parameter]);
break;
}
@ -307,6 +199,7 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
/*
NzMatrix4f NzRenderer::GetMatrix(nzMatrixCombination combination)
{
///FIXME: Duplication
switch (combination)
{
case nzMatrixCombination_ViewProj:
@ -431,14 +324,16 @@ bool NzRenderer::Initialize()
s_vertexBuffer = nullptr;
s_vertexDeclaration = nullptr;
// Récupération des capacités
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter);
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
// Récupération des capacités d'OpenGL
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
s_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
// MultipleRenderTargets (Techniquement natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation)
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr);
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(NzOpenGL::PixelBufferObject);
s_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2
s_capabilities[nzRendererCap_TextureCubemap] = 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
@ -458,7 +353,10 @@ bool NzRenderer::Initialize()
GLint maxDrawBuffers;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
s_maxRenderTarget = static_cast<unsigned int>(maxDrawBuffers);
GLint maxColorAttachments;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
s_maxRenderTarget = static_cast<unsigned int>(std::min(maxColorAttachments, maxDrawBuffers));
}
else
s_maxRenderTarget = 1;
@ -472,7 +370,7 @@ bool NzRenderer::Initialize()
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
// Impossible de binder plus de texcoords que d'attributes (en sachant qu'un certain nombre est déjà pris par les autres attributs)
s_maxTextureUnit = static_cast<unsigned int>(std::min(maxTextureUnits, maxVertexAttribs-attribIndex[nzElementUsage_TexCoord]));
s_maxTextureUnit = static_cast<unsigned int>(std::min(maxTextureUnits, maxVertexAttribs-NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]));
}
else
s_maxTextureUnit = 1;
@ -499,7 +397,7 @@ void NzRenderer::SetBlendFunc(nzBlendFunc src, nzBlendFunc dest)
}
#endif
glBlendFunc(blendFunc[src], blendFunc[dest]);
glBlendFunc(NzOpenGL::BlendFunc[src], NzOpenGL::BlendFunc[dest]);
}
void NzRenderer::SetClearColor(const NzColor& color)
@ -564,7 +462,7 @@ void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode)
}
#endif
glCullFace(faceCullingMode[cullingMode]);
glCullFace(NzOpenGL::FaceCulling[cullingMode]);
}
void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
@ -577,7 +475,7 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
}
#endif
glPolygonMode(GL_FRONT_AND_BACK, faceFillingMode[fillingMode]);
glPolygonMode(GL_FRONT_AND_BACK, NzOpenGL::FaceFilling[fillingMode]);
}
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
@ -603,10 +501,6 @@ void NzRenderer::SetMatrix(nzMatrixType type, const NzMatrix4f& matrix)
{
s_matrix[type] = matrix;
// Cas particulier, la matrice projection doit être inversée sur l'axe Y à cause des conventions d'OpenGL
if (type == nzMatrixType_Projection)
s_matrix[type] *= NzMatrix4f::Scale(NzVector3f(1.f, -1.f, 1.f));
// Invalidation des combinaisons
switch (type)
{
@ -722,15 +616,15 @@ bool NzRenderer::SetTarget(NzRenderTarget* target)
if (s_target == target)
return true;
if (s_target && !target->HasContext())
if (s_target && !s_target->HasContext())
s_target->Desactivate();
if (target)
{
#if NAZARA_RENDERER_SAFE
if (!target->IsValid())
if (!target->IsRenderable())
{
NazaraError("Target not valid");
NazaraError("Target not renderable");
return false;
}
#endif
@ -895,13 +789,13 @@ bool NzRenderer::EnsureStateUpdate()
if (!s_stencilFuncUpdated)
{
glStencilFunc(rendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask);
glStencilFunc(NzOpenGL::RendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask);
s_stencilFuncUpdated = true;
}
if (!s_stencilOpUpdated)
{
glStencilOp(stencilOperation[s_stencilFail], stencilOperation[s_stencilZFail], stencilOperation[s_stencilPass]);
glStencilOp(NzOpenGL::StencilOperation[s_stencilFail], NzOpenGL::StencilOperation[s_stencilZFail], NzOpenGL::StencilOperation[s_stencilPass]);
s_stencilOpUpdated = true;
}
@ -921,7 +815,7 @@ bool NzRenderer::EnsureStateUpdate()
}
#endif
static const bool vaoSupported = NzOpenGL::IsSupported(NzOpenGL::VertexArrayObject);
static const bool vaoSupported = NzOpenGL::IsSupported(nzOpenGLExtension_VertexArrayObject);
bool update;
GLuint vao;
@ -970,16 +864,16 @@ bool NzRenderer::EnsureStateUpdate()
if (element)
{
glEnableVertexAttribArray(attribIndex[i]);
glVertexAttribPointer(attribIndex[i],
openglSize[element->type],
openglType[element->type],
glEnableVertexAttribArray(NzOpenGL::AttributeIndex[i]);
glVertexAttribPointer(NzOpenGL::AttributeIndex[i],
NzVertexDeclaration::GetElementCount(element->type),
NzOpenGL::ElementType[element->type],
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
stride,
&buffer[element->offset]);
}
else
glDisableVertexAttribArray(attribIndex[i]);
glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]);
}
if (s_indexBuffer)

View File

@ -60,6 +60,7 @@ bool NzShader::Create(nzShaderLanguage language)
return false;
}
NotifyCreated();
return true;
}
@ -86,6 +87,8 @@ void NzShader::Destroy()
{
if (m_impl)
{
NotifyDestroy();
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;
@ -595,7 +598,7 @@ bool NzShader::IsLanguageSupported(nzShaderLanguage language)
switch (language)
{
case nzShaderLanguage_Cg:
return false; // ??
return false; //FIXME: ??
case nzShaderLanguage_GLSL:
return true;

View File

@ -17,7 +17,7 @@ struct NzTextureImpl
nzImageType type;
nzPixelFormat format;
nzUInt8 levelCount;
bool isTarget = false;
NzRenderTexture* renderTexture = nullptr;
bool mipmapping = false;
bool mipmapsUpdated = true;
unsigned int depth;
@ -27,137 +27,18 @@ struct NzTextureImpl
namespace
{
GLenum cubemapFace[] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X, // nzCubemapFace_PositiveX
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // nzCubemapFace_NegativeX
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // nzCubemapFace_PositiveY
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // nzCubemapFace_NegativeY
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // nzCubemapFace_PositiveZ
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // nzCubemapFace_NegativeZ
};
GLenum openglTarget[] =
{
GL_TEXTURE_1D, // nzImageType_1D
GL_TEXTURE_1D_ARRAY, // nzImageType_1D_Array
GL_TEXTURE_2D, // nzImageType_2D
GL_TEXTURE_2D_ARRAY, // nzImageType_2D_Array
GL_TEXTURE_3D, // nzImageType_3D
GL_TEXTURE_CUBE_MAP // nzImageType_Cubemap
};
GLenum openglTargetBinding[] =
{
GL_TEXTURE_BINDING_1D, // nzImageType_1D
GL_TEXTURE_BINDING_1D_ARRAY, // nzImageType_1D
GL_TEXTURE_BINDING_2D, // nzImageType_2D
GL_TEXTURE_BINDING_3D, // nzImageType_3D
GL_TEXTURE_BINDING_CUBE_MAP // nzImageType_Cubemap
};
GLenum openglTargetProxy[] =
{
GL_PROXY_TEXTURE_1D, // nzImageType_1D
GL_PROXY_TEXTURE_1D_ARRAY, // nzImageType_1D_Array
GL_PROXY_TEXTURE_2D, // nzImageType_2D
GL_PROXY_TEXTURE_2D_ARRAY, // nzImageType_2D_Array
GL_PROXY_TEXTURE_3D, // nzImageType_3D
GL_PROXY_TEXTURE_CUBE_MAP // nzImageType_Cubemap
};
struct OpenGLFormat
{
GLint internalFormat;
GLenum dataFormat;
GLenum dataType;
};
bool GetOpenGLFormat(nzPixelFormat pixelFormat, OpenGLFormat* format)
{
switch (pixelFormat)
{
case nzPixelFormat_BGR8:
format->dataFormat = GL_BGR;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGB8;
return true;
case nzPixelFormat_BGRA8:
format->dataFormat = GL_BGRA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGBA8;
return true;
case nzPixelFormat_DXT1:
format->dataFormat = GL_RGB;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
return true;
case nzPixelFormat_DXT3:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
return true;
case nzPixelFormat_DXT5:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
return true;
case nzPixelFormat_L8:
case nzPixelFormat_LA8:
NazaraError("Pixel format not supported");
return false;
case nzPixelFormat_RGB5A1:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_SHORT_5_5_5_1;
format->internalFormat = GL_RGB5_A1;
return true;
case nzPixelFormat_RGB8:
format->dataFormat = GL_RGB;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGB8;
return true;
case nzPixelFormat_RGBA4:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_SHORT_4_4_4_4;
format->internalFormat = GL_RGBA4;
return true;
case nzPixelFormat_RGBA8:
format->dataFormat = GL_RGBA;
format->dataType = GL_UNSIGNED_BYTE;
format->internalFormat = GL_RGBA8;
return true;
case nzPixelFormat_Undefined:
NazaraInternalError("Invalid pixel format");
return false;
}
NazaraError("Pixel format not handled");
return false;
}
bool CreateTexture(NzTextureImpl* impl, bool proxy)
{
OpenGLFormat openGLFormat;
if (!GetOpenGLFormat(impl->format, &openGLFormat))
NzOpenGL::Format openGLFormat;
if (!NzOpenGL::TranslateFormat(impl->format, &openGLFormat, NzOpenGL::FormatType_Texture))
{
NazaraError("Failed to get OpenGL format");
NazaraError("Format not supported by OpenGL");
return false;
}
GLenum target = (proxy) ? openglTargetProxy[impl->type] : openglTarget[impl->type];
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type];
GLint previous;
glGetIntegerv(openglTargetBinding[impl->type], &previous);
glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous);
switch (impl->type)
{
case nzImageType_1D:
@ -234,7 +115,7 @@ namespace
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
{
for (GLenum face : cubemapFace)
for (GLenum face : NzOpenGL::CubemapFace)
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
if (size > 1U)
@ -266,12 +147,12 @@ namespace
NzContext::EnsureContext();
GLint previous;
glGetIntegerv(openglTargetBinding[impl->type], &previous);
glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous);
lockedPrevious[impl->type] = static_cast<GLuint>(previous);
if (lockedPrevious[impl->type] != impl->id)
glBindTexture(openglTarget[impl->type], impl->id);
glBindTexture(NzOpenGL::TextureTarget[impl->type], impl->id);
}
}
@ -306,7 +187,7 @@ namespace
#endif
if (--lockedLevel[impl->type] == 0 && lockedPrevious[impl->type] != impl->id)
glBindTexture(openglTarget[impl->type], lockedPrevious[impl->type]);
glBindTexture(NzOpenGL::TextureTarget[impl->type], lockedPrevious[impl->type]);
}
}
@ -334,42 +215,10 @@ NzTexture::~NzTexture()
Destroy();
}
bool NzTexture::Bind() const
{
#if NAZARA_RENDERER_SAFE
if (lockedLevel[m_impl->type] > 0)
{
NazaraError("Cannot bind texture while a texture is locked");
return false;
}
#endif
glBindTexture(openglTarget[m_impl->type], m_impl->id);
if (m_impl->mipmapping && !m_impl->mipmapsUpdated)
{
glGenerateMipmap(openglTarget[m_impl->type]);
m_impl->mipmapsUpdated = true;
}
return true;
}
bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount, bool lock)
{
#if NAZARA_RENDERER_SAFE
if (m_impl && m_impl->isTarget)
{
NazaraError("Texture is a target, it cannot be recreated");
return false;
}
#endif
Destroy();
if (width == 0 || height == 0 || depth == 0)
return true;
#if NAZARA_RENDERER_SAFE
if (!IsTypeSupported(type))
{
@ -389,6 +238,24 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
return false;
}
if (width == 0)
{
NazaraError("Width must be at least 1 (0)");
return false;
}
if (height == 0)
{
NazaraError("Height must be at least 1 (0)");
return false;
}
if (depth == 0)
{
NazaraError("Depth must be at least 1 (0)");
return false;
}
switch (type)
{
case nzImageType_1D:
@ -491,6 +358,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
if (!lock)
UnlockTexture(impl);
NotifyCreated();
return true;
}
@ -498,13 +366,7 @@ void NzTexture::Destroy()
{
if (m_impl)
{
#if NAZARA_RENDERER_SAFE
if (m_impl->isTarget)
{
NazaraError("Texture is a target, it cannot be destroyed");
return;
}
#endif
NotifyDestroy();
NzContext::EnsureContext();
@ -530,8 +392,8 @@ bool NzTexture::Download(NzImage* image) const
}
#endif
OpenGLFormat format;
if (!GetOpenGLFormat(m_impl->format, &format))
NzOpenGL::Format format;
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
{
NazaraError("Failed to get OpenGL format");
return false;
@ -552,7 +414,7 @@ bool NzTexture::Download(NzImage* image) const
// Téléchargement...
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
{
glGetTexImage(openglTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level));
glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level));
if (width > 1)
width >>= 1;
@ -610,7 +472,7 @@ unsigned int NzTexture::GetAnisotropyLevel() const
}
#endif
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter))
if (!NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
return 1;
LockTexture(m_impl);
@ -806,7 +668,7 @@ bool NzTexture::IsTarget() const
}
#endif
return m_impl->isTarget;
return m_impl->renderTexture != nullptr;
}
bool NzTexture::IsValid() const
@ -937,7 +799,7 @@ bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel)
}
#endif
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter) && anistropyLevel > 1)
if (anistropyLevel > 1 && !NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
{
NazaraError("Anisotropic filter not supported");
return false;
@ -970,7 +832,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter)
LockTexture(m_impl);
GLenum target = openglTarget[m_impl->type];
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
switch (filter)
{
case nzTextureFilter_Bilinear:
@ -1028,8 +890,8 @@ bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
#endif
LockTexture(m_impl);
glTexParameteri(openglTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel);
glTexParameteri(openglTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, std::min(m_impl->levelCount, maxLevel));
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel);
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, std::min(m_impl->levelCount, maxLevel));
UnlockTexture(m_impl);
return true;
@ -1063,7 +925,7 @@ bool NzTexture::SetWrapMode(nzTextureWrap wrap)
LockTexture(m_impl);
GLenum target = openglTarget[m_impl->type];
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
switch (m_impl->type)
{
// Notez l'absence de "break" ici
@ -1197,7 +1059,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
return false;
}
if (m_impl->isTarget)
if (m_impl->renderTexture)
{
NazaraError("Texture is a target, it cannot be updated");
return false;
@ -1244,8 +1106,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
}
#endif
OpenGLFormat format;
if (!GetOpenGLFormat(m_impl->format, &format))
NzOpenGL::Format format;
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
{
NazaraError("Failed to get OpenGL format");
return false;
@ -1272,12 +1134,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
case nzImageType_1D_Array:
case nzImageType_2D:
glTexSubImage2D(openglTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored.GetConstPixels());
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored.GetConstPixels());
break;
case nzImageType_2D_Array:
case nzImageType_3D:
glTexSubImage3D(openglTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, mirrored.GetConstPixels());
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, mirrored.GetConstPixels());
break;
case nzImageType_Cubemap:
@ -1298,7 +1160,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
return false;
}
if (m_impl->isTarget)
if (m_impl->renderTexture)
{
NazaraError("Texture is a target, it cannot be updated");
return false;
@ -1341,8 +1203,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
}
#endif
OpenGLFormat format;
if (!GetOpenGLFormat(m_impl->format, &format))
NzOpenGL::Format format;
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
{
NazaraError("Failed to get OpenGL format");
return false;
@ -1370,12 +1232,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
case nzImageType_1D_Array:
case nzImageType_2D:
glTexSubImage2D(openglTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored);
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored);
break;
case nzImageType_2D_Array:
case nzImageType_3D:
glTexSubImage3D(openglTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored);
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored);
break;
case nzImageType_Cubemap:
@ -1455,7 +1317,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
return false;
}
if (m_impl->isTarget)
if (m_impl->renderTexture)
{
NazaraError("Texture is a target, it cannot be updated");
return false;
@ -1496,8 +1358,8 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
}
#endif
OpenGLFormat format;
if (!GetOpenGLFormat(m_impl->format, &format))
NzOpenGL::Format format;
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
{
NazaraError("Failed to get OpenGL format");
return false;
@ -1517,7 +1379,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
SetUnpackAlignement(bpp);
LockTexture(m_impl);
glTexSubImage2D(cubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
UnlockTexture(m_impl);
@ -1537,6 +1399,40 @@ void NzTexture::Unlock()
UnlockTexture(m_impl);
}
unsigned int NzTexture::GetOpenGLID() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Texture must be valid");
return 0;
}
#endif
return m_impl->id;
}
bool NzTexture::Prepare() const
{
#if NAZARA_RENDERER_SAFE
if (lockedLevel[m_impl->type] > 0)
{
NazaraError("Cannot bind texture while a texture is locked");
return false;
}
#endif
glBindTexture(NzOpenGL::TextureTarget[m_impl->type], m_impl->id);
if (m_impl->mipmapping && !m_impl->mipmapsUpdated)
{
glGenerateMipmap(NzOpenGL::TextureTarget[m_impl->type]);
m_impl->mipmapsUpdated = true;
}
return true;
}
unsigned int NzTexture::GetValidSize(unsigned int size)
{
if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT))
@ -1567,6 +1463,23 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
case nzPixelFormat_RGBA4:
return true;
// Formats de profondeur (Supportés avec les FBOs)
case nzPixelFormat_Depth16:
case nzPixelFormat_Depth24:
case nzPixelFormat_Depth32:
case nzPixelFormat_Depth24Stencil8:
{
static const bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
return supported;
}
// Formats de stencil (Non supportés pour les textures)
case nzPixelFormat_Stencil1:
case nzPixelFormat_Stencil4:
case nzPixelFormat_Stencil8:
case nzPixelFormat_Stencil16:
return false;
// Dépréciés depuis OpenGL 3 (FIXME: Il doit bien exister des remplaçants ..)
case nzPixelFormat_L8:
case nzPixelFormat_LA8:
@ -1576,7 +1489,7 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
case nzPixelFormat_DXT3:
case nzPixelFormat_DXT5:
{
static const bool supported = NzOpenGL::IsSupported(NzOpenGL::TextureCompression_s3tc);
static const bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_TextureCompression_s3tc);
return supported;
}
@ -1607,7 +1520,7 @@ bool NzTexture::IsTypeSupported(nzImageType type)
case nzImageType_1D_Array:
case nzImageType_2D_Array:
{
static bool supported = NzOpenGL::IsSupported(NzOpenGL::TextureArray);
static bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_TextureArray);
return supported;
}
}
@ -1616,9 +1529,22 @@ bool NzTexture::IsTypeSupported(nzImageType type)
return false;
}
void NzTexture::SetTarget(bool isTarget)
NzRenderTexture* NzTexture::GetRenderTexture() const
{
#if NAZARA_RENDERER_SAFE
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraInternalError("Texture must be valid");
return nullptr;
}
#endif
return m_impl->renderTexture;
}
void NzTexture::SetRenderTexture(NzRenderTexture* renderTexture)
{
#ifdef NAZARA_DEBUG
if (!m_impl)
{
NazaraInternalError("Texture must be valid");
@ -1626,5 +1552,5 @@ void NzTexture::SetTarget(bool isTarget)
}
#endif
m_impl->isTarget = isTarget;
m_impl->renderTexture = renderTexture;
}

View File

@ -153,28 +153,19 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
*attrib++ = parameters.minorVersion;
int flags = 0;
if (parameters.majorVersion >= 3)
{
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
if (parameters.compatibilityProfile)
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
else
{
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
}
*attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
}
if (parameters.debugMode)
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
if (flags)
{
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
*attrib++ = flags;
*attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB;
// Les contextes forward-compatible ne sont plus utilisés pour cette raison :
// http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile
}
*attrib++ = 0;
@ -210,13 +201,25 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
void NzContextImpl::Destroy()
{
if (m_context)
{
if (wglGetCurrentContext() == m_context)
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(m_context);
m_context = nullptr;
}
if (m_deviceContext)
{
ReleaseDC(m_window, m_deviceContext);
m_deviceContext = nullptr;
}
if (m_ownsWindow)
{
DestroyWindow(m_window);
m_window = nullptr;
}
}
void NzContextImpl::SwapBuffers()

View File

@ -33,13 +33,13 @@ NzAnimation::~NzAnimation()
Destroy();
}
unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
bool NzAnimation::AddSequence(const NzSequence& sequence)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Animation not created");
return 0;
return false;
}
#endif
@ -52,7 +52,7 @@ unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
if (it != m_impl->sequenceMap.end())
{
NazaraError("Sequence name \"" + sequence.name + "\" is already used");
return 0;
return false;
}
#endif
@ -61,7 +61,7 @@ unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
m_impl->sequences.push_back(sequence);
return index;
return true;
}
bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount)
@ -86,6 +86,7 @@ bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount)
m_impl->frameCount = frameCount;
m_impl->type = type;
NotifyCreated();
return true;
}
@ -93,6 +94,8 @@ void NzAnimation::Destroy()
{
if (m_impl)
{
NotifyDestroy();
delete m_impl;
m_impl = nullptr;
}
@ -206,6 +209,28 @@ unsigned int NzAnimation::GetSequenceCount() const
return m_impl->sequences.size();
}
int NzAnimation::GetSequenceIndex(const NzString& sequenceName) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Animation not created");
return -1;
}
auto it = m_impl->sequenceMap.find(sequenceName);
if (it == m_impl->sequenceMap.end())
{
NazaraError("Sequence not found");
return -1;
}
return it->second;
#else
return m_impl->sequenceMap[sequenceName];
#endif
}
nzAnimationType NzAnimation::GetType() const
{
#if NAZARA_UTILITY_SAFE
@ -277,13 +302,13 @@ void NzAnimation::RemoveSequence(const NzString& identifier)
auto it = m_impl->sequenceMap.find(identifier);
if (it == m_impl->sequenceMap.end())
{
NazaraError("SubMesh not found");
NazaraError("Sequence not found");
return;
}
unsigned int index = it->second;
int index = it->second;
#else
unsigned int index = m_impl->sequenceMap[identifier];
int index = m_impl->sequenceMap[identifier];
#endif
auto it2 = m_impl->sequences.begin();

View File

@ -113,14 +113,16 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto
m_storage = storage;
m_usage = usage;
// Si on arrive ici c'est que tout s'est bien passé.
return true;
NotifyCreated();
return true; // Si on arrive ici c'est que tout s'est bien passé.
}
void NzBuffer::Destroy()
{
if (m_impl)
{
NotifyDestroy();
m_impl->Destroy();
delete m_impl;
m_impl = nullptr;

View File

@ -215,9 +215,6 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
{
ReleaseImage();
if (width == 0 || height == 0 || depth == 0)
return true;
#if NAZARA_UTILITY_SAFE
if (!NzPixelFormat::IsValid(format))
{
@ -225,6 +222,24 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
return false;
}
if (width == 0)
{
NazaraError("Width must be at least 1 (0)");
return false;
}
if (height == 0)
{
NazaraError("Height must be at least 1 (0)");
return false;
}
if (depth == 0)
{
NazaraError("Depth must be at least 1 (0)");
return false;
}
switch (type)
{
case nzImageType_1D:
@ -315,11 +330,13 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
m_sharedImage = new SharedImage(1, type, format, levelCount, levels, width, height, depth);
NotifyCreated();
return true;
}
void NzImage::Destroy()
{
NotifyDestroy();
ReleaseImage();
}

View File

@ -43,27 +43,6 @@ namespace
return false;
}
// Les fichiers MD2 sont en little endian
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.ident, sizeof(nzUInt32));
#endif
if (header.ident != md2Ident)
{
NazaraError("Invalid MD2 file");
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.version, sizeof(nzUInt32));
#endif
if (header.version != 8)
{
NazaraError("Bad version number (" + NzString::Number(header.version) + ')');
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
@ -99,7 +78,7 @@ namespace
else
animated = false;
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait pas échouer
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait jamais échouer
{
NazaraInternalError("Failed to create mesh");
return false;

View File

@ -31,7 +31,7 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
m_frameCount = endFrame - startFrame + 1;
m_vertexCount = header.num_tris*3;
m_vertexCount = header.num_tris * 3;
/// Chargement des vertices
std::vector<md2_texCoord> texCoords(header.num_st);
@ -71,8 +71,9 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
md2_frame frame;
frame.vertices.resize(header.num_vertices);
// Pour que le modèle soit correctement aligné, on génère une matrice de rotation que nous appliquerons à chacune des vertices
NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(90.f, -90.f, 0.f));
// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
NzQuaternionf rotationQuat = NzEulerAnglesf(-90.f, 90.f, 0.f);
//NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(-90.f, -90.f, 0.f));
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
@ -94,7 +95,7 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
NzByteSwap(&frame.translate.z, sizeof(float));
#endif
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice de la normale plutôt que la normale (gain d'espace)
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice MD2 de la normale plutôt que la normale (gain d'espace)
m_frames[i].vertices = new NzVector3f[m_vertexCount];
NzVector3f max, min;
@ -104,12 +105,16 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
{
const md2_vertex& vert = frame.vertices[triangles[t].vertices[v]];
NzVector3f vertex = rotationMatrix * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z);
max.MakeCeil(vertex);
min.MakeFloor(vertex);
NzVector3f vertex = rotationQuat * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z);
m_frames[i].normal[t*3+v] = vert.n;
m_frames[i].vertices[t*3+v] = vertex;
// On fait en sorte d'avoir deux vertices de délimitation, définissant un rectangle dans l'espace
max.Maximize(vertex);
min.Minimize(vertex);
// Le MD2 ne définit pas ses vertices dans le bon ordre, il nous faut donc les ajouter dans l'ordre inverse
unsigned int index = m_vertexCount - (t*3 + v) - 1;
m_frames[i].normal[index] = vert.n;
m_frames[i].vertices[index] = vertex;
}
}
@ -128,8 +133,8 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
return false;
}
// On avance jusqu'aux premières coordonnées de texture
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset;
// On avance jusqu'aux dernières coordonnées de texture et on les définit dans l'ordre inverse
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset + stride * (m_vertexCount-1);
for (unsigned int t = 0; t < header.num_tris; ++t)
{
for (unsigned int v = 0; v < 3; ++v)
@ -140,7 +145,7 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
coords->x = texC.u / static_cast<float>(header.skinwidth);
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
ptr += stride;
ptr -= stride;
}
}

View File

@ -59,12 +59,6 @@ namespace
return false;
}
if (header.manufacturer != 0x0a)
{
NazaraError("Bad version number (" + NzString::Number(header.manufacturer) + ')');
return false;
}
#if defined(NAZARA_BIG_ENDIAN)
// Les fichiers PCX sont en little endian
NzByteSwap(&header.xmin, sizeof(nzUInt16));

View File

@ -31,8 +31,8 @@ bool NzMeshParams::IsValid() const
struct NzMeshImpl
{
std::map<NzString, nzUInt8> subMeshMap;
std::deque<NzString> skins;
std::map<NzString, unsigned int> subMeshMap;
std::vector<NzSubMesh*> subMeshes;
nzAnimationType animationType;
NzAxisAlignedBox aabb;
@ -44,19 +44,19 @@ NzMesh::~NzMesh()
Destroy();
}
unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
bool NzMesh::AddSkin(const NzString& skin, bool setDefault)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
return false;
}
if (skin.IsEmpty())
{
NazaraError("Skin is empty");
return 0;
return false;
}
#endif
@ -65,71 +65,71 @@ unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
else
m_impl->skins.push_back(skin);
return m_impl->skins.size()-1;
return true;
}
nzUInt8 NzMesh::AddSubMesh(NzSubMesh* subMesh)
bool NzMesh::AddSubMesh(NzSubMesh* subMesh)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
return false;
}
if (!subMesh)
{
NazaraError("Invalid submesh");
return 0;
return false;
}
#endif
subMesh->AddResourceReference();
subMesh->AddResourceListener(this, m_impl->subMeshes.size());
m_impl->aabb.SetNull(); // On invalide l'AABB
m_impl->subMeshes.push_back(subMesh);
return m_impl->subMeshes.size()-1;
return true;
}
nzUInt8 NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh)
bool NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return 0;
return false;
}
if (identifier.IsEmpty())
{
NazaraError("Identifier is empty");
return 0;
return false;
}
auto it = m_impl->subMeshMap.find(identifier);
if (it != m_impl->subMeshMap.end())
{
NazaraError("SubMesh identifier \"" + identifier + "\" is already used");
return it->second;
return false;
}
if (!subMesh)
{
NazaraError("Invalid submesh");
return 0;
return false;
}
#endif
nzUInt8 index = m_impl->subMeshes.size();
int index = m_impl->subMeshes.size();
subMesh->AddResourceReference();
subMesh->AddResourceListener(this, index);
m_impl->aabb.SetNull(); // On invalide l'AABB
m_impl->subMeshes.push_back(subMesh);
m_impl->subMeshMap[identifier] = index;
return index;
return true;
}
void NzMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation)
@ -180,6 +180,8 @@ bool NzMesh::Create(nzAnimationType type)
m_impl = new NzMeshImpl;
m_impl->animationType = type;
NotifyCreated();
return true;
}
@ -187,11 +189,13 @@ void NzMesh::Destroy()
{
if (m_impl)
{
NotifyDestroy();
if (m_impl->animation)
m_impl->animation->RemoveResourceReference();
m_impl->animation->RemoveResourceListener(this);
for (NzSubMesh* subMesh : m_impl->subMeshes)
subMesh->RemoveResourceReference();
subMesh->RemoveResourceListener(this);
delete m_impl;
m_impl = nullptr;
@ -316,7 +320,7 @@ NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier)
#endif
}
NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index)
NzSubMesh* NzMesh::GetSubMesh(unsigned int index)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@ -357,7 +361,7 @@ const NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier) const
#endif
}
const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
const NzSubMesh* NzMesh::GetSubMesh(unsigned int index) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@ -376,7 +380,7 @@ const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
return m_impl->subMeshes[index];
}
nzUInt8 NzMesh::GetSubMeshCount() const
unsigned int NzMesh::GetSubMeshCount() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@ -389,6 +393,28 @@ nzUInt8 NzMesh::GetSubMeshCount() const
return m_impl->subMeshes.size();
}
int NzMesh::GetSubMeshIndex(const NzString& identifier) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
{
NazaraError("Mesh not created");
return -1;
}
auto it = m_impl->subMeshMap.find(identifier);
if (it == m_impl->subMeshMap.end())
{
NazaraError("SubMesh not found");
return -1;
}
return it->second;
#else
return m_impl->subMeshMap[identifier];
#endif
}
unsigned int NzMesh::GetVertexCount() const
{
#if NAZARA_UTILITY_SAFE
@ -458,7 +484,7 @@ bool NzMesh::HasSubMesh(const NzString& identifier) const
return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end();
}
bool NzMesh::HasSubMesh(nzUInt8 index) const
bool NzMesh::HasSubMesh(unsigned int index) const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@ -520,6 +546,7 @@ void NzMesh::RemoveSkin(unsigned int index)
}
#endif
// On accède à l'itérateur correspondant à l'entrée #index
auto it = m_impl->skins.begin();
std::advance(it, index);
@ -547,15 +574,18 @@ void NzMesh::RemoveSubMesh(const NzString& identifier)
unsigned int index = m_impl->subMeshMap[identifier];
#endif
// On déplace l'itérateur du début d'une distance de x
auto it2 = m_impl->subMeshes.begin();
std::advance(it2, index);
std::advance(it, index);
// On libère la ressource
(*it2)->RemoveResourceListener(this);
m_impl->subMeshes.erase(it2);
m_impl->aabb.SetNull(); // On invalide l'AABB
}
void NzMesh::RemoveSubMesh(nzUInt8 index)
void NzMesh::RemoveSubMesh(unsigned int index)
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@ -571,9 +601,12 @@ void NzMesh::RemoveSubMesh(nzUInt8 index)
}
#endif
// On déplace l'itérateur du début de x
auto it = m_impl->subMeshes.begin();
std::advance(it, index);
// On libère la ressource
(*it)->RemoveResourceListener(this);
m_impl->subMeshes.erase(it);
m_impl->aabb.SetNull(); // On invalide l'AABB
@ -599,7 +632,7 @@ bool NzMesh::SetAnimation(const NzAnimation* animation)
return true;
if (m_impl->animation)
m_impl->animation->RemoveResourceReference();
m_impl->animation->RemoveResourceListener(this);
if (animation)
{
@ -611,13 +644,38 @@ bool NzMesh::SetAnimation(const NzAnimation* animation)
}
#endif
m_impl->animation = animation;
m_impl->animation->AddResourceReference();
animation->AddResourceListener(this);
}
else
m_impl->animation = nullptr;
m_impl->animation = animation;
return true;
}
void NzMesh::OnResourceCreated(const NzResource* resource, int index)
{
NazaraUnused(index);
if (resource == m_impl->animation)
{
#if NAZARA_UTILITY_SAFE
if (m_impl->animation->GetType() != m_impl->animationType)
{
NazaraError("Animation's type must match mesh animation type");
m_impl->animation->RemoveResourceListener(this);
m_impl->animation = nullptr;
}
#endif
}
}
void NzMesh::OnResourceReleased(const NzResource* resource, int index)
{
if (resource == m_impl->animation)
SetAnimation(nullptr);
else
RemoveSubMesh(index);
}
NzMeshLoader::LoaderList NzMesh::s_loaders;

View File

@ -38,28 +38,27 @@ bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertex
#if NAZARA_UTILITY_SAFE
if (!vertexDeclaration)
{
NazaraError("Vertex declaration is null");
NazaraError("Invalid vertex declaration");
return false;
}
if (!vertexBuffer)
{
NazaraError("Vertex buffer is null");
NazaraError("Invalid vertex buffer");
return false;
}
#endif
if (indexBuffer)
{
m_indexBuffer = indexBuffer;
m_indexBuffer->AddResourceReference();
}
indexBuffer->AddResourceListener(this);
m_indexBuffer = indexBuffer;
m_vertexBuffer = vertexBuffer;
m_vertexBuffer->AddResourceReference();
m_vertexBuffer->AddResourceListener(this);
m_vertexDeclaration = vertexDeclaration;
m_vertexDeclaration->AddResourceReference();
m_vertexDeclaration->AddResourceListener(this);
return true;
}
@ -70,19 +69,19 @@ void NzStaticMesh::Destroy()
if (m_indexBuffer)
{
m_indexBuffer->RemoveResourceReference();
m_indexBuffer->RemoveResourceListener(this);
m_indexBuffer = nullptr;
}
if (m_vertexBuffer)
{
m_vertexBuffer->RemoveResourceReference();
m_vertexBuffer->RemoveResourceListener(this);
m_vertexBuffer = nullptr;
}
if (m_vertexDeclaration)
{
m_vertexDeclaration->RemoveResourceReference();
m_vertexDeclaration->RemoveResourceListener(this);
m_vertexDeclaration = nullptr;
}
}
@ -184,3 +183,17 @@ void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float i
// Le safe mode est censé nous protéger de cet appel
NazaraError("Static mesh have no animation, please enable safe mode");
}
void NzStaticMesh::OnResourceReleased(const NzResource* resource, int index)
{
NazaraUnused(index);
if (resource == m_indexBuffer)
m_indexBuffer = nullptr;
else if (resource == m_vertexBuffer)
m_vertexBuffer = nullptr;
else if (resource == m_vertexDeclaration)
m_vertexDeclaration = nullptr;
else
NazaraInternalError("Not listening to " + NzString::Pointer(resource));
}

View File

@ -20,9 +20,22 @@
namespace
{
const unsigned int size[] =
const unsigned int elementCount[] =
{
sizeof(nzUInt32), // nzElementType_Color
4, // nzElementType_Color
1, // nzElementType_Double1
2, // nzElementType_Double2
3, // nzElementType_Double3
4, // nzElementType_Double4
1, // nzElementType_Float1
2, // nzElementType_Float2
3, // nzElementType_Float3
4 // nzElementType_Float4
};
const unsigned int elementSize[] =
{
4*sizeof(nzUInt8), // nzElementType_Color
1*sizeof(double), // nzElementType_Double1
2*sizeof(double), // nzElementType_Double2
3*sizeof(double), // nzElementType_Double3
@ -143,7 +156,7 @@ bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int e
if (impl->streamPos[current.stream] == -1)
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
impl->stride[current.stream] += size[current.type];
impl->stride[current.stream] += elementSize[current.type];
}
#if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
@ -153,6 +166,7 @@ bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int e
m_sharedImpl = impl;
NotifyCreated();
return true;
}
@ -161,6 +175,8 @@ void NzVertexDeclaration::Destroy()
if (!m_sharedImpl)
return;
NotifyDestroy();
NazaraMutexLock(m_sharedImpl->mutex);
bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
NazaraMutexUnlock(m_sharedImpl->mutex);
@ -344,3 +360,13 @@ NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declar
return *this;
}
unsigned int NzVertexDeclaration::GetElementCount(nzElementType type)
{
return elementCount[type];
}
unsigned int NzVertexDeclaration::GetElementSize(nzElementType type)
{
return elementSize[type];
}

View File

@ -107,7 +107,7 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
{
if (!mode.IsFullscreenValid())
{
NazaraWarning("Mode is not fullscreen valid");
NazaraWarning("Video mode is not fullscreen valid");
mode = NzVideoMode::GetFullscreenModes()[0];
}
@ -184,7 +184,7 @@ void NzWindow::Destroy()
{
if (m_impl)
{
OnWindowDestroying();
OnWindowDestroy();
m_impl->Destroy();
delete m_impl;
@ -212,7 +212,7 @@ NzWindowHandle NzWindow::GetHandle() const
if (m_impl)
return m_impl->GetHandle();
else
return reinterpret_cast<NzWindowHandle>(0);
return static_cast<NzWindowHandle>(0);
}
unsigned int NzWindow::GetHeight() const
@ -276,6 +276,11 @@ bool NzWindow::IsMinimized() const
return false;
}
bool NzWindow::IsValid() const
{
return m_impl != nullptr;
}
bool NzWindow::IsVisible() const
{
if (m_impl)
@ -483,15 +488,15 @@ bool NzWindow::WaitEvent(NzEvent* event)
#endif
}
void NzWindow::OnWindowDestroying()
{
}
bool NzWindow::OnWindowCreated()
{
return true;
}
void NzWindow::OnWindowDestroy()
{
}
void NzWindow::IgnoreNextMouseEvent(int mouseX, int mouseY) const
{
if (m_impl)