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:
parent
a6ed70123b
commit
cd5a1b7a5e
|
|
@ -2,6 +2,8 @@ if (not _OPTIONS["one-library"]) then
|
||||||
project "NazaraRenderer"
|
project "NazaraRenderer"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defines "NAZARA_RENDERER_OPENGL"
|
||||||
|
|
||||||
files
|
files
|
||||||
{
|
{
|
||||||
"../include/Nazara/Renderer/**.hpp",
|
"../include/Nazara/Renderer/**.hpp",
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,10 @@ void SetSequence(AnimatedModel& model, const NzString& name);
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Tout d'abord on affiche les instructions
|
// Tout d'abord on affiche les instructions
|
||||||
std::cout << "Camera controls: ZQSD" << std::endl;
|
std::cout << "Controls: ZQSD" << std::endl;
|
||||||
std::cout << "Dr. Freak controls: Up, down, left and right" << std::endl;
|
|
||||||
std::cout << "Escape to quit" << 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)
|
// Cette ligne active le mode de compatibilité d'OpenGL lors de l'initialisation de Nazara (Nécessaire pour le shader)
|
||||||
NzContextParameters::defaultCompatibilityProfile = true;
|
NzContextParameters::defaultCompatibilityProfile = true;
|
||||||
|
|
@ -135,8 +136,8 @@ int main()
|
||||||
// Le sol ne subit aucune transformation
|
// Le sol ne subit aucune transformation
|
||||||
floor.matrix.MakeIdentity();
|
floor.matrix.MakeIdentity();
|
||||||
|
|
||||||
// Pour effectuer un rendu, il faut que la carte graphique sache quoi faire.
|
// 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 du pipeline.
|
// 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 !
|
// 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.
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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"))
|
if (!shader.LoadFromFile(nzShaderType_Fragment, "shaders/basic.frag"))
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load fragment shader from file" << std::endl;
|
std::cout << "Failed to load fragment shader from file" << std::endl;
|
||||||
|
|
@ -161,7 +164,7 @@ int main()
|
||||||
return EXIT_FAILURE;
|
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"))
|
if (!shader.LoadFromFile(nzShaderType_Vertex, "shaders/basic.vert"))
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load vertex shader from file" << std::endl;
|
std::cout << "Failed to load vertex shader from file" << std::endl;
|
||||||
|
|
@ -170,7 +173,7 @@ int main()
|
||||||
return EXIT_FAILURE;
|
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())
|
if (!shader.Compile())
|
||||||
{
|
{
|
||||||
std::cout << "Failed to compile shader" << std::endl;
|
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
|
// 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
|
// 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
|
// 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.width /= 2;
|
||||||
mode.height /= 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;
|
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.
|
// 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)
|
// 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::cout << "Failed to create window" << std::endl;
|
||||||
std::getchar();
|
std::getchar();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notre belle fenêtre est créée, nous pouvons la configurer
|
||||||
|
|
||||||
// On cache le curseur
|
// On cache le curseur
|
||||||
window.SetCursor(nzWindowCursor_None);
|
window.SetCursor(nzWindowCursor_None);
|
||||||
|
|
||||||
|
|
@ -215,40 +227,27 @@ int main()
|
||||||
unsigned int fps = 0; // Compteur de FPS
|
unsigned int fps = 0; // Compteur de FPS
|
||||||
|
|
||||||
// Quelques variables pour notre improvisation de physique
|
// Quelques variables pour notre improvisation de physique
|
||||||
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Pas très exact
|
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Les coordonnées locales du "bas" du modèle
|
||||||
NzVector3f modelPos(0.f, groundPos, -50.f);
|
NzVector3f modelPos(0.f, -groundPos, -50.f);
|
||||||
NzVector3f modelVel(0.f, 0.f, 0.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
|
NzQuaternionf modelOrient(NzQuaternionf::Identity());
|
||||||
float speed = 60.f;
|
NzEulerAnglesf modelRot(0.f, 0.f, 0.f);
|
||||||
|
float modelSpeed = 150.f;
|
||||||
|
|
||||||
// Nous initialisons la matrice
|
// Nous initialisons la matrice
|
||||||
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
|
drfreak.matrix = NzMatrix4f::Rotate(modelOrient) * NzMatrix4f::Translate(modelPos);
|
||||||
|
|
||||||
// Notre caméra
|
// Notre caméra
|
||||||
NzVector3f camPos(0.f, 25.f, -20.f);
|
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);
|
NzMatrix4f camMatrix = NzMatrix4f::Translate(camPos);
|
||||||
float camSpeed = 2.f;
|
float camSpeed = 100.f;
|
||||||
float sensitivity = 0.5;
|
float sensitivity = 0.8f;
|
||||||
|
|
||||||
// Dernière étape, nos touches
|
// Quelques variables
|
||||||
|
|
||||||
// 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
|
|
||||||
bool camMode = true;
|
bool camMode = true;
|
||||||
|
bool thirdPerson = false;
|
||||||
bool windowOpen = true;
|
bool windowOpen = true;
|
||||||
|
|
||||||
// On peut commencer la boucle du programme
|
// On peut commencer la boucle du programme
|
||||||
|
|
@ -258,36 +257,38 @@ int main()
|
||||||
NzEvent event;
|
NzEvent event;
|
||||||
while (window.PollEvent(&event)) // Avons-nous un évènement dans la file ?
|
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 ?
|
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
|
case nzEventType_Quit: // L'utilisateur/L'OS nous a demandé de terminer notre exécution
|
||||||
windowOpen = false; // Nous terminons alors la boucle
|
windowOpen = false; // Nous terminons alors la boucle
|
||||||
break;
|
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
|
// Si nous ne sommes pas en mode free-fly, on ne traite pas l'évènement
|
||||||
if (!camMode)
|
if (!camMode || thirdPerson)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// On modifie l'angle de la caméra grâce au déplacement relatif de la souris
|
// 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);
|
camRot.yaw = NzNormalizeAngle(camRot.yaw - event.mouseMove.deltaX*sensitivity);
|
||||||
|
|
||||||
// Pour éviter les loopings, on restreint les angles
|
// 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, -90.f, 90.f);
|
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
|
// 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
|
// 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
|
// 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);
|
NzMouse::SetPosition(window.GetWidth()/2, window.GetHeight()/2, window);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case nzEventType_MouseButtonPressed:
|
case nzEventType_MouseButtonPressed: // L'utilisateur (ou son chat) vient de cliquer sur la souris
|
||||||
if (event.mouseButton.button == NzMouse::Left)
|
if (event.mouseButton.button == NzMouse::Left) // Est-ce le clic gauche ?
|
||||||
{
|
{
|
||||||
// L'utilisateur vient d'appuyer sur le bouton left de la souris
|
// 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
|
// Nous allons inverser le mode caméra et montrer/cacher le curseur en conséquence
|
||||||
|
|
@ -301,44 +302,54 @@ int main()
|
||||||
camMode = true;
|
camMode = true;
|
||||||
window.SetCursor(nzWindowCursor_None);
|
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;
|
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
|
NzRenderer::SetViewport(NzRectui(0, 0, event.size.width, event.size.height)); // Adaptons l'affichage
|
||||||
|
|
||||||
// Il nous faut aussi mettre à jour notre matrice de projection
|
// 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));
|
NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(event.size.width)/event.size.height, 1.f, 1000.f));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzEventType_KeyPressed:
|
case nzEventType_KeyPressed: // Une touche du clavier vient d'être enfoncée
|
||||||
if (!event.key.repeated) // Si la touche n'est pas répété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);
|
// Si une touche concernant le déplacement est appuyée
|
||||||
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
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
else if (event.key.code == NzKeyboard::Escape)
|
||||||
|
|
||||||
if (event.key.code == NzKeyboard::Escape)
|
|
||||||
windowOpen = false;
|
windowOpen = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzEventType_KeyReleased:
|
case nzEventType_KeyReleased: // Une touche du clavier vient d'être relachée
|
||||||
if (event.key.code == currentKey)
|
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");
|
SetSequence(drfreak, "stand");
|
||||||
modelVel = NzVector3f(0.f); // On arrête le déplacement
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -348,81 +359,115 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On active le shader et paramètrons le rendu
|
// Mise à jour de la partie logique
|
||||||
NzRenderer::SetShader(&shader);
|
|
||||||
NzRenderer::Enable(nzRendererParameter_DepthTest, true);
|
|
||||||
|
|
||||||
NzRenderer::SetClearColor(128, 128, 128);
|
|
||||||
NzRenderer::Clear(nzRendererClear_Color | nzRendererClear_Depth);
|
|
||||||
|
|
||||||
if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde
|
if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde
|
||||||
{
|
{
|
||||||
float elapsedTime = updateClock.GetSeconds(); // Le temps depuis la dernière mise à jour
|
float elapsedTime = updateClock.GetSeconds(); // Le temps depuis la dernière mise à jour
|
||||||
|
|
||||||
// Déplacement de la caméra
|
// Déplacement de la caméra
|
||||||
static const NzVector3f forward(NzVector3f::UnitZ());
|
static const NzVector3f forward(NzVector3f::Forward());
|
||||||
static const NzVector3f left(NzVector3f::UnitX());
|
static const NzVector3f left(NzVector3f::Left());
|
||||||
static const NzVector3f up(NzVector3f::UnitY());
|
static const NzVector3f up(NzVector3f::Up());
|
||||||
|
|
||||||
// Notre rotation sous forme de quaternion nous permet de tourner un vecteur
|
// 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"
|
// Par exemple ici, quaternion * forward nous permet de récupérer le vecteur de la direction "avant"
|
||||||
|
|
||||||
|
if (thirdPerson)
|
||||||
|
{
|
||||||
|
// Nous déplaçons le personnage en fonction des touches pressées
|
||||||
|
|
||||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
|
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
|
||||||
camPos += quaternion * forward * camSpeed;
|
modelPos += modelOrient * forward * modelSpeed * elapsedTime;
|
||||||
|
|
||||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
|
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
|
||||||
camPos -= quaternion * forward * camSpeed;
|
modelPos -= modelOrient * forward * modelSpeed * elapsedTime;
|
||||||
|
|
||||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
|
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
|
||||||
camPos += quaternion * left * camSpeed;
|
modelRot.yaw += camSpeed * elapsedTime;
|
||||||
|
|
||||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
|
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
|
||||||
camPos -= quaternion * left * camSpeed;
|
modelRot.yaw -= camSpeed * elapsedTime;
|
||||||
|
|
||||||
|
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
|
// En revanche, ici la hauteur est toujours la même, peu importe notre orientation
|
||||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
|
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
|
||||||
camPos += up * camSpeed;
|
camPos += up * speed * elapsedTime;
|
||||||
|
|
||||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
|
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
|
||||||
camPos -= up * camSpeed;
|
camPos -= up * speed * elapsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
// Oui le quaternion et la matrice sont calculés même si la caméra ne bouge pas
|
// 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
|
// 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
|
// Animation
|
||||||
AnimateModel(drfreak, elapsedTime);
|
AnimateModel(drfreak, elapsedTime);
|
||||||
updateClock.Restart();
|
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
|
// Affichage des meshs
|
||||||
DrawModel(floor);
|
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);
|
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
|
||||||
|
|
||||||
DrawModel(drfreak);
|
DrawModel(drfreak);
|
||||||
|
|
||||||
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
|
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
|
||||||
|
|
||||||
window.Display(); // Nous mettons à jour l'écran
|
// Nous mettons à jour l'écran
|
||||||
|
window.Display();
|
||||||
|
|
||||||
fps++;
|
fps++;
|
||||||
|
|
||||||
// Toutes les secondes
|
// Toutes les secondes
|
||||||
if (secondClock.GetMilliseconds() >= 1000)
|
if (secondClock.GetMilliseconds() >= 1000)
|
||||||
{
|
{
|
||||||
window.SetTitle(title + " (FPS: " + NzString::Number(fps) + ')');
|
window.SetTitle(windowTitle + " (FPS: " + NzString::Number(fps) + ')');
|
||||||
fps = 0;
|
fps = 0;
|
||||||
secondClock.Restart();
|
secondClock.Restart();
|
||||||
}
|
}
|
||||||
|
|
@ -567,10 +612,10 @@ bool CreateFloorMesh(NzMesh* mesh)
|
||||||
mesh->AddSubMesh(subMesh);
|
mesh->AddSubMesh(subMesh);
|
||||||
|
|
||||||
// Nos ressources sont notifiées utilisées par le mesh et le submesh, nous pouvons les rendre éphèmères.
|
// 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);
|
buffer->SetPersistent(false);
|
||||||
declaration->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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -606,8 +651,12 @@ void SetSequence(AnimatedModel& model, const NzString& sequenceName)
|
||||||
const NzAnimation* animation = model.mesh.GetAnimation();
|
const NzAnimation* animation = model.mesh.GetAnimation();
|
||||||
|
|
||||||
// Nous nous basons sur l'assertion que la séquence existe (Chose que nous pouvons tester avec HasSequence())
|
// 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
|
// Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame
|
||||||
model.nextFrame = model.currentSequence->firstFrame;
|
model.nextFrame = model.currentSequence->firstFrame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include <Nazara/Core/Mutex.hpp>
|
#include <Nazara/Core/Mutex.hpp>
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
#include <Nazara/Core/NonCopyable.hpp>
|
||||||
#include <Nazara/Core/Resource.hpp>
|
#include <Nazara/Core/Resource.hpp>
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
#include <Nazara/Core/ResourceLoader.hpp>
|
#include <Nazara/Core/ResourceLoader.hpp>
|
||||||
#include <Nazara/Core/Semaphore.hpp>
|
#include <Nazara/Core/Semaphore.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
|
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
|
||||||
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
|
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
|
||||||
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
|
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
|
||||||
|
#define NAZARA_THREADSAFETY_RESOURCE 1 // NzResource
|
||||||
#define NAZARA_THREADSAFETY_STRING 1 // NzString (COW)
|
#define NAZARA_THREADSAFETY_STRING 1 // NzString (COW)
|
||||||
#define NAZARA_THREADSAFETY_STRINGSTREAM 0 // NzStringStream
|
#define NAZARA_THREADSAFETY_STRINGSTREAM 0 // NzStringStream
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ enum nzEndianness
|
||||||
nzEndianness_Unknown = -1,
|
nzEndianness_Unknown = -1,
|
||||||
|
|
||||||
nzEndianness_BigEndian,
|
nzEndianness_BigEndian,
|
||||||
nzEndianness_LittleEndian
|
nzEndianness_LittleEndian,
|
||||||
|
|
||||||
|
nzEndianness_Max = nzEndianness_LittleEndian
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzErrorType
|
enum nzErrorType
|
||||||
|
|
@ -20,7 +22,9 @@ enum nzErrorType
|
||||||
nzErrorType_AssertFailed,
|
nzErrorType_AssertFailed,
|
||||||
nzErrorType_Internal,
|
nzErrorType_Internal,
|
||||||
nzErrorType_Normal,
|
nzErrorType_Normal,
|
||||||
nzErrorType_Warning
|
nzErrorType_Warning,
|
||||||
|
|
||||||
|
nzErrorType_Max = nzErrorType_Warning
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_ENUMS_CORE_HPP
|
#endif // NAZARA_ENUMS_CORE_HPP
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,32 @@
|
||||||
#define NAZARA_RESOURCE_HPP
|
#define NAZARA_RESOURCE_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.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
|
class NAZARA_API NzResource
|
||||||
{
|
{
|
||||||
|
|
@ -16,14 +42,30 @@ class NAZARA_API NzResource
|
||||||
NzResource(const NzResource& resource);
|
NzResource(const NzResource& resource);
|
||||||
virtual ~NzResource();
|
virtual ~NzResource();
|
||||||
|
|
||||||
|
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
|
||||||
void AddResourceReference() const;
|
void AddResourceReference() const;
|
||||||
|
|
||||||
bool IsPersistent() const;
|
bool IsPersistent() const;
|
||||||
|
|
||||||
|
void RemoveResourceListener(NzResourceListener* listener) const;
|
||||||
void RemoveResourceReference() const;
|
void RemoveResourceReference() const;
|
||||||
|
|
||||||
void SetPersistent(bool persistent = true);
|
void SetPersistent(bool persistent = true);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NotifyCreated();
|
||||||
|
void NotifyDestroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void EnsureResourceListenerUpdate() const;
|
||||||
|
|
||||||
|
NazaraMutexAttrib(m_mutex, mutable)
|
||||||
|
|
||||||
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
|
// 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;
|
mutable unsigned int m_resourceReferenceCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -15,7 +15,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzSt
|
||||||
#if NAZARA_CORE_SAFE
|
#if NAZARA_CORE_SAFE
|
||||||
if (!parameters.IsValid())
|
if (!parameters.IsValid())
|
||||||
{
|
{
|
||||||
NazaraError("Invalid Parameters");
|
NazaraError("Invalid parameters");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -81,7 +81,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
|
||||||
#if NAZARA_CORE_SAFE
|
#if NAZARA_CORE_SAFE
|
||||||
if (!parameters.IsValid())
|
if (!parameters.IsValid())
|
||||||
{
|
{
|
||||||
NazaraError("Invalid Parameters");
|
NazaraError("Invalid parameters");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
|
||||||
template<typename Type, typename Parameters>
|
template<typename Type, typename Parameters>
|
||||||
void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
|
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;
|
std::vector<NzString> exts;
|
||||||
fileExtensions.SplitAny(exts, " /\\.,;|-_");
|
fileExtensions.SplitAny(exts, " /\\.,;|-_");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ class NAZARA_API NzString : public NzHashable
|
||||||
};
|
};
|
||||||
|
|
||||||
static SharedString emptyString;
|
static SharedString emptyString;
|
||||||
static unsigned int npos;
|
static const unsigned int npos;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnsureOwnership();
|
void EnsureOwnership();
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,6 @@
|
||||||
// Définit le radian comme l'unité utilisée pour les angles
|
// Définit le radian comme l'unité utilisée pour les angles
|
||||||
#define NAZARA_MATH_ANGLE_RADIAN 0
|
#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)
|
// 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
|
#define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ template<typename T> class NzMatrix4
|
||||||
~NzMatrix4();
|
~NzMatrix4();
|
||||||
|
|
||||||
NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
|
NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
|
||||||
|
NzMatrix4 ConcatenateAffine(const NzMatrix4& matrix) const;
|
||||||
|
|
||||||
T GetDeterminant() const;
|
T GetDeterminant() const;
|
||||||
NzMatrix4 GetInverse() const;
|
NzMatrix4 GetInverse() const;
|
||||||
|
|
@ -54,7 +55,7 @@ template<typename T> class NzMatrix4
|
||||||
bool IsDefined() const;
|
bool IsDefined() const;
|
||||||
|
|
||||||
void MakeIdentity();
|
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 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 MakePerspective(T angle, T ratio, T zNear, T zFar);
|
||||||
void MakeRotation(const NzQuaternion<T>& rotation);
|
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 Concatenate(const NzMatrix4& m1, const NzMatrix4& m2);
|
||||||
static NzMatrix4 ConcatenateAffine(const NzMatrix4& m1, const NzMatrix4& m2);
|
static NzMatrix4 ConcatenateAffine(const NzMatrix4& m1, const NzMatrix4& m2);
|
||||||
static NzMatrix4 Identity();
|
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 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 Perspective(T angle, T ratio, T zNear, T zFar);
|
||||||
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
|
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,12 @@ NzMatrix4<T> NzMatrix4<T>::Concatenate(const NzMatrix4& matrix) const
|
||||||
return Concatenate(*this, matrix);
|
return Concatenate(*this, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& matrix) const
|
||||||
|
{
|
||||||
|
return ConcatenateAffine(*this, matrix);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T NzMatrix4<T>::GetDeterminant() const
|
T NzMatrix4<T>::GetDeterminant() const
|
||||||
{
|
{
|
||||||
|
|
@ -162,11 +168,7 @@ NzVector3<T> NzMatrix4<T>::GetTranslation() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
|
||||||
return NzVector3<T>(m_sharedMatrix->m41, m_sharedMatrix->m42, m_sharedMatrix->m43);
|
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>
|
template<typename T>
|
||||||
|
|
@ -229,17 +231,10 @@ bool NzMatrix4<T>::IsAffine() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
|
||||||
return NzNumberEquals(m_sharedMatrix->m14, F(0.0)) &&
|
return NzNumberEquals(m_sharedMatrix->m14, F(0.0)) &&
|
||||||
NzNumberEquals(m_sharedMatrix->m24, F(0.0)) &&
|
NzNumberEquals(m_sharedMatrix->m24, F(0.0)) &&
|
||||||
NzNumberEquals(m_sharedMatrix->m34, F(0.0)) &&
|
NzNumberEquals(m_sharedMatrix->m34, F(0.0)) &&
|
||||||
NzNumberEquals(m_sharedMatrix->m44, F(1.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>
|
template<typename T>
|
||||||
|
|
@ -260,86 +255,80 @@ void NzMatrix4<T>::MakeIdentity()
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzMatrix4<T>::MakeOrtho(T left, T top, T width, T height, T zNear, T zFar)
|
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),
|
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(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(-2.0)/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
|
||||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
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>
|
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 = NzVector3<T>::Normalize(target - eye);
|
||||||
NzVector3<T> f = center - eye;
|
NzVector3<T> u(up.GetNormal());
|
||||||
f.Normalize();
|
NzVector3<T> s = NzVector3<T>::Normalize(f.CrossProduct(u));
|
||||||
|
|
||||||
NzVector3<T> u = up;
|
|
||||||
u.Normalize();
|
|
||||||
|
|
||||||
NzVector3<T> s = f.CrossProduct(u);
|
|
||||||
u = s.CrossProduct(f);
|
u = s.CrossProduct(f);
|
||||||
|
|
||||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
Set(s.x, u.x, -f.x, T(0.0),
|
||||||
Set(s.x, s.y, s.z, F(0.0),
|
s.y, u.y, -f.y, T(0.0),
|
||||||
u.x, u.y, u.z, F(0.0),
|
s.z, u.z, -f.z, T(0.0),
|
||||||
-f.x, -f.y, -f.z, F(0.0),
|
-s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
|
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
|
#if NAZARA_MATH_ANGLE_RADIAN
|
||||||
angle /= F(2.0);
|
angle /= F(2.0);
|
||||||
#else
|
#else
|
||||||
angle = NzDegreeToRadian(angle/2);
|
angle = NzDegreeToRadian(angle/F(2.0));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
T f = F(1.0) / std::tan(angle);
|
T yScale = F(1.0) / std::tan(angle);
|
||||||
|
|
||||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
Set(yScale / ratio, F(0.0), F(0.0), F(0.0),
|
||||||
Set(f / ratio, F(0.0), F(0.0), F(0.0),
|
F(0.0), yScale, F(0.0), F(0.0),
|
||||||
F(0.0), f, 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(-1.0),
|
F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzMatrix4<T>::MakeRotation(const NzQuaternion<T>& rotation)
|
void NzMatrix4<T>::MakeRotation(const NzQuaternion<T>& rotation)
|
||||||
{
|
{
|
||||||
// http://stackoverflow.com/questions/1556260/convert-quaternion-rotation-to-rotation-matrix
|
// http://www.flipcode.com/documents/matrfaq.html#Q54
|
||||||
#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),
|
| 2 2 |
|
||||||
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),
|
| 1 - 2Y - 2Z 2XY + 2ZW 2XZ - 2YW |
|
||||||
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));
|
| 2 2 |
|
||||||
#else
|
M = | 2XY - 2ZW 1 - 2X - 2Z 2YZ + 2XW |
|
||||||
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),
|
| 2 2 |
|
||||||
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),
|
| 2XZ + 2YW 2YZ - 2XW 1 - 2X - 2Y |
|
||||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
| |
|
||||||
#endif
|
*/
|
||||||
|
///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>
|
template<typename T>
|
||||||
|
|
@ -354,17 +343,10 @@ void NzMatrix4<T>::MakeScale(const NzVector3<T>& scale)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzMatrix4<T>::MakeTranslation(const NzVector3<T>& translation)
|
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),
|
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(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(1.0), F(0.0),
|
||||||
translation.x, translation.y, translation.z, F(1.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>
|
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->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;
|
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->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->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->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->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->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;
|
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>
|
template<typename T>
|
||||||
|
|
@ -483,17 +456,10 @@ void NzMatrix4<T>::SetTranslation(const NzVector3<T>& translation)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
|
||||||
m_sharedMatrix->m41 = translation.x;
|
m_sharedMatrix->m41 = translation.x;
|
||||||
m_sharedMatrix->m42 = translation.y;
|
m_sharedMatrix->m42 = translation.y;
|
||||||
m_sharedMatrix->m43 = translation.z;
|
m_sharedMatrix->m43 = translation.z;
|
||||||
m_sharedMatrix->m44 = F(1.0);
|
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>
|
template<typename T>
|
||||||
|
|
@ -832,7 +798,6 @@ NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& m1, const NzMatrix
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
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->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->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->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,
|
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));
|
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>
|
template<typename T>
|
||||||
|
|
@ -885,10 +829,10 @@ NzMatrix4<T> NzMatrix4<T>::Identity()
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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;
|
NzMatrix4 matrix;
|
||||||
matrix.MakeLookAt(eye, center, up);
|
matrix.MakeLookAt(eye, target, up);
|
||||||
|
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,10 @@ template<typename T> class NzQuaternion
|
||||||
T DotProduct(const NzQuaternion& vec) const;
|
T DotProduct(const NzQuaternion& vec) const;
|
||||||
|
|
||||||
NzQuaternion GetConjugate() const;
|
NzQuaternion GetConjugate() const;
|
||||||
NzQuaternion GetNormalized() const;
|
NzQuaternion GetInverse() const;
|
||||||
|
NzQuaternion GetNormal() const;
|
||||||
|
|
||||||
|
void Inverse();
|
||||||
|
|
||||||
void MakeIdentity();
|
void MakeIdentity();
|
||||||
void MakeZero();
|
void MakeZero();
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,16 @@ NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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);
|
NzQuaternion<T> quat(*this);
|
||||||
quat.Normalize();
|
quat.Normalize();
|
||||||
|
|
@ -75,16 +84,31 @@ NzQuaternion<T> NzQuaternion<T>::GetNormalized() const
|
||||||
return quat;
|
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>
|
template<typename T>
|
||||||
void NzQuaternion<T>::MakeIdentity()
|
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>
|
template<typename T>
|
||||||
void NzQuaternion<T>::MakeZero()
|
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>
|
template<typename T>
|
||||||
|
|
@ -98,16 +122,18 @@ T NzQuaternion<T>::Normalize()
|
||||||
{
|
{
|
||||||
T squaredMagnitude = SquaredMagnitude();
|
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;
|
w *= invNorm;
|
||||||
x /= magnitude;
|
x *= invNorm;
|
||||||
y /= magnitude;
|
y *= invNorm;
|
||||||
z /= magnitude;
|
z *= invNorm;
|
||||||
|
|
||||||
return magnitude;
|
return norm;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return F(1.0); // Le quaternion est déjà normalisé
|
return F(1.0); // Le quaternion est déjà normalisé
|
||||||
|
|
@ -132,20 +158,24 @@ void NzQuaternion<T>::Set(T quat[4])
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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
|
#if !NAZARA_MATH_ANGLE_RADIAN
|
||||||
angle = NzDegreeToRadian(angle);
|
angle = NzDegreeToRadian(angle);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
angle /= 2;
|
NzVector3<T> normalizedAxis = axis.GetNormal();
|
||||||
|
|
||||||
auto sinAngle = std::sin(angle);
|
T sinAngle = std::sin(angle);
|
||||||
|
|
||||||
w = std::cos(angle);
|
w = std::cos(angle);
|
||||||
x = normalizedAxis.x * sinAngle;
|
x = normalizedAxis.x * sinAngle;
|
||||||
y = normalizedAxis.y * sinAngle;
|
y = normalizedAxis.y * sinAngle;
|
||||||
z = normalizedAxis.z * sinAngle;
|
z = normalizedAxis.z * sinAngle;
|
||||||
|
|
||||||
|
Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -190,12 +220,8 @@ NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
|
||||||
if (test < F(-0.499))
|
if (test < F(-0.499))
|
||||||
return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
|
return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
|
||||||
|
|
||||||
T xx = x*x;
|
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)),
|
||||||
T yy = y*y;
|
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)),
|
||||||
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)),
|
|
||||||
NzRadians(std::asin(F(2.0)*test)));
|
NzRadians(std::asin(F(2.0)*test)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,14 +268,13 @@ NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
|
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
|
||||||
{
|
{
|
||||||
NzVector3<T> normal(vec);
|
NzVector3f quatVec(x, y, z);
|
||||||
normal.Normalize();
|
NzVector3f uv = quatVec.CrossProduct(vec);
|
||||||
|
NzVector3f uuv = quatVec.CrossProduct(uv);
|
||||||
NzQuaternion qvec(0.0, normal.x, normal.y, normal.z);
|
uv *= F(2.0) * w;
|
||||||
NzQuaternion result(operator*(qvec * GetConjugate()));
|
uuv *= F(2.0);
|
||||||
|
|
||||||
return NzVector3<T>(result.x, result.y, result.z);
|
|
||||||
|
|
||||||
|
return vec + uv + uuv;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,15 @@ template<typename T> class NzVector2
|
||||||
|
|
||||||
NzVector2 GetNormal() const;
|
NzVector2 GetNormal() const;
|
||||||
|
|
||||||
void MakeCeil(const NzVector2& vec);
|
T Length() const;
|
||||||
void MakeFloor(const NzVector2& vec);
|
float Lengthf() const;
|
||||||
|
|
||||||
void MakeUnitX();
|
void MakeUnitX();
|
||||||
void MakeUnitY();
|
void MakeUnitY();
|
||||||
void MakeZero();
|
void MakeZero();
|
||||||
|
|
||||||
T Length() const;
|
void Maximize(const NzVector2& vec);
|
||||||
float Lengthf() const;
|
void Minimize(const NzVector2& vec);
|
||||||
|
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,26 +99,6 @@ float NzVector2<T>::Lengthf() const
|
||||||
return std::sqrt(static_cast<float>(SquaredLength()));
|
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>
|
template<typename T>
|
||||||
void NzVector2<T>::MakeUnitX()
|
void NzVector2<T>::MakeUnitX()
|
||||||
{
|
{
|
||||||
|
|
@ -137,6 +117,26 @@ void NzVector2<T>::MakeZero()
|
||||||
Set(F(0.0), F(0.0));
|
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>
|
template<typename T>
|
||||||
void NzVector2<T>::Normalize()
|
void NzVector2<T>::Normalize()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,17 @@ template<typename T> class NzVector3
|
||||||
T Length() const;
|
T Length() const;
|
||||||
float Lengthf() const;
|
float Lengthf() const;
|
||||||
|
|
||||||
void MakeCeil(const NzVector3& vec);
|
void MakeForward();
|
||||||
void MakeFloor(const NzVector3& vec);
|
void MakeLeft();
|
||||||
void MakeUnitX();
|
void MakeUnitX();
|
||||||
void MakeUnitY();
|
void MakeUnitY();
|
||||||
void MakeUnitZ();
|
void MakeUnitZ();
|
||||||
|
void MakeUp();
|
||||||
void MakeZero();
|
void MakeZero();
|
||||||
|
|
||||||
|
void Maximize(const NzVector3& vec);
|
||||||
|
void Minimize(const NzVector3& vec);
|
||||||
|
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
|
||||||
void Set(T X, T Y, T Z);
|
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;
|
||||||
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 UnitX();
|
||||||
static NzVector3 UnitY();
|
static NzVector3 UnitY();
|
||||||
static NzVector3 UnitZ();
|
static NzVector3 UnitZ();
|
||||||
|
static NzVector3 Up();
|
||||||
static NzVector3 Zero();
|
static NzVector3 Zero();
|
||||||
|
|
||||||
T x, y, z;
|
T x, y, z;
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ inline unsigned int NzVector3<unsigned int>::AbsDotProduct(const NzVector3<unsig
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector3<T> NzVector3<T>::CrossProduct(const NzVector3& vec) const
|
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>
|
template<typename T>
|
||||||
|
|
@ -100,29 +100,27 @@ NzVector3<T> NzVector3<T>::GetNormal() const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzVector3<T>::MakeCeil(const NzVector3& vec)
|
T NzVector3<T>::Length() const
|
||||||
{
|
{
|
||||||
if (vec.x > x)
|
return std::sqrt(SquaredLength());
|
||||||
x = vec.x;
|
|
||||||
|
|
||||||
if (vec.y > y)
|
|
||||||
y = vec.y;
|
|
||||||
|
|
||||||
if (vec.z > z)
|
|
||||||
z = vec.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void NzVector3<T>::MakeFloor(const NzVector3& vec)
|
float NzVector3<T>::Lengthf() const
|
||||||
{
|
{
|
||||||
if (vec.x < x)
|
return std::sqrt(static_cast<float>(SquaredLength()));
|
||||||
x = vec.x;
|
}
|
||||||
|
|
||||||
if (vec.y < y)
|
template<typename T>
|
||||||
y = vec.y;
|
void NzVector3<T>::MakeForward()
|
||||||
|
{
|
||||||
|
Set(F(0.0), F(0.0), F(-1.0));
|
||||||
|
}
|
||||||
|
|
||||||
if (vec.z < z)
|
template<typename T>
|
||||||
z = vec.z;
|
void NzVector3<T>::MakeLeft()
|
||||||
|
{
|
||||||
|
Set(F(-1.0), F(0.0), F(0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -143,6 +141,12 @@ void NzVector3<T>::MakeUnitZ()
|
||||||
Set(F(0.0), F(0.0), F(1.0));
|
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>
|
template<typename T>
|
||||||
void NzVector3<T>::MakeZero()
|
void NzVector3<T>::MakeZero()
|
||||||
{
|
{
|
||||||
|
|
@ -150,15 +154,29 @@ void NzVector3<T>::MakeZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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>
|
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>
|
template<typename T>
|
||||||
|
|
@ -166,13 +184,13 @@ void NzVector3<T>::Normalize()
|
||||||
{
|
{
|
||||||
T squaredLength = SquaredLength();
|
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;
|
x *= invLength;
|
||||||
y /= length;
|
y *= invLength;
|
||||||
z /= length;
|
z *= invLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,6 +485,42 @@ bool NzVector3<T>::operator>=(const NzVector3& vec) const
|
||||||
return !operator<(vec);
|
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>
|
template<typename T>
|
||||||
NzVector3<T> NzVector3<T>::UnitX()
|
NzVector3<T> NzVector3<T>::UnitX()
|
||||||
{
|
{
|
||||||
|
|
@ -494,6 +548,15 @@ NzVector3<T> NzVector3<T>::UnitZ()
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NzVector3<T> NzVector3<T>::Up()
|
||||||
|
{
|
||||||
|
NzVector3 vector;
|
||||||
|
vector.MakeUp();
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
NzVector3<T> NzVector3<T>::Zero()
|
NzVector3<T> NzVector3<T>::Zero()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,14 @@ template<typename T> class NzVector4
|
||||||
|
|
||||||
T DotProduct(const NzVector4& vec) const;
|
T DotProduct(const NzVector4& vec) const;
|
||||||
|
|
||||||
void MakeCeil(const NzVector4& vec);
|
|
||||||
void MakeFloor(const NzVector4& vec);
|
|
||||||
void MakeUnitX();
|
void MakeUnitX();
|
||||||
void MakeUnitY();
|
void MakeUnitY();
|
||||||
void MakeUnitZ();
|
void MakeUnitZ();
|
||||||
void MakeZero();
|
void MakeZero();
|
||||||
|
|
||||||
|
void Maximize(const NzVector4& vec);
|
||||||
|
void Minimize(const NzVector4& vec);
|
||||||
|
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
|
||||||
void Set(T X, T Y, T Z, T W = 1.0);
|
void Set(T X, T Y, T Z, T W = 1.0);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
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>
|
template<typename T>
|
||||||
void NzVector4<T>::MakeUnitX()
|
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));
|
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>
|
template<typename T>
|
||||||
void NzVector4<T>::Normalize()
|
void NzVector4<T>::Normalize()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
#include <Nazara/Renderer/RenderTargetParameters.hpp>
|
#include <Nazara/Renderer/RenderTargetParameters.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
#include <Nazara/Renderer/RenderWindow.hpp>
|
#include <Nazara/Renderer/RenderWindow.hpp>
|
||||||
#include <Nazara/Renderer/Shader.hpp>
|
#include <Nazara/Renderer/Shader.hpp>
|
||||||
#include <Nazara/Renderer/Texture.hpp>
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,6 @@
|
||||||
|
|
||||||
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
|
/// 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)
|
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
|
||||||
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 0
|
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,19 @@
|
||||||
// This file is part of the "Nazara Engine - Renderer module"
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#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
|
#pragma once
|
||||||
|
|
||||||
#ifndef NAZARA_CONTEXT_HPP
|
#ifndef NAZARA_CONTEXT_HPP
|
||||||
#define NAZARA_CONTEXT_HPP
|
#define NAZARA_CONTEXT_HPP
|
||||||
|
|
||||||
|
#ifdef NAZARA_RENDERER_OPENGL
|
||||||
|
|
||||||
|
#include <Nazara/Core/Resource.hpp>
|
||||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||||
|
|
||||||
class NzContextImpl;
|
class NzContextImpl;
|
||||||
|
|
||||||
class NAZARA_API NzContext
|
class NAZARA_API NzContext : public NzResource
|
||||||
{
|
{
|
||||||
friend NzContextImpl;
|
friend NzContextImpl;
|
||||||
|
|
||||||
|
|
@ -25,6 +24,7 @@ class NAZARA_API NzContext
|
||||||
|
|
||||||
bool Create(const NzContextParameters& parameters = NzContextParameters());
|
bool Create(const NzContextParameters& parameters = NzContextParameters());
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
const NzContextParameters& GetParameters() const;
|
const NzContextParameters& GetParameters() const;
|
||||||
bool IsActive() const;
|
bool IsActive() const;
|
||||||
bool SetActive(bool active);
|
bool SetActive(bool active);
|
||||||
|
|
@ -44,4 +44,6 @@ class NAZARA_API NzContext
|
||||||
static NzContext* s_reference;
|
static NzContext* s_reference;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERER_OPENGL
|
||||||
|
|
||||||
#endif // NAZARA_CONTEXT_HPP
|
#endif // NAZARA_CONTEXT_HPP
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,16 @@
|
||||||
#ifndef NAZARA_ENUMS_RENDERER_HPP
|
#ifndef NAZARA_ENUMS_RENDERER_HPP
|
||||||
#define 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
|
enum nzBlendFunc
|
||||||
{
|
{
|
||||||
nzBlendFunc_DestAlpha,
|
nzBlendFunc_DestAlpha,
|
||||||
|
|
@ -18,21 +28,27 @@ enum nzBlendFunc
|
||||||
nzBlendFunc_InvSrcAlpha,
|
nzBlendFunc_InvSrcAlpha,
|
||||||
nzBlendFunc_InvSrcColor,
|
nzBlendFunc_InvSrcColor,
|
||||||
nzBlendFunc_One,
|
nzBlendFunc_One,
|
||||||
nzBlendFunc_Zero
|
nzBlendFunc_Zero,
|
||||||
|
|
||||||
|
nzBlendFunc_Max = nzBlendFunc_Zero
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzFaceCulling
|
enum nzFaceCulling
|
||||||
{
|
{
|
||||||
nzFaceCulling_Back,
|
nzFaceCulling_Back,
|
||||||
nzFaceCulling_Front,
|
nzFaceCulling_Front,
|
||||||
nzFaceCulling_FrontAndBack
|
nzFaceCulling_FrontAndBack,
|
||||||
|
|
||||||
|
nzFaceCulling_Max = nzFaceCulling_FrontAndBack
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzFaceFilling
|
enum nzFaceFilling
|
||||||
{
|
{
|
||||||
nzFaceFilling_Point,
|
nzFaceFilling_Point,
|
||||||
nzFaceFilling_Line,
|
nzFaceFilling_Line,
|
||||||
nzFaceFilling_Fill
|
nzFaceFilling_Fill,
|
||||||
|
|
||||||
|
nzFaceFilling_Max = nzFaceFilling_Fill
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzMatrixType
|
enum nzMatrixType
|
||||||
|
|
@ -47,7 +63,9 @@ enum nzMatrixType
|
||||||
enum nzPixelBufferType
|
enum nzPixelBufferType
|
||||||
{
|
{
|
||||||
nzPixelBufferType_Pack,
|
nzPixelBufferType_Pack,
|
||||||
nzPixelBufferType_Unpack
|
nzPixelBufferType_Unpack,
|
||||||
|
|
||||||
|
nzPixelBufferType_Max = nzPixelBufferType_Unpack
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzRendererCap
|
enum nzRendererCap
|
||||||
|
|
@ -58,6 +76,7 @@ enum nzRendererCap
|
||||||
nzRendererCap_MultipleRenderTargets,
|
nzRendererCap_MultipleRenderTargets,
|
||||||
nzRendererCap_OcclusionQuery,
|
nzRendererCap_OcclusionQuery,
|
||||||
nzRendererCap_PixelBufferObject,
|
nzRendererCap_PixelBufferObject,
|
||||||
|
nzRendererCap_RenderTexture,
|
||||||
nzRendererCap_Texture3D,
|
nzRendererCap_Texture3D,
|
||||||
nzRendererCap_TextureCubemap,
|
nzRendererCap_TextureCubemap,
|
||||||
nzRendererCap_TextureMulti,
|
nzRendererCap_TextureMulti,
|
||||||
|
|
@ -66,7 +85,7 @@ enum nzRendererCap
|
||||||
nzRendererCap_Max = nzRendererCap_TextureNPOT
|
nzRendererCap_Max = nzRendererCap_TextureNPOT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzRendererClear
|
enum nzRendererClearFlags
|
||||||
{
|
{
|
||||||
nzRendererClear_Color = 0x01,
|
nzRendererClear_Color = 0x01,
|
||||||
nzRendererClear_Depth = 0x02,
|
nzRendererClear_Depth = 0x02,
|
||||||
|
|
@ -81,7 +100,9 @@ enum nzRendererComparison
|
||||||
nzRendererComparison_GreaterOrEqual,
|
nzRendererComparison_GreaterOrEqual,
|
||||||
nzRendererComparison_Less,
|
nzRendererComparison_Less,
|
||||||
nzRendererComparison_LessOrEqual,
|
nzRendererComparison_LessOrEqual,
|
||||||
nzRendererComparison_Never
|
nzRendererComparison_Never,
|
||||||
|
|
||||||
|
nzRendererComparison_Max = nzRendererComparison_Never
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzRendererParameter
|
enum nzRendererParameter
|
||||||
|
|
@ -91,15 +112,19 @@ enum nzRendererParameter
|
||||||
nzRendererParameter_DepthTest,
|
nzRendererParameter_DepthTest,
|
||||||
nzRendererParameter_DepthWrite,
|
nzRendererParameter_DepthWrite,
|
||||||
nzRendererParameter_FaceCulling,
|
nzRendererParameter_FaceCulling,
|
||||||
nzRendererParameter_Stencil
|
nzRendererParameter_Stencil,
|
||||||
|
|
||||||
|
nzRendererParameter_Max = nzRendererParameter_Stencil
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzShaderLanguage
|
enum nzShaderLanguage
|
||||||
{
|
{
|
||||||
nzShaderLanguage_Unknown,
|
nzShaderLanguage_Unknown = -1,
|
||||||
|
|
||||||
nzShaderLanguage_Cg,
|
nzShaderLanguage_Cg,
|
||||||
nzShaderLanguage_GLSL
|
nzShaderLanguage_GLSL,
|
||||||
|
|
||||||
|
nzShaderLanguage_Max = nzShaderLanguage_GLSL
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzShaderType
|
enum nzShaderType
|
||||||
|
|
@ -120,22 +145,30 @@ enum nzStencilOperation
|
||||||
nzStencilOperation_Invert,
|
nzStencilOperation_Invert,
|
||||||
nzStencilOperation_Keep,
|
nzStencilOperation_Keep,
|
||||||
nzStencilOperation_Replace,
|
nzStencilOperation_Replace,
|
||||||
nzStencilOperation_Zero
|
nzStencilOperation_Zero,
|
||||||
|
|
||||||
|
nzStencilOperation_Max = nzStencilOperation_Zero
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzTextureFilter
|
enum nzTextureFilter
|
||||||
{
|
{
|
||||||
|
nzTextureFilter_Unknown = -1,
|
||||||
|
|
||||||
nzTextureFilter_Bilinear,
|
nzTextureFilter_Bilinear,
|
||||||
nzTextureFilter_Nearest,
|
nzTextureFilter_Nearest,
|
||||||
nzTextureFilter_Trilinear,
|
nzTextureFilter_Trilinear,
|
||||||
nzTextureFilter_Unknown
|
|
||||||
|
nzTextureFilter_Max = nzTextureFilter_Trilinear
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzTextureWrap
|
enum nzTextureWrap
|
||||||
{
|
{
|
||||||
|
nzTextureWrap_Unknown = -1,
|
||||||
|
|
||||||
nzTextureWrap_Clamp,
|
nzTextureWrap_Clamp,
|
||||||
nzTextureWrap_Repeat,
|
nzTextureWrap_Repeat,
|
||||||
nzTextureWrap_Unknown
|
|
||||||
|
nzTextureWrap_Max = nzTextureWrap_Repeat
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NAZARA_ENUMS_RENDERER_HPP
|
#endif // NAZARA_ENUMS_RENDERER_HPP
|
||||||
|
|
|
||||||
|
|
@ -2,19 +2,19 @@
|
||||||
// This file is part of the "Nazara Engine - Renderer module"
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#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
|
#pragma once
|
||||||
|
|
||||||
#ifndef NAZARA_OPENGL_HPP
|
#ifndef NAZARA_OPENGL_HPP
|
||||||
#define 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
|
// 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 <GL3/glcorearb.h>
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
|
|
||||||
// Inclusion des extensions
|
// Inclusion des extensions
|
||||||
#include <GL3/glext.h>
|
#include <GL3/glext.h>
|
||||||
|
|
@ -24,35 +24,69 @@
|
||||||
#include <GL3/glxext.h>
|
#include <GL3/glxext.h>
|
||||||
#endif
|
#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 (*)();
|
using NzOpenGLFunc = void (*)();
|
||||||
|
|
||||||
class NAZARA_API NzOpenGL
|
namespace NzOpenGL
|
||||||
{
|
{
|
||||||
public:
|
enum FormatType
|
||||||
enum Extension
|
|
||||||
{
|
{
|
||||||
AnisotropicFilter,
|
FormatType_RenderBuffer,
|
||||||
DebugOutput,
|
// FormatType_MultisampleTexture,
|
||||||
FP64,
|
FormatType_Texture
|
||||||
FrameBufferObject,
|
|
||||||
PixelBufferObject,
|
|
||||||
SeparateShaderObjects,
|
|
||||||
Texture3D,
|
|
||||||
TextureArray,
|
|
||||||
TextureCompression_s3tc,
|
|
||||||
TextureStorage,
|
|
||||||
VertexArrayObject,
|
|
||||||
|
|
||||||
Max = VertexArrayObject
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static NzOpenGLFunc GetEntry(const NzString& entryPoint);
|
struct Format
|
||||||
static unsigned int GetVersion();
|
{
|
||||||
static bool Initialize();
|
GLenum dataFormat;
|
||||||
static bool IsSupported(Extension extension);
|
GLenum dataType;
|
||||||
static bool IsSupported(const NzString& string);
|
GLint internalFormat;
|
||||||
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 PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||||
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
|
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
|
||||||
|
|
@ -60,6 +94,7 @@ NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery;
|
||||||
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
||||||
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
|
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
|
||||||
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
||||||
|
NAZARA_API extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
|
||||||
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
|
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
|
||||||
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
|
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
|
||||||
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||||
|
|
@ -99,7 +134,11 @@ NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
|
||||||
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
|
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
|
||||||
NAZARA_API extern PFNGLFLUSHPROC glFlush;
|
NAZARA_API extern PFNGLFLUSHPROC glFlush;
|
||||||
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
||||||
|
NAZARA_API extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
|
||||||
|
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
|
||||||
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
|
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
|
||||||
|
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
|
||||||
|
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
|
||||||
NAZARA_API extern PFNGLENABLEPROC glEnable;
|
NAZARA_API extern PFNGLENABLEPROC glEnable;
|
||||||
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||||
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
|
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
|
||||||
|
|
@ -189,4 +228,6 @@ NAZARA_API extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
|
||||||
NAZARA_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval;
|
NAZARA_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERER_OPENGL
|
||||||
|
|
||||||
#endif // NAZARA_OPENGL_HPP
|
#endif // NAZARA_OPENGL_HPP
|
||||||
|
|
|
||||||
|
|
@ -21,19 +21,18 @@ class NAZARA_API NzRenderTarget
|
||||||
NzRenderTarget() = default;
|
NzRenderTarget() = default;
|
||||||
virtual ~NzRenderTarget();
|
virtual ~NzRenderTarget();
|
||||||
|
|
||||||
#ifndef NAZARA_RENDERER_COMMON
|
|
||||||
virtual bool HasContext() const = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual unsigned int GetHeight() const = 0;
|
virtual unsigned int GetHeight() const = 0;
|
||||||
virtual NzRenderTargetParameters GetParameters() const = 0;
|
virtual NzRenderTargetParameters GetParameters() const = 0;
|
||||||
virtual unsigned int GetWidth() const = 0;
|
virtual unsigned int GetWidth() const = 0;
|
||||||
|
|
||||||
bool IsActive() const;
|
bool IsActive() const;
|
||||||
virtual bool IsValid() const = 0;
|
virtual bool IsRenderable() const = 0;
|
||||||
|
|
||||||
bool SetActive(bool active);
|
bool SetActive(bool active);
|
||||||
|
|
||||||
|
// Fonctions OpenGL
|
||||||
|
virtual bool HasContext() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool Activate() = 0;
|
virtual bool Activate() = 0;
|
||||||
virtual void Desactivate();
|
virtual void Desactivate();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -39,28 +39,25 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
|
||||||
|
|
||||||
void EnableVerticalSync(bool enabled);
|
void EnableVerticalSync(bool enabled);
|
||||||
|
|
||||||
#ifndef NAZARA_RENDERER_COMMON
|
|
||||||
NzContextParameters GetContextParameters() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned int GetHeight() const;
|
unsigned int GetHeight() const;
|
||||||
NzRenderTargetParameters GetParameters() const;
|
NzRenderTargetParameters GetParameters() const;
|
||||||
unsigned int GetWidth() const;
|
unsigned int GetWidth() const;
|
||||||
|
|
||||||
#ifndef NAZARA_RENDERER_COMMON
|
bool IsRenderable() const;
|
||||||
bool HasContext() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
void SetFramerateLimit(unsigned int limit);
|
void SetFramerateLimit(unsigned int limit);
|
||||||
|
|
||||||
|
// Fonctions OpenGL
|
||||||
|
NzContextParameters GetContextParameters() const;
|
||||||
|
bool HasContext() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool Activate() override;
|
bool Activate() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void OnWindowDestroying() override;
|
bool OnWindowCreated() override;
|
||||||
virtual bool OnWindowCreated() override;
|
void OnWindowDestroy() override;
|
||||||
|
|
||||||
NzClock m_clock;
|
NzClock m_clock;
|
||||||
NzContextParameters m_parameters;
|
NzContextParameters m_parameters;
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,12 @@
|
||||||
#include <Nazara/Utility/Image.hpp>
|
#include <Nazara/Utility/Image.hpp>
|
||||||
#include <Nazara/Utility/PixelFormat.hpp>
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
|
|
||||||
|
class NzRenderTexture;
|
||||||
struct NzTextureImpl;
|
struct NzTextureImpl;
|
||||||
|
|
||||||
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
{
|
{
|
||||||
|
friend NzRenderTexture;
|
||||||
friend class NzShader;
|
friend class NzShader;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -24,10 +26,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
explicit NzTexture(const NzImage& image);
|
explicit NzTexture(const NzImage& image);
|
||||||
~NzTexture();
|
~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);
|
bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
|
@ -75,13 +73,18 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||||
|
|
||||||
void Unlock();
|
void Unlock();
|
||||||
|
|
||||||
|
// Fonctions OpenGL
|
||||||
|
unsigned int GetOpenGLID() const;
|
||||||
|
bool Prepare() const;
|
||||||
|
|
||||||
static unsigned int GetValidSize(unsigned int size);
|
static unsigned int GetValidSize(unsigned int size);
|
||||||
static bool IsFormatSupported(nzPixelFormat format);
|
static bool IsFormatSupported(nzPixelFormat format);
|
||||||
static bool IsMipmappingSupported();
|
static bool IsMipmappingSupported();
|
||||||
static bool IsTypeSupported(nzImageType type);
|
static bool IsTypeSupported(nzImageType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetTarget(bool isTarget);
|
NzRenderTexture* GetRenderTexture() const;
|
||||||
|
void SetRenderTexture(NzRenderTexture* renderTexture);
|
||||||
|
|
||||||
NzTextureImpl* m_impl;
|
NzTextureImpl* m_impl;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class NAZARA_API NzAnimation : public NzResource
|
||||||
NzAnimation() = default;
|
NzAnimation() = default;
|
||||||
~NzAnimation();
|
~NzAnimation();
|
||||||
|
|
||||||
unsigned int AddSequence(const NzSequence& sequence);
|
bool AddSequence(const NzSequence& sequence);
|
||||||
|
|
||||||
bool Create(nzAnimationType type, unsigned int frameCount);
|
bool Create(nzAnimationType type, unsigned int frameCount);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
@ -54,6 +54,7 @@ class NAZARA_API NzAnimation : public NzResource
|
||||||
const NzSequence* GetSequence(const NzString& sequenceName) const;
|
const NzSequence* GetSequence(const NzString& sequenceName) const;
|
||||||
const NzSequence* GetSequence(unsigned int index) const;
|
const NzSequence* GetSequence(unsigned int index) const;
|
||||||
unsigned int GetSequenceCount() const;
|
unsigned int GetSequenceCount() const;
|
||||||
|
int GetSequenceIndex(const NzString& sequenceName) const;
|
||||||
nzAnimationType GetType() const;
|
nzAnimationType GetType() const;
|
||||||
|
|
||||||
bool HasSequence(const NzString& sequenceName) const;
|
bool HasSequence(const NzString& sequenceName) const;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,9 @@ enum nzAnimationType
|
||||||
{
|
{
|
||||||
nzAnimationType_Keyframe,
|
nzAnimationType_Keyframe,
|
||||||
nzAnimationType_Skeletal,
|
nzAnimationType_Skeletal,
|
||||||
nzAnimationType_Static
|
nzAnimationType_Static,
|
||||||
|
|
||||||
|
nzAnimationType_Max = nzAnimationType_Static
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzBufferAccess
|
enum nzBufferAccess
|
||||||
|
|
@ -19,7 +21,9 @@ enum nzBufferAccess
|
||||||
nzBufferAccess_DiscardAndWrite,
|
nzBufferAccess_DiscardAndWrite,
|
||||||
nzBufferAccess_ReadOnly,
|
nzBufferAccess_ReadOnly,
|
||||||
nzBufferAccess_ReadWrite,
|
nzBufferAccess_ReadWrite,
|
||||||
nzBufferAccess_WriteOnly
|
nzBufferAccess_WriteOnly,
|
||||||
|
|
||||||
|
nzBufferAccess_Max = nzBufferAccess_WriteOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzBufferStorage
|
enum nzBufferStorage
|
||||||
|
|
@ -34,13 +38,17 @@ enum nzBufferStorage
|
||||||
enum nzBufferType
|
enum nzBufferType
|
||||||
{
|
{
|
||||||
nzBufferType_Index,
|
nzBufferType_Index,
|
||||||
nzBufferType_Vertex
|
nzBufferType_Vertex,
|
||||||
|
|
||||||
|
nzBufferType_Max = nzBufferType_Vertex
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzBufferUsage
|
enum nzBufferUsage
|
||||||
{
|
{
|
||||||
nzBufferUsage_Dynamic,
|
nzBufferUsage_Dynamic,
|
||||||
nzBufferUsage_Static
|
nzBufferUsage_Static,
|
||||||
|
|
||||||
|
nzBufferUsage_Max = nzBufferUsage_Static
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzCubemapFace
|
enum nzCubemapFace
|
||||||
|
|
@ -52,7 +60,9 @@ enum nzCubemapFace
|
||||||
nzCubemapFace_PositiveZ = 4,
|
nzCubemapFace_PositiveZ = 4,
|
||||||
nzCubemapFace_NegativeX = 1,
|
nzCubemapFace_NegativeX = 1,
|
||||||
nzCubemapFace_NegativeY = 3,
|
nzCubemapFace_NegativeY = 3,
|
||||||
nzCubemapFace_NegativeZ = 5
|
nzCubemapFace_NegativeZ = 5,
|
||||||
|
|
||||||
|
nzCubemapFace_Max = nzCubemapFace_NegativeZ
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzElementStream
|
enum nzElementStream
|
||||||
|
|
@ -73,7 +83,9 @@ enum nzElementType
|
||||||
nzElementType_Float1,
|
nzElementType_Float1,
|
||||||
nzElementType_Float2,
|
nzElementType_Float2,
|
||||||
nzElementType_Float3,
|
nzElementType_Float3,
|
||||||
nzElementType_Float4
|
nzElementType_Float4,
|
||||||
|
|
||||||
|
nzElementType_Max = nzElementType_Float4
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzElementUsage
|
enum nzElementUsage
|
||||||
|
|
@ -103,14 +115,18 @@ enum nzEventType
|
||||||
nzEventType_Moved,
|
nzEventType_Moved,
|
||||||
nzEventType_Quit,
|
nzEventType_Quit,
|
||||||
nzEventType_Resized,
|
nzEventType_Resized,
|
||||||
nzEventType_TextEntered
|
nzEventType_TextEntered,
|
||||||
|
|
||||||
|
nzEventType_Max = nzEventType_TextEntered
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzExtend
|
enum nzExtend
|
||||||
{
|
{
|
||||||
nzExtend_Finite,
|
nzExtend_Finite,
|
||||||
nzExtend_Infinite,
|
nzExtend_Infinite,
|
||||||
nzExtend_Null
|
nzExtend_Null,
|
||||||
|
|
||||||
|
nzExtend_Max = nzExtend_Null
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzImageType
|
enum nzImageType
|
||||||
|
|
@ -150,7 +166,6 @@ enum nzPixelFormat
|
||||||
nzPixelFormat_RGB5A1, // 1*nzUInt16
|
nzPixelFormat_RGB5A1, // 1*nzUInt16
|
||||||
nzPixelFormat_RGB8, // 3*nzUInt8
|
nzPixelFormat_RGB8, // 3*nzUInt8
|
||||||
nzPixelFormat_RGBA8, // 4*nzUInt8
|
nzPixelFormat_RGBA8, // 4*nzUInt8
|
||||||
/*
|
|
||||||
nzPixelFormat_Depth16,
|
nzPixelFormat_Depth16,
|
||||||
nzPixelFormat_Depth24,
|
nzPixelFormat_Depth24,
|
||||||
nzPixelFormat_Depth24Stencil8,
|
nzPixelFormat_Depth24Stencil8,
|
||||||
|
|
@ -159,9 +174,20 @@ enum nzPixelFormat
|
||||||
nzPixelFormat_Stencil4,
|
nzPixelFormat_Stencil4,
|
||||||
nzPixelFormat_Stencil8,
|
nzPixelFormat_Stencil8,
|
||||||
nzPixelFormat_Stencil16,
|
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
|
enum nzPixelFlipping
|
||||||
|
|
@ -179,7 +205,9 @@ enum nzPrimitiveType
|
||||||
nzPrimitiveType_PointList,
|
nzPrimitiveType_PointList,
|
||||||
nzPrimitiveType_TriangleList,
|
nzPrimitiveType_TriangleList,
|
||||||
nzPrimitiveType_TriangleStrip,
|
nzPrimitiveType_TriangleStrip,
|
||||||
nzPrimitiveType_TriangleFan
|
nzPrimitiveType_TriangleFan,
|
||||||
|
|
||||||
|
nzPrimitiveType_Max = nzPrimitiveType_TriangleFan
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzWindowCursor
|
enum nzWindowCursor
|
||||||
|
|
@ -202,10 +230,12 @@ enum nzWindowCursor
|
||||||
nzWindowCursor_ResizeSW,
|
nzWindowCursor_ResizeSW,
|
||||||
nzWindowCursor_ResizeW,
|
nzWindowCursor_ResizeW,
|
||||||
nzWindowCursor_Text,
|
nzWindowCursor_Text,
|
||||||
nzWindowCursor_Wait
|
nzWindowCursor_Wait,
|
||||||
|
|
||||||
|
nzWindowCursor_Max = nzWindowCursor_Wait
|
||||||
};
|
};
|
||||||
|
|
||||||
enum nzWindowStyle
|
enum nzWindowStyleFlags
|
||||||
{
|
{
|
||||||
nzWindowStyle_None = 0x0,
|
nzWindowStyle_None = 0x0,
|
||||||
nzWindowStyle_Fullscreen = 0x1,
|
nzWindowStyle_Fullscreen = 0x1,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/InputStream.hpp>
|
#include <Nazara/Core/InputStream.hpp>
|
||||||
#include <Nazara/Core/Resource.hpp>
|
#include <Nazara/Core/Resource.hpp>
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
#include <Nazara/Core/ResourceLoader.hpp>
|
#include <Nazara/Core/ResourceLoader.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Utility/Animation.hpp>
|
#include <Nazara/Utility/Animation.hpp>
|
||||||
|
|
@ -34,7 +35,7 @@ using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
|
||||||
|
|
||||||
struct NzMeshImpl;
|
struct NzMeshImpl;
|
||||||
|
|
||||||
class NAZARA_API NzMesh : public NzResource
|
class NAZARA_API NzMesh : public NzResource, NzResourceListener
|
||||||
{
|
{
|
||||||
friend NzMeshLoader;
|
friend NzMeshLoader;
|
||||||
|
|
||||||
|
|
@ -42,9 +43,9 @@ class NAZARA_API NzMesh : public NzResource
|
||||||
NzMesh() = default;
|
NzMesh() = default;
|
||||||
~NzMesh();
|
~NzMesh();
|
||||||
|
|
||||||
unsigned int AddSkin(const NzString& skin, bool setDefault = false);
|
bool AddSkin(const NzString& skin, bool setDefault = false);
|
||||||
nzUInt8 AddSubMesh(NzSubMesh* subMesh);
|
bool AddSubMesh(NzSubMesh* subMesh);
|
||||||
nzUInt8 AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
|
bool AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
|
||||||
|
|
||||||
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
|
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;
|
NzString GetSkin(unsigned int index = 0) const;
|
||||||
unsigned int GetSkinCount() const;
|
unsigned int GetSkinCount() const;
|
||||||
NzSubMesh* GetSubMesh(const NzString& identifier);
|
NzSubMesh* GetSubMesh(const NzString& identifier);
|
||||||
NzSubMesh* GetSubMesh(nzUInt8 index);
|
NzSubMesh* GetSubMesh(unsigned int index);
|
||||||
const NzSubMesh* GetSubMesh(const NzString& identifier) const;
|
const NzSubMesh* GetSubMesh(const NzString& identifier) const;
|
||||||
const NzSubMesh* GetSubMesh(nzUInt8 index) const;
|
const NzSubMesh* GetSubMesh(unsigned int index) const;
|
||||||
nzUInt8 GetSubMeshCount() const;
|
unsigned int GetSubMeshCount() const;
|
||||||
|
int GetSubMeshIndex(const NzString& identifier) const;
|
||||||
unsigned int GetVertexCount() const;
|
unsigned int GetVertexCount() const;
|
||||||
|
|
||||||
bool HasAnimation() const;
|
bool HasAnimation() const;
|
||||||
bool HasSkin(unsigned int index = 0) const;
|
bool HasSkin(unsigned int index = 0) const;
|
||||||
bool HasSubMesh(const NzString& identifier) const;
|
bool HasSubMesh(const NzString& identifier) const;
|
||||||
bool HasSubMesh(nzUInt8 index = 0) const;
|
bool HasSubMesh(unsigned int index = 0) const;
|
||||||
|
|
||||||
void InvalidateAABB() const;
|
void InvalidateAABB() const;
|
||||||
|
|
||||||
|
|
@ -80,11 +82,14 @@ class NAZARA_API NzMesh : public NzResource
|
||||||
|
|
||||||
void RemoveSkin(unsigned int index = 0);
|
void RemoveSkin(unsigned int index = 0);
|
||||||
void RemoveSubMesh(const NzString& identifier);
|
void RemoveSubMesh(const NzString& identifier);
|
||||||
void RemoveSubMesh(nzUInt8 index = 0);
|
void RemoveSubMesh(unsigned int index = 0);
|
||||||
|
|
||||||
bool SetAnimation(const NzAnimation* animation);
|
bool SetAnimation(const NzAnimation* animation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void OnResourceCreated(const NzResource* resource, int index) override;
|
||||||
|
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||||
|
|
||||||
NzMeshImpl* m_impl = nullptr;
|
NzMeshImpl* m_impl = nullptr;
|
||||||
|
|
||||||
static NzMeshLoader::LoaderList s_loaders;
|
static NzMeshLoader::LoaderList s_loaders;
|
||||||
|
|
|
||||||
|
|
@ -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 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 nzUInt8 GetBPP(nzPixelFormat format);
|
||||||
|
static nzPixelFormatType GetType(nzPixelFormat format);
|
||||||
|
|
||||||
static bool HasAlpha(nzPixelFormat format);
|
static bool HasAlpha(nzPixelFormat format);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,16 +225,79 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
|
||||||
case nzPixelFormat_RGBA8:
|
case nzPixelFormat_RGBA8:
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
case nzPixelFormat_Undefined:
|
case nzPixelFormat_Depth16:
|
||||||
NazaraError("Invalid pixel format");
|
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;
|
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;
|
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)
|
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
|
|
@ -252,6 +315,14 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
|
||||||
case nzPixelFormat_DXT1:
|
case nzPixelFormat_DXT1:
|
||||||
case nzPixelFormat_L8:
|
case nzPixelFormat_L8:
|
||||||
case nzPixelFormat_RGB8:
|
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;
|
return false;
|
||||||
|
|
||||||
case nzPixelFormat_Undefined:
|
case nzPixelFormat_Undefined:
|
||||||
|
|
@ -271,9 +342,30 @@ inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
|
||||||
case nzPixelFormat_DXT5:
|
case nzPixelFormat_DXT5:
|
||||||
return true;
|
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;
|
return false;
|
||||||
|
|
||||||
|
case nzPixelFormat_Undefined:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NazaraError("Invalid pixel format");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat)
|
inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat)
|
||||||
|
|
@ -360,6 +452,30 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format)
|
||||||
case nzPixelFormat_RGBA8:
|
case nzPixelFormat_RGBA8:
|
||||||
return "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:
|
case nzPixelFormat_Undefined:
|
||||||
return "Undefined";
|
return "Undefined";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@
|
||||||
#define NAZARA_STATICMESH_HPP
|
#define NAZARA_STATICMESH_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
#include <Nazara/Utility/SubMesh.hpp>
|
#include <Nazara/Utility/SubMesh.hpp>
|
||||||
|
|
||||||
class NAZARA_API NzStaticMesh final : public NzSubMesh
|
class NAZARA_API NzStaticMesh final : public NzSubMesh, NzResourceListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzStaticMesh(const NzMesh* parent);
|
NzStaticMesh(const NzMesh* parent);
|
||||||
|
|
@ -38,6 +39,7 @@ class NAZARA_API NzStaticMesh final : public NzSubMesh
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
|
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
|
||||||
|
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||||
|
|
||||||
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
|
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
|
||||||
NzAxisAlignedBox m_aabb;
|
NzAxisAlignedBox m_aabb;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ class NAZARA_API NzVertexDeclaration : public NzResource
|
||||||
NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration);
|
NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration);
|
||||||
NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept;
|
NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept;
|
||||||
|
|
||||||
|
static unsigned int GetElementCount(nzElementType type);
|
||||||
|
static unsigned int GetElementSize(nzElementType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NzVertexDeclarationImpl* m_sharedImpl = nullptr;
|
NzVertexDeclarationImpl* m_sharedImpl = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||||
|
#include <Nazara/Core/ConditionVariable.hpp>
|
||||||
#include <Nazara/Core/Mutex.hpp>
|
#include <Nazara/Core/Mutex.hpp>
|
||||||
#include <Nazara/Core/ThreadCondition.hpp>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class NzCursor;
|
class NzCursor;
|
||||||
|
|
@ -61,6 +61,7 @@ class NAZARA_API NzWindow : NzNonCopyable
|
||||||
|
|
||||||
bool IsMinimized() const;
|
bool IsMinimized() const;
|
||||||
bool IsOpen() const;
|
bool IsOpen() const;
|
||||||
|
bool IsValid() const;
|
||||||
bool IsVisible() const;
|
bool IsVisible() const;
|
||||||
|
|
||||||
bool PollEvent(NzEvent* event);
|
bool PollEvent(NzEvent* event);
|
||||||
|
|
@ -85,8 +86,8 @@ class NAZARA_API NzWindow : NzNonCopyable
|
||||||
bool WaitEvent(NzEvent* event);
|
bool WaitEvent(NzEvent* event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnWindowDestroying();
|
|
||||||
virtual bool OnWindowCreated();
|
virtual bool OnWindowCreated();
|
||||||
|
virtual void OnWindowDestroy();
|
||||||
|
|
||||||
NzWindowImpl* m_impl;
|
NzWindowImpl* m_impl;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,6 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
if (sampleCount == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#if NAZARA_AUDIO_SAFE
|
#if NAZARA_AUDIO_SAFE
|
||||||
if (!IsFormatSupported(format))
|
if (!IsFormatSupported(format))
|
||||||
{
|
{
|
||||||
|
|
@ -60,6 +57,12 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sampleCount == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Sample rate must be different from zero");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sampleRate == 0)
|
if (sampleRate == 0)
|
||||||
{
|
{
|
||||||
NazaraError("Sample rate must be different from zero");
|
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];
|
m_impl->samples = new nzInt16[sampleCount];
|
||||||
std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16));
|
std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16));
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,6 +115,8 @@ void NzSoundBuffer::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
delete[] m_impl->samples;
|
delete[] m_impl->samples;
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
|
||||||
// Copyright (C) 2012 Jérôme Leclercq
|
// Copyright (C) 2012 Jérôme Leclercq
|
||||||
// This file is part of the "Nazara Engine - Core module"
|
// This file is part of the "Nazara Engine - Core module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
/*
|
||||||
#include <Nazara/Core/ByteArray.hpp>
|
#include <Nazara/Core/ByteArray.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#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)
|
m_sharedArray(buffer.m_sharedArray)
|
||||||
{
|
{
|
||||||
buffer.m_sharedArray = &emptyArray;
|
buffer.m_sharedArray = &emptyArray;
|
||||||
|
|
|
||||||
|
|
@ -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"
|
// This file is part of the "Nazara Engine - Core module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
|
@ -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)));
|
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
|
||||||
if (!ptr)
|
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->array = multi;
|
||||||
ptr->file = file;
|
ptr->file = file;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <Nazara/Core/Resource.hpp>
|
#include <Nazara/Core/Resource.hpp>
|
||||||
#include <Nazara/Core/Config.hpp>
|
#include <Nazara/Core/Config.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
NzResource::NzResource(bool persistent) :
|
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
|
void NzResource::AddResourceReference() const
|
||||||
{
|
{
|
||||||
|
NazaraLock(m_mutex)
|
||||||
|
|
||||||
m_resourceReferenceCount++;
|
m_resourceReferenceCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzResource::IsPersistent() const
|
bool NzResource::IsPersistent() const
|
||||||
{
|
{
|
||||||
|
NazaraLock(m_mutex)
|
||||||
|
|
||||||
return m_resourcePersistent;
|
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
|
void NzResource::RemoveResourceReference() const
|
||||||
{
|
{
|
||||||
|
NazaraMutexLock(m_mutex);
|
||||||
|
|
||||||
#if NAZARA_CORE_SAFE
|
#if NAZARA_CORE_SAFE
|
||||||
if (m_resourceReferenceCount == 0)
|
if (m_resourceReferenceCount == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -42,13 +80,59 @@ void NzResource::RemoveResourceReference() const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent)
|
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent)
|
||||||
|
{
|
||||||
|
NazaraMutexUnlock(m_mutex);
|
||||||
delete this;
|
delete this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NazaraMutexUnlock(m_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzResource::SetPersistent(bool persistent)
|
void NzResource::SetPersistent(bool persistent)
|
||||||
{
|
{
|
||||||
|
NazaraMutexLock(m_mutex);
|
||||||
|
|
||||||
m_resourcePersistent = persistent;
|
m_resourcePersistent = persistent;
|
||||||
|
|
||||||
if (!persistent && m_resourceReferenceCount == 0)
|
if (!persistent && m_resourceReferenceCount == 0)
|
||||||
|
{
|
||||||
|
NazaraMutexUnlock(m_mutex);
|
||||||
delete this;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <Utfcpp/utf8.h>
|
#include <Utfcpp/utf8.h>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
@ -108,7 +109,7 @@ NzString::NzString(const char* string)
|
||||||
m_sharedString->capacity = size;
|
m_sharedString->capacity = size;
|
||||||
m_sharedString->size = size;
|
m_sharedString->size = size;
|
||||||
m_sharedString->string = new char[size+1];
|
m_sharedString->string = new char[size+1];
|
||||||
std::strcpy(m_sharedString->string, string);
|
std::memcpy(m_sharedString->string, string, size+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_sharedString = &emptyString;
|
m_sharedString = &emptyString;
|
||||||
|
|
@ -125,7 +126,7 @@ NzString::NzString(const std::string& string)
|
||||||
m_sharedString->capacity = string.capacity();
|
m_sharedString->capacity = string.capacity();
|
||||||
m_sharedString->size = string.size();
|
m_sharedString->size = string.size();
|
||||||
m_sharedString->string = new char[string.capacity()+1];
|
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
|
else
|
||||||
m_sharedString = &emptyString;
|
m_sharedString = &emptyString;
|
||||||
|
|
@ -180,7 +181,7 @@ NzString& NzString::Append(char character)
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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[m_sharedString->size] = character;
|
||||||
str[newSize] = '\0';
|
str[newSize] = '\0';
|
||||||
|
|
||||||
|
|
@ -207,7 +208,7 @@ NzString& NzString::Append(const char* string)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
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;
|
m_sharedString->size += length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -216,8 +217,8 @@ NzString& NzString::Append(const char* string)
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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);
|
||||||
std::strcpy(&str[m_sharedString->size], string);
|
std::memcpy(&str[m_sharedString->size], string, length+1);
|
||||||
|
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
m_sharedString = new SharedString;
|
m_sharedString = new SharedString;
|
||||||
|
|
@ -241,7 +242,7 @@ NzString& NzString::Append(const NzString& string)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
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;
|
m_sharedString->size += string.m_sharedString->size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -250,8 +251,8 @@ NzString& NzString::Append(const NzString& string)
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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);
|
||||||
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
|
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||||
|
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
m_sharedString = new SharedString;
|
m_sharedString = new SharedString;
|
||||||
|
|
@ -2270,7 +2271,7 @@ char* NzString::GetUtf8Buffer(unsigned int* size) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
char* buffer = new char[m_sharedString->size+1];
|
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)
|
if (size)
|
||||||
*size = m_sharedString->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
|
if (cp <= 0xFFFF && (cp < 0xD800 || cp > 0xDFFF)) // @Laurent Gomila
|
||||||
*ptr++ = static_cast<wchar_t>(cp);
|
*ptr++ = static_cast<wchar_t>(cp);
|
||||||
else
|
else
|
||||||
*ptr++ = static_cast<wchar_t>('?');
|
*ptr++ = L'?';
|
||||||
}
|
}
|
||||||
while (*it++);
|
while (*it++);
|
||||||
}
|
}
|
||||||
|
|
@ -2480,7 +2481,7 @@ NzString& NzString::Insert(int pos, char character)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
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->string[start] = character;
|
||||||
|
|
||||||
m_sharedString->size += 1;
|
m_sharedString->size += 1;
|
||||||
|
|
@ -2526,8 +2527,8 @@ NzString& NzString::Insert(int pos, const char* string)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
std::memmove(&m_sharedString->string[start+len], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
|
std::memmove(&m_sharedString->string[start+len], &m_sharedString->string[start], m_sharedString->size);
|
||||||
std::memcpy(&m_sharedString->string[start], string, len*sizeof(char));
|
std::memcpy(&m_sharedString->string[start], string, len+1);
|
||||||
|
|
||||||
m_sharedString->size += len;
|
m_sharedString->size += len;
|
||||||
}
|
}
|
||||||
|
|
@ -2576,8 +2577,8 @@ NzString& NzString::Insert(int pos, const NzString& string)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
std::memmove(&m_sharedString->string[start+string.m_sharedString->size], &m_sharedString->string[start], 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*sizeof(char));
|
std::memcpy(&m_sharedString->string[start], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||||
|
|
||||||
m_sharedString->size += string.m_sharedString->size;
|
m_sharedString->size += string.m_sharedString->size;
|
||||||
}
|
}
|
||||||
|
|
@ -2837,7 +2838,7 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&m_sharedString->string[pos], replaceString, oSize*sizeof(char));
|
std::memcpy(&m_sharedString->string[pos], replaceString, oSize);
|
||||||
pos += oSize;
|
pos += oSize;
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
|
|
@ -2859,9 +2860,9 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
|
||||||
{
|
{
|
||||||
const char* r = &m_sharedString->string[pos];
|
const char* r = &m_sharedString->string[pos];
|
||||||
|
|
||||||
std::memcpy(ptr, p, (r-p)*sizeof(char));
|
std::memcpy(ptr, p, r-p);
|
||||||
ptr += r-p;
|
ptr += r-p;
|
||||||
std::memcpy(ptr, replaceString, rSize*sizeof(char));
|
std::memcpy(ptr, replaceString, rSize);
|
||||||
ptr += rSize;
|
ptr += rSize;
|
||||||
p = r+oSize;
|
p = r+oSize;
|
||||||
pos += oSize;
|
pos += oSize;
|
||||||
|
|
@ -2907,7 +2908,7 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
|
||||||
found = true;
|
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;
|
pos += oldString.m_sharedString->size;
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
|
|
@ -2929,9 +2930,9 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
|
||||||
{
|
{
|
||||||
const char* r = &m_sharedString->string[pos];
|
const char* r = &m_sharedString->string[pos];
|
||||||
|
|
||||||
std::memcpy(ptr, p, (r-p)*sizeof(char));
|
std::memcpy(ptr, p, r-p);
|
||||||
ptr += 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;
|
ptr += replaceString.m_sharedString->size;
|
||||||
p = r+oldString.m_sharedString->size;
|
p = r+oldString.m_sharedString->size;
|
||||||
pos += 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];
|
char* ptr = new char[bufferSize+1];
|
||||||
if (m_sharedString->size > 0)
|
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;
|
unsigned int size = m_sharedString->size;
|
||||||
|
|
||||||
|
|
@ -3233,7 +3234,7 @@ NzString& NzString::Resize(int size, char character)
|
||||||
{
|
{
|
||||||
char* newString = new char[newSize+1];
|
char* newString = new char[newSize+1];
|
||||||
if (m_sharedString->size != 0)
|
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* ptr = &newString[m_sharedString->size];
|
||||||
char* limit = &newString[newSize];
|
char* limit = &newString[newSize];
|
||||||
|
|
@ -3673,7 +3674,7 @@ bool NzString::StartsWith(const NzString& string, nzUInt32 flags) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -3699,7 +3700,7 @@ NzString NzString::Substr(int startPos, int endPos) const
|
||||||
|
|
||||||
unsigned int size = minEnd-start+1;
|
unsigned int size = minEnd-start+1;
|
||||||
char* str = new char[size+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';
|
str[size] = '\0';
|
||||||
|
|
||||||
return NzString(new SharedString(1, size, size, str));
|
return NzString(new SharedString(1, size, size, str));
|
||||||
|
|
@ -4185,7 +4186,7 @@ NzString& NzString::operator=(const char* string)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sharedString->size = size;
|
m_sharedString->size = size;
|
||||||
std::strcpy(m_sharedString->string, string);
|
std::memcpy(m_sharedString->string, string, size+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
|
|
@ -4209,7 +4210,7 @@ NzString& NzString::operator=(const std::string& string)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sharedString->size = string.size();
|
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
|
else
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
|
|
@ -4246,7 +4247,7 @@ NzString NzString::operator+(char character) const
|
||||||
|
|
||||||
unsigned int totalSize = m_sharedString->size+1;
|
unsigned int totalSize = m_sharedString->size+1;
|
||||||
char* str = new char[totalSize+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[m_sharedString->size] = character;
|
||||||
str[totalSize] = '\0';
|
str[totalSize] = '\0';
|
||||||
|
|
@ -4268,8 +4269,8 @@ NzString NzString::operator+(const char* string) const
|
||||||
|
|
||||||
unsigned int totalSize = m_sharedString->size + length;
|
unsigned int totalSize = m_sharedString->size + length;
|
||||||
char* str = new char[totalSize+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);
|
||||||
std::strcpy(&str[m_sharedString->size], string);
|
std::memcpy(&str[m_sharedString->size], string, length+1);
|
||||||
|
|
||||||
return NzString(new SharedString(1, totalSize, totalSize, str));
|
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();
|
unsigned int totalSize = m_sharedString->size + string.size();
|
||||||
char* str = new char[totalSize+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);
|
||||||
std::strcpy(&str[m_sharedString->size], string.c_str());
|
std::memcpy(&str[m_sharedString->size], string.c_str(), string.size()+1);
|
||||||
|
|
||||||
return NzString(new SharedString(1, totalSize, totalSize, str));
|
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;
|
unsigned int totalSize = m_sharedString->size + string.m_sharedString->size;
|
||||||
char* str = new char[totalSize+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);
|
||||||
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
|
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||||
|
|
||||||
return NzString(new SharedString(1, totalSize, totalSize, str));
|
return NzString(new SharedString(1, totalSize, totalSize, str));
|
||||||
}
|
}
|
||||||
|
|
@ -4328,7 +4329,7 @@ NzString& NzString::operator+=(char character)
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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[m_sharedString->size] = character;
|
||||||
str[newSize] = '\0';
|
str[newSize] = '\0';
|
||||||
|
|
||||||
|
|
@ -4350,25 +4351,25 @@ NzString& NzString::operator+=(const char* string)
|
||||||
if (m_sharedString->size == 0)
|
if (m_sharedString->size == 0)
|
||||||
return operator=(string);
|
return operator=(string);
|
||||||
|
|
||||||
unsigned int length = std::strlen(string);
|
unsigned int size = std::strlen(string);
|
||||||
if (length == 0)
|
if (size == 0)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (m_sharedString->capacity >= m_sharedString->size + length)
|
if (m_sharedString->capacity >= m_sharedString->size + size)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
std::strcpy(&m_sharedString->string[m_sharedString->size], string);
|
std::memcpy(&m_sharedString->string[m_sharedString->size], string, size+1);
|
||||||
m_sharedString->size += length;
|
m_sharedString->size += size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int newSize = m_sharedString->size + length;
|
unsigned int newSize = m_sharedString->size + size;
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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);
|
||||||
std::strcpy(&str[m_sharedString->size], string);
|
std::memcpy(&str[m_sharedString->size], string, size+1);
|
||||||
|
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
m_sharedString = new SharedString;
|
m_sharedString = new SharedString;
|
||||||
|
|
@ -4392,7 +4393,7 @@ NzString& NzString::operator+=(const std::string& string)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
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();
|
m_sharedString->size += string.size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -4401,8 +4402,8 @@ NzString& NzString::operator+=(const std::string& string)
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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);
|
||||||
std::strcpy(&str[m_sharedString->size], string.c_str());
|
std::memcpy(&str[m_sharedString->size], string.c_str(), string.size()+1);
|
||||||
|
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
m_sharedString = new SharedString;
|
m_sharedString = new SharedString;
|
||||||
|
|
@ -4426,7 +4427,7 @@ NzString& NzString::operator+=(const NzString& string)
|
||||||
{
|
{
|
||||||
EnsureOwnership();
|
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;
|
m_sharedString->size += string.m_sharedString->size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -4435,8 +4436,8 @@ NzString& NzString::operator+=(const NzString& string)
|
||||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||||
|
|
||||||
char* str = new char[bufferSize+1];
|
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);
|
||||||
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
|
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||||
|
|
||||||
ReleaseString();
|
ReleaseString();
|
||||||
m_sharedString = new SharedString;
|
m_sharedString = new SharedString;
|
||||||
|
|
@ -4902,7 +4903,7 @@ NzString operator+(char character, const NzString& string)
|
||||||
unsigned int totalSize = string.m_sharedString->size+1;
|
unsigned int totalSize = string.m_sharedString->size+1;
|
||||||
char* str = new char[totalSize+1];
|
char* str = new char[totalSize+1];
|
||||||
str[0] = character;
|
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));
|
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 size = std::strlen(string);
|
||||||
unsigned int totalSize = size + nstring.m_sharedString->size;
|
unsigned int totalSize = size + nstring.m_sharedString->size;
|
||||||
char* str = new char[totalSize+1];
|
char* str = new char[totalSize+1];
|
||||||
std::memcpy(str, string, size*sizeof(char));
|
std::memcpy(str, string, size);
|
||||||
std::strcpy(&str[size], nstring.m_sharedString->string);
|
std::memcpy(&str[size], nstring.m_sharedString->string, nstring.m_sharedString->size+1);
|
||||||
|
|
||||||
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
|
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;
|
unsigned int totalSize = string.size() + nstring.m_sharedString->size;
|
||||||
char* str = new char[totalSize+1];
|
char* str = new char[totalSize+1];
|
||||||
std::memcpy(str, string.c_str(), string.size()*sizeof(char));
|
std::memcpy(str, string.c_str(), string.size());
|
||||||
std::strcpy(&str[string.size()], nstring.m_sharedString->string);
|
std::memcpy(&str[string.size()], nstring.m_sharedString->string, nstring.m_sharedString->size+1);
|
||||||
|
|
||||||
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
|
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
|
||||||
}
|
}
|
||||||
|
|
@ -5083,7 +5084,7 @@ void NzString::EnsureOwnership()
|
||||||
m_sharedString->refCount--;
|
m_sharedString->refCount--;
|
||||||
|
|
||||||
char* string = new char[m_sharedString->capacity+1];
|
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);
|
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);
|
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
|
namespace std
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -172,15 +172,17 @@ bool NzContext::Create(const NzContextParameters& parameters)
|
||||||
if (m_parameters.antialiasingLevel > 0)
|
if (m_parameters.antialiasingLevel > 0)
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
if (NzOpenGL::IsSupported(NzOpenGL::DebugOutput) && m_parameters.debugMode)
|
if (NzOpenGL::IsSupported(nzOpenGLExtension_DebugOutput) && m_parameters.debugMode)
|
||||||
{
|
{
|
||||||
glDebugMessageCallback(&DebugCallback, this);
|
glDebugMessageCallback(&DebugCallback, this);
|
||||||
|
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,6 +190,8 @@ void NzContext::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
if (currentContext == this)
|
if (currentContext == this)
|
||||||
NzContextImpl::Desactivate();
|
NzContextImpl::Desactivate();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,6 @@
|
||||||
|
|
||||||
namespace
|
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;
|
GLuint lockedPrevious = 0;
|
||||||
nzUInt8 lockedLevel = 0;
|
nzUInt8 lockedLevel = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -41,6 +25,8 @@ m_parent(parent)
|
||||||
|
|
||||||
NzGLSLShader::~NzGLSLShader()
|
NzGLSLShader::~NzGLSLShader()
|
||||||
{
|
{
|
||||||
|
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
|
||||||
|
it->second.texture->RemoveResourceListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzGLSLShader::Bind()
|
bool NzGLSLShader::Bind()
|
||||||
|
|
@ -71,11 +57,11 @@ bool NzGLSLShader::BindTextures()
|
||||||
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
|
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
|
||||||
{
|
{
|
||||||
TextureSlot& slot = it->second;
|
TextureSlot& slot = it->second;
|
||||||
if (!slot.updated)
|
if (slot.enabled && !slot.updated)
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0 + slot.unit);
|
glActiveTexture(GL_TEXTURE0 + slot.unit);
|
||||||
if (!slot.texture->Bind())
|
if (!slot.texture->Prepare())
|
||||||
NazaraWarning("Failed to bind texture");
|
NazaraWarning("Failed to prepare texture");
|
||||||
|
|
||||||
slot.updated = true;
|
slot.updated = true;
|
||||||
}
|
}
|
||||||
|
|
@ -137,17 +123,35 @@ bool NzGLSLShader::Create()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Position], "Position");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Position], "Position");
|
||||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Normal], "Normal");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Normal], "Normal");
|
||||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Diffuse], "Diffuse");
|
||||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Tangent], "Tangent");
|
||||||
|
|
||||||
NzString uniform = "TexCoord";
|
NzString uniform;
|
||||||
unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
|
|
||||||
|
static const unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
|
||||||
|
|
||||||
|
uniform.Reserve(10); // 8 + 2
|
||||||
|
uniform = "TexCoord";
|
||||||
for (unsigned int i = 0; i < maxTexCoords; ++i)
|
for (unsigned int i = 0; i < maxTexCoords; ++i)
|
||||||
{
|
{
|
||||||
NzString uniformName = uniform + NzString::Number(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)
|
for (int i = 0; i <= nzShaderType_Max; ++i)
|
||||||
|
|
@ -224,7 +228,7 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source)
|
||||||
{
|
{
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
GLuint shader = glCreateShader(shaderType[type]);
|
GLuint shader = glCreateShader(NzOpenGL::ShaderType[type]);
|
||||||
if (!shader)
|
if (!shader)
|
||||||
{
|
{
|
||||||
m_log = "Failed to create shader object";
|
m_log = "Failed to create shader object";
|
||||||
|
|
@ -301,7 +305,12 @@ bool NzGLSLShader::SendBoolean(int location, bool value)
|
||||||
glProgramUniform1i(m_program, location, value);
|
glProgramUniform1i(m_program, location, value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform1i(location, value);
|
glUniform1i(location, value);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +324,12 @@ bool NzGLSLShader::SendDouble(int location, double value)
|
||||||
glProgramUniform1d(m_program, location, value);
|
glProgramUniform1d(m_program, location, value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform1d(location, value);
|
glUniform1d(location, value);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -329,7 +343,12 @@ bool NzGLSLShader::SendFloat(int location, float value)
|
||||||
glProgramUniform1f(m_program, location, value);
|
glProgramUniform1f(m_program, location, value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform1f(location, value);
|
glUniform1f(location, value);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +362,12 @@ bool NzGLSLShader::SendInteger(int location, int value)
|
||||||
glProgramUniform1i(m_program, location, value);
|
glProgramUniform1i(m_program, location, value);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform1i(location, value);
|
glUniform1i(location, value);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -357,7 +381,12 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4d& matrix)
|
||||||
glProgramUniformMatrix4dv(m_program, location, 1, GL_FALSE, matrix);
|
glProgramUniformMatrix4dv(m_program, location, 1, GL_FALSE, matrix);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniformMatrix4dv(location, 1, GL_FALSE, matrix);
|
glUniformMatrix4dv(location, 1, GL_FALSE, matrix);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -371,7 +400,12 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4f& matrix)
|
||||||
glProgramUniformMatrix4fv(m_program, location, 1, GL_FALSE, matrix);
|
glProgramUniformMatrix4fv(m_program, location, 1, GL_FALSE, matrix);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniformMatrix4fv(location, 1, GL_FALSE, matrix);
|
glUniformMatrix4fv(location, 1, GL_FALSE, matrix);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -388,12 +422,12 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture)
|
||||||
TextureSlot& slot = it->second;
|
TextureSlot& slot = it->second;
|
||||||
if (slot.texture != texture)
|
if (slot.texture != texture)
|
||||||
{
|
{
|
||||||
slot.texture->RemoveResourceReference();
|
slot.texture->RemoveResourceListener(this);
|
||||||
|
|
||||||
if (texture)
|
if (texture)
|
||||||
{
|
{
|
||||||
slot.texture = texture;
|
slot.texture = texture;
|
||||||
slot.texture->AddResourceReference();
|
slot.texture->AddResourceListener(this, location);
|
||||||
|
|
||||||
slot.updated = false;
|
slot.updated = false;
|
||||||
}
|
}
|
||||||
|
|
@ -439,21 +473,30 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureSlot slot;
|
TextureSlot slot;
|
||||||
|
slot.enabled = texture->IsValid();
|
||||||
slot.unit = unit;
|
slot.unit = unit;
|
||||||
slot.texture = texture;
|
slot.texture = texture;
|
||||||
texture->AddResourceReference();
|
texture->AddResourceListener(this, location);
|
||||||
|
|
||||||
m_textures[location] = slot;
|
m_textures[location] = slot;
|
||||||
|
|
||||||
|
if (slot.enabled)
|
||||||
|
{
|
||||||
if (glProgramUniform1i)
|
if (glProgramUniform1i)
|
||||||
glProgramUniform1i(m_program, location, unit);
|
glProgramUniform1i(m_program, location, unit);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform1i(location, unit);
|
glUniform1i(location, unit);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +507,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector2d& vector)
|
||||||
glProgramUniform2dv(m_program, location, 1, vector);
|
glProgramUniform2dv(m_program, location, 1, vector);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform2dv(location, 1, vector);
|
glUniform2dv(location, 1, vector);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -478,7 +526,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector2f& vector)
|
||||||
glProgramUniform2fv(m_program, location, 1, vector);
|
glProgramUniform2fv(m_program, location, 1, vector);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform2fv(location, 1, vector);
|
glUniform2fv(location, 1, vector);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -492,7 +545,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector3d& vector)
|
||||||
glProgramUniform3dv(m_program, location, 1, vector);
|
glProgramUniform3dv(m_program, location, 1, vector);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform3dv(location, 1, vector);
|
glUniform3dv(location, 1, vector);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -506,7 +564,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector3f& vector)
|
||||||
glProgramUniform3fv(m_program, location, 1, vector);
|
glProgramUniform3fv(m_program, location, 1, vector);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform3fv(location, 1, vector);
|
glUniform3fv(location, 1, vector);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -520,7 +583,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector4d& vector)
|
||||||
glProgramUniform4dv(m_program, location, 1, vector);
|
glProgramUniform4dv(m_program, location, 1, vector);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform4dv(location, 1, vector);
|
glUniform4dv(location, 1, vector);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -534,7 +602,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector4f& vector)
|
||||||
glProgramUniform4fv(m_program, location, 1, vector);
|
glProgramUniform4fv(m_program, location, 1, vector);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lock();
|
if (!Lock())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to lock shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glUniform4fv(location, 1, vector);
|
glUniform4fv(location, 1, vector);
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -576,3 +649,64 @@ void NzGLSLShader::Unlock()
|
||||||
if (--lockedLevel == 0 && lockedPrevious != m_program)
|
if (--lockedLevel == 0 && lockedPrevious != m_program)
|
||||||
glUseProgram(lockedPrevious);
|
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");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,16 @@
|
||||||
#ifndef NAZARA_GLSLSHADER_HPP
|
#ifndef NAZARA_GLSLSHADER_HPP
|
||||||
#define NAZARA_GLSLSHADER_HPP
|
#define NAZARA_GLSLSHADER_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
#include <Nazara/Renderer/Shader.hpp>
|
#include <Nazara/Renderer/Shader.hpp>
|
||||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class NzGLSLShader : public NzShaderImpl
|
class NzResource;
|
||||||
|
|
||||||
|
class NzGLSLShader : public NzShaderImpl, NzResourceListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzGLSLShader(NzShader* parent);
|
NzGLSLShader(NzShader* parent);
|
||||||
|
|
@ -55,8 +58,13 @@ class NzGLSLShader : public NzShaderImpl
|
||||||
void Unlock();
|
void Unlock();
|
||||||
|
|
||||||
private:
|
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
|
struct TextureSlot
|
||||||
{
|
{
|
||||||
|
bool enabled;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
nzUInt8 unit;
|
nzUInt8 unit;
|
||||||
const NzTexture* texture;
|
const NzTexture* texture;
|
||||||
|
|
|
||||||
|
|
@ -12,38 +12,6 @@
|
||||||
|
|
||||||
namespace
|
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);
|
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)
|
nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
|
||||||
|
|
@ -53,16 +21,16 @@ namespace
|
||||||
if (access == nzBufferAccess_DiscardAndWrite)
|
if (access == nzBufferAccess_DiscardAndWrite)
|
||||||
{
|
{
|
||||||
GLint bufSize;
|
GLint bufSize;
|
||||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
|
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
|
||||||
|
|
||||||
GLint bufUsage;
|
GLint bufUsage;
|
||||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
|
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
|
||||||
|
|
||||||
// On discard le buffer
|
// 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)
|
if (ptr)
|
||||||
return reinterpret_cast<nzUInt8*>(ptr) + offset;
|
return reinterpret_cast<nzUInt8*>(ptr) + offset;
|
||||||
else
|
else
|
||||||
|
|
@ -71,7 +39,7 @@ namespace
|
||||||
|
|
||||||
nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
|
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);
|
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
|
||||||
|
|
@ -109,7 +77,7 @@ void NzHardwareBuffer::Bind()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
|
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
|
||||||
|
|
@ -120,14 +88,14 @@ bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
|
||||||
glGenBuffers(1, &m_buffer);
|
glGenBuffers(1, &m_buffer);
|
||||||
|
|
||||||
GLint previous;
|
GLint previous;
|
||||||
glGetIntegerv(bufferTargetBinding[m_type], &previous);
|
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], &previous);
|
||||||
|
|
||||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||||
glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]);
|
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
|
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||||
if (previous != 0)
|
if (previous != 0)
|
||||||
glBindBuffer(bufferTarget[m_type], previous);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -144,10 +112,10 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
GLuint previous;
|
GLuint previous;
|
||||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||||
|
|
||||||
if (previous != m_buffer)
|
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
|
// 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/
|
// 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
|
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
|
||||||
if (size == m_parent->GetSize())
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -170,12 +138,12 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
|
||||||
|
|
||||||
std::memcpy(ptr, data, size);
|
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
|
// 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) + ')');
|
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;
|
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)
|
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||||
if (previous != m_buffer && previous != 0)
|
if (previous != m_buffer && previous != 0)
|
||||||
glBindBuffer(bufferTarget[m_type], previous);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||||
|
|
||||||
return true;
|
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
|
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||||
GLuint previous;
|
GLuint previous;
|
||||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||||
|
|
||||||
if (previous != m_buffer)
|
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);
|
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)
|
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||||
if (previous != m_buffer && previous != 0)
|
if (previous != m_buffer && previous != 0)
|
||||||
glBindBuffer(bufferTarget[m_type], previous);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
@ -223,28 +191,28 @@ bool NzHardwareBuffer::Unmap()
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
GLuint previous;
|
GLuint previous;
|
||||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||||
|
|
||||||
if (previous != m_buffer)
|
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
|
// 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) + ')');
|
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)
|
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||||
if (previous != m_buffer && previous != 0)
|
if (previous != m_buffer && previous != 0)
|
||||||
glBindBuffer(bufferTarget[m_type], previous);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||||
if (previous != m_buffer && previous != 0)
|
if (previous != m_buffer && previous != 0)
|
||||||
glBindBuffer(bufferTarget[m_type], previous);
|
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,17 @@
|
||||||
NzOcclusionQuery::NzOcclusionQuery() :
|
NzOcclusionQuery::NzOcclusionQuery() :
|
||||||
m_id(0)
|
m_id(0)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (IsSupported())
|
if (IsSupported())
|
||||||
{
|
{
|
||||||
#endif
|
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
|
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NazaraError("Occlusion queries not supported");
|
NazaraError("Occlusion queries not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
if (!m_id)
|
if (!m_id)
|
||||||
|
|
|
||||||
|
|
@ -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 - Renderer module"
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<NzString> openGLextensionSet;
|
std::set<NzString> openGLextensionSet;
|
||||||
bool openGLextensions[NzOpenGL::Max+1] = {false};
|
bool openGLextensions[nzOpenGLExtension_Max+1] = {false};
|
||||||
unsigned int openGLversion = 0;
|
unsigned int openGLversion = 0;
|
||||||
|
|
||||||
bool LoadExtensionsString(const NzString& extensionString)
|
bool LoadExtensionsString(const NzString& extensionString)
|
||||||
|
|
@ -69,7 +69,7 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// On peut sûrement faire plus rapide mais comme ça ne se fait qu'une fois et que NzString implémente le COW...
|
// On peut sûrement faire plus rapide mais comme ça ne se fait qu'une fois et que NzString implémente le COW...
|
||||||
std::vector<NzString> ext;
|
std::vector<NzString> ext;
|
||||||
extensionString.Split(ext);
|
extensionString.Split(ext);
|
||||||
|
|
||||||
|
|
@ -106,36 +106,38 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NzOpenGLFunc NzOpenGL::GetEntry(const NzString& entryPoint)
|
namespace NzOpenGL
|
||||||
{
|
{
|
||||||
|
NzOpenGLFunc GetEntry(const NzString& entryPoint)
|
||||||
|
{
|
||||||
return LoadEntry(entryPoint.GetConstBuffer(), false);
|
return LoadEntry(entryPoint.GetConstBuffer(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzOpenGL::GetVersion()
|
unsigned int GetVersion()
|
||||||
{
|
{
|
||||||
return openGLversion;
|
return openGLversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzOpenGL::Initialize()
|
bool Initialize()
|
||||||
{
|
{
|
||||||
if (!LoadLibrary())
|
if (!LoadLibrary())
|
||||||
{
|
{
|
||||||
NazaraError("Failed to load OpenGL library");
|
NazaraError("Failed to load OpenGL library");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Le chargement des fonctions OpenGL nécessite un contexte OpenGL
|
// Le chargement des fonctions OpenGL nécessite un contexte OpenGL
|
||||||
NzContextParameters parameters;
|
NzContextParameters parameters;
|
||||||
parameters.majorVersion = 2;
|
parameters.majorVersion = 2;
|
||||||
parameters.minorVersion = 0;
|
parameters.minorVersion = 0;
|
||||||
parameters.shared = false;
|
parameters.shared = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note: Même le contexte de chargement nécessite quelques fonctions de base pour correctement s'initialiser
|
Note: Même le contexte de chargement nécessite quelques fonctions de base pour correctement s'initialiser
|
||||||
Pour cette raison, deux contextes sont créés, le premier sert à récupérer les fonctions permetttant
|
Pour cette raison, deux contextes sont créés, le premier sert à récupérer les fonctions permetttant
|
||||||
de créer le second avec les bons paramètres.
|
de créer le second avec les bons paramètres.
|
||||||
|
|
||||||
Non sérieusement si quelqu'un a une meilleure idée qu'il me le dise
|
Non sérieusement si quelqu'un a une meilleure idée qu'il me le dise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/****************************************Initialisation****************************************/
|
/****************************************Initialisation****************************************/
|
||||||
|
|
@ -158,9 +160,9 @@ bool NzOpenGL::Initialize()
|
||||||
glXCreateContextAttribs = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
|
glXCreateContextAttribs = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Récupération de la version d'OpenGL
|
// Récupération de la version d'OpenGL
|
||||||
// Ce code se base sur le fait que la carte graphique renverra un contexte de compatibilité avec la plus haute version supportée
|
// Ce code se base sur le fait que la carte graphique renverra un contexte de compatibilité avec la plus haute version supportée
|
||||||
// Ce qui semble vrai au moins chez ATI/AMD et NVidia, mais si quelqu'un à une meilleure idée ...
|
// Ce qui semble vrai au moins chez ATI/AMD et NVidia, mais si quelqu'un à une meilleure idée ...
|
||||||
glGetString = reinterpret_cast<PFNGLGETSTRINGPROC>(LoadEntry("glGetString", false));
|
glGetString = reinterpret_cast<PFNGLGETSTRINGPROC>(LoadEntry("glGetString", false));
|
||||||
if (!glGetString)
|
if (!glGetString)
|
||||||
{
|
{
|
||||||
|
|
@ -197,7 +199,7 @@ bool NzOpenGL::Initialize()
|
||||||
openGLversion = major*100 + minor*10;
|
openGLversion = major*100 + minor*10;
|
||||||
if (openGLversion < 200)
|
if (openGLversion < 200)
|
||||||
{
|
{
|
||||||
NazaraError("OpenGL version is too low, please upgrade your drivers or your graphics card");
|
NazaraError("OpenGL version is too low, please upgrade your drivers or your video card");
|
||||||
Uninitialize();
|
Uninitialize();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -207,8 +209,7 @@ bool NzOpenGL::Initialize()
|
||||||
parameters.majorVersion = NzContextParameters::defaultMajorVersion = major;
|
parameters.majorVersion = NzContextParameters::defaultMajorVersion = major;
|
||||||
parameters.minorVersion = NzContextParameters::defaultMinorVersion = minor;
|
parameters.minorVersion = NzContextParameters::defaultMinorVersion = minor;
|
||||||
|
|
||||||
// Destruction implicite du premier contexte
|
if (!loadContext.Create(parameters)) // Destruction implicite du premier contexte
|
||||||
if (!loadContext.Create(parameters))
|
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create load context");
|
NazaraError("Failed to create load context");
|
||||||
Uninitialize();
|
Uninitialize();
|
||||||
|
|
@ -286,9 +287,11 @@ bool NzOpenGL::Initialize()
|
||||||
glStencilFunc = reinterpret_cast<PFNGLSTENCILFUNCPROC>(LoadEntry("glStencilFunc"));
|
glStencilFunc = reinterpret_cast<PFNGLSTENCILFUNCPROC>(LoadEntry("glStencilFunc"));
|
||||||
glStencilOp = reinterpret_cast<PFNGLSTENCILOPPROC>(LoadEntry("glStencilOp"));
|
glStencilOp = reinterpret_cast<PFNGLSTENCILOPPROC>(LoadEntry("glStencilOp"));
|
||||||
glTexImage2D = reinterpret_cast<PFNGLTEXIMAGE2DPROC>(LoadEntry("glTexImage2D"));
|
glTexImage2D = reinterpret_cast<PFNGLTEXIMAGE2DPROC>(LoadEntry("glTexImage2D"));
|
||||||
|
glTexImage3D = reinterpret_cast<PFNGLTEXIMAGE3DPROC>(LoadEntry("glTexImage3D"));
|
||||||
glTexParameterf = reinterpret_cast<PFNGLTEXPARAMETERFPROC>(LoadEntry("glTexParameterf"));
|
glTexParameterf = reinterpret_cast<PFNGLTEXPARAMETERFPROC>(LoadEntry("glTexParameterf"));
|
||||||
glTexParameteri = reinterpret_cast<PFNGLTEXPARAMETERIPROC>(LoadEntry("glTexParameteri"));
|
glTexParameteri = reinterpret_cast<PFNGLTEXPARAMETERIPROC>(LoadEntry("glTexParameteri"));
|
||||||
glTexSubImage2D = reinterpret_cast<PFNGLTEXSUBIMAGE2DPROC>(LoadEntry("glTexSubImage2D"));
|
glTexSubImage2D = reinterpret_cast<PFNGLTEXSUBIMAGE2DPROC>(LoadEntry("glTexSubImage2D"));
|
||||||
|
glTexSubImage3D = reinterpret_cast<PFNGLTEXSUBIMAGE3DPROC>(LoadEntry("glTexSubImage3D"));
|
||||||
glUniform1f = reinterpret_cast<PFNGLUNIFORM1FPROC>(LoadEntry("glUniform1f"));
|
glUniform1f = reinterpret_cast<PFNGLUNIFORM1FPROC>(LoadEntry("glUniform1f"));
|
||||||
glUniform1i = reinterpret_cast<PFNGLUNIFORM1IPROC>(LoadEntry("glUniform1i"));
|
glUniform1i = reinterpret_cast<PFNGLUNIFORM1IPROC>(LoadEntry("glUniform1i"));
|
||||||
glUniform2fv = reinterpret_cast<PFNGLUNIFORM2FVPROC>(LoadEntry("glUniform2fv"));
|
glUniform2fv = reinterpret_cast<PFNGLUNIFORM2FVPROC>(LoadEntry("glUniform2fv"));
|
||||||
|
|
@ -311,6 +314,11 @@ bool NzOpenGL::Initialize()
|
||||||
|
|
||||||
/****************************************Extensions****************************************/
|
/****************************************Extensions****************************************/
|
||||||
|
|
||||||
|
// Fonctions optionnelles
|
||||||
|
glBindFragDataLocation = reinterpret_cast<PFNGLBINDFRAGDATALOCATIONPROC>(LoadEntry("glBindFragDataLocation", false));
|
||||||
|
if (!glBindFragDataLocation)
|
||||||
|
glBindFragDataLocation = reinterpret_cast<PFNGLBINDFRAGDATALOCATIONEXTPROC>(LoadEntry("glBindFragDataLocationEXT", false));
|
||||||
|
|
||||||
glGetStringi = reinterpret_cast<PFNGLGETSTRINGIPROC>(LoadEntry("glGetStringi", false));
|
glGetStringi = reinterpret_cast<PFNGLGETSTRINGIPROC>(LoadEntry("glGetStringi", false));
|
||||||
glMapBufferRange = reinterpret_cast<PFNGLMAPBUFFERRANGEPROC>(LoadEntry("glMapBufferRange", false));
|
glMapBufferRange = reinterpret_cast<PFNGLMAPBUFFERRANGEPROC>(LoadEntry("glMapBufferRange", false));
|
||||||
|
|
||||||
|
|
@ -347,7 +355,7 @@ bool NzOpenGL::Initialize()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// AnisotropicFilter
|
// AnisotropicFilter
|
||||||
openGLextensions[NzOpenGL::AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic");
|
openGLextensions[nzOpenGLExtension_AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic");
|
||||||
|
|
||||||
// DebugOutput
|
// DebugOutput
|
||||||
if (openGLversion >= 430 || IsSupported("GL_KHR_debug"))
|
if (openGLversion >= 430 || IsSupported("GL_KHR_debug"))
|
||||||
|
|
@ -359,7 +367,7 @@ bool NzOpenGL::Initialize()
|
||||||
glDebugMessageInsert = reinterpret_cast<PFNGLDEBUGMESSAGEINSERTPROC>(LoadEntry("glDebugMessageInsert"));
|
glDebugMessageInsert = reinterpret_cast<PFNGLDEBUGMESSAGEINSERTPROC>(LoadEntry("glDebugMessageInsert"));
|
||||||
glGetDebugMessageLog = reinterpret_cast<PFNGLGETDEBUGMESSAGELOGPROC>(LoadEntry("glGetDebugMessageLog"));
|
glGetDebugMessageLog = reinterpret_cast<PFNGLGETDEBUGMESSAGELOGPROC>(LoadEntry("glGetDebugMessageLog"));
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::DebugOutput] = true;
|
openGLextensions[nzOpenGLExtension_DebugOutput] = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -367,7 +375,7 @@ bool NzOpenGL::Initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!openGLextensions[NzOpenGL::DebugOutput] && IsSupported("GL_ARB_debug_output"))
|
if (!openGLextensions[nzOpenGLExtension_DebugOutput] && IsSupported("GL_ARB_debug_output"))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -376,7 +384,7 @@ bool NzOpenGL::Initialize()
|
||||||
glDebugMessageInsert = reinterpret_cast<PFNGLDEBUGMESSAGEINSERTARBPROC>(LoadEntry("glDebugMessageInsertARB"));
|
glDebugMessageInsert = reinterpret_cast<PFNGLDEBUGMESSAGEINSERTARBPROC>(LoadEntry("glDebugMessageInsertARB"));
|
||||||
glGetDebugMessageLog = reinterpret_cast<PFNGLGETDEBUGMESSAGELOGARBPROC>(LoadEntry("glGetDebugMessageLogARB"));
|
glGetDebugMessageLog = reinterpret_cast<PFNGLGETDEBUGMESSAGELOGARBPROC>(LoadEntry("glGetDebugMessageLogARB"));
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::DebugOutput] = true;
|
openGLextensions[nzOpenGLExtension_DebugOutput] = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -394,7 +402,7 @@ bool NzOpenGL::Initialize()
|
||||||
glUniform3dv = reinterpret_cast<PFNGLUNIFORM3DVPROC>(LoadEntry("glUniform3dv"));
|
glUniform3dv = reinterpret_cast<PFNGLUNIFORM3DVPROC>(LoadEntry("glUniform3dv"));
|
||||||
glUniform4dv = reinterpret_cast<PFNGLUNIFORM4DVPROC>(LoadEntry("glUniform4dv"));
|
glUniform4dv = reinterpret_cast<PFNGLUNIFORM4DVPROC>(LoadEntry("glUniform4dv"));
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::FP64] = true;
|
openGLextensions[nzOpenGLExtension_FP64] = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -413,13 +421,17 @@ bool NzOpenGL::Initialize()
|
||||||
glDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(LoadEntry("glDeleteFramebuffers"));
|
glDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(LoadEntry("glDeleteFramebuffers"));
|
||||||
glDeleteRenderbuffers = reinterpret_cast<PFNGLDELETERENDERBUFFERSPROC>(LoadEntry("glDeleteRenderbuffers"));
|
glDeleteRenderbuffers = reinterpret_cast<PFNGLDELETERENDERBUFFERSPROC>(LoadEntry("glDeleteRenderbuffers"));
|
||||||
glFramebufferRenderbuffer = reinterpret_cast<PFNGLFRAMEBUFFERRENDERBUFFERPROC>(LoadEntry("glFramebufferRenderbuffer"));
|
glFramebufferRenderbuffer = reinterpret_cast<PFNGLFRAMEBUFFERRENDERBUFFERPROC>(LoadEntry("glFramebufferRenderbuffer"));
|
||||||
|
glFramebufferTexture = reinterpret_cast<PFNGLFRAMEBUFFERTEXTUREPROC>(LoadEntry("glFramebufferTexture"));
|
||||||
|
glFramebufferTexture1D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE1DPROC>(LoadEntry("glFramebufferTexture1D"));
|
||||||
glFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(LoadEntry("glFramebufferTexture2D"));
|
glFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(LoadEntry("glFramebufferTexture2D"));
|
||||||
|
glFramebufferTexture3D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE3DPROC>(LoadEntry("glFramebufferTexture3D"));
|
||||||
|
glFramebufferTextureLayer = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURELAYERPROC>(LoadEntry("glFramebufferTextureLayer"));
|
||||||
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPPROC>(LoadEntry("glGenerateMipmap"));
|
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPPROC>(LoadEntry("glGenerateMipmap"));
|
||||||
glGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(LoadEntry("glGenFramebuffers"));
|
glGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(LoadEntry("glGenFramebuffers"));
|
||||||
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSPROC>(LoadEntry("glGenRenderbuffers"));
|
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSPROC>(LoadEntry("glGenRenderbuffers"));
|
||||||
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEPROC>(LoadEntry("glRenderbufferStorage"));
|
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEPROC>(LoadEntry("glRenderbufferStorage"));
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::FrameBufferObject] = true;
|
openGLextensions[nzOpenGLExtension_FrameBufferObject] = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -428,7 +440,7 @@ bool NzOpenGL::Initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PixelBufferObject
|
// PixelBufferObject
|
||||||
openGLextensions[NzOpenGL::PixelBufferObject] = (openGLversion >= 210 || IsSupported("GL_ARB_pixel_buffer_object"));
|
openGLextensions[nzOpenGLExtension_PixelBufferObject] = (openGLversion >= 210 || IsSupported("GL_ARB_pixel_buffer_object"));
|
||||||
|
|
||||||
// SeparateShaderObjects
|
// SeparateShaderObjects
|
||||||
if (openGLversion >= 400 || IsSupported("GL_ARB_separate_shader_objects"))
|
if (openGLversion >= 400 || IsSupported("GL_ARB_separate_shader_objects"))
|
||||||
|
|
@ -440,8 +452,8 @@ bool NzOpenGL::Initialize()
|
||||||
glProgramUniform4fv = reinterpret_cast<PFNGLPROGRAMUNIFORM4FVPROC>(LoadEntry("glProgramUniform4fv"));
|
glProgramUniform4fv = reinterpret_cast<PFNGLPROGRAMUNIFORM4FVPROC>(LoadEntry("glProgramUniform4fv"));
|
||||||
glProgramUniformMatrix4fv = reinterpret_cast<PFNGLPROGRAMUNIFORMMATRIX4FVPROC>(LoadEntry("glProgramUniformMatrix4fv"));
|
glProgramUniformMatrix4fv = reinterpret_cast<PFNGLPROGRAMUNIFORMMATRIX4FVPROC>(LoadEntry("glProgramUniformMatrix4fv"));
|
||||||
|
|
||||||
// Si ARB_gpu_shader_fp64 est supporté, alors cette extension donne également accès aux fonctions utilisant des double
|
// Si ARB_gpu_shader_fp64 est supporté, alors cette extension donne également accès aux fonctions utilisant des double
|
||||||
if (openGLextensions[NzOpenGL::FP64])
|
if (openGLextensions[nzOpenGLExtension_FP64])
|
||||||
{
|
{
|
||||||
glProgramUniform1d = reinterpret_cast<PFNGLPROGRAMUNIFORM1DPROC>(LoadEntry("glProgramUniform1d"));
|
glProgramUniform1d = reinterpret_cast<PFNGLPROGRAMUNIFORM1DPROC>(LoadEntry("glProgramUniform1d"));
|
||||||
glProgramUniform2dv = reinterpret_cast<PFNGLPROGRAMUNIFORM2DVPROC>(LoadEntry("glProgramUniform2dv"));
|
glProgramUniform2dv = reinterpret_cast<PFNGLPROGRAMUNIFORM2DVPROC>(LoadEntry("glProgramUniform2dv"));
|
||||||
|
|
@ -450,45 +462,14 @@ bool NzOpenGL::Initialize()
|
||||||
glProgramUniformMatrix4dv = reinterpret_cast<PFNGLPROGRAMUNIFORMMATRIX4DVPROC>(LoadEntry("glProgramUniformMatrix4dv"));
|
glProgramUniformMatrix4dv = reinterpret_cast<PFNGLPROGRAMUNIFORMMATRIX4DVPROC>(LoadEntry("glProgramUniformMatrix4dv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::SeparateShaderObjects] = true;
|
openGLextensions[nzOpenGLExtension_SeparateShaderObjects] = true;
|
||||||
}
|
|
||||||
|
|
||||||
// Texture3D
|
|
||||||
try
|
|
||||||
{
|
|
||||||
glTexImage3D = reinterpret_cast<PFNGLTEXIMAGE3DPROC>(LoadEntry("glTexImage3D"));
|
|
||||||
glTexSubImage3D = reinterpret_cast<PFNGLTEXSUBIMAGE3DPROC>(LoadEntry("glTexSubImage3D"));
|
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::Texture3D] = true;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
NazaraWarning("Failed to load core texture 3D (" + NzString(e.what()) + ")");
|
|
||||||
|
|
||||||
if (IsSupported("GL_EXT_texture3D"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Hacky: Normalement incompatible à cause du internalFormat, GLenum pour l'extension et GLint pour le noyau
|
|
||||||
// Mais la taille du type étant la même (GLenum est un typedef équivalent à GLint) et Nazara n'utilisant pas
|
|
||||||
// Ce qui cause l'incompatibilité (les paramètres 1,2,3,4), je prends cette liberté
|
|
||||||
glTexImage3D = reinterpret_cast<PFNGLTEXIMAGE3DPROC>(LoadEntry("glTexImage3DEXT"));
|
|
||||||
glTexSubImage3D = reinterpret_cast<PFNGLTEXSUBIMAGE3DEXTPROC>(LoadEntry("glTexSubImage3DEXT"));
|
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::Texture3D] = true;
|
|
||||||
}
|
|
||||||
catch (const std::exception& e2)
|
|
||||||
{
|
|
||||||
NazaraWarning("Failed to load EXT_texture3D: " + NzString(e2.what()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextureArray
|
// TextureArray
|
||||||
openGLextensions[NzOpenGL::TextureArray] = (openGLversion >= 300 || IsSupported("GL_EXT_texture_array"));
|
openGLextensions[nzOpenGLExtension_TextureArray] = (openGLversion >= 300 || IsSupported("GL_EXT_texture_array"));
|
||||||
|
|
||||||
// TextureCompression_s3tc
|
// TextureCompression_s3tc
|
||||||
openGLextensions[NzOpenGL::TextureCompression_s3tc] = IsSupported("GL_EXT_texture_compression_s3tc");
|
openGLextensions[nzOpenGLExtension_TextureCompression_s3tc] = IsSupported("GL_EXT_texture_compression_s3tc");
|
||||||
|
|
||||||
// TextureStorage
|
// TextureStorage
|
||||||
if (openGLversion >= 420 || IsSupported("GL_ARB_texture_storage"))
|
if (openGLversion >= 420 || IsSupported("GL_ARB_texture_storage"))
|
||||||
|
|
@ -499,7 +480,7 @@ bool NzOpenGL::Initialize()
|
||||||
glTexStorage2D = reinterpret_cast<PFNGLTEXSTORAGE2DPROC>(LoadEntry("glTexStorage2D"));
|
glTexStorage2D = reinterpret_cast<PFNGLTEXSTORAGE2DPROC>(LoadEntry("glTexStorage2D"));
|
||||||
glTexStorage3D = reinterpret_cast<PFNGLTEXSTORAGE3DPROC>(LoadEntry("glTexStorage3D"));
|
glTexStorage3D = reinterpret_cast<PFNGLTEXSTORAGE3DPROC>(LoadEntry("glTexStorage3D"));
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::TextureStorage] = true;
|
openGLextensions[nzOpenGLExtension_TextureStorage] = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -516,7 +497,7 @@ bool NzOpenGL::Initialize()
|
||||||
glDeleteVertexArrays = reinterpret_cast<PFNGLDELETEVERTEXARRAYSPROC>(LoadEntry("glDeleteVertexArrays"));
|
glDeleteVertexArrays = reinterpret_cast<PFNGLDELETEVERTEXARRAYSPROC>(LoadEntry("glDeleteVertexArrays"));
|
||||||
glGenVertexArrays = reinterpret_cast<PFNGLGENVERTEXARRAYSPROC>(LoadEntry("glGenVertexArrays"));
|
glGenVertexArrays = reinterpret_cast<PFNGLGENVERTEXARRAYSPROC>(LoadEntry("glGenVertexArrays"));
|
||||||
|
|
||||||
openGLextensions[NzOpenGL::VertexArrayObject] = true;
|
openGLextensions[nzOpenGLExtension_VertexArrayObject] = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
@ -528,9 +509,9 @@ bool NzOpenGL::Initialize()
|
||||||
if (!glGenerateMipmap)
|
if (!glGenerateMipmap)
|
||||||
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPEXTPROC>(LoadEntry("glGenerateMipmapEXT", false));
|
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPEXTPROC>(LoadEntry("glGenerateMipmapEXT", false));
|
||||||
|
|
||||||
/****************************************Contexte de référence****************************************/
|
/****************************************Contexte de référence****************************************/
|
||||||
|
|
||||||
///FIXME: Utiliser le contexte de chargement comme référence ? (Vérifier mode debug)
|
///FIXME: Utiliser le contexte de chargement comme référence ? (Vérifier mode debug)
|
||||||
if (!NzContext::Initialize())
|
if (!NzContext::Initialize())
|
||||||
{
|
{
|
||||||
NazaraError("Failed to initialize contexts");
|
NazaraError("Failed to initialize contexts");
|
||||||
|
|
@ -542,20 +523,158 @@ bool NzOpenGL::Initialize()
|
||||||
NzContextParameters::defaultShareContext = NzContext::GetReference();
|
NzContextParameters::defaultShareContext = NzContext::GetReference();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzOpenGL::IsSupported(Extension extension)
|
bool IsSupported(nzOpenGLExtension extension)
|
||||||
{
|
{
|
||||||
return openGLextensions[extension];
|
return openGLextensions[extension];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzOpenGL::IsSupported(const NzString& string)
|
bool IsSupported(const NzString& string)
|
||||||
{
|
{
|
||||||
return openGLextensionSet.find(string) != openGLextensionSet.end();
|
return openGLextensionSet.find(string) != openGLextensionSet.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzOpenGL::Uninitialize()
|
bool TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType type)
|
||||||
{
|
{
|
||||||
|
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:
|
||||||
|
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_Depth16:
|
||||||
|
format->dataFormat = GL_DEPTH_COMPONENT;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_DEPTH_COMPONENT16;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case nzPixelFormat_Depth24:
|
||||||
|
format->dataFormat = GL_DEPTH_COMPONENT;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_DEPTH_COMPONENT24;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case nzPixelFormat_Depth24Stencil8:
|
||||||
|
format->dataFormat = GL_DEPTH_STENCIL;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_DEPTH24_STENCIL8;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case nzPixelFormat_Depth32:
|
||||||
|
format->dataFormat = GL_DEPTH_COMPONENT;
|
||||||
|
format->dataType = GL_UNSIGNED_BYTE;
|
||||||
|
format->internalFormat = GL_DEPTH_COMPONENT32;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case nzPixelFormat_Stencil1:
|
||||||
|
if (type == FormatType_Texture) // Les formats de stencil ne sont pas supportés par les textures
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_NONE;
|
||||||
|
format->dataType = GL_NONE;
|
||||||
|
format->internalFormat = GL_STENCIL_INDEX1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzPixelFormat_Stencil4:
|
||||||
|
if (type == FormatType_Texture)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_NONE;
|
||||||
|
format->dataType = GL_NONE;
|
||||||
|
format->internalFormat = GL_STENCIL_INDEX4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzPixelFormat_Stencil8:
|
||||||
|
if (type == FormatType_Texture)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_NONE;
|
||||||
|
format->dataType = GL_NONE;
|
||||||
|
format->internalFormat = GL_STENCIL_INDEX8;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzPixelFormat_Stencil16:
|
||||||
|
if (type == FormatType_Texture)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format->dataFormat = GL_NONE;
|
||||||
|
format->dataType = GL_NONE;
|
||||||
|
format->internalFormat = GL_STENCIL_INDEX16;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case nzPixelFormat_Undefined:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Invalid pixel format");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uninitialize()
|
||||||
|
{
|
||||||
NzContext::Uninitialize();
|
NzContext::Uninitialize();
|
||||||
|
|
||||||
for (bool& ext : openGLextensions)
|
for (bool& ext : openGLextensions)
|
||||||
|
|
@ -565,6 +684,193 @@ void NzOpenGL::Uninitialize()
|
||||||
openGLversion = 0;
|
openGLversion = 0;
|
||||||
|
|
||||||
UnloadLibrary();
|
UnloadLibrary();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum Attachment[nzAttachmentPoint_Max+1] =
|
||||||
|
{
|
||||||
|
GL_COLOR_ATTACHMENT0, // nzAttachmentPoint_Color
|
||||||
|
GL_DEPTH_ATTACHMENT, // nzAttachmentPoint_Depth
|
||||||
|
GL_DEPTH_STENCIL_ATTACHMENT, // nzAttachmentPoint_DepthStencil
|
||||||
|
GL_STENCIL_ATTACHMENT // nzAttachmentPoint_Stencil
|
||||||
|
};
|
||||||
|
|
||||||
|
nzUInt8 AttributeIndex[nzElementUsage_Max+1] =
|
||||||
|
{
|
||||||
|
2, // nzElementUsage_Diffuse
|
||||||
|
1, // nzElementUsage_Normal
|
||||||
|
0, // nzElementUsage_Position
|
||||||
|
3, // nzElementUsage_Tangent
|
||||||
|
|
||||||
|
4 // nzElementUsage_TexCoord (Doit être le dernier de la liste car extensible)
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum BlendFunc[nzBlendFunc_Max+1] =
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum BufferLock[nzBufferAccess_Max+1] =
|
||||||
|
{
|
||||||
|
GL_WRITE_ONLY, // nzBufferAccess_DiscardAndWrite
|
||||||
|
GL_READ_ONLY, // nzBufferAccess_ReadOnly
|
||||||
|
GL_READ_WRITE, // nzBufferAccess_ReadWrite
|
||||||
|
GL_WRITE_ONLY // nzBufferAccess_WriteOnly
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum BufferLockRange[nzBufferAccess_Max+1] =
|
||||||
|
{
|
||||||
|
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[nzBufferType_Max+1] =
|
||||||
|
{
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
|
||||||
|
GL_ARRAY_BUFFER, // nzBufferType_Vertex
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum BufferTargetBinding[nzBufferType_Max+1] =
|
||||||
|
{
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER_BINDING, // nzBufferType_Index,
|
||||||
|
GL_ARRAY_BUFFER_BINDING, // nzBufferType_Vertex
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum BufferUsage[nzBufferUsage_Max+1] =
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum CubemapFace[6] =
|
||||||
|
{
|
||||||
|
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 ElementType[nzElementType_Max+1] =
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum FaceCulling[nzFaceCulling_Max+1] =
|
||||||
|
{
|
||||||
|
GL_BACK, // nzFaceCulling_Back
|
||||||
|
GL_FRONT, // nzFaceCulling_Front
|
||||||
|
GL_FRONT_AND_BACK // nzFaceCulling_FrontAndBack
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum FaceFilling[nzFaceFilling_Max+1] =
|
||||||
|
{
|
||||||
|
GL_POINT, // nzFaceFilling_Point
|
||||||
|
GL_LINE, // nzFaceFilling_Line
|
||||||
|
GL_FILL // nzFaceFilling_Fill
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum PrimitiveType[nzPrimitiveType_Max+1] =
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum RendererComparison[nzRendererComparison_Max+1] =
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum RendererParameter[nzRendererParameter_Max+1] =
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum ShaderType[nzShaderType_Max+1] =
|
||||||
|
{
|
||||||
|
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
|
||||||
|
GL_GEOMETRY_SHADER, // nzShaderType_Geometry
|
||||||
|
GL_VERTEX_SHADER // nzShaderType_Vertex
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum StencilOperation[nzStencilOperation_Max+1] =
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum TextureTarget[nzImageType_Max+1]
|
||||||
|
{
|
||||||
|
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 TextureTargetBinding[nzImageType_Max+1]
|
||||||
|
{
|
||||||
|
GL_TEXTURE_BINDING_1D, // nzImageType_1D
|
||||||
|
GL_TEXTURE_BINDING_1D_ARRAY, // nzImageType_1D_Array
|
||||||
|
GL_TEXTURE_BINDING_2D, // nzImageType_2D
|
||||||
|
GL_TEXTURE_BINDING_2D_ARRAY, // nzImageType_2D_Array
|
||||||
|
GL_TEXTURE_BINDING_3D, // nzImageType_3D
|
||||||
|
GL_TEXTURE_BINDING_CUBE_MAP // nzImageType_Cubemap
|
||||||
|
};
|
||||||
|
|
||||||
|
GLenum TextureTargetProxy[nzImageType_Max+1]
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
|
PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
|
||||||
|
|
@ -573,6 +879,7 @@ PFNGLBEGINQUERYPROC glBeginQuery = nullptr;
|
||||||
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr;
|
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr;
|
||||||
PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
|
PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
|
||||||
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
|
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
|
||||||
|
PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation = nullptr;
|
||||||
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
|
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
|
||||||
PFNGLBINDTEXTUREPROC glBindTexture = nullptr;
|
PFNGLBINDTEXTUREPROC glBindTexture = nullptr;
|
||||||
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
|
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
|
||||||
|
|
@ -612,7 +919,11 @@ PFNGLDRAWELEMENTSPROC glDrawElements = nullptr;
|
||||||
PFNGLENDQUERYPROC glEndQuery = nullptr;
|
PFNGLENDQUERYPROC glEndQuery = nullptr;
|
||||||
PFNGLFLUSHPROC glFlush = nullptr;
|
PFNGLFLUSHPROC glFlush = nullptr;
|
||||||
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr;
|
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr;
|
||||||
|
PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture = nullptr;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = nullptr;
|
||||||
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
|
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = nullptr;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = nullptr;
|
||||||
PFNGLENABLEPROC glEnable = nullptr;
|
PFNGLENABLEPROC glEnable = nullptr;
|
||||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
||||||
PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr;
|
PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters&
|
||||||
NzRenderWindow::~NzRenderWindow()
|
NzRenderWindow::~NzRenderWindow()
|
||||||
{
|
{
|
||||||
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
|
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
|
||||||
OnWindowDestroying();
|
OnWindowDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzRenderWindow::CopyToImage(NzImage* image)
|
bool NzRenderWindow::CopyToImage(NzImage* image)
|
||||||
|
|
@ -178,17 +178,6 @@ void NzRenderWindow::EnableVerticalSync(bool enabled)
|
||||||
NazaraError("No context");
|
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
|
unsigned int NzRenderWindow::GetHeight() const
|
||||||
{
|
{
|
||||||
return NzWindow::GetHeight();
|
return NzWindow::GetHeight();
|
||||||
|
|
@ -213,14 +202,9 @@ unsigned int NzRenderWindow::GetWidth() const
|
||||||
return NzWindow::GetWidth();
|
return NzWindow::GetWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzRenderWindow::HasContext() const
|
bool NzRenderWindow::IsRenderable() const
|
||||||
{
|
{
|
||||||
return true;
|
return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
|
||||||
}
|
|
||||||
|
|
||||||
bool NzRenderWindow::IsValid() const
|
|
||||||
{
|
|
||||||
return m_impl != nullptr && m_context != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
|
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
|
||||||
|
|
@ -228,6 +212,22 @@ void NzRenderWindow::SetFramerateLimit(unsigned int limit)
|
||||||
m_framerateLimit = 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()
|
bool NzRenderWindow::Activate()
|
||||||
{
|
{
|
||||||
if (m_context->SetActive(true))
|
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()
|
bool NzRenderWindow::OnWindowCreated()
|
||||||
{
|
{
|
||||||
m_parameters.doubleBuffered = true;
|
m_parameters.doubleBuffered = true;
|
||||||
|
|
@ -267,12 +258,19 @@ bool NzRenderWindow::OnWindowCreated()
|
||||||
|
|
||||||
EnableVerticalSync(false);
|
EnableVerticalSync(false);
|
||||||
|
|
||||||
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION
|
|
||||||
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
||||||
NazaraWarning("Failed to activate window");
|
NazaraWarning("Failed to activate window");
|
||||||
#endif
|
|
||||||
|
|
||||||
m_clock.Restart();
|
m_clock.Restart();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzRenderWindow::OnWindowDestroy()
|
||||||
|
{
|
||||||
|
if (m_context)
|
||||||
|
{
|
||||||
|
delete m_context;
|
||||||
|
m_context = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,114 +24,6 @@
|
||||||
|
|
||||||
namespace
|
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é
|
///FIXME: Solution temporaire pour plus de facilité
|
||||||
enum nzMatrixCombination
|
enum nzMatrixCombination
|
||||||
{
|
{
|
||||||
|
|
@ -227,7 +119,7 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_indexBuffer->IsSequential())
|
if (s_indexBuffer->IsSequential())
|
||||||
glDrawArrays(openglPrimitive[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
|
glDrawArrays(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nzUInt8 indexSize = s_indexBuffer->GetIndexSize();
|
nzUInt8 indexSize = s_indexBuffer->GetIndexSize();
|
||||||
|
|
@ -252,7 +144,7 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount);
|
glDrawArrays(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
||||||
|
|
@ -297,9 +189,9 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (enable)
|
if (enable)
|
||||||
glEnable(rendererParameter[parameter]);
|
glEnable(NzOpenGL::RendererParameter[parameter]);
|
||||||
else
|
else
|
||||||
glDisable(rendererParameter[parameter]);
|
glDisable(NzOpenGL::RendererParameter[parameter]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -307,6 +199,7 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
||||||
/*
|
/*
|
||||||
NzMatrix4f NzRenderer::GetMatrix(nzMatrixCombination combination)
|
NzMatrix4f NzRenderer::GetMatrix(nzMatrixCombination combination)
|
||||||
{
|
{
|
||||||
|
///FIXME: Duplication
|
||||||
switch (combination)
|
switch (combination)
|
||||||
{
|
{
|
||||||
case nzMatrixCombination_ViewProj:
|
case nzMatrixCombination_ViewProj:
|
||||||
|
|
@ -431,14 +324,16 @@ bool NzRenderer::Initialize()
|
||||||
s_vertexBuffer = nullptr;
|
s_vertexBuffer = nullptr;
|
||||||
s_vertexDeclaration = nullptr;
|
s_vertexDeclaration = nullptr;
|
||||||
|
|
||||||
// Récupération des capacités
|
// Récupération des capacités d'OpenGL
|
||||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter);
|
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
|
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||||
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
||||||
s_capabilities[nzRendererCap_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_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
||||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(NzOpenGL::PixelBufferObject);
|
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
||||||
s_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
|
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_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||||
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||||
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||||
|
|
@ -458,7 +353,10 @@ bool NzRenderer::Initialize()
|
||||||
GLint maxDrawBuffers;
|
GLint maxDrawBuffers;
|
||||||
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &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
|
else
|
||||||
s_maxRenderTarget = 1;
|
s_maxRenderTarget = 1;
|
||||||
|
|
@ -472,7 +370,7 @@ bool NzRenderer::Initialize()
|
||||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
|
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)
|
// 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
|
else
|
||||||
s_maxTextureUnit = 1;
|
s_maxTextureUnit = 1;
|
||||||
|
|
@ -499,7 +397,7 @@ void NzRenderer::SetBlendFunc(nzBlendFunc src, nzBlendFunc dest)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glBlendFunc(blendFunc[src], blendFunc[dest]);
|
glBlendFunc(NzOpenGL::BlendFunc[src], NzOpenGL::BlendFunc[dest]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzRenderer::SetClearColor(const NzColor& color)
|
void NzRenderer::SetClearColor(const NzColor& color)
|
||||||
|
|
@ -564,7 +462,7 @@ void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glCullFace(faceCullingMode[cullingMode]);
|
glCullFace(NzOpenGL::FaceCulling[cullingMode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
|
void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
|
||||||
|
|
@ -577,7 +475,7 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, faceFillingMode[fillingMode]);
|
glPolygonMode(GL_FRONT_AND_BACK, NzOpenGL::FaceFilling[fillingMode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
|
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
|
||||||
|
|
@ -603,10 +501,6 @@ void NzRenderer::SetMatrix(nzMatrixType type, const NzMatrix4f& matrix)
|
||||||
{
|
{
|
||||||
s_matrix[type] = 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
|
// Invalidation des combinaisons
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
@ -722,15 +616,15 @@ bool NzRenderer::SetTarget(NzRenderTarget* target)
|
||||||
if (s_target == target)
|
if (s_target == target)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (s_target && !target->HasContext())
|
if (s_target && !s_target->HasContext())
|
||||||
s_target->Desactivate();
|
s_target->Desactivate();
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!target->IsValid())
|
if (!target->IsRenderable())
|
||||||
{
|
{
|
||||||
NazaraError("Target not valid");
|
NazaraError("Target not renderable");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -895,13 +789,13 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
|
|
||||||
if (!s_stencilFuncUpdated)
|
if (!s_stencilFuncUpdated)
|
||||||
{
|
{
|
||||||
glStencilFunc(rendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask);
|
glStencilFunc(NzOpenGL::RendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask);
|
||||||
s_stencilFuncUpdated = true;
|
s_stencilFuncUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s_stencilOpUpdated)
|
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;
|
s_stencilOpUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -921,7 +815,7 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const bool vaoSupported = NzOpenGL::IsSupported(NzOpenGL::VertexArrayObject);
|
static const bool vaoSupported = NzOpenGL::IsSupported(nzOpenGLExtension_VertexArrayObject);
|
||||||
bool update;
|
bool update;
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
|
|
||||||
|
|
@ -970,16 +864,16 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
|
|
||||||
if (element)
|
if (element)
|
||||||
{
|
{
|
||||||
glEnableVertexAttribArray(attribIndex[i]);
|
glEnableVertexAttribArray(NzOpenGL::AttributeIndex[i]);
|
||||||
glVertexAttribPointer(attribIndex[i],
|
glVertexAttribPointer(NzOpenGL::AttributeIndex[i],
|
||||||
openglSize[element->type],
|
NzVertexDeclaration::GetElementCount(element->type),
|
||||||
openglType[element->type],
|
NzOpenGL::ElementType[element->type],
|
||||||
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
|
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
|
||||||
stride,
|
stride,
|
||||||
&buffer[element->offset]);
|
&buffer[element->offset]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
glDisableVertexAttribArray(attribIndex[i]);
|
glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_indexBuffer)
|
if (s_indexBuffer)
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ bool NzShader::Create(nzShaderLanguage language)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,6 +87,8 @@ void NzShader::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
m_impl->Destroy();
|
m_impl->Destroy();
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
|
|
@ -595,7 +598,7 @@ bool NzShader::IsLanguageSupported(nzShaderLanguage language)
|
||||||
switch (language)
|
switch (language)
|
||||||
{
|
{
|
||||||
case nzShaderLanguage_Cg:
|
case nzShaderLanguage_Cg:
|
||||||
return false; // ??
|
return false; //FIXME: ??
|
||||||
|
|
||||||
case nzShaderLanguage_GLSL:
|
case nzShaderLanguage_GLSL:
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ struct NzTextureImpl
|
||||||
nzImageType type;
|
nzImageType type;
|
||||||
nzPixelFormat format;
|
nzPixelFormat format;
|
||||||
nzUInt8 levelCount;
|
nzUInt8 levelCount;
|
||||||
bool isTarget = false;
|
NzRenderTexture* renderTexture = nullptr;
|
||||||
bool mipmapping = false;
|
bool mipmapping = false;
|
||||||
bool mipmapsUpdated = true;
|
bool mipmapsUpdated = true;
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
|
|
@ -27,137 +27,18 @@ struct NzTextureImpl
|
||||||
|
|
||||||
namespace
|
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)
|
bool CreateTexture(NzTextureImpl* impl, bool proxy)
|
||||||
{
|
{
|
||||||
OpenGLFormat openGLFormat;
|
NzOpenGL::Format openGLFormat;
|
||||||
if (!GetOpenGLFormat(impl->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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum target = (proxy) ? openglTargetProxy[impl->type] : openglTarget[impl->type];
|
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type];
|
||||||
GLint previous;
|
GLint previous;
|
||||||
glGetIntegerv(openglTargetBinding[impl->type], &previous);
|
glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous);
|
||||||
switch (impl->type)
|
switch (impl->type)
|
||||||
{
|
{
|
||||||
case nzImageType_1D:
|
case nzImageType_1D:
|
||||||
|
|
@ -234,7 +115,7 @@ namespace
|
||||||
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
||||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
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);
|
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||||
|
|
||||||
if (size > 1U)
|
if (size > 1U)
|
||||||
|
|
@ -266,12 +147,12 @@ namespace
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
GLint previous;
|
GLint previous;
|
||||||
glGetIntegerv(openglTargetBinding[impl->type], &previous);
|
glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous);
|
||||||
|
|
||||||
lockedPrevious[impl->type] = static_cast<GLuint>(previous);
|
lockedPrevious[impl->type] = static_cast<GLuint>(previous);
|
||||||
|
|
||||||
if (lockedPrevious[impl->type] != impl->id)
|
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
|
#endif
|
||||||
|
|
||||||
if (--lockedLevel[impl->type] == 0 && lockedPrevious[impl->type] != impl->id)
|
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();
|
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)
|
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();
|
Destroy();
|
||||||
|
|
||||||
if (width == 0 || height == 0 || depth == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
#if NAZARA_RENDERER_SAFE
|
||||||
if (!IsTypeSupported(type))
|
if (!IsTypeSupported(type))
|
||||||
{
|
{
|
||||||
|
|
@ -389,6 +238,24 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||||
return false;
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
case nzImageType_1D:
|
case nzImageType_1D:
|
||||||
|
|
@ -491,6 +358,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
||||||
if (!lock)
|
if (!lock)
|
||||||
UnlockTexture(impl);
|
UnlockTexture(impl);
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,13 +366,7 @@ void NzTexture::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
#if NAZARA_RENDERER_SAFE
|
NotifyDestroy();
|
||||||
if (m_impl->isTarget)
|
|
||||||
{
|
|
||||||
NazaraError("Texture is a target, it cannot be destroyed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
|
|
@ -530,8 +392,8 @@ bool NzTexture::Download(NzImage* image) const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OpenGLFormat format;
|
NzOpenGL::Format format;
|
||||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to get OpenGL format");
|
NazaraError("Failed to get OpenGL format");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -552,7 +414,7 @@ bool NzTexture::Download(NzImage* image) const
|
||||||
// Téléchargement...
|
// Téléchargement...
|
||||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
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)
|
if (width > 1)
|
||||||
width >>= 1;
|
width >>= 1;
|
||||||
|
|
@ -610,7 +472,7 @@ unsigned int NzTexture::GetAnisotropyLevel() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter))
|
if (!NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
LockTexture(m_impl);
|
LockTexture(m_impl);
|
||||||
|
|
@ -806,7 +668,7 @@ bool NzTexture::IsTarget() const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return m_impl->isTarget;
|
return m_impl->renderTexture != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::IsValid() const
|
bool NzTexture::IsValid() const
|
||||||
|
|
@ -937,7 +799,7 @@ bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter) && anistropyLevel > 1)
|
if (anistropyLevel > 1 && !NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
|
||||||
{
|
{
|
||||||
NazaraError("Anisotropic filter not supported");
|
NazaraError("Anisotropic filter not supported");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -970,7 +832,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter)
|
||||||
|
|
||||||
LockTexture(m_impl);
|
LockTexture(m_impl);
|
||||||
|
|
||||||
GLenum target = openglTarget[m_impl->type];
|
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
|
||||||
switch (filter)
|
switch (filter)
|
||||||
{
|
{
|
||||||
case nzTextureFilter_Bilinear:
|
case nzTextureFilter_Bilinear:
|
||||||
|
|
@ -1028,8 +890,8 @@ bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LockTexture(m_impl);
|
LockTexture(m_impl);
|
||||||
glTexParameteri(openglTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel);
|
glTexParameteri(NzOpenGL::TextureTarget[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_MAX_LEVEL, std::min(m_impl->levelCount, maxLevel));
|
||||||
UnlockTexture(m_impl);
|
UnlockTexture(m_impl);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1063,7 +925,7 @@ bool NzTexture::SetWrapMode(nzTextureWrap wrap)
|
||||||
|
|
||||||
LockTexture(m_impl);
|
LockTexture(m_impl);
|
||||||
|
|
||||||
GLenum target = openglTarget[m_impl->type];
|
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
|
||||||
switch (m_impl->type)
|
switch (m_impl->type)
|
||||||
{
|
{
|
||||||
// Notez l'absence de "break" ici
|
// Notez l'absence de "break" ici
|
||||||
|
|
@ -1197,7 +1059,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_impl->isTarget)
|
if (m_impl->renderTexture)
|
||||||
{
|
{
|
||||||
NazaraError("Texture is a target, it cannot be updated");
|
NazaraError("Texture is a target, it cannot be updated");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1244,8 +1106,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OpenGLFormat format;
|
NzOpenGL::Format format;
|
||||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to get OpenGL format");
|
NazaraError("Failed to get OpenGL format");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1272,12 +1134,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
||||||
|
|
||||||
case nzImageType_1D_Array:
|
case nzImageType_1D_Array:
|
||||||
case nzImageType_2D:
|
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;
|
break;
|
||||||
|
|
||||||
case nzImageType_2D_Array:
|
case nzImageType_2D_Array:
|
||||||
case nzImageType_3D:
|
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;
|
break;
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
case nzImageType_Cubemap:
|
||||||
|
|
@ -1298,7 +1160,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_impl->isTarget)
|
if (m_impl->renderTexture)
|
||||||
{
|
{
|
||||||
NazaraError("Texture is a target, it cannot be updated");
|
NazaraError("Texture is a target, it cannot be updated");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1341,8 +1203,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OpenGLFormat format;
|
NzOpenGL::Format format;
|
||||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to get OpenGL format");
|
NazaraError("Failed to get OpenGL format");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1370,12 +1232,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
||||||
|
|
||||||
case nzImageType_1D_Array:
|
case nzImageType_1D_Array:
|
||||||
case nzImageType_2D:
|
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;
|
break;
|
||||||
|
|
||||||
case nzImageType_2D_Array:
|
case nzImageType_2D_Array:
|
||||||
case nzImageType_3D:
|
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;
|
break;
|
||||||
|
|
||||||
case nzImageType_Cubemap:
|
case nzImageType_Cubemap:
|
||||||
|
|
@ -1455,7 +1317,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_impl->isTarget)
|
if (m_impl->renderTexture)
|
||||||
{
|
{
|
||||||
NazaraError("Texture is a target, it cannot be updated");
|
NazaraError("Texture is a target, it cannot be updated");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1496,8 +1358,8 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OpenGLFormat format;
|
NzOpenGL::Format format;
|
||||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to get OpenGL format");
|
NazaraError("Failed to get OpenGL format");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1517,7 +1379,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
||||||
SetUnpackAlignement(bpp);
|
SetUnpackAlignement(bpp);
|
||||||
|
|
||||||
LockTexture(m_impl);
|
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);
|
UnlockTexture(m_impl);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1537,6 +1399,40 @@ void NzTexture::Unlock()
|
||||||
UnlockTexture(m_impl);
|
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)
|
unsigned int NzTexture::GetValidSize(unsigned int size)
|
||||||
{
|
{
|
||||||
if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT))
|
if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT))
|
||||||
|
|
@ -1567,6 +1463,23 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||||
case nzPixelFormat_RGBA4:
|
case nzPixelFormat_RGBA4:
|
||||||
return true;
|
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 ..)
|
// Dépréciés depuis OpenGL 3 (FIXME: Il doit bien exister des remplaçants ..)
|
||||||
case nzPixelFormat_L8:
|
case nzPixelFormat_L8:
|
||||||
case nzPixelFormat_LA8:
|
case nzPixelFormat_LA8:
|
||||||
|
|
@ -1576,7 +1489,7 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
||||||
case nzPixelFormat_DXT3:
|
case nzPixelFormat_DXT3:
|
||||||
case nzPixelFormat_DXT5:
|
case nzPixelFormat_DXT5:
|
||||||
{
|
{
|
||||||
static const bool supported = NzOpenGL::IsSupported(NzOpenGL::TextureCompression_s3tc);
|
static const bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_TextureCompression_s3tc);
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1607,7 +1520,7 @@ bool NzTexture::IsTypeSupported(nzImageType type)
|
||||||
case nzImageType_1D_Array:
|
case nzImageType_1D_Array:
|
||||||
case nzImageType_2D_Array:
|
case nzImageType_2D_Array:
|
||||||
{
|
{
|
||||||
static bool supported = NzOpenGL::IsSupported(NzOpenGL::TextureArray);
|
static bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_TextureArray);
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1616,9 +1529,22 @@ bool NzTexture::IsTypeSupported(nzImageType type)
|
||||||
return false;
|
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)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraInternalError("Texture must be valid");
|
NazaraInternalError("Texture must be valid");
|
||||||
|
|
@ -1626,5 +1552,5 @@ void NzTexture::SetTarget(bool isTarget)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_impl->isTarget = isTarget;
|
m_impl->renderTexture = renderTexture;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,28 +153,19 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
|
||||||
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
|
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||||
*attrib++ = parameters.minorVersion;
|
*attrib++ = parameters.minorVersion;
|
||||||
|
|
||||||
int flags = 0;
|
|
||||||
|
|
||||||
if (parameters.majorVersion >= 3)
|
if (parameters.majorVersion >= 3)
|
||||||
{
|
{
|
||||||
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
|
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||||
if (parameters.compatibilityProfile)
|
*attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
|
||||||
|
|
||||||
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.debugMode)
|
if (parameters.debugMode)
|
||||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
|
||||||
|
|
||||||
if (flags)
|
|
||||||
{
|
{
|
||||||
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
|
*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;
|
*attrib++ = 0;
|
||||||
|
|
@ -210,13 +201,25 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
|
||||||
void NzContextImpl::Destroy()
|
void NzContextImpl::Destroy()
|
||||||
{
|
{
|
||||||
if (m_context)
|
if (m_context)
|
||||||
|
{
|
||||||
|
if (wglGetCurrentContext() == m_context)
|
||||||
|
wglMakeCurrent(nullptr, nullptr);
|
||||||
|
|
||||||
wglDeleteContext(m_context);
|
wglDeleteContext(m_context);
|
||||||
|
m_context = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_deviceContext)
|
if (m_deviceContext)
|
||||||
|
{
|
||||||
ReleaseDC(m_window, m_deviceContext);
|
ReleaseDC(m_window, m_deviceContext);
|
||||||
|
m_deviceContext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_ownsWindow)
|
if (m_ownsWindow)
|
||||||
|
{
|
||||||
DestroyWindow(m_window);
|
DestroyWindow(m_window);
|
||||||
|
m_window = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzContextImpl::SwapBuffers()
|
void NzContextImpl::SwapBuffers()
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ NzAnimation::~NzAnimation()
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
|
bool NzAnimation::AddSequence(const NzSequence& sequence)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Animation not created");
|
NazaraError("Animation not created");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
|
||||||
if (it != m_impl->sequenceMap.end())
|
if (it != m_impl->sequenceMap.end())
|
||||||
{
|
{
|
||||||
NazaraError("Sequence name \"" + sequence.name + "\" is already used");
|
NazaraError("Sequence name \"" + sequence.name + "\" is already used");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
|
||||||
|
|
||||||
m_impl->sequences.push_back(sequence);
|
m_impl->sequences.push_back(sequence);
|
||||||
|
|
||||||
return index;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount)
|
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->frameCount = frameCount;
|
||||||
m_impl->type = type;
|
m_impl->type = type;
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,6 +94,8 @@ void NzAnimation::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -206,6 +209,28 @@ unsigned int NzAnimation::GetSequenceCount() const
|
||||||
return m_impl->sequences.size();
|
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
|
nzAnimationType NzAnimation::GetType() const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
|
|
@ -277,13 +302,13 @@ void NzAnimation::RemoveSequence(const NzString& identifier)
|
||||||
auto it = m_impl->sequenceMap.find(identifier);
|
auto it = m_impl->sequenceMap.find(identifier);
|
||||||
if (it == m_impl->sequenceMap.end())
|
if (it == m_impl->sequenceMap.end())
|
||||||
{
|
{
|
||||||
NazaraError("SubMesh not found");
|
NazaraError("Sequence not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int index = it->second;
|
int index = it->second;
|
||||||
#else
|
#else
|
||||||
unsigned int index = m_impl->sequenceMap[identifier];
|
int index = m_impl->sequenceMap[identifier];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto it2 = m_impl->sequences.begin();
|
auto it2 = m_impl->sequences.begin();
|
||||||
|
|
|
||||||
|
|
@ -113,14 +113,16 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto
|
||||||
m_storage = storage;
|
m_storage = storage;
|
||||||
m_usage = usage;
|
m_usage = usage;
|
||||||
|
|
||||||
// Si on arrive ici c'est que tout s'est bien passé.
|
NotifyCreated();
|
||||||
return true;
|
return true; // Si on arrive ici c'est que tout s'est bien passé.
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzBuffer::Destroy()
|
void NzBuffer::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
m_impl->Destroy();
|
m_impl->Destroy();
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -215,9 +215,6 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
||||||
{
|
{
|
||||||
ReleaseImage();
|
ReleaseImage();
|
||||||
|
|
||||||
if (width == 0 || height == 0 || depth == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!NzPixelFormat::IsValid(format))
|
if (!NzPixelFormat::IsValid(format))
|
||||||
{
|
{
|
||||||
|
|
@ -225,6 +222,24 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
||||||
return false;
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
case nzImageType_1D:
|
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);
|
m_sharedImage = new SharedImage(1, type, format, levelCount, levels, width, height, depth);
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzImage::Destroy()
|
void NzImage::Destroy()
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
ReleaseImage();
|
ReleaseImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,27 +43,6 @@ namespace
|
||||||
return false;
|
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)
|
#if defined(NAZARA_BIG_ENDIAN)
|
||||||
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
|
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
|
||||||
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
|
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
|
||||||
|
|
@ -99,7 +78,7 @@ namespace
|
||||||
else
|
else
|
||||||
animated = false;
|
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");
|
NazaraInternalError("Failed to create mesh");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -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));
|
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
|
||||||
|
|
||||||
m_frameCount = endFrame - startFrame + 1;
|
m_frameCount = endFrame - startFrame + 1;
|
||||||
m_vertexCount = header.num_tris*3;
|
m_vertexCount = header.num_tris * 3;
|
||||||
|
|
||||||
/// Chargement des vertices
|
/// Chargement des vertices
|
||||||
std::vector<md2_texCoord> texCoords(header.num_st);
|
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;
|
md2_frame frame;
|
||||||
frame.vertices.resize(header.num_vertices);
|
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
|
// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
|
||||||
NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(90.f, -90.f, 0.f));
|
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);
|
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));
|
NzByteSwap(&frame.translate.z, sizeof(float));
|
||||||
#endif
|
#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];
|
m_frames[i].vertices = new NzVector3f[m_vertexCount];
|
||||||
|
|
||||||
NzVector3f max, min;
|
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]];
|
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);
|
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);
|
||||||
max.MakeCeil(vertex);
|
|
||||||
min.MakeFloor(vertex);
|
|
||||||
|
|
||||||
m_frames[i].normal[t*3+v] = vert.n;
|
// On fait en sorte d'avoir deux vertices de délimitation, définissant un rectangle dans l'espace
|
||||||
m_frames[i].vertices[t*3+v] = vertex;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// On avance jusqu'aux premières coordonnées de texture
|
// 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;
|
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 t = 0; t < header.num_tris; ++t)
|
||||||
{
|
{
|
||||||
for (unsigned int v = 0; v < 3; ++v)
|
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->x = texC.u / static_cast<float>(header.skinwidth);
|
||||||
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
|
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
|
||||||
|
|
||||||
ptr += stride;
|
ptr -= stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,6 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.manufacturer != 0x0a)
|
|
||||||
{
|
|
||||||
NazaraError("Bad version number (" + NzString::Number(header.manufacturer) + ')');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(NAZARA_BIG_ENDIAN)
|
#if defined(NAZARA_BIG_ENDIAN)
|
||||||
// Les fichiers PCX sont en little endian
|
// Les fichiers PCX sont en little endian
|
||||||
NzByteSwap(&header.xmin, sizeof(nzUInt16));
|
NzByteSwap(&header.xmin, sizeof(nzUInt16));
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ bool NzMeshParams::IsValid() const
|
||||||
|
|
||||||
struct NzMeshImpl
|
struct NzMeshImpl
|
||||||
{
|
{
|
||||||
std::map<NzString, nzUInt8> subMeshMap;
|
|
||||||
std::deque<NzString> skins;
|
std::deque<NzString> skins;
|
||||||
|
std::map<NzString, unsigned int> subMeshMap;
|
||||||
std::vector<NzSubMesh*> subMeshes;
|
std::vector<NzSubMesh*> subMeshes;
|
||||||
nzAnimationType animationType;
|
nzAnimationType animationType;
|
||||||
NzAxisAlignedBox aabb;
|
NzAxisAlignedBox aabb;
|
||||||
|
|
@ -44,19 +44,19 @@ NzMesh::~NzMesh()
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
|
bool NzMesh::AddSkin(const NzString& skin, bool setDefault)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Mesh not created");
|
NazaraError("Mesh not created");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin.IsEmpty())
|
if (skin.IsEmpty())
|
||||||
{
|
{
|
||||||
NazaraError("Skin is empty");
|
NazaraError("Skin is empty");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -65,71 +65,71 @@ unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
|
||||||
else
|
else
|
||||||
m_impl->skins.push_back(skin);
|
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 NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Mesh not created");
|
NazaraError("Mesh not created");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subMesh)
|
if (!subMesh)
|
||||||
{
|
{
|
||||||
NazaraError("Invalid submesh");
|
NazaraError("Invalid submesh");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
subMesh->AddResourceReference();
|
subMesh->AddResourceListener(this, m_impl->subMeshes.size());
|
||||||
|
|
||||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||||
m_impl->subMeshes.push_back(subMesh);
|
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 NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
{
|
{
|
||||||
NazaraError("Mesh not created");
|
NazaraError("Mesh not created");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identifier.IsEmpty())
|
if (identifier.IsEmpty())
|
||||||
{
|
{
|
||||||
NazaraError("Identifier is empty");
|
NazaraError("Identifier is empty");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = m_impl->subMeshMap.find(identifier);
|
auto it = m_impl->subMeshMap.find(identifier);
|
||||||
if (it != m_impl->subMeshMap.end())
|
if (it != m_impl->subMeshMap.end())
|
||||||
{
|
{
|
||||||
NazaraError("SubMesh identifier \"" + identifier + "\" is already used");
|
NazaraError("SubMesh identifier \"" + identifier + "\" is already used");
|
||||||
return it->second;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subMesh)
|
if (!subMesh)
|
||||||
{
|
{
|
||||||
NazaraError("Invalid submesh");
|
NazaraError("Invalid submesh");
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#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->aabb.SetNull(); // On invalide l'AABB
|
||||||
m_impl->subMeshes.push_back(subMesh);
|
m_impl->subMeshes.push_back(subMesh);
|
||||||
m_impl->subMeshMap[identifier] = index;
|
m_impl->subMeshMap[identifier] = index;
|
||||||
|
|
||||||
return index;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation)
|
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 = new NzMeshImpl;
|
||||||
m_impl->animationType = type;
|
m_impl->animationType = type;
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,11 +189,13 @@ void NzMesh::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
if (m_impl->animation)
|
if (m_impl->animation)
|
||||||
m_impl->animation->RemoveResourceReference();
|
m_impl->animation->RemoveResourceListener(this);
|
||||||
|
|
||||||
for (NzSubMesh* subMesh : m_impl->subMeshes)
|
for (NzSubMesh* subMesh : m_impl->subMeshes)
|
||||||
subMesh->RemoveResourceReference();
|
subMesh->RemoveResourceListener(this);
|
||||||
|
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
|
|
@ -316,7 +320,7 @@ NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index)
|
NzSubMesh* NzMesh::GetSubMesh(unsigned int index)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -357,7 +361,7 @@ const NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier) const
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
|
const NzSubMesh* NzMesh::GetSubMesh(unsigned int index) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -376,7 +380,7 @@ const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
|
||||||
return m_impl->subMeshes[index];
|
return m_impl->subMeshes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt8 NzMesh::GetSubMeshCount() const
|
unsigned int NzMesh::GetSubMeshCount() const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -389,6 +393,28 @@ nzUInt8 NzMesh::GetSubMeshCount() const
|
||||||
return m_impl->subMeshes.size();
|
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
|
unsigned int NzMesh::GetVertexCount() const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#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();
|
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 NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -520,6 +546,7 @@ void NzMesh::RemoveSkin(unsigned int index)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// On accède à l'itérateur correspondant à l'entrée #index
|
||||||
auto it = m_impl->skins.begin();
|
auto it = m_impl->skins.begin();
|
||||||
std::advance(it, index);
|
std::advance(it, index);
|
||||||
|
|
||||||
|
|
@ -547,15 +574,18 @@ void NzMesh::RemoveSubMesh(const NzString& identifier)
|
||||||
unsigned int index = m_impl->subMeshMap[identifier];
|
unsigned int index = m_impl->subMeshMap[identifier];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// On déplace l'itérateur du début d'une distance de x
|
||||||
auto it2 = m_impl->subMeshes.begin();
|
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->subMeshes.erase(it2);
|
||||||
|
|
||||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzMesh::RemoveSubMesh(nzUInt8 index)
|
void NzMesh::RemoveSubMesh(unsigned int index)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -571,9 +601,12 @@ void NzMesh::RemoveSubMesh(nzUInt8 index)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// On déplace l'itérateur du début de x
|
||||||
auto it = m_impl->subMeshes.begin();
|
auto it = m_impl->subMeshes.begin();
|
||||||
std::advance(it, index);
|
std::advance(it, index);
|
||||||
|
|
||||||
|
// On libère la ressource
|
||||||
|
(*it)->RemoveResourceListener(this);
|
||||||
m_impl->subMeshes.erase(it);
|
m_impl->subMeshes.erase(it);
|
||||||
|
|
||||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||||
|
|
@ -599,7 +632,7 @@ bool NzMesh::SetAnimation(const NzAnimation* animation)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (m_impl->animation)
|
if (m_impl->animation)
|
||||||
m_impl->animation->RemoveResourceReference();
|
m_impl->animation->RemoveResourceListener(this);
|
||||||
|
|
||||||
if (animation)
|
if (animation)
|
||||||
{
|
{
|
||||||
|
|
@ -611,13 +644,38 @@ bool NzMesh::SetAnimation(const NzAnimation* animation)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_impl->animation = animation;
|
animation->AddResourceListener(this);
|
||||||
m_impl->animation->AddResourceReference();
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_impl->animation = nullptr;
|
m_impl->animation = animation;
|
||||||
|
|
||||||
return true;
|
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;
|
NzMeshLoader::LoaderList NzMesh::s_loaders;
|
||||||
|
|
|
||||||
|
|
@ -38,28 +38,27 @@ bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertex
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (!vertexDeclaration)
|
if (!vertexDeclaration)
|
||||||
{
|
{
|
||||||
NazaraError("Vertex declaration is null");
|
NazaraError("Invalid vertex declaration");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vertexBuffer)
|
if (!vertexBuffer)
|
||||||
{
|
{
|
||||||
NazaraError("Vertex buffer is null");
|
NazaraError("Invalid vertex buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (indexBuffer)
|
if (indexBuffer)
|
||||||
{
|
indexBuffer->AddResourceListener(this);
|
||||||
|
|
||||||
m_indexBuffer = indexBuffer;
|
m_indexBuffer = indexBuffer;
|
||||||
m_indexBuffer->AddResourceReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vertexBuffer = vertexBuffer;
|
m_vertexBuffer = vertexBuffer;
|
||||||
m_vertexBuffer->AddResourceReference();
|
m_vertexBuffer->AddResourceListener(this);
|
||||||
|
|
||||||
m_vertexDeclaration = vertexDeclaration;
|
m_vertexDeclaration = vertexDeclaration;
|
||||||
m_vertexDeclaration->AddResourceReference();
|
m_vertexDeclaration->AddResourceListener(this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -70,19 +69,19 @@ void NzStaticMesh::Destroy()
|
||||||
|
|
||||||
if (m_indexBuffer)
|
if (m_indexBuffer)
|
||||||
{
|
{
|
||||||
m_indexBuffer->RemoveResourceReference();
|
m_indexBuffer->RemoveResourceListener(this);
|
||||||
m_indexBuffer = nullptr;
|
m_indexBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vertexBuffer)
|
if (m_vertexBuffer)
|
||||||
{
|
{
|
||||||
m_vertexBuffer->RemoveResourceReference();
|
m_vertexBuffer->RemoveResourceListener(this);
|
||||||
m_vertexBuffer = nullptr;
|
m_vertexBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vertexDeclaration)
|
if (m_vertexDeclaration)
|
||||||
{
|
{
|
||||||
m_vertexDeclaration->RemoveResourceReference();
|
m_vertexDeclaration->RemoveResourceListener(this);
|
||||||
m_vertexDeclaration = nullptr;
|
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
|
// Le safe mode est censé nous protéger de cet appel
|
||||||
NazaraError("Static mesh have no animation, please enable safe mode");
|
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));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,22 @@
|
||||||
|
|
||||||
namespace
|
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
|
1*sizeof(double), // nzElementType_Double1
|
||||||
2*sizeof(double), // nzElementType_Double2
|
2*sizeof(double), // nzElementType_Double2
|
||||||
3*sizeof(double), // nzElementType_Double3
|
3*sizeof(double), // nzElementType_Double3
|
||||||
|
|
@ -143,7 +156,7 @@ bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int e
|
||||||
if (impl->streamPos[current.stream] == -1)
|
if (impl->streamPos[current.stream] == -1)
|
||||||
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
|
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
|
#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;
|
m_sharedImpl = impl;
|
||||||
|
|
||||||
|
NotifyCreated();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,6 +175,8 @@ void NzVertexDeclaration::Destroy()
|
||||||
if (!m_sharedImpl)
|
if (!m_sharedImpl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
NotifyDestroy();
|
||||||
|
|
||||||
NazaraMutexLock(m_sharedImpl->mutex);
|
NazaraMutexLock(m_sharedImpl->mutex);
|
||||||
bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
|
bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
|
||||||
NazaraMutexUnlock(m_sharedImpl->mutex);
|
NazaraMutexUnlock(m_sharedImpl->mutex);
|
||||||
|
|
@ -344,3 +360,13 @@ NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declar
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int NzVertexDeclaration::GetElementCount(nzElementType type)
|
||||||
|
{
|
||||||
|
return elementCount[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int NzVertexDeclaration::GetElementSize(nzElementType type)
|
||||||
|
{
|
||||||
|
return elementSize[type];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
|
||||||
{
|
{
|
||||||
if (!mode.IsFullscreenValid())
|
if (!mode.IsFullscreenValid())
|
||||||
{
|
{
|
||||||
NazaraWarning("Mode is not fullscreen valid");
|
NazaraWarning("Video mode is not fullscreen valid");
|
||||||
mode = NzVideoMode::GetFullscreenModes()[0];
|
mode = NzVideoMode::GetFullscreenModes()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ void NzWindow::Destroy()
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
{
|
{
|
||||||
OnWindowDestroying();
|
OnWindowDestroy();
|
||||||
|
|
||||||
m_impl->Destroy();
|
m_impl->Destroy();
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
|
|
@ -212,7 +212,7 @@ NzWindowHandle NzWindow::GetHandle() const
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
return m_impl->GetHandle();
|
return m_impl->GetHandle();
|
||||||
else
|
else
|
||||||
return reinterpret_cast<NzWindowHandle>(0);
|
return static_cast<NzWindowHandle>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzWindow::GetHeight() const
|
unsigned int NzWindow::GetHeight() const
|
||||||
|
|
@ -276,6 +276,11 @@ bool NzWindow::IsMinimized() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NzWindow::IsValid() const
|
||||||
|
{
|
||||||
|
return m_impl != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool NzWindow::IsVisible() const
|
bool NzWindow::IsVisible() const
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
|
|
@ -483,15 +488,15 @@ bool NzWindow::WaitEvent(NzEvent* event)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzWindow::OnWindowDestroying()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzWindow::OnWindowCreated()
|
bool NzWindow::OnWindowCreated()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzWindow::OnWindowDestroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void NzWindow::IgnoreNextMouseEvent(int mouseX, int mouseY) const
|
void NzWindow::IgnoreNextMouseEvent(int mouseX, int mouseY) const
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue