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"
|
||||
end
|
||||
|
||||
defines "NAZARA_RENDERER_OPENGL"
|
||||
|
||||
files
|
||||
{
|
||||
"../include/Nazara/Renderer/**.hpp",
|
||||
|
|
|
|||
|
|
@ -38,9 +38,10 @@ void SetSequence(AnimatedModel& model, const NzString& name);
|
|||
int main()
|
||||
{
|
||||
// Tout d'abord on affiche les instructions
|
||||
std::cout << "Camera controls: ZQSD" << std::endl;
|
||||
std::cout << "Dr. Freak controls: Up, down, left and right" << std::endl;
|
||||
std::cout << "Controls: ZQSD" << std::endl;
|
||||
std::cout << "Escape to quit" << std::endl;
|
||||
std::cout << "Left click to capture/free the mouse" << std::endl;
|
||||
std::cout << "Right click to control Dr. Freak" << std::endl;
|
||||
|
||||
// Cette ligne active le mode de compatibilité d'OpenGL lors de l'initialisation de Nazara (Nécessaire pour le shader)
|
||||
NzContextParameters::defaultCompatibilityProfile = true;
|
||||
|
|
@ -135,8 +136,8 @@ int main()
|
|||
// Le sol ne subit aucune transformation
|
||||
floor.matrix.MakeIdentity();
|
||||
|
||||
// Pour effectuer un rendu, il faut que la carte graphique sache quoi faire.
|
||||
// Les shaders sont de petits programmes qui donnent des instructions à la carte graphique lors du pipeline.
|
||||
// Pour effectuer un rendu, il faut que la carte graphique sache comment le faire.
|
||||
// Les shaders sont de petits programmes qui donnent des instructions à la carte graphique lors de son pipeline.
|
||||
// Ils sont aujourd'hui indispensables pour un rendu 3D, mais sont très utiles pour divers effets !
|
||||
// Il existe plusieurs langages de shaders, GLSL pour OpenGL, HLSL pour Direct3D et Cg qui peut être utilisé pour les deux.
|
||||
// Le Renderer de Nazara utilise OpenGL, par conséquent nous utiliserons le GLSL
|
||||
|
|
@ -152,6 +153,8 @@ int main()
|
|||
// Une fois le shader créé, nous devons lui spécifier les codes sources de nos shaders
|
||||
// Pour notre exemple nous prendrons un shader très simple
|
||||
// Un shader doit obligatoirement posséder au moins deux codes, un pour le fragment shader et un pour le vertex shader
|
||||
|
||||
// Le fragment shader traite la couleur de nos pixels
|
||||
if (!shader.LoadFromFile(nzShaderType_Fragment, "shaders/basic.frag"))
|
||||
{
|
||||
std::cout << "Failed to load fragment shader from file" << std::endl;
|
||||
|
|
@ -161,7 +164,7 @@ int main()
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Maintenant le vertex shader
|
||||
// Le vertex shader (Transformation des vertices de l'espace 3D vers l'espace écran)
|
||||
if (!shader.LoadFromFile(nzShaderType_Vertex, "shaders/basic.vert"))
|
||||
{
|
||||
std::cout << "Failed to load vertex shader from file" << std::endl;
|
||||
|
|
@ -170,7 +173,7 @@ int main()
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Une fois le code source de nos shaders chargé, nous pouvons le compiler, afin de le rendre utilisable
|
||||
// Une fois les codes sources de notre shader chargé, nous pouvons le compiler, afin de le rendre utilisable
|
||||
if (!shader.Compile())
|
||||
{
|
||||
std::cout << "Failed to compile shader" << std::endl;
|
||||
|
|
@ -182,25 +185,34 @@ int main()
|
|||
// Nos ressources sont chargées, et c'est bien beau, mais il nous faudrait une fenêtre pour afficher tout ça
|
||||
// Window représente une fenêtre singulière, pour y effectuer un rendu il nous faut une RenderWindow
|
||||
// Tout d'abord, sa taille, disons celle du bureau divisé par deux
|
||||
NzVideoMode mode = NzVideoMode::GetDesktopMode();
|
||||
|
||||
// Un VideoMode est une structure contenant une longueur (width), une largeur (height) et le nombre de bits par pixels (bitsPerPixel)
|
||||
NzVideoMode mode = NzVideoMode::GetDesktopMode(); // Nous récupérons le mode actuellement utilisé par le bureau
|
||||
|
||||
// Nous divisons sa longueur et sa largeur par deux
|
||||
mode.width /= 2;
|
||||
mode.height /= 2;
|
||||
|
||||
NzString title = "Nazara Demo - AnimatedMesh";
|
||||
// Maintenant le titre, rien de plus simple...
|
||||
NzString windowTitle = "Nazara Demo - AnimatedMesh";
|
||||
|
||||
// Nous pouvons créer notre fenêtre ! (Via le constructeur directement ou par la méthode Create)
|
||||
NzRenderWindow window;
|
||||
// Le premier argument définit la taille de rendu de la fenêtre (Si elle possède une bordure elle sera légèrement plus grande)
|
||||
// Le deuxième argument est le titre de la fenêtre lors de sa création, vous pouvez le modifier à tout moment via window.SetTitle
|
||||
|
||||
// Le premier argument définit la taille de rendu de la fenêtre (Si elle possède une bordure elle sera légèrement plus grande).
|
||||
// Le deuxième argument est le titre de la fenêtre lors de sa création, vous pouvez le modifier à tout moment via window.SetTitle.
|
||||
// Le troisième argument représente la décoration de la fenêtre, sa bordure, ses boutons.
|
||||
// Attention que cela permet à la fenêtre d'envoyer des évènements, et de changer sa taille
|
||||
// Attention que cela permet à la fenêtre de changer sa taille et qu'il faudra donc traiter l'évènement.
|
||||
// Par défaut le troisième argument vaut nzWindowStyle_Default (Bordure + Bouton de fermeture + Redimensionnement)
|
||||
if (!window.Create(mode, title, nzWindowStyle_Default))
|
||||
if (!window.Create(mode, windowTitle, nzWindowStyle_Default))
|
||||
{
|
||||
std::cout << "Failed to create window" << std::endl;
|
||||
std::getchar();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Notre belle fenêtre est créée, nous pouvons la configurer
|
||||
|
||||
// On cache le curseur
|
||||
window.SetCursor(nzWindowCursor_None);
|
||||
|
||||
|
|
@ -215,40 +227,27 @@ int main()
|
|||
unsigned int fps = 0; // Compteur de FPS
|
||||
|
||||
// Quelques variables pour notre improvisation de physique
|
||||
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Pas très exact
|
||||
NzVector3f modelPos(0.f, groundPos, -50.f);
|
||||
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Les coordonnées locales du "bas" du modèle
|
||||
NzVector3f modelPos(0.f, -groundPos, -50.f);
|
||||
NzVector3f modelVel(0.f, 0.f, 0.f);
|
||||
NzQuaternionf modelRot(NzEulerAnglesf(0.f, 0.f, 0.f)); // Les angles d'eulers sont bien plus facile à se représenter
|
||||
float speed = 60.f;
|
||||
NzQuaternionf modelOrient(NzQuaternionf::Identity());
|
||||
NzEulerAnglesf modelRot(0.f, 0.f, 0.f);
|
||||
float modelSpeed = 150.f;
|
||||
|
||||
// Nous initialisons la matrice
|
||||
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
|
||||
drfreak.matrix = NzMatrix4f::Rotate(modelOrient) * NzMatrix4f::Translate(modelPos);
|
||||
|
||||
// Notre caméra
|
||||
NzVector3f camPos(0.f, 25.f, -20.f);
|
||||
NzEulerAnglesf camRot(0.f, 0.f, 0.f);
|
||||
NzQuaternionf camOrient(NzQuaternionf::Identity());
|
||||
NzEulerAnglesf camRot(0.f, 0.f, 0.f); // Les angles d'eulers sont bien plus facile à utiliser
|
||||
NzMatrix4f camMatrix = NzMatrix4f::Translate(camPos);
|
||||
float camSpeed = 2.f;
|
||||
float sensitivity = 0.5;
|
||||
float camSpeed = 100.f;
|
||||
float sensitivity = 0.8f;
|
||||
|
||||
// Dernière étape, nos touches
|
||||
|
||||
// Chaque touche fera bouger
|
||||
struct Movement
|
||||
{
|
||||
NzVector3f direction; // La direction
|
||||
NzQuaternionf rotation; // La rotation du modèle
|
||||
};
|
||||
|
||||
std::map<NzKeyboard::Key, Movement> movements;
|
||||
movements[NzKeyboard::Up] = Movement{NzVector3f(0.f, 0.f, -1.f), NzQuaternionf(NzEulerAnglesf(0.f, 180.f, 0.f))};
|
||||
movements[NzKeyboard::Down] = Movement{NzVector3f(0.f, 0.f, 1.f), NzQuaternionf(NzEulerAnglesf(0.f, 0.f, 0.f))};
|
||||
movements[NzKeyboard::Left] = Movement{NzVector3f(-1.f, 0.f, 0.f), NzQuaternionf(NzEulerAnglesf(0.f, 90.f, 0.f))};
|
||||
movements[NzKeyboard::Right] = Movement{NzVector3f(1.f, 0.f, 0.f), NzQuaternionf(NzEulerAnglesf(0.f, -90.f, 0.f))};
|
||||
NzKeyboard::Key currentKey = NzKeyboard::Undefined;
|
||||
|
||||
// Quelques booléens
|
||||
// Quelques variables
|
||||
bool camMode = true;
|
||||
bool thirdPerson = false;
|
||||
bool windowOpen = true;
|
||||
|
||||
// On peut commencer la boucle du programme
|
||||
|
|
@ -258,36 +257,38 @@ int main()
|
|||
NzEvent event;
|
||||
while (window.PollEvent(&event)) // Avons-nous un évènement dans la file ?
|
||||
{
|
||||
// Nous avons un évènement
|
||||
// Nous avons un évènement !
|
||||
|
||||
switch (event.type) // De quel type est cet évènement ?
|
||||
{
|
||||
case nzEventType_Quit: // L'utilisateur/L'OS nous a demandé de terminer notre exécution
|
||||
windowOpen = false; // Nous terminons alors la boucle
|
||||
break;
|
||||
|
||||
case nzEventType_MouseMoved:
|
||||
case nzEventType_MouseMoved: // La souris a bougé
|
||||
{
|
||||
// Si nous ne sommes pas en mode caméra, on ne traite pas l'évènement
|
||||
if (!camMode)
|
||||
// Si nous ne sommes pas en mode free-fly, on ne traite pas l'évènement
|
||||
if (!camMode || thirdPerson)
|
||||
break;
|
||||
|
||||
// On modifie l'angle de la caméra grâce au déplacement relatif de la souris
|
||||
camRot.yaw = NzNormalizeAngle(camRot.yaw - event.mouseMove.deltaX*sensitivity);
|
||||
|
||||
// Pour éviter les loopings, on restreint les angles
|
||||
camRot.pitch = NzClamp(camRot.pitch + event.mouseMove.deltaY*sensitivity, -90.f, 90.f);
|
||||
// Pour éviter les loopings mais surtout les problèmes de calculation de la matrice de vue, on restreint les angles
|
||||
camRot.pitch = NzClamp(camRot.pitch - event.mouseMove.deltaY*sensitivity, -89.f, 89.f);
|
||||
|
||||
// La matrice vue représente les transformations effectuées par la caméra
|
||||
// On recalcule la matrice de la caméra et on l'envoie au renderer
|
||||
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot));
|
||||
camOrient = camRot; // Conversion des angles d'euler en quaternion
|
||||
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::LookAt(camPos, camPos + camOrient * NzVector3f::Forward()));
|
||||
|
||||
// Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre
|
||||
NzMouse::SetPosition(window.GetWidth()/2, window.GetHeight()/2, window);
|
||||
break;
|
||||
}
|
||||
|
||||
case nzEventType_MouseButtonPressed:
|
||||
if (event.mouseButton.button == NzMouse::Left)
|
||||
case nzEventType_MouseButtonPressed: // L'utilisateur (ou son chat) vient de cliquer sur la souris
|
||||
if (event.mouseButton.button == NzMouse::Left) // Est-ce le clic gauche ?
|
||||
{
|
||||
// L'utilisateur vient d'appuyer sur le bouton left de la souris
|
||||
// Nous allons inverser le mode caméra et montrer/cacher le curseur en conséquence
|
||||
|
|
@ -301,44 +302,54 @@ int main()
|
|||
camMode = true;
|
||||
window.SetCursor(nzWindowCursor_None);
|
||||
}
|
||||
}
|
||||
else if (event.mouseButton.button == NzMouse::Right) // Est-ce le clic droit ?
|
||||
{
|
||||
if (thirdPerson)
|
||||
{
|
||||
// On arrête le mouvement
|
||||
SetSequence(drfreak, "stand");
|
||||
|
||||
// Afin de synchroniser le quaternion avec les angles d'euler
|
||||
camRot = camOrient.ToEulerAngles();
|
||||
thirdPerson = false;
|
||||
}
|
||||
else
|
||||
thirdPerson = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case nzEventType_Resized: // L'utilisateur a changé notre taille, le coquin !
|
||||
case nzEventType_Resized: // L'utilisateur a changé la taille de la fenêtre, le coquin !
|
||||
NzRenderer::SetViewport(NzRectui(0, 0, event.size.width, event.size.height)); // Adaptons l'affichage
|
||||
|
||||
// Il nous faut aussi mettre à jour notre matrice de projection
|
||||
NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(event.size.width)/event.size.height, 1.f, 1000.f));
|
||||
break;
|
||||
|
||||
case nzEventType_KeyPressed:
|
||||
if (!event.key.repeated) // Si la touche n'est pas répétée
|
||||
case nzEventType_KeyPressed: // Une touche du clavier vient d'être enfoncée
|
||||
if (thirdPerson &&
|
||||
(event.key.code == NzKeyboard::Z || // Est-ce la touche Z ?
|
||||
event.key.code == NzKeyboard::S || // Ou bien la touche S ?
|
||||
event.key.code == NzKeyboard::Q || // Ou encore la touche Q ?
|
||||
event.key.code == NzKeyboard::D)) // Et pourquoi pas la touche D ?
|
||||
{
|
||||
auto it = movements.find(event.key.code);
|
||||
if (it != movements.end())
|
||||
{
|
||||
// Si la touche est une touche de mouvement
|
||||
SetSequence(drfreak, "run"); // On anime le personnage pour qu'il ait une animation de déplacement
|
||||
|
||||
modelRot = it->second.rotation; // On change la rotation du modèle
|
||||
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos); // On recalcule sa matrice
|
||||
modelVel = it->second.direction * speed; // On change la vitesse de déplacement
|
||||
currentKey = event.key.code;
|
||||
}
|
||||
// Si une touche concernant le déplacement est appuyée
|
||||
SetSequence(drfreak, "run"); // On anime le personnage pour qu'il ait une animation de déplacement
|
||||
}
|
||||
|
||||
if (event.key.code == NzKeyboard::Escape)
|
||||
else if (event.key.code == NzKeyboard::Escape)
|
||||
windowOpen = false;
|
||||
|
||||
break;
|
||||
|
||||
case nzEventType_KeyReleased:
|
||||
if (event.key.code == currentKey)
|
||||
case nzEventType_KeyReleased: // Une touche du clavier vient d'être relachée
|
||||
if (thirdPerson &&
|
||||
!NzKeyboard::IsKeyPressed(NzKeyboard::Z) && // Est-ce que la touche Z est enfoncée en ce moment ?
|
||||
!NzKeyboard::IsKeyPressed(NzKeyboard::S) && // Ou bien la touche S ?
|
||||
!NzKeyboard::IsKeyPressed(NzKeyboard::Q) && // Etc..
|
||||
!NzKeyboard::IsKeyPressed(NzKeyboard::D)) // Etc..
|
||||
{
|
||||
// Si plus aucune touche de déplacement n'est enfoncée
|
||||
SetSequence(drfreak, "stand");
|
||||
modelVel = NzVector3f(0.f); // On arrête le déplacement
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -348,81 +359,115 @@ int main()
|
|||
}
|
||||
}
|
||||
|
||||
// On active le shader et paramètrons le rendu
|
||||
NzRenderer::SetShader(&shader);
|
||||
NzRenderer::Enable(nzRendererParameter_DepthTest, true);
|
||||
|
||||
NzRenderer::SetClearColor(128, 128, 128);
|
||||
NzRenderer::Clear(nzRendererClear_Color | nzRendererClear_Depth);
|
||||
|
||||
// Mise à jour de la partie logique
|
||||
if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde
|
||||
{
|
||||
float elapsedTime = updateClock.GetSeconds(); // Le temps depuis la dernière mise à jour
|
||||
|
||||
// Déplacement de la caméra
|
||||
static const NzVector3f forward(NzVector3f::UnitZ());
|
||||
static const NzVector3f left(NzVector3f::UnitX());
|
||||
static const NzVector3f up(NzVector3f::UnitY());
|
||||
static const NzVector3f forward(NzVector3f::Forward());
|
||||
static const NzVector3f left(NzVector3f::Left());
|
||||
static const NzVector3f up(NzVector3f::Up());
|
||||
|
||||
// Notre rotation sous forme de quaternion nous permet de tourner un vecteur
|
||||
NzQuaternionf quaternion(camRot);
|
||||
|
||||
// Par exemple ici, quaternion * forward nous permet de récupérer le vecteur de la direction "avant"
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
|
||||
camPos += quaternion * forward * camSpeed;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
|
||||
camPos -= quaternion * forward * camSpeed;
|
||||
if (thirdPerson)
|
||||
{
|
||||
// Nous déplaçons le personnage en fonction des touches pressées
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
|
||||
camPos += quaternion * left * camSpeed;
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
|
||||
modelPos += modelOrient * forward * modelSpeed * elapsedTime;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
|
||||
camPos -= quaternion * left * camSpeed;
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
|
||||
modelPos -= modelOrient * forward * modelSpeed * elapsedTime;
|
||||
|
||||
// En revanche, ici la hauteur est toujours la même, peu importe notre orientation
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
|
||||
camPos += up * camSpeed;
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
|
||||
modelRot.yaw += camSpeed * elapsedTime;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
|
||||
camPos -= up * camSpeed;
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
|
||||
modelRot.yaw -= camSpeed * elapsedTime;
|
||||
|
||||
// Oui le quaternion et la matrice sont calculés même si la caméra ne bouge pas
|
||||
modelOrient = modelRot;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sinon, c'est la caméra qui se déplace (en fonction des mêmes touches)
|
||||
|
||||
// Un boost en maintenant le shift gauche
|
||||
float speed = (NzKeyboard::IsKeyPressed(NzKeyboard::Key::LShift)) ? camSpeed*5 : camSpeed;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
|
||||
camPos += camOrient * forward * speed * elapsedTime;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::S))
|
||||
camPos -= camOrient * forward * speed * elapsedTime;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Q))
|
||||
camPos += camOrient * left * speed * elapsedTime;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
|
||||
camPos -= camOrient * left * speed * elapsedTime;
|
||||
|
||||
// En revanche, ici la hauteur est toujours la même, peu importe notre orientation
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
|
||||
camPos += up * speed * elapsedTime;
|
||||
|
||||
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
|
||||
camPos -= up * speed * elapsedTime;
|
||||
}
|
||||
|
||||
// Oui les quaternions et les matrices sont calculés même si la caméra ne bouge pas
|
||||
// C'est une limitation de mon implémentation, qui ne sera pas présente une fois les NzSceneNode intégrés
|
||||
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot));
|
||||
if (thirdPerson)
|
||||
{
|
||||
static NzQuaternionf rotDown(NzEulerAnglesf(-15.f, 0.f, 0.f)); // Une rotation pour regarder vers le bas
|
||||
camOrient = modelOrient * rotDown;
|
||||
|
||||
camPos = modelPos + camOrient * NzVector3f(0.f, 25.f, 60.f);
|
||||
}
|
||||
|
||||
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::LookAt(camPos, camPos + camOrient * NzVector3f::Forward()));
|
||||
|
||||
// Mise à jour de la matrice du personnage
|
||||
drfreak.matrix = NzMatrix4f::Rotate(modelOrient) * NzMatrix4f::Translate(modelPos);
|
||||
|
||||
// Animation
|
||||
AnimateModel(drfreak, elapsedTime);
|
||||
updateClock.Restart();
|
||||
|
||||
// "Physique"
|
||||
if (modelVel != NzVector3f::Zero())
|
||||
{
|
||||
modelPos += modelVel * elapsedTime;
|
||||
|
||||
// Mise à jour de la matrice
|
||||
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
|
||||
}
|
||||
}
|
||||
|
||||
// On active le shader et paramètrons le rendu
|
||||
NzRenderer::SetShader(&shader);
|
||||
|
||||
// Notre scène 3D requiert un test de profondeur
|
||||
NzRenderer::Enable(nzRendererParameter_DepthTest, true);
|
||||
|
||||
// Nous voulons avoir un fond bien gris
|
||||
NzRenderer::SetClearColor(128, 128, 128);
|
||||
|
||||
// Et nous effaçons les buffers de couleur et de profondeur
|
||||
NzRenderer::Clear(nzRendererClear_Color | nzRendererClear_Depth);
|
||||
|
||||
// Affichage des meshs
|
||||
DrawModel(floor);
|
||||
|
||||
// Notre Dr. Freak possède des normales, nous pouvons alors culler les faces qu'on ne voit pas
|
||||
// Notre Dr. Freak possède des normales, nous pouvons alors éliminer les faces qu'on ne voit pas
|
||||
NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
|
||||
|
||||
DrawModel(drfreak);
|
||||
|
||||
NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
|
||||
|
||||
window.Display(); // Nous mettons à jour l'écran
|
||||
// Nous mettons à jour l'écran
|
||||
window.Display();
|
||||
|
||||
fps++;
|
||||
|
||||
// Toutes les secondes
|
||||
if (secondClock.GetMilliseconds() >= 1000)
|
||||
{
|
||||
window.SetTitle(title + " (FPS: " + NzString::Number(fps) + ')');
|
||||
window.SetTitle(windowTitle + " (FPS: " + NzString::Number(fps) + ')');
|
||||
fps = 0;
|
||||
secondClock.Restart();
|
||||
}
|
||||
|
|
@ -567,10 +612,10 @@ bool CreateFloorMesh(NzMesh* mesh)
|
|||
mesh->AddSubMesh(subMesh);
|
||||
|
||||
// Nos ressources sont notifiées utilisées par le mesh et le submesh, nous pouvons les rendre éphèmères.
|
||||
// Les ressources seront donc automatiquement libérées lorsque plus aucune classe n'en aura besoin
|
||||
// Les ressources seront donc automatiquement libérées lorsqu'elles ne seront plus référencées par une classe
|
||||
buffer->SetPersistent(false);
|
||||
declaration->SetPersistent(false);
|
||||
subMesh->SetPersistent(false); // Pour le submesh, c'est déjà à false à la base
|
||||
subMesh->SetPersistent(false); // Pour le submesh, c'est déjà le comportement par défaut
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -606,8 +651,12 @@ void SetSequence(AnimatedModel& model, const NzString& sequenceName)
|
|||
const NzAnimation* animation = model.mesh.GetAnimation();
|
||||
|
||||
// Nous nous basons sur l'assertion que la séquence existe (Chose que nous pouvons tester avec HasSequence())
|
||||
model.currentSequence = animation->GetSequence(sequenceName);
|
||||
const NzSequence* sequence = animation->GetSequence(sequenceName);
|
||||
if (model.currentSequence != sequence)
|
||||
{
|
||||
model.currentSequence = sequence;
|
||||
|
||||
// Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame
|
||||
model.nextFrame = model.currentSequence->firstFrame;
|
||||
// Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame
|
||||
model.nextFrame = model.currentSequence->firstFrame;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/NonCopyable.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceListener.hpp>
|
||||
#include <Nazara/Core/ResourceLoader.hpp>
|
||||
#include <Nazara/Core/Semaphore.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
|
||||
#define NAZARA_THREADSAFETY_HASHDIGEST 0 // NzHashDigest
|
||||
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
|
||||
#define NAZARA_THREADSAFETY_RESOURCE 1 // NzResource
|
||||
#define NAZARA_THREADSAFETY_STRING 1 // NzString (COW)
|
||||
#define NAZARA_THREADSAFETY_STRINGSTREAM 0 // NzStringStream
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ enum nzEndianness
|
|||
nzEndianness_Unknown = -1,
|
||||
|
||||
nzEndianness_BigEndian,
|
||||
nzEndianness_LittleEndian
|
||||
nzEndianness_LittleEndian,
|
||||
|
||||
nzEndianness_Max = nzEndianness_LittleEndian
|
||||
};
|
||||
|
||||
enum nzErrorType
|
||||
|
|
@ -20,7 +22,9 @@ enum nzErrorType
|
|||
nzErrorType_AssertFailed,
|
||||
nzErrorType_Internal,
|
||||
nzErrorType_Normal,
|
||||
nzErrorType_Warning
|
||||
nzErrorType_Warning,
|
||||
|
||||
nzErrorType_Max = nzErrorType_Warning
|
||||
};
|
||||
|
||||
#endif // NAZARA_ENUMS_CORE_HPP
|
||||
|
|
|
|||
|
|
@ -8,6 +8,32 @@
|
|||
#define NAZARA_RESOURCE_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <set>
|
||||
|
||||
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#else
|
||||
#include <Nazara/Core/ThreadSafetyOff.hpp>
|
||||
#endif
|
||||
|
||||
class NzResourceListener;
|
||||
|
||||
struct NzResourceEntry
|
||||
{
|
||||
NzResourceEntry(NzResourceListener* resourceListener, int i = 0) :
|
||||
listener(resourceListener),
|
||||
index(i)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const NzResourceEntry& rhs) const
|
||||
{
|
||||
return listener < rhs.listener;
|
||||
}
|
||||
|
||||
NzResourceListener* listener;
|
||||
int index;
|
||||
};
|
||||
|
||||
class NAZARA_API NzResource
|
||||
{
|
||||
|
|
@ -16,14 +42,30 @@ class NAZARA_API NzResource
|
|||
NzResource(const NzResource& resource);
|
||||
virtual ~NzResource();
|
||||
|
||||
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
|
||||
void AddResourceReference() const;
|
||||
|
||||
bool IsPersistent() const;
|
||||
|
||||
void RemoveResourceListener(NzResourceListener* listener) const;
|
||||
void RemoveResourceReference() const;
|
||||
|
||||
void SetPersistent(bool persistent = true);
|
||||
|
||||
protected:
|
||||
void NotifyCreated();
|
||||
void NotifyDestroy();
|
||||
|
||||
private:
|
||||
void EnsureResourceListenerUpdate() const;
|
||||
|
||||
NazaraMutexAttrib(m_mutex, mutable)
|
||||
|
||||
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
|
||||
mutable bool m_resourcePersistent;
|
||||
mutable std::set<NzResourceEntry> m_resourceListeners;
|
||||
mutable std::set<NzResourceEntry> m_resourceListenersCache;
|
||||
mutable bool m_resourceListenerUpdated;
|
||||
bool m_resourcePersistent;
|
||||
mutable unsigned int m_resourceReferenceCount;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (!parameters.IsValid())
|
||||
{
|
||||
NazaraError("Invalid Parameters");
|
||||
NazaraError("Invalid parameters");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -81,7 +81,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
|
|||
#if NAZARA_CORE_SAFE
|
||||
if (!parameters.IsValid())
|
||||
{
|
||||
NazaraError("Invalid Parameters");
|
||||
NazaraError("Invalid parameters");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ bool NzResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, NzInputS
|
|||
template<typename Type, typename Parameters>
|
||||
void NzResourceLoader<Type, Parameters>::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc)
|
||||
{
|
||||
/// Trouver une alternative à ce code monstrueux
|
||||
///FIXME: Trouver une alternative à ce code monstrueux
|
||||
std::vector<NzString> exts;
|
||||
fileExtensions.SplitAny(exts, " /\\.,;|-_");
|
||||
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ class NAZARA_API NzString : public NzHashable
|
|||
};
|
||||
|
||||
static SharedString emptyString;
|
||||
static unsigned int npos;
|
||||
static const unsigned int npos;
|
||||
|
||||
private:
|
||||
void EnsureOwnership();
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@
|
|||
// Définit le radian comme l'unité utilisée pour les angles
|
||||
#define NAZARA_MATH_ANGLE_RADIAN 0
|
||||
|
||||
// Définit la disposition des matrices en colonnes (Façon OpenGL)
|
||||
#define NAZARA_MATH_MATRIX_COLUMN_MAJOR 1
|
||||
|
||||
// Optimise les opérations entre matrices affines (Demande plusieurs comparaisons pour déterminer si une matrice est affine)
|
||||
#define NAZARA_MATH_MATRIX4_CHECK_AFFINE 0
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ template<typename T> class NzMatrix4
|
|||
~NzMatrix4();
|
||||
|
||||
NzMatrix4 Concatenate(const NzMatrix4& matrix) const;
|
||||
NzMatrix4 ConcatenateAffine(const NzMatrix4& matrix) const;
|
||||
|
||||
T GetDeterminant() const;
|
||||
NzMatrix4 GetInverse() const;
|
||||
|
|
@ -54,7 +55,7 @@ template<typename T> class NzMatrix4
|
|||
bool IsDefined() const;
|
||||
|
||||
void MakeIdentity();
|
||||
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up);
|
||||
void MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
|
||||
void MakeOrtho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
|
||||
void MakePerspective(T angle, T ratio, T zNear, T zFar);
|
||||
void MakeRotation(const NzQuaternion<T>& rotation);
|
||||
|
|
@ -106,7 +107,7 @@ template<typename T> class NzMatrix4
|
|||
static NzMatrix4 Concatenate(const NzMatrix4& m1, const NzMatrix4& m2);
|
||||
static NzMatrix4 ConcatenateAffine(const NzMatrix4& m1, const NzMatrix4& m2);
|
||||
static NzMatrix4 Identity();
|
||||
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up);
|
||||
static NzMatrix4 LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up = NzVector3<T>::Up());
|
||||
static NzMatrix4 Ortho(T left, T top, T width, T height, T zNear = -1.0, T zFar = 1.0);
|
||||
static NzMatrix4 Perspective(T angle, T ratio, T zNear, T zFar);
|
||||
static NzMatrix4 Rotate(const NzQuaternion<T>& rotation);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,12 @@ NzMatrix4<T> NzMatrix4<T>::Concatenate(const NzMatrix4& matrix) const
|
|||
return Concatenate(*this, matrix);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& matrix) const
|
||||
{
|
||||
return ConcatenateAffine(*this, matrix);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzMatrix4<T>::GetDeterminant() const
|
||||
{
|
||||
|
|
@ -162,11 +168,7 @@ NzVector3<T> NzMatrix4<T>::GetTranslation() const
|
|||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
return NzVector3<T>(m_sharedMatrix->m41, m_sharedMatrix->m42, m_sharedMatrix->m43);
|
||||
#else
|
||||
return NzVector3<T>(m_sharedMatrix->m14, m_sharedMatrix->m24, m_sharedMatrix->m34);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -229,17 +231,10 @@ bool NzMatrix4<T>::IsAffine() const
|
|||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
return NzNumberEquals(m_sharedMatrix->m14, F(0.0)) &&
|
||||
NzNumberEquals(m_sharedMatrix->m24, F(0.0)) &&
|
||||
NzNumberEquals(m_sharedMatrix->m34, F(0.0)) &&
|
||||
NzNumberEquals(m_sharedMatrix->m44, F(1.0));
|
||||
#else
|
||||
return NzNumberEquals(m_sharedMatrix->m41, F(0.0)) &&
|
||||
NzNumberEquals(m_sharedMatrix->m42, F(0.0)) &&
|
||||
NzNumberEquals(m_sharedMatrix->m43, F(0.0)) &&
|
||||
NzNumberEquals(m_sharedMatrix->m44, F(1.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -260,86 +255,80 @@ void NzMatrix4<T>::MakeIdentity()
|
|||
template<typename T>
|
||||
void NzMatrix4<T>::MakeOrtho(T left, T top, T width, T height, T zNear, T zFar)
|
||||
{
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb204941(v=vs.85).aspx
|
||||
Set(F(2.0)/(width-left), F(0.0), F(0.0), -(width+left)/(width-left),
|
||||
F(0.0), F(2.0)/(top-height), F(0.0), -(top+height)/(top-height),
|
||||
F(0.0), F(0.0), F(-2.0)/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
#else
|
||||
Set(F(2.0)/(width-left), F(0.0), F(0.0), F(0.0),
|
||||
F(0.0), F(2.0)/(top-height), F(0.0), F(0.0),
|
||||
F(0.0), F(0.0), F(-2.0)/(zFar-zNear), F(0.0),
|
||||
-(width+left)/(width-left), -(top+height)/(top-height), -(zFar+zNear)/(zFar-zNear), F(1.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzMatrix4<T>::MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up)
|
||||
void NzMatrix4<T>::MakeLookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
|
||||
{
|
||||
// http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml
|
||||
NzVector3<T> f = center - eye;
|
||||
f.Normalize();
|
||||
|
||||
NzVector3<T> u = up;
|
||||
u.Normalize();
|
||||
|
||||
NzVector3<T> s = f.CrossProduct(u);
|
||||
NzVector3<T> f = NzVector3<T>::Normalize(target - eye);
|
||||
NzVector3<T> u(up.GetNormal());
|
||||
NzVector3<T> s = NzVector3<T>::Normalize(f.CrossProduct(u));
|
||||
u = s.CrossProduct(f);
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
Set(s.x, s.y, s.z, F(0.0),
|
||||
u.x, u.y, u.z, F(0.0),
|
||||
-f.x, -f.y, -f.z, F(0.0),
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
#else
|
||||
Set(s.x, u.x, -f.x, F(0.0),
|
||||
s.y, u.y, -f.y, F(0.0),
|
||||
s.z, u.z, -f.z, F(0.0),
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
#endif
|
||||
|
||||
Concatenate(Translate(-eye));
|
||||
Set(s.x, u.x, -f.x, T(0.0),
|
||||
s.y, u.y, -f.y, T(0.0),
|
||||
s.z, u.z, -f.z, T(0.0),
|
||||
-s.DotProduct(eye), -u.DotProduct(eye), f.DotProduct(eye), T(1.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzMatrix4<T>::MakePerspective(T angle, T ratio, T zNear, T zFar)
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb204944(v=vs.85).aspx
|
||||
#if NAZARA_MATH_ANGLE_RADIAN
|
||||
angle /= F(2.0);
|
||||
#else
|
||||
angle = NzDegreeToRadian(angle/2);
|
||||
angle = NzDegreeToRadian(angle/F(2.0));
|
||||
#endif
|
||||
|
||||
T f = F(1.0) / std::tan(angle);
|
||||
T yScale = F(1.0) / std::tan(angle);
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
Set(f / ratio, F(0.0), F(0.0), F(0.0),
|
||||
F(0.0), f, F(0.0), F(0.0),
|
||||
F(0.0), F(0.0), (zNear+zFar) / (zNear-zFar), F(-1.0),
|
||||
F(0.0), F(0.0), (F(2.0)*zNear*zFar) / (zNear-zFar), F(1.0));
|
||||
#else
|
||||
Set(f / ratio, F(0.0), F(0.0), F(0.0),
|
||||
F(0.0), f, F(0.0), F(0.0),
|
||||
F(0.0), F(0.0), (zNear+zFar) / (zNear-zFar), (F(2.0)*zNear*zFar) / (zNear-zFar),
|
||||
F(0.0), F(0.0), F(-1.0), F(1.0));
|
||||
#endif
|
||||
Set(yScale / ratio, F(0.0), F(0.0), F(0.0),
|
||||
F(0.0), yScale, F(0.0), F(0.0),
|
||||
F(0.0), F(0.0), zFar / (zNear-zFar), F(-1.0),
|
||||
F(0.0), F(0.0), (zNear*zFar) / (zNear-zFar), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzMatrix4<T>::MakeRotation(const NzQuaternion<T>& rotation)
|
||||
{
|
||||
// http://stackoverflow.com/questions/1556260/convert-quaternion-rotation-to-rotation-matrix
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
Set(F(1.0) - F(2.0)*rotation.y*rotation.y - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w, F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w, F(0.0),
|
||||
F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w, F(0.0),
|
||||
F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w, F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y, F(0.0),
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
#else
|
||||
Set(F(1.0) - F(2.0)*rotation.y*rotation.y - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w, F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w, F(0.0),
|
||||
F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z, F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w, F(0.0),
|
||||
F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w, F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w, F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y, F(0.0),
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
#endif
|
||||
// http://www.flipcode.com/documents/matrfaq.html#Q54
|
||||
/*
|
||||
| 2 2 |
|
||||
| 1 - 2Y - 2Z 2XY + 2ZW 2XZ - 2YW |
|
||||
| |
|
||||
| 2 2 |
|
||||
M = | 2XY - 2ZW 1 - 2X - 2Z 2YZ + 2XW |
|
||||
| |
|
||||
| 2 2 |
|
||||
| 2XZ + 2YW 2YZ - 2XW 1 - 2X - 2Y |
|
||||
| |
|
||||
*/
|
||||
///FIXME: À corriger (Rotation quaternino != rotation matricielle)
|
||||
Set(F(1.0) - F(2.0)*rotation.y*rotation.y - F(2.0)*rotation.z*rotation.z,
|
||||
F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w,
|
||||
F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w,
|
||||
F(0.0),
|
||||
|
||||
F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w,
|
||||
F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z,
|
||||
F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w,
|
||||
F(0.0),
|
||||
|
||||
F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w,
|
||||
F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w,
|
||||
F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y,
|
||||
F(0.0),
|
||||
|
||||
F(0.0),
|
||||
F(0.0),
|
||||
F(0.0),
|
||||
F(1.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -354,17 +343,10 @@ void NzMatrix4<T>::MakeScale(const NzVector3<T>& scale)
|
|||
template<typename T>
|
||||
void NzMatrix4<T>::MakeTranslation(const NzVector3<T>& translation)
|
||||
{
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
Set(F(1.0), F(0.0), F(0.0), F(0.0),
|
||||
F(0.0), F(1.0), F(0.0), F(0.0),
|
||||
F(0.0), F(0.0), F(1.0), F(0.0),
|
||||
translation.x, translation.y, translation.z, F(1.0));
|
||||
#else
|
||||
Set(F(1.0), F(0.0), F(0.0), translation.x,
|
||||
F(0.0), F(1.0), F(0.0), translation.y,
|
||||
F(0.0), F(0.0), F(1.0), translation.z,
|
||||
F(0.0), F(0.0), F(0.0), F(1.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -451,21 +433,12 @@ void NzMatrix4<T>::SetRotation(const NzQuaternion<T>& rotation)
|
|||
m_sharedMatrix->m22 = F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.z*rotation.z;
|
||||
m_sharedMatrix->m33 = F(1.0) - F(2.0)*rotation.x*rotation.x - F(2.0)*rotation.y*rotation.y;
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
m_sharedMatrix->m12 = F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w;
|
||||
m_sharedMatrix->m13 = F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w;
|
||||
m_sharedMatrix->m21 = F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w;
|
||||
m_sharedMatrix->m23 = F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w;
|
||||
m_sharedMatrix->m31 = F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w;
|
||||
m_sharedMatrix->m32 = F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w;
|
||||
#else
|
||||
m_sharedMatrix->m12 = F(2.0)*rotation.x*rotation.y + F(2.0)*rotation.z*rotation.w;
|
||||
m_sharedMatrix->m13 = F(2.0)*rotation.x*rotation.z - F(2.0)*rotation.y*rotation.w;
|
||||
m_sharedMatrix->m21 = F(2.0)*rotation.x*rotation.y - F(2.0)*rotation.z*rotation.w;
|
||||
m_sharedMatrix->m23 = F(2.0)*rotation.y*rotation.z + F(2.0)*rotation.x*rotation.w;
|
||||
m_sharedMatrix->m31 = F(2.0)*rotation.x*rotation.z + F(2.0)*rotation.y*rotation.w;
|
||||
m_sharedMatrix->m32 = F(2.0)*rotation.y*rotation.z - F(2.0)*rotation.x*rotation.w;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -483,17 +456,10 @@ void NzMatrix4<T>::SetTranslation(const NzVector3<T>& translation)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
m_sharedMatrix->m41 = translation.x;
|
||||
m_sharedMatrix->m42 = translation.y;
|
||||
m_sharedMatrix->m43 = translation.z;
|
||||
m_sharedMatrix->m44 = F(1.0);
|
||||
#else
|
||||
m_sharedMatrix->m14 = translation.x;
|
||||
m_sharedMatrix->m24 = translation.y;
|
||||
m_sharedMatrix->m34 = translation.z;
|
||||
m_sharedMatrix->m44 = F(1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -832,7 +798,6 @@ NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& m1, const NzMatrix
|
|||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_MATH_MATRIX_COLUMN_MAJOR
|
||||
return NzMatrix4(m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m31,
|
||||
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m32,
|
||||
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m33,
|
||||
|
|
@ -852,27 +817,6 @@ NzMatrix4<T> NzMatrix4<T>::ConcatenateAffine(const NzMatrix4& m1, const NzMatrix
|
|||
m1.m_sharedMatrix->m41*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m42*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m43*m2.m_sharedMatrix->m32 + m2.m_sharedMatrix->m42,
|
||||
m1.m_sharedMatrix->m41*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m42*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m43*m2.m_sharedMatrix->m33 + m2.m_sharedMatrix->m43,
|
||||
F(1.0));
|
||||
#else
|
||||
return NzMatrix4(m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m31,
|
||||
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m32,
|
||||
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m33,
|
||||
m1.m_sharedMatrix->m11*m2.m_sharedMatrix->m14 + m1.m_sharedMatrix->m12*m2.m_sharedMatrix->m24 + m1.m_sharedMatrix->m13*m2.m_sharedMatrix->m34 + m1.m_sharedMatrix->m14,
|
||||
|
||||
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m31,
|
||||
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m32,
|
||||
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m33,
|
||||
m1.m_sharedMatrix->m21*m2.m_sharedMatrix->m14 + m1.m_sharedMatrix->m22*m2.m_sharedMatrix->m24 + m1.m_sharedMatrix->m23*m2.m_sharedMatrix->m34 + m1.m_sharedMatrix->m24,
|
||||
|
||||
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m11 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m21 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m31,
|
||||
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m12 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m22 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m32,
|
||||
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m13 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m23 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m33,
|
||||
m1.m_sharedMatrix->m31*m2.m_sharedMatrix->m14 + m1.m_sharedMatrix->m32*m2.m_sharedMatrix->m24 + m1.m_sharedMatrix->m33*m2.m_sharedMatrix->m34 + m1.m_sharedMatrix->m34,
|
||||
|
||||
F(0.0),
|
||||
F(0.0),
|
||||
F(0.0),
|
||||
F(1.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -885,10 +829,10 @@ NzMatrix4<T> NzMatrix4<T>::Identity()
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
NzMatrix4<T> NzMatrix4<T>::LookAt(const NzVector3<T>& eye, const NzVector3<T>& center, const NzVector3<T>& up)
|
||||
NzMatrix4<T> NzMatrix4<T>::LookAt(const NzVector3<T>& eye, const NzVector3<T>& target, const NzVector3<T>& up)
|
||||
{
|
||||
NzMatrix4 matrix;
|
||||
matrix.MakeLookAt(eye, center, up);
|
||||
matrix.MakeLookAt(eye, target, up);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,10 @@ template<typename T> class NzQuaternion
|
|||
T DotProduct(const NzQuaternion& vec) const;
|
||||
|
||||
NzQuaternion GetConjugate() const;
|
||||
NzQuaternion GetNormalized() const;
|
||||
NzQuaternion GetInverse() const;
|
||||
NzQuaternion GetNormal() const;
|
||||
|
||||
void Inverse();
|
||||
|
||||
void MakeIdentity();
|
||||
void MakeZero();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,16 @@ NzQuaternion<T> NzQuaternion<T>::GetConjugate() const
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::GetNormalized() const
|
||||
NzQuaternion<T> NzQuaternion<T>::GetInverse() const
|
||||
{
|
||||
NzQuaternion<T> quat(*this);
|
||||
quat.Inverse();
|
||||
|
||||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzQuaternion<T> NzQuaternion<T>::GetNormal() const
|
||||
{
|
||||
NzQuaternion<T> quat(*this);
|
||||
quat.Normalize();
|
||||
|
|
@ -75,16 +84,31 @@ NzQuaternion<T> NzQuaternion<T>::GetNormalized() const
|
|||
return quat;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzQuaternion<T>::Inverse()
|
||||
{
|
||||
T norm = SquaredMagnitude();
|
||||
if (norm > F(0.0))
|
||||
{
|
||||
T invNorm = F(1.0) / norm;
|
||||
|
||||
w *= invNorm;
|
||||
x *= -invNorm;
|
||||
y *= -invNorm;
|
||||
z *= -invNorm;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzQuaternion<T>::MakeIdentity()
|
||||
{
|
||||
Set(1.0, 0.0, 0.0, 0.0);
|
||||
Set(F(1.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzQuaternion<T>::MakeZero()
|
||||
{
|
||||
Set(0.0, 0.0, 0.0, 0.0);
|
||||
Set(F(0.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -98,16 +122,18 @@ T NzQuaternion<T>::Normalize()
|
|||
{
|
||||
T squaredMagnitude = SquaredMagnitude();
|
||||
|
||||
if (squaredMagnitude-F(1.0) > std::numeric_limits<T>::epsilon())
|
||||
// Inutile de vérifier si la magnitude au carrée est négative (Elle ne peut pas l'être)
|
||||
if (!NzNumberEquals(squaredMagnitude, F(1.0)))
|
||||
{
|
||||
T magnitude = std::sqrt(squaredMagnitude);
|
||||
T norm = std::sqrt(squaredMagnitude);
|
||||
T invNorm = F(1.0) / norm;
|
||||
|
||||
w /= magnitude;
|
||||
x /= magnitude;
|
||||
y /= magnitude;
|
||||
z /= magnitude;
|
||||
w *= invNorm;
|
||||
x *= invNorm;
|
||||
y *= invNorm;
|
||||
z *= invNorm;
|
||||
|
||||
return magnitude;
|
||||
return norm;
|
||||
}
|
||||
else
|
||||
return F(1.0); // Le quaternion est déjà normalisé
|
||||
|
|
@ -132,20 +158,24 @@ void NzQuaternion<T>::Set(T quat[4])
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& normalizedAxis)
|
||||
void NzQuaternion<T>::Set(T angle, const NzVector3<T>& axis)
|
||||
{
|
||||
angle /= F(2.0);
|
||||
|
||||
#if !NAZARA_MATH_ANGLE_RADIAN
|
||||
angle = NzDegreeToRadian(angle);
|
||||
#endif
|
||||
|
||||
angle /= 2;
|
||||
NzVector3<T> normalizedAxis = axis.GetNormal();
|
||||
|
||||
auto sinAngle = std::sin(angle);
|
||||
T sinAngle = std::sin(angle);
|
||||
|
||||
w = std::cos(angle);
|
||||
x = normalizedAxis.x * sinAngle;
|
||||
y = normalizedAxis.y * sinAngle;
|
||||
z = normalizedAxis.z * sinAngle;
|
||||
|
||||
Normalize();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -190,12 +220,8 @@ NzEulerAngles<T> NzQuaternion<T>::ToEulerAngles() const
|
|||
if (test < F(-0.499))
|
||||
return NzEulerAngles<T>(NzDegrees(F(-90.0)), NzRadians(F(-2.0) * std::atan2(x, w)), F(0.0));
|
||||
|
||||
T xx = x*x;
|
||||
T yy = y*y;
|
||||
T zz = z*z;
|
||||
|
||||
return NzEulerAngles<T>(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*xx - F(2.0)*zz)),
|
||||
NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*yy - F(2.0)*zz)),
|
||||
return NzEulerAngles<T>(NzRadians(std::atan2(F(2.0)*x*w - F(2.0)*y*z, F(1.0) - F(2.0)*x* - F(2.0)*z*z)),
|
||||
NzRadians(std::atan2(F(2.0)*y*w - F(2.0)*x*z, F(1.0) - F(2.0)*y*y - F(2.0)*z*z)),
|
||||
NzRadians(std::asin(F(2.0)*test)));
|
||||
}
|
||||
|
||||
|
|
@ -242,14 +268,13 @@ NzQuaternion<T> NzQuaternion<T>::operator*(const NzQuaternion& quat) const
|
|||
template<typename T>
|
||||
NzVector3<T> NzQuaternion<T>::operator*(const NzVector3<T>& vec) const
|
||||
{
|
||||
NzVector3<T> normal(vec);
|
||||
normal.Normalize();
|
||||
|
||||
NzQuaternion qvec(0.0, normal.x, normal.y, normal.z);
|
||||
NzQuaternion result(operator*(qvec * GetConjugate()));
|
||||
|
||||
return NzVector3<T>(result.x, result.y, result.z);
|
||||
NzVector3f quatVec(x, y, z);
|
||||
NzVector3f uv = quatVec.CrossProduct(vec);
|
||||
NzVector3f uuv = quatVec.CrossProduct(uv);
|
||||
uv *= F(2.0) * w;
|
||||
uuv *= F(2.0);
|
||||
|
||||
return vec + uv + uuv;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -29,14 +29,15 @@ template<typename T> class NzVector2
|
|||
|
||||
NzVector2 GetNormal() const;
|
||||
|
||||
void MakeCeil(const NzVector2& vec);
|
||||
void MakeFloor(const NzVector2& vec);
|
||||
T Length() const;
|
||||
float Lengthf() const;
|
||||
|
||||
void MakeUnitX();
|
||||
void MakeUnitY();
|
||||
void MakeZero();
|
||||
|
||||
T Length() const;
|
||||
float Lengthf() const;
|
||||
void Maximize(const NzVector2& vec);
|
||||
void Minimize(const NzVector2& vec);
|
||||
|
||||
void Normalize();
|
||||
|
||||
|
|
|
|||
|
|
@ -99,26 +99,6 @@ float NzVector2<T>::Lengthf() const
|
|||
return std::sqrt(static_cast<float>(SquaredLength()));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector2<T>::MakeCeil(const NzVector2& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector2<T>::MakeFloor(const NzVector2& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector2<T>::MakeUnitX()
|
||||
{
|
||||
|
|
@ -137,6 +117,26 @@ void NzVector2<T>::MakeZero()
|
|||
Set(F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector2<T>::Maximize(const NzVector2& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector2<T>::Minimize(const NzVector2& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector2<T>::Normalize()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,13 +36,17 @@ template<typename T> class NzVector3
|
|||
T Length() const;
|
||||
float Lengthf() const;
|
||||
|
||||
void MakeCeil(const NzVector3& vec);
|
||||
void MakeFloor(const NzVector3& vec);
|
||||
void MakeForward();
|
||||
void MakeLeft();
|
||||
void MakeUnitX();
|
||||
void MakeUnitY();
|
||||
void MakeUnitZ();
|
||||
void MakeUp();
|
||||
void MakeZero();
|
||||
|
||||
void Maximize(const NzVector3& vec);
|
||||
void Minimize(const NzVector3& vec);
|
||||
|
||||
void Normalize();
|
||||
|
||||
void Set(T X, T Y, T Z);
|
||||
|
|
@ -88,9 +92,15 @@ template<typename T> class NzVector3
|
|||
bool operator>(const NzVector3& vec) const;
|
||||
bool operator>=(const NzVector3& vec) const;
|
||||
|
||||
static NzVector3 CrossProduct(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static T DotProduct(const NzVector3& vec1, const NzVector3& vec2);
|
||||
static NzVector3 Forward();
|
||||
static NzVector3 Left();
|
||||
static NzVector3 Normalize(const NzVector3& vec);
|
||||
static NzVector3 UnitX();
|
||||
static NzVector3 UnitY();
|
||||
static NzVector3 UnitZ();
|
||||
static NzVector3 Up();
|
||||
static NzVector3 Zero();
|
||||
|
||||
T x, y, z;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ inline unsigned int NzVector3<unsigned int>::AbsDotProduct(const NzVector3<unsig
|
|||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::CrossProduct(const NzVector3& vec) const
|
||||
{
|
||||
return NzVector3(y * vec.z - z * vec.y, z * vec.x - x * vec.y, x * vec.y - y * vec.x);
|
||||
return NzVector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -100,29 +100,27 @@ NzVector3<T> NzVector3<T>::GetNormal() const
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector3<T>::MakeCeil(const NzVector3& vec)
|
||||
T NzVector3<T>::Length() const
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z > z)
|
||||
z = vec.z;
|
||||
return std::sqrt(SquaredLength());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector3<T>::MakeFloor(const NzVector3& vec)
|
||||
float NzVector3<T>::Lengthf() const
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
return std::sqrt(static_cast<float>(SquaredLength()));
|
||||
}
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
template<typename T>
|
||||
void NzVector3<T>::MakeForward()
|
||||
{
|
||||
Set(F(0.0), F(0.0), F(-1.0));
|
||||
}
|
||||
|
||||
if (vec.z < z)
|
||||
z = vec.z;
|
||||
template<typename T>
|
||||
void NzVector3<T>::MakeLeft()
|
||||
{
|
||||
Set(F(-1.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -143,6 +141,12 @@ void NzVector3<T>::MakeUnitZ()
|
|||
Set(F(0.0), F(0.0), F(1.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector3<T>::MakeUp()
|
||||
{
|
||||
Set(F(0.0), F(1.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector3<T>::MakeZero()
|
||||
{
|
||||
|
|
@ -150,15 +154,29 @@ void NzVector3<T>::MakeZero()
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector3<T>::Length() const
|
||||
void NzVector3<T>::Maximize(const NzVector3& vec)
|
||||
{
|
||||
return std::sqrt(SquaredLength());
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z > z)
|
||||
z = vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
float NzVector3<T>::Lengthf() const
|
||||
void NzVector3<T>::Minimize(const NzVector3& vec)
|
||||
{
|
||||
return std::sqrt(static_cast<float>(SquaredLength()));
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z < z)
|
||||
z = vec.z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -166,13 +184,13 @@ void NzVector3<T>::Normalize()
|
|||
{
|
||||
T squaredLength = SquaredLength();
|
||||
|
||||
if (squaredLength-F(1.0) > std::numeric_limits<T>::epsilon())
|
||||
if (!NzNumberEquals(squaredLength, F(1.0)))
|
||||
{
|
||||
T length = std::sqrt(squaredLength);
|
||||
T invLength = F(1.0) / std::sqrt(squaredLength);
|
||||
|
||||
x /= length;
|
||||
y /= length;
|
||||
z /= length;
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
z *= invLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -467,6 +485,42 @@ bool NzVector3<T>::operator>=(const NzVector3& vec) const
|
|||
return !operator<(vec);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::CrossProduct(const NzVector3& vec1, const NzVector3& vec2)
|
||||
{
|
||||
return vec1.CrossProduct(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzVector3<T>::DotProduct(const NzVector3& vec1, const NzVector3& vec2)
|
||||
{
|
||||
return vec1.DotProduct(vec2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Forward()
|
||||
{
|
||||
NzVector3 vector;
|
||||
vector.MakeForward();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Left()
|
||||
{
|
||||
NzVector3 vector;
|
||||
vector.MakeLeft();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Normalize(const NzVector3& vec)
|
||||
{
|
||||
return vec.GetNormal();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::UnitX()
|
||||
{
|
||||
|
|
@ -494,6 +548,15 @@ NzVector3<T> NzVector3<T>::UnitZ()
|
|||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Up()
|
||||
{
|
||||
NzVector3 vector;
|
||||
vector.MakeUp();
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzVector3<T> NzVector3<T>::Zero()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,13 +26,14 @@ template<typename T> class NzVector4
|
|||
|
||||
T DotProduct(const NzVector4& vec) const;
|
||||
|
||||
void MakeCeil(const NzVector4& vec);
|
||||
void MakeFloor(const NzVector4& vec);
|
||||
void MakeUnitX();
|
||||
void MakeUnitY();
|
||||
void MakeUnitZ();
|
||||
void MakeZero();
|
||||
|
||||
void Maximize(const NzVector4& vec);
|
||||
void Minimize(const NzVector4& vec);
|
||||
|
||||
void Normalize();
|
||||
|
||||
void Set(T X, T Y, T Z, T W = 1.0);
|
||||
|
|
|
|||
|
|
@ -73,38 +73,6 @@ T NzVector4<T>::DotProduct(const NzVector4& vec) const
|
|||
return x*vec.x + y*vec.y + z*vec.z + w*vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector4<T>::MakeCeil(const NzVector4& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z > z)
|
||||
z = vec.z;
|
||||
|
||||
if (vec.w > w)
|
||||
w = vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector4<T>::MakeFloor(const NzVector4& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z < z)
|
||||
z = vec.z;
|
||||
|
||||
if (vec.w < w)
|
||||
w = vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector4<T>::MakeUnitX()
|
||||
{
|
||||
|
|
@ -129,6 +97,38 @@ void NzVector4<T>::MakeZero()
|
|||
Set(F(0.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector4<T>::Maximize(const NzVector4& vec)
|
||||
{
|
||||
if (vec.x > x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y > y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z > z)
|
||||
z = vec.z;
|
||||
|
||||
if (vec.w > w)
|
||||
w = vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector4<T>::Minimize(const NzVector4& vec)
|
||||
{
|
||||
if (vec.x < x)
|
||||
x = vec.x;
|
||||
|
||||
if (vec.y < y)
|
||||
y = vec.y;
|
||||
|
||||
if (vec.z < z)
|
||||
z = vec.z;
|
||||
|
||||
if (vec.w < w)
|
||||
w = vec.w;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NzVector4<T>::Normalize()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||
#include <Nazara/Renderer/RenderTargetParameters.hpp>
|
||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||
#include <Nazara/Renderer/RenderWindow.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Renderer/Texture.hpp>
|
||||
|
|
|
|||
|
|
@ -29,9 +29,6 @@
|
|||
|
||||
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
|
||||
|
||||
// Active une fenêtre de rendu (NzRenderWindow) lors de sa création
|
||||
#define NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION 1
|
||||
|
||||
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
|
||||
#define NAZARA_RENDERER_MEMORYLEAKTRACKER 0
|
||||
|
||||
|
|
|
|||
|
|
@ -2,20 +2,19 @@
|
|||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#ifdef NAZARA_RENDERER_COMMON
|
||||
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CONTEXT_HPP
|
||||
#define NAZARA_CONTEXT_HPP
|
||||
|
||||
#ifdef NAZARA_RENDERER_OPENGL
|
||||
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
|
||||
class NzContextImpl;
|
||||
|
||||
class NAZARA_API NzContext
|
||||
class NAZARA_API NzContext : public NzResource
|
||||
{
|
||||
friend NzContextImpl;
|
||||
|
||||
|
|
@ -25,6 +24,7 @@ class NAZARA_API NzContext
|
|||
|
||||
bool Create(const NzContextParameters& parameters = NzContextParameters());
|
||||
void Destroy();
|
||||
|
||||
const NzContextParameters& GetParameters() const;
|
||||
bool IsActive() const;
|
||||
bool SetActive(bool active);
|
||||
|
|
@ -44,4 +44,6 @@ class NAZARA_API NzContext
|
|||
static NzContext* s_reference;
|
||||
};
|
||||
|
||||
#endif // NAZARA_RENDERER_OPENGL
|
||||
|
||||
#endif // NAZARA_CONTEXT_HPP
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@
|
|||
#ifndef NAZARA_ENUMS_RENDERER_HPP
|
||||
#define NAZARA_ENUMS_RENDERER_HPP
|
||||
|
||||
enum nzAttachmentPoint
|
||||
{
|
||||
nzAttachmentPoint_Color,
|
||||
nzAttachmentPoint_Depth,
|
||||
nzAttachmentPoint_DepthStencil,
|
||||
nzAttachmentPoint_Stencil,
|
||||
|
||||
nzAttachmentPoint_Max = nzAttachmentPoint_Stencil
|
||||
};
|
||||
|
||||
enum nzBlendFunc
|
||||
{
|
||||
nzBlendFunc_DestAlpha,
|
||||
|
|
@ -18,21 +28,27 @@ enum nzBlendFunc
|
|||
nzBlendFunc_InvSrcAlpha,
|
||||
nzBlendFunc_InvSrcColor,
|
||||
nzBlendFunc_One,
|
||||
nzBlendFunc_Zero
|
||||
nzBlendFunc_Zero,
|
||||
|
||||
nzBlendFunc_Max = nzBlendFunc_Zero
|
||||
};
|
||||
|
||||
enum nzFaceCulling
|
||||
{
|
||||
nzFaceCulling_Back,
|
||||
nzFaceCulling_Front,
|
||||
nzFaceCulling_FrontAndBack
|
||||
nzFaceCulling_FrontAndBack,
|
||||
|
||||
nzFaceCulling_Max = nzFaceCulling_FrontAndBack
|
||||
};
|
||||
|
||||
enum nzFaceFilling
|
||||
{
|
||||
nzFaceFilling_Point,
|
||||
nzFaceFilling_Line,
|
||||
nzFaceFilling_Fill
|
||||
nzFaceFilling_Fill,
|
||||
|
||||
nzFaceFilling_Max = nzFaceFilling_Fill
|
||||
};
|
||||
|
||||
enum nzMatrixType
|
||||
|
|
@ -47,7 +63,9 @@ enum nzMatrixType
|
|||
enum nzPixelBufferType
|
||||
{
|
||||
nzPixelBufferType_Pack,
|
||||
nzPixelBufferType_Unpack
|
||||
nzPixelBufferType_Unpack,
|
||||
|
||||
nzPixelBufferType_Max = nzPixelBufferType_Unpack
|
||||
};
|
||||
|
||||
enum nzRendererCap
|
||||
|
|
@ -58,6 +76,7 @@ enum nzRendererCap
|
|||
nzRendererCap_MultipleRenderTargets,
|
||||
nzRendererCap_OcclusionQuery,
|
||||
nzRendererCap_PixelBufferObject,
|
||||
nzRendererCap_RenderTexture,
|
||||
nzRendererCap_Texture3D,
|
||||
nzRendererCap_TextureCubemap,
|
||||
nzRendererCap_TextureMulti,
|
||||
|
|
@ -66,7 +85,7 @@ enum nzRendererCap
|
|||
nzRendererCap_Max = nzRendererCap_TextureNPOT
|
||||
};
|
||||
|
||||
enum nzRendererClear
|
||||
enum nzRendererClearFlags
|
||||
{
|
||||
nzRendererClear_Color = 0x01,
|
||||
nzRendererClear_Depth = 0x02,
|
||||
|
|
@ -81,7 +100,9 @@ enum nzRendererComparison
|
|||
nzRendererComparison_GreaterOrEqual,
|
||||
nzRendererComparison_Less,
|
||||
nzRendererComparison_LessOrEqual,
|
||||
nzRendererComparison_Never
|
||||
nzRendererComparison_Never,
|
||||
|
||||
nzRendererComparison_Max = nzRendererComparison_Never
|
||||
};
|
||||
|
||||
enum nzRendererParameter
|
||||
|
|
@ -91,15 +112,19 @@ enum nzRendererParameter
|
|||
nzRendererParameter_DepthTest,
|
||||
nzRendererParameter_DepthWrite,
|
||||
nzRendererParameter_FaceCulling,
|
||||
nzRendererParameter_Stencil
|
||||
nzRendererParameter_Stencil,
|
||||
|
||||
nzRendererParameter_Max = nzRendererParameter_Stencil
|
||||
};
|
||||
|
||||
enum nzShaderLanguage
|
||||
{
|
||||
nzShaderLanguage_Unknown,
|
||||
nzShaderLanguage_Unknown = -1,
|
||||
|
||||
nzShaderLanguage_Cg,
|
||||
nzShaderLanguage_GLSL
|
||||
nzShaderLanguage_GLSL,
|
||||
|
||||
nzShaderLanguage_Max = nzShaderLanguage_GLSL
|
||||
};
|
||||
|
||||
enum nzShaderType
|
||||
|
|
@ -120,22 +145,30 @@ enum nzStencilOperation
|
|||
nzStencilOperation_Invert,
|
||||
nzStencilOperation_Keep,
|
||||
nzStencilOperation_Replace,
|
||||
nzStencilOperation_Zero
|
||||
nzStencilOperation_Zero,
|
||||
|
||||
nzStencilOperation_Max = nzStencilOperation_Zero
|
||||
};
|
||||
|
||||
enum nzTextureFilter
|
||||
{
|
||||
nzTextureFilter_Unknown = -1,
|
||||
|
||||
nzTextureFilter_Bilinear,
|
||||
nzTextureFilter_Nearest,
|
||||
nzTextureFilter_Trilinear,
|
||||
nzTextureFilter_Unknown
|
||||
|
||||
nzTextureFilter_Max = nzTextureFilter_Trilinear
|
||||
};
|
||||
|
||||
enum nzTextureWrap
|
||||
{
|
||||
nzTextureWrap_Unknown = -1,
|
||||
|
||||
nzTextureWrap_Clamp,
|
||||
nzTextureWrap_Repeat,
|
||||
nzTextureWrap_Unknown
|
||||
|
||||
nzTextureWrap_Max = nzTextureWrap_Repeat
|
||||
};
|
||||
|
||||
#endif // NAZARA_ENUMS_RENDERER_HPP
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@
|
|||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#ifdef NAZARA_RENDERER_COMMON
|
||||
#error This file is not part of the common renderer interface, you must undefine NAZARA_RENDERER_COMMON to use it
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_OPENGL_HPP
|
||||
#define NAZARA_OPENGL_HPP
|
||||
|
||||
#ifdef NAZARA_RENDERER_OPENGL
|
||||
|
||||
// gl3.h définit WIN32_LEAN_AND_MEAN qui entre en conflit avec la définition de Nazara et doit donc être inclut en premier
|
||||
#include <GL3/glcorearb.h>
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
#include <Nazara/Renderer/Enums.hpp>
|
||||
|
||||
// Inclusion des extensions
|
||||
#include <GL3/glext.h>
|
||||
|
|
@ -24,35 +24,69 @@
|
|||
#include <GL3/glxext.h>
|
||||
#endif
|
||||
|
||||
enum nzOpenGLExtension
|
||||
{
|
||||
nzOpenGLExtension_AnisotropicFilter,
|
||||
nzOpenGLExtension_DebugOutput,
|
||||
nzOpenGLExtension_FP64,
|
||||
nzOpenGLExtension_FrameBufferObject,
|
||||
nzOpenGLExtension_PixelBufferObject,
|
||||
nzOpenGLExtension_SeparateShaderObjects,
|
||||
nzOpenGLExtension_TextureArray,
|
||||
nzOpenGLExtension_TextureCompression_s3tc,
|
||||
nzOpenGLExtension_TextureStorage,
|
||||
nzOpenGLExtension_VertexArrayObject,
|
||||
|
||||
nzOpenGLExtension_Max = nzOpenGLExtension_VertexArrayObject
|
||||
};
|
||||
|
||||
using NzOpenGLFunc = void (*)();
|
||||
|
||||
class NAZARA_API NzOpenGL
|
||||
namespace NzOpenGL
|
||||
{
|
||||
public:
|
||||
enum Extension
|
||||
{
|
||||
AnisotropicFilter,
|
||||
DebugOutput,
|
||||
FP64,
|
||||
FrameBufferObject,
|
||||
PixelBufferObject,
|
||||
SeparateShaderObjects,
|
||||
Texture3D,
|
||||
TextureArray,
|
||||
TextureCompression_s3tc,
|
||||
TextureStorage,
|
||||
VertexArrayObject,
|
||||
enum FormatType
|
||||
{
|
||||
FormatType_RenderBuffer,
|
||||
// FormatType_MultisampleTexture,
|
||||
FormatType_Texture
|
||||
};
|
||||
|
||||
Max = VertexArrayObject
|
||||
};
|
||||
struct Format
|
||||
{
|
||||
GLenum dataFormat;
|
||||
GLenum dataType;
|
||||
GLint internalFormat;
|
||||
};
|
||||
|
||||
static NzOpenGLFunc GetEntry(const NzString& entryPoint);
|
||||
static unsigned int GetVersion();
|
||||
static bool Initialize();
|
||||
static bool IsSupported(Extension extension);
|
||||
static bool IsSupported(const NzString& string);
|
||||
static void Uninitialize();
|
||||
};
|
||||
NzOpenGLFunc GetEntry(const NzString& entryPoint);
|
||||
unsigned int GetVersion();
|
||||
bool Initialize();
|
||||
bool IsSupported(nzOpenGLExtension extension);
|
||||
bool IsSupported(const NzString& string);
|
||||
bool TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType target);
|
||||
void Uninitialize();
|
||||
|
||||
extern GLenum Attachment[nzAttachmentPoint_Max+1];
|
||||
extern nzUInt8 AttributeIndex[nzElementUsage_Max+1];
|
||||
extern GLenum BlendFunc[nzBlendFunc_Max+1];
|
||||
extern GLenum BufferLock[nzBufferAccess_Max+1];
|
||||
extern GLenum BufferLockRange[nzBufferAccess_Max+1];
|
||||
extern GLenum BufferTarget[nzBufferType_Max+1];
|
||||
extern GLenum BufferTargetBinding[nzBufferType_Max+1];
|
||||
extern GLenum BufferUsage[nzBufferUsage_Max+1];
|
||||
extern GLenum CubemapFace[6]; // Un cube possède six faces et ça n'est pas prêt de changer
|
||||
extern GLenum ElementType[nzElementType_Max+1];
|
||||
extern GLenum FaceCulling[nzFaceCulling_Max+1];
|
||||
extern GLenum FaceFilling[nzFaceFilling_Max+1];
|
||||
extern GLenum PrimitiveType[nzPrimitiveType_Max+1];
|
||||
extern GLenum RendererComparison[nzRendererComparison_Max+1];
|
||||
extern GLenum RendererParameter[nzRendererParameter_Max+1];
|
||||
extern GLenum ShaderType[nzShaderType_Max+1];
|
||||
extern GLenum StencilOperation[nzStencilOperation_Max+1];
|
||||
extern GLenum TextureTarget[nzImageType_Max+1];
|
||||
extern GLenum TextureTargetBinding[nzImageType_Max+1];
|
||||
extern GLenum TextureTargetProxy[nzImageType_Max+1];
|
||||
}
|
||||
|
||||
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||
NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader;
|
||||
|
|
@ -60,6 +94,7 @@ NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery;
|
|||
NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
||||
NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
|
||||
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
||||
NAZARA_API extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation;
|
||||
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
|
||||
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
|
||||
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||
|
|
@ -99,7 +134,11 @@ NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
|
|||
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
|
||||
NAZARA_API extern PFNGLFLUSHPROC glFlush;
|
||||
NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
||||
NAZARA_API extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture;
|
||||
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
|
||||
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
|
||||
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
|
||||
NAZARA_API extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
|
||||
NAZARA_API extern PFNGLENABLEPROC glEnable;
|
||||
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||
NAZARA_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
|
||||
|
|
@ -189,4 +228,6 @@ NAZARA_API extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs;
|
|||
NAZARA_API extern PFNGLXSWAPINTERVALSGIPROC glXSwapInterval;
|
||||
#endif
|
||||
|
||||
#endif // NAZARA_RENDERER_OPENGL
|
||||
|
||||
#endif // NAZARA_OPENGL_HPP
|
||||
|
|
|
|||
|
|
@ -21,19 +21,18 @@ class NAZARA_API NzRenderTarget
|
|||
NzRenderTarget() = default;
|
||||
virtual ~NzRenderTarget();
|
||||
|
||||
#ifndef NAZARA_RENDERER_COMMON
|
||||
virtual bool HasContext() const = 0;
|
||||
#endif
|
||||
|
||||
virtual unsigned int GetHeight() const = 0;
|
||||
virtual NzRenderTargetParameters GetParameters() const = 0;
|
||||
virtual unsigned int GetWidth() const = 0;
|
||||
|
||||
bool IsActive() const;
|
||||
virtual bool IsValid() const = 0;
|
||||
virtual bool IsRenderable() const = 0;
|
||||
|
||||
bool SetActive(bool active);
|
||||
|
||||
// Fonctions OpenGL
|
||||
virtual bool HasContext() const = 0;
|
||||
|
||||
protected:
|
||||
virtual bool Activate() = 0;
|
||||
virtual void Desactivate();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
#ifndef NAZARA_RENDERER_COMMON
|
||||
NzContextParameters GetContextParameters() const;
|
||||
#endif
|
||||
|
||||
unsigned int GetHeight() const;
|
||||
NzRenderTargetParameters GetParameters() const;
|
||||
unsigned int GetWidth() const;
|
||||
|
||||
#ifndef NAZARA_RENDERER_COMMON
|
||||
bool HasContext() const;
|
||||
#endif
|
||||
|
||||
bool IsRenderable() const;
|
||||
bool IsValid() const;
|
||||
|
||||
void SetFramerateLimit(unsigned int limit);
|
||||
|
||||
// Fonctions OpenGL
|
||||
NzContextParameters GetContextParameters() const;
|
||||
bool HasContext() const;
|
||||
|
||||
protected:
|
||||
virtual bool Activate() override;
|
||||
bool Activate() override;
|
||||
|
||||
private:
|
||||
virtual void OnWindowDestroying() override;
|
||||
virtual bool OnWindowCreated() override;
|
||||
bool OnWindowCreated() override;
|
||||
void OnWindowDestroy() override;
|
||||
|
||||
NzClock m_clock;
|
||||
NzContextParameters m_parameters;
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@
|
|||
#include <Nazara/Utility/Image.hpp>
|
||||
#include <Nazara/Utility/PixelFormat.hpp>
|
||||
|
||||
class NzRenderTexture;
|
||||
struct NzTextureImpl;
|
||||
|
||||
class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
||||
{
|
||||
friend NzRenderTexture;
|
||||
friend class NzShader;
|
||||
|
||||
public:
|
||||
|
|
@ -24,10 +26,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
|||
explicit NzTexture(const NzImage& image);
|
||||
~NzTexture();
|
||||
|
||||
#ifndef NAZARA_RENDERER_COMMON
|
||||
bool Bind() const;
|
||||
#endif
|
||||
|
||||
bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false);
|
||||
void Destroy();
|
||||
|
||||
|
|
@ -75,13 +73,18 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
|||
|
||||
void Unlock();
|
||||
|
||||
// Fonctions OpenGL
|
||||
unsigned int GetOpenGLID() const;
|
||||
bool Prepare() const;
|
||||
|
||||
static unsigned int GetValidSize(unsigned int size);
|
||||
static bool IsFormatSupported(nzPixelFormat format);
|
||||
static bool IsMipmappingSupported();
|
||||
static bool IsTypeSupported(nzImageType type);
|
||||
|
||||
private:
|
||||
void SetTarget(bool isTarget);
|
||||
NzRenderTexture* GetRenderTexture() const;
|
||||
void SetRenderTexture(NzRenderTexture* renderTexture);
|
||||
|
||||
NzTextureImpl* m_impl;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class NAZARA_API NzAnimation : public NzResource
|
|||
NzAnimation() = default;
|
||||
~NzAnimation();
|
||||
|
||||
unsigned int AddSequence(const NzSequence& sequence);
|
||||
bool AddSequence(const NzSequence& sequence);
|
||||
|
||||
bool Create(nzAnimationType type, unsigned int frameCount);
|
||||
void Destroy();
|
||||
|
|
@ -54,6 +54,7 @@ class NAZARA_API NzAnimation : public NzResource
|
|||
const NzSequence* GetSequence(const NzString& sequenceName) const;
|
||||
const NzSequence* GetSequence(unsigned int index) const;
|
||||
unsigned int GetSequenceCount() const;
|
||||
int GetSequenceIndex(const NzString& sequenceName) const;
|
||||
nzAnimationType GetType() const;
|
||||
|
||||
bool HasSequence(const NzString& sequenceName) const;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ enum nzAnimationType
|
|||
{
|
||||
nzAnimationType_Keyframe,
|
||||
nzAnimationType_Skeletal,
|
||||
nzAnimationType_Static
|
||||
nzAnimationType_Static,
|
||||
|
||||
nzAnimationType_Max = nzAnimationType_Static
|
||||
};
|
||||
|
||||
enum nzBufferAccess
|
||||
|
|
@ -19,7 +21,9 @@ enum nzBufferAccess
|
|||
nzBufferAccess_DiscardAndWrite,
|
||||
nzBufferAccess_ReadOnly,
|
||||
nzBufferAccess_ReadWrite,
|
||||
nzBufferAccess_WriteOnly
|
||||
nzBufferAccess_WriteOnly,
|
||||
|
||||
nzBufferAccess_Max = nzBufferAccess_WriteOnly
|
||||
};
|
||||
|
||||
enum nzBufferStorage
|
||||
|
|
@ -34,13 +38,17 @@ enum nzBufferStorage
|
|||
enum nzBufferType
|
||||
{
|
||||
nzBufferType_Index,
|
||||
nzBufferType_Vertex
|
||||
nzBufferType_Vertex,
|
||||
|
||||
nzBufferType_Max = nzBufferType_Vertex
|
||||
};
|
||||
|
||||
enum nzBufferUsage
|
||||
{
|
||||
nzBufferUsage_Dynamic,
|
||||
nzBufferUsage_Static
|
||||
nzBufferUsage_Static,
|
||||
|
||||
nzBufferUsage_Max = nzBufferUsage_Static
|
||||
};
|
||||
|
||||
enum nzCubemapFace
|
||||
|
|
@ -52,7 +60,9 @@ enum nzCubemapFace
|
|||
nzCubemapFace_PositiveZ = 4,
|
||||
nzCubemapFace_NegativeX = 1,
|
||||
nzCubemapFace_NegativeY = 3,
|
||||
nzCubemapFace_NegativeZ = 5
|
||||
nzCubemapFace_NegativeZ = 5,
|
||||
|
||||
nzCubemapFace_Max = nzCubemapFace_NegativeZ
|
||||
};
|
||||
|
||||
enum nzElementStream
|
||||
|
|
@ -73,7 +83,9 @@ enum nzElementType
|
|||
nzElementType_Float1,
|
||||
nzElementType_Float2,
|
||||
nzElementType_Float3,
|
||||
nzElementType_Float4
|
||||
nzElementType_Float4,
|
||||
|
||||
nzElementType_Max = nzElementType_Float4
|
||||
};
|
||||
|
||||
enum nzElementUsage
|
||||
|
|
@ -103,14 +115,18 @@ enum nzEventType
|
|||
nzEventType_Moved,
|
||||
nzEventType_Quit,
|
||||
nzEventType_Resized,
|
||||
nzEventType_TextEntered
|
||||
nzEventType_TextEntered,
|
||||
|
||||
nzEventType_Max = nzEventType_TextEntered
|
||||
};
|
||||
|
||||
enum nzExtend
|
||||
{
|
||||
nzExtend_Finite,
|
||||
nzExtend_Infinite,
|
||||
nzExtend_Null
|
||||
nzExtend_Null,
|
||||
|
||||
nzExtend_Max = nzExtend_Null
|
||||
};
|
||||
|
||||
enum nzImageType
|
||||
|
|
@ -129,28 +145,27 @@ enum nzPixelFormat
|
|||
{
|
||||
nzPixelFormat_Undefined = -1,
|
||||
|
||||
nzPixelFormat_BGR8, // 3*nzUInt8
|
||||
nzPixelFormat_BGRA8, // 4*nzUInt8
|
||||
nzPixelFormat_BGR8, // 3*nzUInt8
|
||||
nzPixelFormat_BGRA8, // 4*nzUInt8
|
||||
nzPixelFormat_DXT1,
|
||||
nzPixelFormat_DXT3,
|
||||
nzPixelFormat_DXT5,
|
||||
nzPixelFormat_L8, // 1*nzUInt8
|
||||
nzPixelFormat_LA8, // 2*nzUInt8
|
||||
nzPixelFormat_L8, // 1*nzUInt8
|
||||
nzPixelFormat_LA8, // 2*nzUInt8
|
||||
/*
|
||||
nzPixelFormat_RGB16F,
|
||||
nzPixelFormat_RGB16I, // 4*nzUInt16
|
||||
nzPixelFormat_RGB16I, // 4*nzUInt16
|
||||
nzPixelFormat_RGB32F,
|
||||
nzPixelFormat_RGB32I, // 4*nzUInt32
|
||||
nzPixelFormat_RGB32I, // 4*nzUInt32
|
||||
nzPixelFormat_RGBA16F,
|
||||
nzPixelFormat_RGBA16I, // 4*nzUInt16
|
||||
nzPixelFormat_RGBA16I, // 4*nzUInt16
|
||||
nzPixelFormat_RGBA32F,
|
||||
nzPixelFormat_RGBA32I, // 4*nzUInt32
|
||||
nzPixelFormat_RGBA32I, // 4*nzUInt32
|
||||
*/
|
||||
nzPixelFormat_RGBA4, // 1*nzUInt16
|
||||
nzPixelFormat_RGB5A1, // 1*nzUInt16
|
||||
nzPixelFormat_RGB8, // 3*nzUInt8
|
||||
nzPixelFormat_RGBA8, // 4*nzUInt8
|
||||
/*
|
||||
nzPixelFormat_RGBA4, // 1*nzUInt16
|
||||
nzPixelFormat_RGB5A1, // 1*nzUInt16
|
||||
nzPixelFormat_RGB8, // 3*nzUInt8
|
||||
nzPixelFormat_RGBA8, // 4*nzUInt8
|
||||
nzPixelFormat_Depth16,
|
||||
nzPixelFormat_Depth24,
|
||||
nzPixelFormat_Depth24Stencil8,
|
||||
|
|
@ -159,9 +174,20 @@ enum nzPixelFormat
|
|||
nzPixelFormat_Stencil4,
|
||||
nzPixelFormat_Stencil8,
|
||||
nzPixelFormat_Stencil16,
|
||||
*/
|
||||
|
||||
nzPixelFormat_Max = nzPixelFormat_RGBA8
|
||||
nzPixelFormat_Max = nzPixelFormat_Stencil16
|
||||
};
|
||||
|
||||
enum nzPixelFormatType
|
||||
{
|
||||
nzPixelFormatType_Undefined = -1,
|
||||
|
||||
nzPixelFormatType_Color,
|
||||
nzPixelFormatType_Depth,
|
||||
nzPixelFormatType_DepthStencil,
|
||||
nzPixelFormatType_Stencil,
|
||||
|
||||
nzPixelFormatType_Max = nzPixelFormatType_Stencil
|
||||
};
|
||||
|
||||
enum nzPixelFlipping
|
||||
|
|
@ -179,7 +205,9 @@ enum nzPrimitiveType
|
|||
nzPrimitiveType_PointList,
|
||||
nzPrimitiveType_TriangleList,
|
||||
nzPrimitiveType_TriangleStrip,
|
||||
nzPrimitiveType_TriangleFan
|
||||
nzPrimitiveType_TriangleFan,
|
||||
|
||||
nzPrimitiveType_Max = nzPrimitiveType_TriangleFan
|
||||
};
|
||||
|
||||
enum nzWindowCursor
|
||||
|
|
@ -202,10 +230,12 @@ enum nzWindowCursor
|
|||
nzWindowCursor_ResizeSW,
|
||||
nzWindowCursor_ResizeW,
|
||||
nzWindowCursor_Text,
|
||||
nzWindowCursor_Wait
|
||||
nzWindowCursor_Wait,
|
||||
|
||||
nzWindowCursor_Max = nzWindowCursor_Wait
|
||||
};
|
||||
|
||||
enum nzWindowStyle
|
||||
enum nzWindowStyleFlags
|
||||
{
|
||||
nzWindowStyle_None = 0x0,
|
||||
nzWindowStyle_Fullscreen = 0x1,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/InputStream.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceListener.hpp>
|
||||
#include <Nazara/Core/ResourceLoader.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Utility/Animation.hpp>
|
||||
|
|
@ -34,7 +35,7 @@ using NzMeshLoader = NzResourceLoader<NzMesh, NzMeshParams>;
|
|||
|
||||
struct NzMeshImpl;
|
||||
|
||||
class NAZARA_API NzMesh : public NzResource
|
||||
class NAZARA_API NzMesh : public NzResource, NzResourceListener
|
||||
{
|
||||
friend NzMeshLoader;
|
||||
|
||||
|
|
@ -42,9 +43,9 @@ class NAZARA_API NzMesh : public NzResource
|
|||
NzMesh() = default;
|
||||
~NzMesh();
|
||||
|
||||
unsigned int AddSkin(const NzString& skin, bool setDefault = false);
|
||||
nzUInt8 AddSubMesh(NzSubMesh* subMesh);
|
||||
nzUInt8 AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
|
||||
bool AddSkin(const NzString& skin, bool setDefault = false);
|
||||
bool AddSubMesh(NzSubMesh* subMesh);
|
||||
bool AddSubMesh(const NzString& identifier, NzSubMesh* subMesh);
|
||||
|
||||
void Animate(unsigned int frameA, unsigned int frameB, float interpolation);
|
||||
|
||||
|
|
@ -58,16 +59,17 @@ class NAZARA_API NzMesh : public NzResource
|
|||
NzString GetSkin(unsigned int index = 0) const;
|
||||
unsigned int GetSkinCount() const;
|
||||
NzSubMesh* GetSubMesh(const NzString& identifier);
|
||||
NzSubMesh* GetSubMesh(nzUInt8 index);
|
||||
NzSubMesh* GetSubMesh(unsigned int index);
|
||||
const NzSubMesh* GetSubMesh(const NzString& identifier) const;
|
||||
const NzSubMesh* GetSubMesh(nzUInt8 index) const;
|
||||
nzUInt8 GetSubMeshCount() const;
|
||||
const NzSubMesh* GetSubMesh(unsigned int index) const;
|
||||
unsigned int GetSubMeshCount() const;
|
||||
int GetSubMeshIndex(const NzString& identifier) const;
|
||||
unsigned int GetVertexCount() const;
|
||||
|
||||
bool HasAnimation() const;
|
||||
bool HasSkin(unsigned int index = 0) const;
|
||||
bool HasSubMesh(const NzString& identifier) const;
|
||||
bool HasSubMesh(nzUInt8 index = 0) const;
|
||||
bool HasSubMesh(unsigned int index = 0) const;
|
||||
|
||||
void InvalidateAABB() const;
|
||||
|
||||
|
|
@ -80,11 +82,14 @@ class NAZARA_API NzMesh : public NzResource
|
|||
|
||||
void RemoveSkin(unsigned int index = 0);
|
||||
void RemoveSubMesh(const NzString& identifier);
|
||||
void RemoveSubMesh(nzUInt8 index = 0);
|
||||
void RemoveSubMesh(unsigned int index = 0);
|
||||
|
||||
bool SetAnimation(const NzAnimation* animation);
|
||||
|
||||
private:
|
||||
void OnResourceCreated(const NzResource* resource, int index) override;
|
||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||
|
||||
NzMeshImpl* m_impl = nullptr;
|
||||
|
||||
static NzMeshLoader::LoaderList s_loaders;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class NzPixelFormat
|
|||
static bool Flip(nzPixelFlipping flipping, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
|
||||
|
||||
static nzUInt8 GetBPP(nzPixelFormat format);
|
||||
static nzPixelFormatType GetType(nzPixelFormat format);
|
||||
|
||||
static bool HasAlpha(nzPixelFormat format);
|
||||
|
||||
|
|
|
|||
|
|
@ -225,16 +225,79 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
|
|||
case nzPixelFormat_RGBA8:
|
||||
return 4;
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
NazaraError("Invalid pixel format");
|
||||
case nzPixelFormat_Depth16:
|
||||
return 2;
|
||||
|
||||
case nzPixelFormat_Depth24:
|
||||
return 3;
|
||||
|
||||
case nzPixelFormat_Depth24Stencil8:
|
||||
return 4;
|
||||
|
||||
case nzPixelFormat_Depth32:
|
||||
return 4;
|
||||
|
||||
case nzPixelFormat_Stencil1:
|
||||
NazaraWarning("This format uses less than one byte per pixel");
|
||||
return 0;
|
||||
|
||||
case nzPixelFormat_Stencil4:
|
||||
NazaraWarning("This format uses less than one byte per pixel");
|
||||
return 0;
|
||||
|
||||
case nzPixelFormat_Stencil8:
|
||||
return 1;
|
||||
|
||||
case nzPixelFormat_Stencil16:
|
||||
return 2;
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraInternalError("Invalid pixel format");
|
||||
|
||||
NazaraError("Invalid pixel format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline nzPixelFormatType NzPixelFormat::GetType(nzPixelFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case nzPixelFormat_BGR8:
|
||||
case nzPixelFormat_BGRA8:
|
||||
case nzPixelFormat_DXT1:
|
||||
case nzPixelFormat_DXT3:
|
||||
case nzPixelFormat_DXT5:
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_LA8:
|
||||
case nzPixelFormat_RGB5A1:
|
||||
case nzPixelFormat_RGB8:
|
||||
case nzPixelFormat_RGBA4:
|
||||
case nzPixelFormat_RGBA8:
|
||||
return nzPixelFormatType_Color;
|
||||
|
||||
case nzPixelFormat_Depth16:
|
||||
case nzPixelFormat_Depth24:
|
||||
case nzPixelFormat_Depth32:
|
||||
return nzPixelFormatType_Depth;
|
||||
|
||||
case nzPixelFormat_Depth24Stencil8:
|
||||
return nzPixelFormatType_DepthStencil;
|
||||
|
||||
case nzPixelFormat_Stencil1:
|
||||
case nzPixelFormat_Stencil4:
|
||||
case nzPixelFormat_Stencil8:
|
||||
case nzPixelFormat_Stencil16:
|
||||
return nzPixelFormatType_Stencil;
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Invalid pixel format");
|
||||
return nzPixelFormatType_Undefined;
|
||||
}
|
||||
|
||||
inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
|
||||
{
|
||||
switch (format)
|
||||
|
|
@ -252,6 +315,14 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format)
|
|||
case nzPixelFormat_DXT1:
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_RGB8:
|
||||
case nzPixelFormat_Depth16:
|
||||
case nzPixelFormat_Depth24:
|
||||
case nzPixelFormat_Depth24Stencil8:
|
||||
case nzPixelFormat_Depth32:
|
||||
case nzPixelFormat_Stencil1:
|
||||
case nzPixelFormat_Stencil4:
|
||||
case nzPixelFormat_Stencil8:
|
||||
case nzPixelFormat_Stencil16:
|
||||
return false;
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
|
|
@ -271,9 +342,30 @@ inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
|
|||
case nzPixelFormat_DXT5:
|
||||
return true;
|
||||
|
||||
default:
|
||||
case nzPixelFormat_BGRA8:
|
||||
case nzPixelFormat_LA8:
|
||||
case nzPixelFormat_RGB5A1:
|
||||
case nzPixelFormat_RGBA4:
|
||||
case nzPixelFormat_RGBA8:
|
||||
case nzPixelFormat_BGR8:
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_RGB8:
|
||||
case nzPixelFormat_Depth16:
|
||||
case nzPixelFormat_Depth24:
|
||||
case nzPixelFormat_Depth24Stencil8:
|
||||
case nzPixelFormat_Depth32:
|
||||
case nzPixelFormat_Stencil1:
|
||||
case nzPixelFormat_Stencil4:
|
||||
case nzPixelFormat_Stencil8:
|
||||
case nzPixelFormat_Stencil16:
|
||||
return false;
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Invalid pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat)
|
||||
|
|
@ -360,6 +452,30 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format)
|
|||
case nzPixelFormat_RGBA8:
|
||||
return "RGBA8";
|
||||
|
||||
case nzPixelFormat_Depth16:
|
||||
return "Depth16";
|
||||
|
||||
case nzPixelFormat_Depth24:
|
||||
return "Depth24";
|
||||
|
||||
case nzPixelFormat_Depth24Stencil8:
|
||||
return "Depth24Stencil8";
|
||||
|
||||
case nzPixelFormat_Depth32:
|
||||
return "Depth32";
|
||||
|
||||
case nzPixelFormat_Stencil1:
|
||||
return "Stencil1";
|
||||
|
||||
case nzPixelFormat_Stencil4:
|
||||
return "Stencil4";
|
||||
|
||||
case nzPixelFormat_Stencil8:
|
||||
return "Stencil8";
|
||||
|
||||
case nzPixelFormat_Stencil16:
|
||||
return "Stencil16";
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
return "Undefined";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
#define NAZARA_STATICMESH_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/ResourceListener.hpp>
|
||||
#include <Nazara/Utility/SubMesh.hpp>
|
||||
|
||||
class NAZARA_API NzStaticMesh final : public NzSubMesh
|
||||
class NAZARA_API NzStaticMesh final : public NzSubMesh, NzResourceListener
|
||||
{
|
||||
public:
|
||||
NzStaticMesh(const NzMesh* parent);
|
||||
|
|
@ -38,6 +39,7 @@ class NAZARA_API NzStaticMesh final : public NzSubMesh
|
|||
|
||||
private:
|
||||
void AnimateImpl(unsigned int frameA, unsigned int frameB, float interpolation);
|
||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||
|
||||
nzPrimitiveType m_primitiveType = nzPrimitiveType_TriangleList;
|
||||
NzAxisAlignedBox m_aabb;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ class NAZARA_API NzVertexDeclaration : public NzResource
|
|||
NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration);
|
||||
NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept;
|
||||
|
||||
static unsigned int GetElementCount(nzElementType type);
|
||||
static unsigned int GetElementSize(nzElementType type);
|
||||
|
||||
private:
|
||||
NzVertexDeclarationImpl* m_sharedImpl = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
#include <queue>
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
#include <Nazara/Core/ConditionVariable.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/ThreadCondition.hpp>
|
||||
#endif
|
||||
|
||||
class NzCursor;
|
||||
|
|
@ -61,6 +61,7 @@ class NAZARA_API NzWindow : NzNonCopyable
|
|||
|
||||
bool IsMinimized() const;
|
||||
bool IsOpen() const;
|
||||
bool IsValid() const;
|
||||
bool IsVisible() const;
|
||||
|
||||
bool PollEvent(NzEvent* event);
|
||||
|
|
@ -85,8 +86,8 @@ class NAZARA_API NzWindow : NzNonCopyable
|
|||
bool WaitEvent(NzEvent* event);
|
||||
|
||||
protected:
|
||||
virtual void OnWindowDestroying();
|
||||
virtual bool OnWindowCreated();
|
||||
virtual void OnWindowDestroy();
|
||||
|
||||
NzWindowImpl* m_impl;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,9 +50,6 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
|
|||
{
|
||||
Destroy();
|
||||
|
||||
if (sampleCount == 0)
|
||||
return true;
|
||||
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!IsFormatSupported(format))
|
||||
{
|
||||
|
|
@ -60,6 +57,12 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sampleCount == 0)
|
||||
{
|
||||
NazaraError("Sample rate must be different from zero");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sampleRate == 0)
|
||||
{
|
||||
NazaraError("Sample rate must be different from zero");
|
||||
|
|
@ -104,6 +107,7 @@ bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsig
|
|||
m_impl->samples = new nzInt16[sampleCount];
|
||||
std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16));
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +115,8 @@ void NzSoundBuffer::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
||||
delete[] m_impl->samples;
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
/*
|
||||
#include <Nazara/Core/ByteArray.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
|
@ -61,7 +61,7 @@ m_sharedArray(buffer.m_sharedArray)
|
|||
}
|
||||
}
|
||||
|
||||
NzByteArray::NzByteArray(NzByteArray&& buffer) :
|
||||
NzByteArray::NzByteArray(NzByteArray&& buffer) noexcept :
|
||||
m_sharedArray(buffer.m_sharedArray)
|
||||
{
|
||||
buffer.m_sharedArray = &emptyArray;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
|
|
@ -73,7 +73,14 @@ void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file,
|
|||
|
||||
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
|
||||
if (!ptr)
|
||||
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
|
||||
{
|
||||
// Pas d'information de temps (Car nécessitant une allocation)
|
||||
FILE* log = std::fopen(MLTFileName, "a");
|
||||
std::fprintf(log, "Failed to allocate memory (%d bytes)\n", size);
|
||||
std::fclose(log);
|
||||
|
||||
return nullptr; // Impossible d'envoyer une exception car cela allouerait de la mémoire avec new (boucle infinie)
|
||||
}
|
||||
|
||||
ptr->array = multi;
|
||||
ptr->file = file;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/ResourceListener.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzResource::NzResource(bool persistent) :
|
||||
|
|
@ -19,20 +20,57 @@ m_resourceReferenceCount(0)
|
|||
{
|
||||
}
|
||||
|
||||
NzResource::~NzResource() = default;
|
||||
NzResource::~NzResource()
|
||||
{
|
||||
EnsureResourceListenerUpdate();
|
||||
|
||||
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
|
||||
(*it).listener->OnResourceReleased(this, (*it).index);
|
||||
}
|
||||
|
||||
void NzResource::AddResourceListener(NzResourceListener* listener, int index) const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_resourceListeners.insert(NzResourceEntry(listener, index)).second)
|
||||
{
|
||||
m_resourceListenerUpdated = false;
|
||||
|
||||
// AddResourceReference()
|
||||
m_resourceReferenceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void NzResource::AddResourceReference() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_resourceReferenceCount++;
|
||||
}
|
||||
|
||||
bool NzResource::IsPersistent() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_resourcePersistent;
|
||||
}
|
||||
|
||||
void NzResource::RemoveResourceListener(NzResourceListener* listener) const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_resourceListeners.erase(listener) != 0)
|
||||
m_resourceListenerUpdated = false;
|
||||
else
|
||||
NazaraError(NzString::Pointer(listener) + " is not listening to " + NzString::Pointer(this));
|
||||
|
||||
RemoveResourceReference();
|
||||
}
|
||||
|
||||
void NzResource::RemoveResourceReference() const
|
||||
{
|
||||
NazaraMutexLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_resourceReferenceCount == 0)
|
||||
{
|
||||
|
|
@ -42,13 +80,59 @@ void NzResource::RemoveResourceReference() const
|
|||
#endif
|
||||
|
||||
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent)
|
||||
{
|
||||
NazaraMutexUnlock(m_mutex);
|
||||
delete this;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraMutexUnlock(m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void NzResource::SetPersistent(bool persistent)
|
||||
{
|
||||
NazaraMutexLock(m_mutex);
|
||||
|
||||
m_resourcePersistent = persistent;
|
||||
|
||||
if (!persistent && m_resourceReferenceCount == 0)
|
||||
{
|
||||
NazaraMutexUnlock(m_mutex);
|
||||
delete this;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraMutexUnlock(m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void NzResource::NotifyCreated()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
EnsureResourceListenerUpdate();
|
||||
|
||||
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
|
||||
(*it).listener->OnResourceCreated(this, (*it).index);
|
||||
}
|
||||
|
||||
void NzResource::NotifyDestroy()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
EnsureResourceListenerUpdate();
|
||||
|
||||
for (auto it = m_resourceListenersCache.begin(); it != m_resourceListenersCache.end(); ++it)
|
||||
(*it).listener->OnResourceDestroy(this, (*it).index);
|
||||
}
|
||||
|
||||
void NzResource::EnsureResourceListenerUpdate() const
|
||||
{
|
||||
// Déjà bloqué par une mutex
|
||||
if (!m_resourceListenerUpdated)
|
||||
{
|
||||
m_resourceListenersCache = m_resourceListeners;
|
||||
m_resourceListenerUpdated = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <cstdio>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <Utfcpp/utf8.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
|
@ -108,7 +109,7 @@ NzString::NzString(const char* string)
|
|||
m_sharedString->capacity = size;
|
||||
m_sharedString->size = size;
|
||||
m_sharedString->string = new char[size+1];
|
||||
std::strcpy(m_sharedString->string, string);
|
||||
std::memcpy(m_sharedString->string, string, size+1);
|
||||
}
|
||||
else
|
||||
m_sharedString = &emptyString;
|
||||
|
|
@ -125,7 +126,7 @@ NzString::NzString(const std::string& string)
|
|||
m_sharedString->capacity = string.capacity();
|
||||
m_sharedString->size = string.size();
|
||||
m_sharedString->string = new char[string.capacity()+1];
|
||||
std::strcpy(m_sharedString->string, string.c_str());
|
||||
std::memcpy(m_sharedString->string, string.c_str(), string.size()+1);
|
||||
}
|
||||
else
|
||||
m_sharedString = &emptyString;
|
||||
|
|
@ -180,7 +181,7 @@ NzString& NzString::Append(char character)
|
|||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
str[m_sharedString->size] = character;
|
||||
str[newSize] = '\0';
|
||||
|
||||
|
|
@ -207,7 +208,7 @@ NzString& NzString::Append(const char* string)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::strcpy(&m_sharedString->string[m_sharedString->size], string);
|
||||
std::memcpy(&m_sharedString->string[m_sharedString->size], string, length+1);
|
||||
m_sharedString->size += length;
|
||||
}
|
||||
else
|
||||
|
|
@ -216,8 +217,8 @@ NzString& NzString::Append(const char* string)
|
|||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string);
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string, length+1);
|
||||
|
||||
ReleaseString();
|
||||
m_sharedString = new SharedString;
|
||||
|
|
@ -241,7 +242,7 @@ NzString& NzString::Append(const NzString& string)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::strcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string);
|
||||
std::memcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
m_sharedString->size += string.m_sharedString->size;
|
||||
}
|
||||
else
|
||||
|
|
@ -250,8 +251,8 @@ NzString& NzString::Append(const NzString& string)
|
|||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
|
||||
ReleaseString();
|
||||
m_sharedString = new SharedString;
|
||||
|
|
@ -2270,7 +2271,7 @@ char* NzString::GetUtf8Buffer(unsigned int* size) const
|
|||
return nullptr;
|
||||
|
||||
char* buffer = new char[m_sharedString->size+1];
|
||||
std::strcpy(buffer, m_sharedString->string);
|
||||
std::memcpy(buffer, m_sharedString->string, m_sharedString->size+1);
|
||||
|
||||
if (size)
|
||||
*size = m_sharedString->size;
|
||||
|
|
@ -2372,7 +2373,7 @@ wchar_t* NzString::GetWideBuffer(unsigned int* size) const
|
|||
if (cp <= 0xFFFF && (cp < 0xD800 || cp > 0xDFFF)) // @Laurent Gomila
|
||||
*ptr++ = static_cast<wchar_t>(cp);
|
||||
else
|
||||
*ptr++ = static_cast<wchar_t>('?');
|
||||
*ptr++ = L'?';
|
||||
}
|
||||
while (*it++);
|
||||
}
|
||||
|
|
@ -2480,7 +2481,7 @@ NzString& NzString::Insert(int pos, char character)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::memmove(&m_sharedString->string[start+1], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
|
||||
std::memmove(&m_sharedString->string[start+1], &m_sharedString->string[start], m_sharedString->size);
|
||||
m_sharedString->string[start] = character;
|
||||
|
||||
m_sharedString->size += 1;
|
||||
|
|
@ -2526,8 +2527,8 @@ NzString& NzString::Insert(int pos, const char* string)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::memmove(&m_sharedString->string[start+len], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
|
||||
std::memcpy(&m_sharedString->string[start], string, len*sizeof(char));
|
||||
std::memmove(&m_sharedString->string[start+len], &m_sharedString->string[start], m_sharedString->size);
|
||||
std::memcpy(&m_sharedString->string[start], string, len+1);
|
||||
|
||||
m_sharedString->size += len;
|
||||
}
|
||||
|
|
@ -2576,8 +2577,8 @@ NzString& NzString::Insert(int pos, const NzString& string)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::memmove(&m_sharedString->string[start+string.m_sharedString->size], &m_sharedString->string[start], m_sharedString->size*sizeof(char));
|
||||
std::memcpy(&m_sharedString->string[start], string.m_sharedString->string, string.m_sharedString->size*sizeof(char));
|
||||
std::memmove(&m_sharedString->string[start+string.m_sharedString->size], &m_sharedString->string[start], m_sharedString->size);
|
||||
std::memcpy(&m_sharedString->string[start], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
|
||||
m_sharedString->size += string.m_sharedString->size;
|
||||
}
|
||||
|
|
@ -2837,7 +2838,7 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
|
|||
found = true;
|
||||
}
|
||||
|
||||
std::memcpy(&m_sharedString->string[pos], replaceString, oSize*sizeof(char));
|
||||
std::memcpy(&m_sharedString->string[pos], replaceString, oSize);
|
||||
pos += oSize;
|
||||
|
||||
++count;
|
||||
|
|
@ -2859,9 +2860,9 @@ unsigned int NzString::Replace(const char* oldString, const char* replaceString,
|
|||
{
|
||||
const char* r = &m_sharedString->string[pos];
|
||||
|
||||
std::memcpy(ptr, p, (r-p)*sizeof(char));
|
||||
std::memcpy(ptr, p, r-p);
|
||||
ptr += r-p;
|
||||
std::memcpy(ptr, replaceString, rSize*sizeof(char));
|
||||
std::memcpy(ptr, replaceString, rSize);
|
||||
ptr += rSize;
|
||||
p = r+oSize;
|
||||
pos += oSize;
|
||||
|
|
@ -2907,7 +2908,7 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
|
|||
found = true;
|
||||
}
|
||||
|
||||
std::memcpy(&m_sharedString->string[pos], replaceString.m_sharedString->string, oldString.m_sharedString->size*sizeof(char));
|
||||
std::memcpy(&m_sharedString->string[pos], replaceString.m_sharedString->string, oldString.m_sharedString->size);
|
||||
pos += oldString.m_sharedString->size;
|
||||
|
||||
++count;
|
||||
|
|
@ -2929,9 +2930,9 @@ unsigned int NzString::Replace(const NzString& oldString, const NzString& replac
|
|||
{
|
||||
const char* r = &m_sharedString->string[pos];
|
||||
|
||||
std::memcpy(ptr, p, (r-p)*sizeof(char));
|
||||
std::memcpy(ptr, p, r-p);
|
||||
ptr += r-p;
|
||||
std::memcpy(ptr, replaceString.m_sharedString->string, replaceString.m_sharedString->size*sizeof(char));
|
||||
std::memcpy(ptr, replaceString.m_sharedString->string, replaceString.m_sharedString->size);
|
||||
ptr += replaceString.m_sharedString->size;
|
||||
p = r+oldString.m_sharedString->size;
|
||||
pos += oldString.m_sharedString->size;
|
||||
|
|
@ -3189,7 +3190,7 @@ void NzString::Reserve(unsigned int bufferSize)
|
|||
|
||||
char* ptr = new char[bufferSize+1];
|
||||
if (m_sharedString->size > 0)
|
||||
std::strcpy(ptr, m_sharedString->string);
|
||||
std::memcpy(ptr, m_sharedString->string, m_sharedString->size+1);
|
||||
|
||||
unsigned int size = m_sharedString->size;
|
||||
|
||||
|
|
@ -3233,7 +3234,7 @@ NzString& NzString::Resize(int size, char character)
|
|||
{
|
||||
char* newString = new char[newSize+1];
|
||||
if (m_sharedString->size != 0)
|
||||
std::memcpy(newString, m_sharedString->string, newSize*sizeof(char));
|
||||
std::memcpy(newString, m_sharedString->string, newSize);
|
||||
|
||||
char* ptr = &newString[m_sharedString->size];
|
||||
char* limit = &newString[newSize];
|
||||
|
|
@ -3673,7 +3674,7 @@ bool NzString::StartsWith(const NzString& string, nzUInt32 flags) const
|
|||
}
|
||||
}
|
||||
else
|
||||
return std::memcmp(m_sharedString->string, string.m_sharedString->string, string.m_sharedString->size*sizeof(char)) == 0;
|
||||
return std::memcmp(m_sharedString->string, string.m_sharedString->string, string.m_sharedString->size) == 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3699,7 +3700,7 @@ NzString NzString::Substr(int startPos, int endPos) const
|
|||
|
||||
unsigned int size = minEnd-start+1;
|
||||
char* str = new char[size+1];
|
||||
std::memcpy(str, &m_sharedString->string[start], size*sizeof(char));
|
||||
std::memcpy(str, &m_sharedString->string[start], size);
|
||||
str[size] = '\0';
|
||||
|
||||
return NzString(new SharedString(1, size, size, str));
|
||||
|
|
@ -4185,7 +4186,7 @@ NzString& NzString::operator=(const char* string)
|
|||
}
|
||||
|
||||
m_sharedString->size = size;
|
||||
std::strcpy(m_sharedString->string, string);
|
||||
std::memcpy(m_sharedString->string, string, size+1);
|
||||
}
|
||||
else
|
||||
ReleaseString();
|
||||
|
|
@ -4209,7 +4210,7 @@ NzString& NzString::operator=(const std::string& string)
|
|||
}
|
||||
|
||||
m_sharedString->size = string.size();
|
||||
std::strcpy(m_sharedString->string, string.c_str());
|
||||
std::memcpy(m_sharedString->string, string.c_str(), string.size()+1);
|
||||
}
|
||||
else
|
||||
ReleaseString();
|
||||
|
|
@ -4246,7 +4247,7 @@ NzString NzString::operator+(char character) const
|
|||
|
||||
unsigned int totalSize = m_sharedString->size+1;
|
||||
char* str = new char[totalSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
|
||||
str[m_sharedString->size] = character;
|
||||
str[totalSize] = '\0';
|
||||
|
|
@ -4268,8 +4269,8 @@ NzString NzString::operator+(const char* string) const
|
|||
|
||||
unsigned int totalSize = m_sharedString->size + length;
|
||||
char* str = new char[totalSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string);
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string, length+1);
|
||||
|
||||
return NzString(new SharedString(1, totalSize, totalSize, str));
|
||||
}
|
||||
|
|
@ -4284,8 +4285,8 @@ NzString NzString::operator+(const std::string& string) const
|
|||
|
||||
unsigned int totalSize = m_sharedString->size + string.size();
|
||||
char* str = new char[totalSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string.c_str());
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string.c_str(), string.size()+1);
|
||||
|
||||
return NzString(new SharedString(1, totalSize, totalSize, str));
|
||||
}
|
||||
|
|
@ -4300,8 +4301,8 @@ NzString NzString::operator+(const NzString& string) const
|
|||
|
||||
unsigned int totalSize = m_sharedString->size + string.m_sharedString->size;
|
||||
char* str = new char[totalSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
|
||||
return NzString(new SharedString(1, totalSize, totalSize, str));
|
||||
}
|
||||
|
|
@ -4328,7 +4329,7 @@ NzString& NzString::operator+=(char character)
|
|||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
str[m_sharedString->size] = character;
|
||||
str[newSize] = '\0';
|
||||
|
||||
|
|
@ -4350,25 +4351,25 @@ NzString& NzString::operator+=(const char* string)
|
|||
if (m_sharedString->size == 0)
|
||||
return operator=(string);
|
||||
|
||||
unsigned int length = std::strlen(string);
|
||||
if (length == 0)
|
||||
unsigned int size = std::strlen(string);
|
||||
if (size == 0)
|
||||
return *this;
|
||||
|
||||
if (m_sharedString->capacity >= m_sharedString->size + length)
|
||||
if (m_sharedString->capacity >= m_sharedString->size + size)
|
||||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::strcpy(&m_sharedString->string[m_sharedString->size], string);
|
||||
m_sharedString->size += length;
|
||||
std::memcpy(&m_sharedString->string[m_sharedString->size], string, size+1);
|
||||
m_sharedString->size += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int newSize = m_sharedString->size + length;
|
||||
unsigned int newSize = m_sharedString->size + size;
|
||||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string);
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string, size+1);
|
||||
|
||||
ReleaseString();
|
||||
m_sharedString = new SharedString;
|
||||
|
|
@ -4392,7 +4393,7 @@ NzString& NzString::operator+=(const std::string& string)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::strcpy(&m_sharedString->string[m_sharedString->size], string.c_str());
|
||||
std::memcpy(&m_sharedString->string[m_sharedString->size], string.c_str(), string.size()+1);
|
||||
m_sharedString->size += string.size();
|
||||
}
|
||||
else
|
||||
|
|
@ -4401,8 +4402,8 @@ NzString& NzString::operator+=(const std::string& string)
|
|||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string.c_str());
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string.c_str(), string.size()+1);
|
||||
|
||||
ReleaseString();
|
||||
m_sharedString = new SharedString;
|
||||
|
|
@ -4426,7 +4427,7 @@ NzString& NzString::operator+=(const NzString& string)
|
|||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::strcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string);
|
||||
std::memcpy(&m_sharedString->string[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
m_sharedString->size += string.m_sharedString->size;
|
||||
}
|
||||
else
|
||||
|
|
@ -4435,8 +4436,8 @@ NzString& NzString::operator+=(const NzString& string)
|
|||
unsigned int bufferSize = nzGetNewSize(newSize);
|
||||
|
||||
char* str = new char[bufferSize+1];
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size*sizeof(char));
|
||||
std::strcpy(&str[m_sharedString->size], string.m_sharedString->string);
|
||||
std::memcpy(str, m_sharedString->string, m_sharedString->size);
|
||||
std::memcpy(&str[m_sharedString->size], string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
|
||||
ReleaseString();
|
||||
m_sharedString = new SharedString;
|
||||
|
|
@ -4902,7 +4903,7 @@ NzString operator+(char character, const NzString& string)
|
|||
unsigned int totalSize = string.m_sharedString->size+1;
|
||||
char* str = new char[totalSize+1];
|
||||
str[0] = character;
|
||||
std::strcpy(str, string.m_sharedString->string);
|
||||
std::memcpy(str, string.m_sharedString->string, string.m_sharedString->size+1);
|
||||
|
||||
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
|
||||
}
|
||||
|
|
@ -4918,8 +4919,8 @@ NzString operator+(const char* string, const NzString& nstring)
|
|||
unsigned int size = std::strlen(string);
|
||||
unsigned int totalSize = size + nstring.m_sharedString->size;
|
||||
char* str = new char[totalSize+1];
|
||||
std::memcpy(str, string, size*sizeof(char));
|
||||
std::strcpy(&str[size], nstring.m_sharedString->string);
|
||||
std::memcpy(str, string, size);
|
||||
std::memcpy(&str[size], nstring.m_sharedString->string, nstring.m_sharedString->size+1);
|
||||
|
||||
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
|
||||
}
|
||||
|
|
@ -4934,8 +4935,8 @@ NzString operator+(const std::string& string, const NzString& nstring)
|
|||
|
||||
unsigned int totalSize = string.size() + nstring.m_sharedString->size;
|
||||
char* str = new char[totalSize+1];
|
||||
std::memcpy(str, string.c_str(), string.size()*sizeof(char));
|
||||
std::strcpy(&str[string.size()], nstring.m_sharedString->string);
|
||||
std::memcpy(str, string.c_str(), string.size());
|
||||
std::memcpy(&str[string.size()], nstring.m_sharedString->string, nstring.m_sharedString->size+1);
|
||||
|
||||
return NzString(new NzString::SharedString(1, totalSize, totalSize, str));
|
||||
}
|
||||
|
|
@ -5083,7 +5084,7 @@ void NzString::EnsureOwnership()
|
|||
m_sharedString->refCount--;
|
||||
|
||||
char* string = new char[m_sharedString->capacity+1];
|
||||
std::strcpy(string, m_sharedString->string);
|
||||
std::memcpy(string, m_sharedString->string, m_sharedString->size+1);
|
||||
|
||||
m_sharedString = new SharedString(1, m_sharedString->capacity, m_sharedString->size, string);
|
||||
}
|
||||
|
|
@ -5115,7 +5116,7 @@ void NzString::ReleaseString()
|
|||
}
|
||||
|
||||
NzString::SharedString NzString::emptyString(0, 0, 0, nullptr);
|
||||
unsigned int NzString::npos(static_cast<unsigned int>(-1));
|
||||
const unsigned int NzString::npos(std::numeric_limits<unsigned int>::max());
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
|
|
|||
|
|
@ -172,15 +172,17 @@ bool NzContext::Create(const NzContextParameters& parameters)
|
|||
if (m_parameters.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
if (NzOpenGL::IsSupported(NzOpenGL::DebugOutput) && m_parameters.debugMode)
|
||||
if (NzOpenGL::IsSupported(nzOpenGLExtension_DebugOutput) && m_parameters.debugMode)
|
||||
{
|
||||
glDebugMessageCallback(&DebugCallback, this);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
#endif
|
||||
}
|
||||
|
||||
NotifyCreated();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +190,8 @@ void NzContext::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
||||
if (currentContext == this)
|
||||
NzContextImpl::Desactivate();
|
||||
|
||||
|
|
|
|||
|
|
@ -14,22 +14,6 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
///FIXME: Déclaré deux fois (ici et dans Renderer.cpp)
|
||||
const nzUInt8 attribIndex[] =
|
||||
{
|
||||
2, // nzElementUsage_Diffuse
|
||||
1, // nzElementUsage_Normal
|
||||
0, // nzElementUsage_Position
|
||||
3, // nzElementUsage_Tangent
|
||||
4 // nzElementUsage_TexCoord
|
||||
};
|
||||
|
||||
const GLenum shaderType[nzShaderType_Max+1] = {
|
||||
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
|
||||
GL_GEOMETRY_SHADER, // nzShaderType_Geometry
|
||||
GL_VERTEX_SHADER // nzShaderType_Vertex
|
||||
};
|
||||
|
||||
GLuint lockedPrevious = 0;
|
||||
nzUInt8 lockedLevel = 0;
|
||||
}
|
||||
|
|
@ -41,6 +25,8 @@ m_parent(parent)
|
|||
|
||||
NzGLSLShader::~NzGLSLShader()
|
||||
{
|
||||
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
|
||||
it->second.texture->RemoveResourceListener(this);
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Bind()
|
||||
|
|
@ -71,11 +57,11 @@ bool NzGLSLShader::BindTextures()
|
|||
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
|
||||
{
|
||||
TextureSlot& slot = it->second;
|
||||
if (!slot.updated)
|
||||
if (slot.enabled && !slot.updated)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + slot.unit);
|
||||
if (!slot.texture->Bind())
|
||||
NazaraWarning("Failed to bind texture");
|
||||
if (!slot.texture->Prepare())
|
||||
NazaraWarning("Failed to prepare texture");
|
||||
|
||||
slot.updated = true;
|
||||
}
|
||||
|
|
@ -137,17 +123,35 @@ bool NzGLSLShader::Create()
|
|||
return false;
|
||||
}
|
||||
|
||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Position], "Position");
|
||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Normal], "Normal");
|
||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
|
||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
|
||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Position], "Position");
|
||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Normal], "Normal");
|
||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Diffuse], "Diffuse");
|
||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Tangent], "Tangent");
|
||||
|
||||
NzString uniform = "TexCoord";
|
||||
unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
|
||||
NzString uniform;
|
||||
|
||||
static const unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
|
||||
|
||||
uniform.Reserve(10); // 8 + 2
|
||||
uniform = "TexCoord";
|
||||
for (unsigned int i = 0; i < maxTexCoords; ++i)
|
||||
{
|
||||
NzString uniformName = uniform + NzString::Number(i);
|
||||
glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
|
||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
|
||||
}
|
||||
|
||||
static const bool mrtSupported = NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets);
|
||||
if (mrtSupported)
|
||||
{
|
||||
static const unsigned int maxRenderTargets = NzRenderer::GetMaxRenderTargets();
|
||||
|
||||
uniform.Reserve(14); // 12 + 2
|
||||
uniform = "RenderTarget";
|
||||
for (unsigned int i = 0; i < maxRenderTargets; ++i)
|
||||
{
|
||||
NzString uniformName = uniform + NzString::Number(i);
|
||||
glBindFragDataLocation(m_program, i, uniformName.GetConstBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i <= nzShaderType_Max; ++i)
|
||||
|
|
@ -224,7 +228,7 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source)
|
|||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
GLuint shader = glCreateShader(shaderType[type]);
|
||||
GLuint shader = glCreateShader(NzOpenGL::ShaderType[type]);
|
||||
if (!shader)
|
||||
{
|
||||
m_log = "Failed to create shader object";
|
||||
|
|
@ -301,7 +305,12 @@ bool NzGLSLShader::SendBoolean(int location, bool value)
|
|||
glProgramUniform1i(m_program, location, value);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform1i(location, value);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -315,7 +324,12 @@ bool NzGLSLShader::SendDouble(int location, double value)
|
|||
glProgramUniform1d(m_program, location, value);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform1d(location, value);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -329,7 +343,12 @@ bool NzGLSLShader::SendFloat(int location, float value)
|
|||
glProgramUniform1f(m_program, location, value);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform1f(location, value);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -343,7 +362,12 @@ bool NzGLSLShader::SendInteger(int location, int value)
|
|||
glProgramUniform1i(m_program, location, value);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform1i(location, value);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -357,7 +381,12 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4d& matrix)
|
|||
glProgramUniformMatrix4dv(m_program, location, 1, GL_FALSE, matrix);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniformMatrix4dv(location, 1, GL_FALSE, matrix);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -371,7 +400,12 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4f& matrix)
|
|||
glProgramUniformMatrix4fv(m_program, location, 1, GL_FALSE, matrix);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniformMatrix4fv(location, 1, GL_FALSE, matrix);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -388,12 +422,12 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture)
|
|||
TextureSlot& slot = it->second;
|
||||
if (slot.texture != texture)
|
||||
{
|
||||
slot.texture->RemoveResourceReference();
|
||||
slot.texture->RemoveResourceListener(this);
|
||||
|
||||
if (texture)
|
||||
{
|
||||
slot.texture = texture;
|
||||
slot.texture->AddResourceReference();
|
||||
slot.texture->AddResourceListener(this, location);
|
||||
|
||||
slot.updated = false;
|
||||
}
|
||||
|
|
@ -439,19 +473,28 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture)
|
|||
}
|
||||
|
||||
TextureSlot slot;
|
||||
slot.enabled = texture->IsValid();
|
||||
slot.unit = unit;
|
||||
slot.texture = texture;
|
||||
texture->AddResourceReference();
|
||||
texture->AddResourceListener(this, location);
|
||||
|
||||
m_textures[location] = slot;
|
||||
|
||||
if (glProgramUniform1i)
|
||||
glProgramUniform1i(m_program, location, unit);
|
||||
else
|
||||
if (slot.enabled)
|
||||
{
|
||||
Lock();
|
||||
glUniform1i(location, unit);
|
||||
Unlock();
|
||||
if (glProgramUniform1i)
|
||||
glProgramUniform1i(m_program, location, unit);
|
||||
else
|
||||
{
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform1i(location, unit);
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +507,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector2d& vector)
|
|||
glProgramUniform2dv(m_program, location, 1, vector);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform2dv(location, 1, vector);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -478,7 +526,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector2f& vector)
|
|||
glProgramUniform2fv(m_program, location, 1, vector);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform2fv(location, 1, vector);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -492,7 +545,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector3d& vector)
|
|||
glProgramUniform3dv(m_program, location, 1, vector);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform3dv(location, 1, vector);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -506,7 +564,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector3f& vector)
|
|||
glProgramUniform3fv(m_program, location, 1, vector);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform3fv(location, 1, vector);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -520,7 +583,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector4d& vector)
|
|||
glProgramUniform4dv(m_program, location, 1, vector);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform4dv(location, 1, vector);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -534,7 +602,12 @@ bool NzGLSLShader::SendVector(int location, const NzVector4f& vector)
|
|||
glProgramUniform4fv(m_program, location, 1, vector);
|
||||
else
|
||||
{
|
||||
Lock();
|
||||
if (!Lock())
|
||||
{
|
||||
NazaraError("Failed to lock shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
glUniform4fv(location, 1, vector);
|
||||
Unlock();
|
||||
}
|
||||
|
|
@ -576,3 +649,64 @@ void NzGLSLShader::Unlock()
|
|||
if (--lockedLevel == 0 && lockedPrevious != m_program)
|
||||
glUseProgram(lockedPrevious);
|
||||
}
|
||||
|
||||
void NzGLSLShader::OnResourceCreated(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(resource);
|
||||
|
||||
auto it = m_textures.find(index);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (it == m_textures.end())
|
||||
{
|
||||
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
TextureSlot& slot = it->second;
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (slot.texture != resource)
|
||||
{
|
||||
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
slot.enabled = true;
|
||||
slot.updated = false;
|
||||
}
|
||||
|
||||
void NzGLSLShader::OnResourceDestroy(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(resource);
|
||||
|
||||
auto it = m_textures.find(index);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (it == m_textures.end())
|
||||
{
|
||||
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
TextureSlot& slot = it->second;
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (slot.texture != resource)
|
||||
{
|
||||
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
slot.enabled = false;
|
||||
}
|
||||
|
||||
void NzGLSLShader::OnResourceReleased(const NzResource* resource, int index)
|
||||
{
|
||||
if (m_textures.erase(index) == 0)
|
||||
NazaraInternalError("Texture " + NzString::Pointer(resource) + " not found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,16 @@
|
|||
#ifndef NAZARA_GLSLSHADER_HPP
|
||||
#define NAZARA_GLSLSHADER_HPP
|
||||
|
||||
#include <Nazara/Core/ResourceListener.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <map>
|
||||
|
||||
class NzGLSLShader : public NzShaderImpl
|
||||
class NzResource;
|
||||
|
||||
class NzGLSLShader : public NzShaderImpl, NzResourceListener
|
||||
{
|
||||
public:
|
||||
NzGLSLShader(NzShader* parent);
|
||||
|
|
@ -55,8 +58,13 @@ class NzGLSLShader : public NzShaderImpl
|
|||
void Unlock();
|
||||
|
||||
private:
|
||||
void OnResourceCreated(const NzResource* resource, int index) override;
|
||||
void OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||
|
||||
struct TextureSlot
|
||||
{
|
||||
bool enabled;
|
||||
bool updated = false;
|
||||
nzUInt8 unit;
|
||||
const NzTexture* texture;
|
||||
|
|
|
|||
|
|
@ -12,38 +12,6 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
GLenum bufferLock[] = {
|
||||
GL_WRITE_ONLY, // nzBufferAccess_DiscardAndWrite
|
||||
GL_READ_ONLY, // nzBufferAccess_ReadOnly
|
||||
GL_READ_WRITE, // nzBufferAccess_ReadWrite
|
||||
GL_WRITE_ONLY // nzBufferAccess_WriteOnly
|
||||
};
|
||||
|
||||
GLenum bufferLockRange[] = {
|
||||
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_DiscardAndWrite
|
||||
GL_MAP_READ_BIT, // nzBufferAccess_ReadOnly
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_ReadWrite
|
||||
GL_MAP_WRITE_BIT // nzBufferAccess_WriteOnly
|
||||
};
|
||||
|
||||
GLenum bufferTarget[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
|
||||
GL_ARRAY_BUFFER, // nzBufferType_Vertex
|
||||
};
|
||||
|
||||
GLenum bufferTargetBinding[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER_BINDING, // nzBufferType_Index,
|
||||
GL_ARRAY_BUFFER_BINDING, // nzBufferType_Vertex
|
||||
};
|
||||
|
||||
GLenum bufferUsage[] = {
|
||||
// J'ai choisi DYNAMIC à la place de STREAM car DYNAMIC semble plus adapté au profil "une mise à jour pour quelques rendus"
|
||||
// Ce qui est je pense le scénario qui arrivera le plus souvent (Prévoir une option pour permettre d'utiliser le STREAM_DRAW ?)
|
||||
// Source: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=160839
|
||||
GL_DYNAMIC_DRAW, // nzBufferUsage_Dynamic
|
||||
GL_STATIC_DRAW // nzBufferUsage_Static
|
||||
};
|
||||
|
||||
using LockRoutine = nzUInt8* (*)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
|
||||
|
||||
nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
|
||||
|
|
@ -53,16 +21,16 @@ namespace
|
|||
if (access == nzBufferAccess_DiscardAndWrite)
|
||||
{
|
||||
GLint bufSize;
|
||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
|
||||
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_SIZE, &bufSize);
|
||||
|
||||
GLint bufUsage;
|
||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
|
||||
glGetBufferParameteriv(NzOpenGL::BufferTargetBinding[type], GL_BUFFER_USAGE, &bufUsage);
|
||||
|
||||
// On discard le buffer
|
||||
glBufferData(bufferTargetBinding[type], bufSize, nullptr, bufUsage);
|
||||
glBufferData(NzOpenGL::BufferTargetBinding[type], bufSize, nullptr, bufUsage);
|
||||
}
|
||||
|
||||
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]);
|
||||
void* ptr = glMapBuffer(NzOpenGL::BufferTarget[type], NzOpenGL::BufferLock[access]);
|
||||
if (ptr)
|
||||
return reinterpret_cast<nzUInt8*>(ptr) + offset;
|
||||
else
|
||||
|
|
@ -71,7 +39,7 @@ namespace
|
|||
|
||||
nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size)
|
||||
{
|
||||
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[access]));
|
||||
return reinterpret_cast<nzUInt8*>(glMapBufferRange(NzOpenGL::BufferTarget[type], offset, size, NzOpenGL::BufferLockRange[access]));
|
||||
}
|
||||
|
||||
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size);
|
||||
|
|
@ -109,7 +77,7 @@ void NzHardwareBuffer::Bind()
|
|||
}
|
||||
#endif
|
||||
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
|
||||
|
|
@ -120,14 +88,14 @@ bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
|
|||
glGenBuffers(1, &m_buffer);
|
||||
|
||||
GLint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], &previous);
|
||||
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], &previous);
|
||||
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], size, nullptr, NzOpenGL::BufferUsage[usage]);
|
||||
|
||||
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||
if (previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -144,10 +112,10 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
|
|||
NzContext::EnsureContext();
|
||||
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||
|
||||
// Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
|
||||
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
|
||||
|
|
@ -155,9 +123,9 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
|
|||
{
|
||||
// http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
|
||||
if (size == m_parent->GetSize())
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
|
||||
|
||||
glBufferSubData(bufferTarget[m_type], offset, size, data);
|
||||
glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -170,12 +138,12 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
|
|||
|
||||
std::memcpy(ptr, data, size);
|
||||
|
||||
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
|
||||
if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -183,7 +151,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
|
|||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -204,16 +172,16 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned
|
|||
|
||||
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||
|
||||
void* ptr = mapBuffer(m_type, access, offset, size);
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
|
@ -223,28 +191,28 @@ bool NzHardwareBuffer::Unmap()
|
|||
NzContext::EnsureContext();
|
||||
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer);
|
||||
|
||||
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
|
||||
if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]);
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,21 +14,17 @@
|
|||
NzOcclusionQuery::NzOcclusionQuery() :
|
||||
m_id(0)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (IsSupported())
|
||||
{
|
||||
#endif
|
||||
NzContext::EnsureContext();
|
||||
|
||||
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Occlusion queries not supported");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_id)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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()
|
||||
{
|
||||
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
|
||||
OnWindowDestroying();
|
||||
OnWindowDestroy();
|
||||
}
|
||||
|
||||
bool NzRenderWindow::CopyToImage(NzImage* image)
|
||||
|
|
@ -178,17 +178,6 @@ void NzRenderWindow::EnableVerticalSync(bool enabled)
|
|||
NazaraError("No context");
|
||||
}
|
||||
|
||||
NzContextParameters NzRenderWindow::GetContextParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
return m_context->GetParameters();
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return NzContextParameters();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int NzRenderWindow::GetHeight() const
|
||||
{
|
||||
return NzWindow::GetHeight();
|
||||
|
|
@ -213,14 +202,9 @@ unsigned int NzRenderWindow::GetWidth() const
|
|||
return NzWindow::GetWidth();
|
||||
}
|
||||
|
||||
bool NzRenderWindow::HasContext() const
|
||||
bool NzRenderWindow::IsRenderable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::IsValid() const
|
||||
{
|
||||
return m_impl != nullptr && m_context != nullptr;
|
||||
return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
|
||||
}
|
||||
|
||||
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
|
||||
|
|
@ -228,6 +212,22 @@ void NzRenderWindow::SetFramerateLimit(unsigned int limit)
|
|||
m_framerateLimit = limit;
|
||||
}
|
||||
|
||||
NzContextParameters NzRenderWindow::GetContextParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
return m_context->GetParameters();
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return NzContextParameters();
|
||||
}
|
||||
}
|
||||
|
||||
bool NzRenderWindow::HasContext() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::Activate()
|
||||
{
|
||||
if (m_context->SetActive(true))
|
||||
|
|
@ -242,15 +242,6 @@ bool NzRenderWindow::Activate()
|
|||
}
|
||||
}
|
||||
|
||||
void NzRenderWindow::OnWindowDestroying()
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
delete m_context;
|
||||
m_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzRenderWindow::OnWindowCreated()
|
||||
{
|
||||
m_parameters.doubleBuffered = true;
|
||||
|
|
@ -267,12 +258,19 @@ bool NzRenderWindow::OnWindowCreated()
|
|||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION
|
||||
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
||||
NazaraWarning("Failed to activate window");
|
||||
#endif
|
||||
|
||||
m_clock.Restart();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderWindow::OnWindowDestroy()
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
delete m_context;
|
||||
m_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,114 +24,6 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
const nzUInt8 attribIndex[] =
|
||||
{
|
||||
2, // nzElementUsage_Diffuse
|
||||
1, // nzElementUsage_Normal
|
||||
0, // nzElementUsage_Position
|
||||
3, // nzElementUsage_Tangent
|
||||
|
||||
4 // nzElementUsage_TexCoord (Doit être le dernier de la liste car extensible)
|
||||
};
|
||||
|
||||
|
||||
const GLenum blendFunc[] =
|
||||
{
|
||||
GL_DST_ALPHA, // nzBlendFunc_DestAlpha
|
||||
GL_DST_COLOR, // nzBlendFunc_DestColor
|
||||
GL_SRC_ALPHA, // nzBlendFunc_SrcAlpha
|
||||
GL_SRC_COLOR, // nzBlendFunc_SrcColor
|
||||
GL_ONE_MINUS_DST_ALPHA, // nzBlendFunc_InvDestAlpha
|
||||
GL_ONE_MINUS_DST_COLOR, // nzBlendFunc_InvDestColor
|
||||
GL_ONE_MINUS_SRC_ALPHA, // nzBlendFunc_InvSrcAlpha
|
||||
GL_ONE_MINUS_SRC_COLOR, // nzBlendFunc_InvSrcColor
|
||||
GL_ONE, // nzBlendFunc_One
|
||||
GL_ZERO // nzBlendFunc_Zero
|
||||
};
|
||||
|
||||
const GLenum faceCullingMode[] =
|
||||
{
|
||||
GL_BACK, // nzFaceCulling_Back
|
||||
GL_FRONT, // nzFaceCulling_Front
|
||||
GL_FRONT_AND_BACK // nzFaceCulling_FrontAndBack
|
||||
};
|
||||
|
||||
const GLenum faceFillingMode[] =
|
||||
{
|
||||
GL_POINT, // nzFaceFilling_Point
|
||||
GL_LINE, // nzFaceFilling_Line
|
||||
GL_FILL // nzFaceFilling_Fill
|
||||
};
|
||||
|
||||
const GLenum openglPrimitive[] =
|
||||
{
|
||||
GL_LINES, // nzPrimitiveType_LineList,
|
||||
GL_LINE_STRIP, // nzPrimitiveType_LineStrip,
|
||||
GL_POINTS, // nzPrimitiveType_PointList,
|
||||
GL_TRIANGLES, // nzPrimitiveType_TriangleList,
|
||||
GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip,
|
||||
GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan
|
||||
};
|
||||
|
||||
const nzUInt8 openglSize[] =
|
||||
{
|
||||
4, // nzElementType_Color
|
||||
1, // nzElementType_Double1
|
||||
2, // nzElementType_Double2
|
||||
3, // nzElementType_Double3
|
||||
4, // nzElementType_Double4
|
||||
1, // nzElementType_Float1
|
||||
2, // nzElementType_Float2
|
||||
3, // nzElementType_Float3
|
||||
4 // nzElementType_Float4
|
||||
};
|
||||
|
||||
const GLenum openglType[] =
|
||||
{
|
||||
GL_UNSIGNED_BYTE, // nzElementType_Color
|
||||
GL_DOUBLE, // nzElementType_Double1
|
||||
GL_DOUBLE, // nzElementType_Double2
|
||||
GL_DOUBLE, // nzElementType_Double3
|
||||
GL_DOUBLE, // nzElementType_Double4
|
||||
GL_FLOAT, // nzElementType_Float1
|
||||
GL_FLOAT, // nzElementType_Float2
|
||||
GL_FLOAT, // nzElementType_Float3
|
||||
GL_FLOAT // nzElementType_Float4
|
||||
};
|
||||
|
||||
const GLenum rendererComparison[] =
|
||||
{
|
||||
GL_ALWAYS, // nzRendererComparison_Always
|
||||
GL_EQUAL, // nzRendererComparison_Equal
|
||||
GL_GREATER, // nzRendererComparison_Greater
|
||||
GL_GEQUAL, // nzRendererComparison_GreaterOrEqual
|
||||
GL_LESS, // nzRendererComparison_Less
|
||||
GL_LEQUAL, // nzRendererComparison_LessOrEqual
|
||||
GL_NEVER // nzRendererComparison_Never
|
||||
};
|
||||
|
||||
const GLenum rendererParameter[] =
|
||||
{
|
||||
GL_BLEND, // nzRendererParameter_Blend
|
||||
GL_NONE, // nzRendererParameter_ColorWrite
|
||||
GL_DEPTH_TEST, // nzRendererParameter_DepthTest
|
||||
GL_NONE, // nzRendererParameter_DepthWrite
|
||||
GL_CULL_FACE, // nzRendererParameter_FaceCulling
|
||||
GL_STENCIL_TEST // nzRendererParameter_Stencil
|
||||
};
|
||||
|
||||
const GLenum stencilOperation[] =
|
||||
{
|
||||
GL_DECR, // nzStencilOperation_Decrement
|
||||
GL_DECR_WRAP, // nzStencilOperation_DecrementToSaturation
|
||||
GL_INCR, // nzStencilOperation_Increment
|
||||
GL_INCR_WRAP, // nzStencilOperation_IncrementToSaturation
|
||||
GL_INVERT, // nzStencilOperation_Invert
|
||||
GL_KEEP, // nzStencilOperation_Keep
|
||||
GL_REPLACE, // nzStencilOperation_Replace
|
||||
GL_ZERO // nzStencilOperation_Zero
|
||||
};
|
||||
|
||||
///FIXME: Solution temporaire pour plus de facilité
|
||||
enum nzMatrixCombination
|
||||
{
|
||||
|
|
@ -227,7 +119,7 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
|
|||
}
|
||||
|
||||
if (s_indexBuffer->IsSequential())
|
||||
glDrawArrays(openglPrimitive[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
|
||||
glDrawArrays(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
|
||||
else
|
||||
{
|
||||
nzUInt8 indexSize = s_indexBuffer->GetIndexSize();
|
||||
|
|
@ -252,7 +144,7 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
|
|||
return;
|
||||
}
|
||||
|
||||
glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer()) + firstIndex*indexSize);
|
||||
glDrawElements(NzOpenGL::PrimitiveType[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer()) + firstIndex*indexSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +164,7 @@ void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVer
|
|||
return;
|
||||
}
|
||||
|
||||
glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount);
|
||||
glDrawArrays(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount);
|
||||
}
|
||||
|
||||
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
||||
|
|
@ -297,9 +189,9 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
|||
|
||||
default:
|
||||
if (enable)
|
||||
glEnable(rendererParameter[parameter]);
|
||||
glEnable(NzOpenGL::RendererParameter[parameter]);
|
||||
else
|
||||
glDisable(rendererParameter[parameter]);
|
||||
glDisable(NzOpenGL::RendererParameter[parameter]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -307,6 +199,7 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
|||
/*
|
||||
NzMatrix4f NzRenderer::GetMatrix(nzMatrixCombination combination)
|
||||
{
|
||||
///FIXME: Duplication
|
||||
switch (combination)
|
||||
{
|
||||
case nzMatrixCombination_ViewProj:
|
||||
|
|
@ -431,14 +324,16 @@ bool NzRenderer::Initialize()
|
|||
s_vertexBuffer = nullptr;
|
||||
s_vertexDeclaration = nullptr;
|
||||
|
||||
// Récupération des capacités
|
||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter);
|
||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
|
||||
// Récupération des capacités d'OpenGL
|
||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
||||
s_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
|
||||
// MultipleRenderTargets (Techniquement natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation)
|
||||
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr);
|
||||
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(NzOpenGL::PixelBufferObject);
|
||||
s_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
|
||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
||||
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
||||
s_capabilities[nzRendererCap_Texture3D] = true; // Natif depuis OpenGL 1.2
|
||||
s_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||
s_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||
s_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||
|
|
@ -458,7 +353,10 @@ bool NzRenderer::Initialize()
|
|||
GLint maxDrawBuffers;
|
||||
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||
|
||||
s_maxRenderTarget = static_cast<unsigned int>(maxDrawBuffers);
|
||||
GLint maxColorAttachments;
|
||||
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
|
||||
|
||||
s_maxRenderTarget = static_cast<unsigned int>(std::min(maxColorAttachments, maxDrawBuffers));
|
||||
}
|
||||
else
|
||||
s_maxRenderTarget = 1;
|
||||
|
|
@ -472,7 +370,7 @@ bool NzRenderer::Initialize()
|
|||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
|
||||
|
||||
// Impossible de binder plus de texcoords que d'attributes (en sachant qu'un certain nombre est déjà pris par les autres attributs)
|
||||
s_maxTextureUnit = static_cast<unsigned int>(std::min(maxTextureUnits, maxVertexAttribs-attribIndex[nzElementUsage_TexCoord]));
|
||||
s_maxTextureUnit = static_cast<unsigned int>(std::min(maxTextureUnits, maxVertexAttribs-NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]));
|
||||
}
|
||||
else
|
||||
s_maxTextureUnit = 1;
|
||||
|
|
@ -499,7 +397,7 @@ void NzRenderer::SetBlendFunc(nzBlendFunc src, nzBlendFunc dest)
|
|||
}
|
||||
#endif
|
||||
|
||||
glBlendFunc(blendFunc[src], blendFunc[dest]);
|
||||
glBlendFunc(NzOpenGL::BlendFunc[src], NzOpenGL::BlendFunc[dest]);
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearColor(const NzColor& color)
|
||||
|
|
@ -564,7 +462,7 @@ void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode)
|
|||
}
|
||||
#endif
|
||||
|
||||
glCullFace(faceCullingMode[cullingMode]);
|
||||
glCullFace(NzOpenGL::FaceCulling[cullingMode]);
|
||||
}
|
||||
|
||||
void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
|
||||
|
|
@ -577,7 +475,7 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode)
|
|||
}
|
||||
#endif
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, faceFillingMode[fillingMode]);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, NzOpenGL::FaceFilling[fillingMode]);
|
||||
}
|
||||
|
||||
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
|
||||
|
|
@ -603,10 +501,6 @@ void NzRenderer::SetMatrix(nzMatrixType type, const NzMatrix4f& matrix)
|
|||
{
|
||||
s_matrix[type] = matrix;
|
||||
|
||||
// Cas particulier, la matrice projection doit être inversée sur l'axe Y à cause des conventions d'OpenGL
|
||||
if (type == nzMatrixType_Projection)
|
||||
s_matrix[type] *= NzMatrix4f::Scale(NzVector3f(1.f, -1.f, 1.f));
|
||||
|
||||
// Invalidation des combinaisons
|
||||
switch (type)
|
||||
{
|
||||
|
|
@ -722,15 +616,15 @@ bool NzRenderer::SetTarget(NzRenderTarget* target)
|
|||
if (s_target == target)
|
||||
return true;
|
||||
|
||||
if (s_target && !target->HasContext())
|
||||
if (s_target && !s_target->HasContext())
|
||||
s_target->Desactivate();
|
||||
|
||||
if (target)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!target->IsValid())
|
||||
if (!target->IsRenderable())
|
||||
{
|
||||
NazaraError("Target not valid");
|
||||
NazaraError("Target not renderable");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -895,13 +789,13 @@ bool NzRenderer::EnsureStateUpdate()
|
|||
|
||||
if (!s_stencilFuncUpdated)
|
||||
{
|
||||
glStencilFunc(rendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask);
|
||||
glStencilFunc(NzOpenGL::RendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask);
|
||||
s_stencilFuncUpdated = true;
|
||||
}
|
||||
|
||||
if (!s_stencilOpUpdated)
|
||||
{
|
||||
glStencilOp(stencilOperation[s_stencilFail], stencilOperation[s_stencilZFail], stencilOperation[s_stencilPass]);
|
||||
glStencilOp(NzOpenGL::StencilOperation[s_stencilFail], NzOpenGL::StencilOperation[s_stencilZFail], NzOpenGL::StencilOperation[s_stencilPass]);
|
||||
s_stencilOpUpdated = true;
|
||||
}
|
||||
|
||||
|
|
@ -921,7 +815,7 @@ bool NzRenderer::EnsureStateUpdate()
|
|||
}
|
||||
#endif
|
||||
|
||||
static const bool vaoSupported = NzOpenGL::IsSupported(NzOpenGL::VertexArrayObject);
|
||||
static const bool vaoSupported = NzOpenGL::IsSupported(nzOpenGLExtension_VertexArrayObject);
|
||||
bool update;
|
||||
GLuint vao;
|
||||
|
||||
|
|
@ -970,16 +864,16 @@ bool NzRenderer::EnsureStateUpdate()
|
|||
|
||||
if (element)
|
||||
{
|
||||
glEnableVertexAttribArray(attribIndex[i]);
|
||||
glVertexAttribPointer(attribIndex[i],
|
||||
openglSize[element->type],
|
||||
openglType[element->type],
|
||||
glEnableVertexAttribArray(NzOpenGL::AttributeIndex[i]);
|
||||
glVertexAttribPointer(NzOpenGL::AttributeIndex[i],
|
||||
NzVertexDeclaration::GetElementCount(element->type),
|
||||
NzOpenGL::ElementType[element->type],
|
||||
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
|
||||
stride,
|
||||
&buffer[element->offset]);
|
||||
}
|
||||
else
|
||||
glDisableVertexAttribArray(attribIndex[i]);
|
||||
glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]);
|
||||
}
|
||||
|
||||
if (s_indexBuffer)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ bool NzShader::Create(nzShaderLanguage language)
|
|||
return false;
|
||||
}
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +87,8 @@ void NzShader::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
|
@ -595,7 +598,7 @@ bool NzShader::IsLanguageSupported(nzShaderLanguage language)
|
|||
switch (language)
|
||||
{
|
||||
case nzShaderLanguage_Cg:
|
||||
return false; // ??
|
||||
return false; //FIXME: ??
|
||||
|
||||
case nzShaderLanguage_GLSL:
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ struct NzTextureImpl
|
|||
nzImageType type;
|
||||
nzPixelFormat format;
|
||||
nzUInt8 levelCount;
|
||||
bool isTarget = false;
|
||||
NzRenderTexture* renderTexture = nullptr;
|
||||
bool mipmapping = false;
|
||||
bool mipmapsUpdated = true;
|
||||
unsigned int depth;
|
||||
|
|
@ -27,137 +27,18 @@ struct NzTextureImpl
|
|||
|
||||
namespace
|
||||
{
|
||||
GLenum cubemapFace[] =
|
||||
{
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_X, // nzCubemapFace_PositiveX
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // nzCubemapFace_NegativeX
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // nzCubemapFace_PositiveY
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // nzCubemapFace_NegativeY
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // nzCubemapFace_PositiveZ
|
||||
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // nzCubemapFace_NegativeZ
|
||||
};
|
||||
|
||||
GLenum openglTarget[] =
|
||||
{
|
||||
GL_TEXTURE_1D, // nzImageType_1D
|
||||
GL_TEXTURE_1D_ARRAY, // nzImageType_1D_Array
|
||||
GL_TEXTURE_2D, // nzImageType_2D
|
||||
GL_TEXTURE_2D_ARRAY, // nzImageType_2D_Array
|
||||
GL_TEXTURE_3D, // nzImageType_3D
|
||||
GL_TEXTURE_CUBE_MAP // nzImageType_Cubemap
|
||||
};
|
||||
|
||||
GLenum openglTargetBinding[] =
|
||||
{
|
||||
GL_TEXTURE_BINDING_1D, // nzImageType_1D
|
||||
GL_TEXTURE_BINDING_1D_ARRAY, // nzImageType_1D
|
||||
GL_TEXTURE_BINDING_2D, // nzImageType_2D
|
||||
GL_TEXTURE_BINDING_3D, // nzImageType_3D
|
||||
GL_TEXTURE_BINDING_CUBE_MAP // nzImageType_Cubemap
|
||||
};
|
||||
|
||||
GLenum openglTargetProxy[] =
|
||||
{
|
||||
GL_PROXY_TEXTURE_1D, // nzImageType_1D
|
||||
GL_PROXY_TEXTURE_1D_ARRAY, // nzImageType_1D_Array
|
||||
GL_PROXY_TEXTURE_2D, // nzImageType_2D
|
||||
GL_PROXY_TEXTURE_2D_ARRAY, // nzImageType_2D_Array
|
||||
GL_PROXY_TEXTURE_3D, // nzImageType_3D
|
||||
GL_PROXY_TEXTURE_CUBE_MAP // nzImageType_Cubemap
|
||||
};
|
||||
|
||||
struct OpenGLFormat
|
||||
{
|
||||
GLint internalFormat;
|
||||
GLenum dataFormat;
|
||||
GLenum dataType;
|
||||
};
|
||||
|
||||
bool GetOpenGLFormat(nzPixelFormat pixelFormat, OpenGLFormat* format)
|
||||
{
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case nzPixelFormat_BGR8:
|
||||
format->dataFormat = GL_BGR;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_RGB8;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_BGRA8:
|
||||
format->dataFormat = GL_BGRA;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_RGBA8;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_DXT1:
|
||||
format->dataFormat = GL_RGB;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_DXT3:
|
||||
format->dataFormat = GL_RGBA;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_DXT5:
|
||||
format->dataFormat = GL_RGBA;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_LA8:
|
||||
NazaraError("Pixel format not supported");
|
||||
return false;
|
||||
|
||||
case nzPixelFormat_RGB5A1:
|
||||
format->dataFormat = GL_RGBA;
|
||||
format->dataType = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
format->internalFormat = GL_RGB5_A1;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_RGB8:
|
||||
format->dataFormat = GL_RGB;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_RGB8;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_RGBA4:
|
||||
format->dataFormat = GL_RGBA;
|
||||
format->dataType = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
format->internalFormat = GL_RGBA4;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_RGBA8:
|
||||
format->dataFormat = GL_RGBA;
|
||||
format->dataType = GL_UNSIGNED_BYTE;
|
||||
format->internalFormat = GL_RGBA8;
|
||||
return true;
|
||||
|
||||
case nzPixelFormat_Undefined:
|
||||
NazaraInternalError("Invalid pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
NazaraError("Pixel format not handled");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CreateTexture(NzTextureImpl* impl, bool proxy)
|
||||
{
|
||||
OpenGLFormat openGLFormat;
|
||||
if (!GetOpenGLFormat(impl->format, &openGLFormat))
|
||||
NzOpenGL::Format openGLFormat;
|
||||
if (!NzOpenGL::TranslateFormat(impl->format, &openGLFormat, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Failed to get OpenGL format");
|
||||
NazaraError("Format not supported by OpenGL");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum target = (proxy) ? openglTargetProxy[impl->type] : openglTarget[impl->type];
|
||||
GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type];
|
||||
GLint previous;
|
||||
glGetIntegerv(openglTargetBinding[impl->type], &previous);
|
||||
glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous);
|
||||
switch (impl->type)
|
||||
{
|
||||
case nzImageType_1D:
|
||||
|
|
@ -234,7 +115,7 @@ namespace
|
|||
unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique
|
||||
for (nzUInt8 level = 0; level < impl->levelCount; ++level)
|
||||
{
|
||||
for (GLenum face : cubemapFace)
|
||||
for (GLenum face : NzOpenGL::CubemapFace)
|
||||
glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr);
|
||||
|
||||
if (size > 1U)
|
||||
|
|
@ -266,12 +147,12 @@ namespace
|
|||
NzContext::EnsureContext();
|
||||
|
||||
GLint previous;
|
||||
glGetIntegerv(openglTargetBinding[impl->type], &previous);
|
||||
glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous);
|
||||
|
||||
lockedPrevious[impl->type] = static_cast<GLuint>(previous);
|
||||
|
||||
if (lockedPrevious[impl->type] != impl->id)
|
||||
glBindTexture(openglTarget[impl->type], impl->id);
|
||||
glBindTexture(NzOpenGL::TextureTarget[impl->type], impl->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -306,7 +187,7 @@ namespace
|
|||
#endif
|
||||
|
||||
if (--lockedLevel[impl->type] == 0 && lockedPrevious[impl->type] != impl->id)
|
||||
glBindTexture(openglTarget[impl->type], lockedPrevious[impl->type]);
|
||||
glBindTexture(NzOpenGL::TextureTarget[impl->type], lockedPrevious[impl->type]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,42 +215,10 @@ NzTexture::~NzTexture()
|
|||
Destroy();
|
||||
}
|
||||
|
||||
bool NzTexture::Bind() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (lockedLevel[m_impl->type] > 0)
|
||||
{
|
||||
NazaraError("Cannot bind texture while a texture is locked");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindTexture(openglTarget[m_impl->type], m_impl->id);
|
||||
|
||||
if (m_impl->mipmapping && !m_impl->mipmapsUpdated)
|
||||
{
|
||||
glGenerateMipmap(openglTarget[m_impl->type]);
|
||||
m_impl->mipmapsUpdated = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount, bool lock)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (m_impl && m_impl->isTarget)
|
||||
{
|
||||
NazaraError("Texture is a target, it cannot be recreated");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
Destroy();
|
||||
|
||||
if (width == 0 || height == 0 || depth == 0)
|
||||
return true;
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
|
|
@ -389,6 +238,24 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
|||
return false;
|
||||
}
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
NazaraError("Width must be at least 1 (0)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (height == 0)
|
||||
{
|
||||
NazaraError("Height must be at least 1 (0)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
NazaraError("Depth must be at least 1 (0)");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case nzImageType_1D:
|
||||
|
|
@ -491,6 +358,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
|||
if (!lock)
|
||||
UnlockTexture(impl);
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -498,13 +366,7 @@ void NzTexture::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (m_impl->isTarget)
|
||||
{
|
||||
NazaraError("Texture is a target, it cannot be destroyed");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
NotifyDestroy();
|
||||
|
||||
NzContext::EnsureContext();
|
||||
|
||||
|
|
@ -530,8 +392,8 @@ bool NzTexture::Download(NzImage* image) const
|
|||
}
|
||||
#endif
|
||||
|
||||
OpenGLFormat format;
|
||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
||||
NzOpenGL::Format format;
|
||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Failed to get OpenGL format");
|
||||
return false;
|
||||
|
|
@ -552,7 +414,7 @@ bool NzTexture::Download(NzImage* image) const
|
|||
// Téléchargement...
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
{
|
||||
glGetTexImage(openglTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level));
|
||||
glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level));
|
||||
|
||||
if (width > 1)
|
||||
width >>= 1;
|
||||
|
|
@ -610,7 +472,7 @@ unsigned int NzTexture::GetAnisotropyLevel() const
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter))
|
||||
if (!NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
|
||||
return 1;
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
|
@ -806,7 +668,7 @@ bool NzTexture::IsTarget() const
|
|||
}
|
||||
#endif
|
||||
|
||||
return m_impl->isTarget;
|
||||
return m_impl->renderTexture != nullptr;
|
||||
}
|
||||
|
||||
bool NzTexture::IsValid() const
|
||||
|
|
@ -937,7 +799,7 @@ bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter) && anistropyLevel > 1)
|
||||
if (anistropyLevel > 1 && !NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
|
||||
{
|
||||
NazaraError("Anisotropic filter not supported");
|
||||
return false;
|
||||
|
|
@ -970,7 +832,7 @@ bool NzTexture::SetFilterMode(nzTextureFilter filter)
|
|||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLenum target = openglTarget[m_impl->type];
|
||||
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
|
||||
switch (filter)
|
||||
{
|
||||
case nzTextureFilter_Bilinear:
|
||||
|
|
@ -1028,8 +890,8 @@ bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
|||
#endif
|
||||
|
||||
LockTexture(m_impl);
|
||||
glTexParameteri(openglTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel);
|
||||
glTexParameteri(openglTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, std::min(m_impl->levelCount, maxLevel));
|
||||
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel);
|
||||
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, std::min(m_impl->levelCount, maxLevel));
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
return true;
|
||||
|
|
@ -1063,7 +925,7 @@ bool NzTexture::SetWrapMode(nzTextureWrap wrap)
|
|||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLenum target = openglTarget[m_impl->type];
|
||||
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
|
||||
switch (m_impl->type)
|
||||
{
|
||||
// Notez l'absence de "break" ici
|
||||
|
|
@ -1197,7 +1059,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->isTarget)
|
||||
if (m_impl->renderTexture)
|
||||
{
|
||||
NazaraError("Texture is a target, it cannot be updated");
|
||||
return false;
|
||||
|
|
@ -1244,8 +1106,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
|||
}
|
||||
#endif
|
||||
|
||||
OpenGLFormat format;
|
||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
||||
NzOpenGL::Format format;
|
||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Failed to get OpenGL format");
|
||||
return false;
|
||||
|
|
@ -1272,12 +1134,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int
|
|||
|
||||
case nzImageType_1D_Array:
|
||||
case nzImageType_2D:
|
||||
glTexSubImage2D(openglTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored.GetConstPixels());
|
||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored.GetConstPixels());
|
||||
break;
|
||||
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_3D:
|
||||
glTexSubImage3D(openglTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, mirrored.GetConstPixels());
|
||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, rect.x, height-rect.height-rect.y, z, rect.width, rect.height, 1, format.dataFormat, format.dataType, mirrored.GetConstPixels());
|
||||
break;
|
||||
|
||||
case nzImageType_Cubemap:
|
||||
|
|
@ -1298,7 +1160,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->isTarget)
|
||||
if (m_impl->renderTexture)
|
||||
{
|
||||
NazaraError("Texture is a target, it cannot be updated");
|
||||
return false;
|
||||
|
|
@ -1341,8 +1203,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
|||
}
|
||||
#endif
|
||||
|
||||
OpenGLFormat format;
|
||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
||||
NzOpenGL::Format format;
|
||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Failed to get OpenGL format");
|
||||
return false;
|
||||
|
|
@ -1370,12 +1232,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve
|
|||
|
||||
case nzImageType_1D_Array:
|
||||
case nzImageType_2D:
|
||||
glTexSubImage2D(openglTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored);
|
||||
glTexSubImage2D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored);
|
||||
break;
|
||||
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_3D:
|
||||
glTexSubImage3D(openglTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored);
|
||||
glTexSubImage3D(NzOpenGL::TextureTarget[m_impl->type], level, cube.x, height-cube.height-cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored);
|
||||
break;
|
||||
|
||||
case nzImageType_Cubemap:
|
||||
|
|
@ -1455,7 +1317,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->isTarget)
|
||||
if (m_impl->renderTexture)
|
||||
{
|
||||
NazaraError("Texture is a target, it cannot be updated");
|
||||
return false;
|
||||
|
|
@ -1496,8 +1358,8 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
|||
}
|
||||
#endif
|
||||
|
||||
OpenGLFormat format;
|
||||
if (!GetOpenGLFormat(m_impl->format, &format))
|
||||
NzOpenGL::Format format;
|
||||
if (!NzOpenGL::TranslateFormat(m_impl->format, &format, NzOpenGL::FormatType_Texture))
|
||||
{
|
||||
NazaraError("Failed to get OpenGL format");
|
||||
return false;
|
||||
|
|
@ -1517,7 +1379,7 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe
|
|||
SetUnpackAlignement(bpp);
|
||||
|
||||
LockTexture(m_impl);
|
||||
glTexSubImage2D(cubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
|
||||
glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, mirrored);
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
|
||||
|
|
@ -1537,6 +1399,40 @@ void NzTexture::Unlock()
|
|||
UnlockTexture(m_impl);
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetOpenGLID() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->id;
|
||||
}
|
||||
|
||||
bool NzTexture::Prepare() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (lockedLevel[m_impl->type] > 0)
|
||||
{
|
||||
NazaraError("Cannot bind texture while a texture is locked");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindTexture(NzOpenGL::TextureTarget[m_impl->type], m_impl->id);
|
||||
|
||||
if (m_impl->mipmapping && !m_impl->mipmapsUpdated)
|
||||
{
|
||||
glGenerateMipmap(NzOpenGL::TextureTarget[m_impl->type]);
|
||||
m_impl->mipmapsUpdated = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetValidSize(unsigned int size)
|
||||
{
|
||||
if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT))
|
||||
|
|
@ -1567,6 +1463,23 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
|||
case nzPixelFormat_RGBA4:
|
||||
return true;
|
||||
|
||||
// Formats de profondeur (Supportés avec les FBOs)
|
||||
case nzPixelFormat_Depth16:
|
||||
case nzPixelFormat_Depth24:
|
||||
case nzPixelFormat_Depth32:
|
||||
case nzPixelFormat_Depth24Stencil8:
|
||||
{
|
||||
static const bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
||||
return supported;
|
||||
}
|
||||
|
||||
// Formats de stencil (Non supportés pour les textures)
|
||||
case nzPixelFormat_Stencil1:
|
||||
case nzPixelFormat_Stencil4:
|
||||
case nzPixelFormat_Stencil8:
|
||||
case nzPixelFormat_Stencil16:
|
||||
return false;
|
||||
|
||||
// Dépréciés depuis OpenGL 3 (FIXME: Il doit bien exister des remplaçants ..)
|
||||
case nzPixelFormat_L8:
|
||||
case nzPixelFormat_LA8:
|
||||
|
|
@ -1576,7 +1489,7 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format)
|
|||
case nzPixelFormat_DXT3:
|
||||
case nzPixelFormat_DXT5:
|
||||
{
|
||||
static const bool supported = NzOpenGL::IsSupported(NzOpenGL::TextureCompression_s3tc);
|
||||
static const bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_TextureCompression_s3tc);
|
||||
return supported;
|
||||
}
|
||||
|
||||
|
|
@ -1607,7 +1520,7 @@ bool NzTexture::IsTypeSupported(nzImageType type)
|
|||
case nzImageType_1D_Array:
|
||||
case nzImageType_2D_Array:
|
||||
{
|
||||
static bool supported = NzOpenGL::IsSupported(NzOpenGL::TextureArray);
|
||||
static bool supported = NzOpenGL::IsSupported(nzOpenGLExtension_TextureArray);
|
||||
return supported;
|
||||
}
|
||||
}
|
||||
|
|
@ -1616,9 +1529,22 @@ bool NzTexture::IsTypeSupported(nzImageType type)
|
|||
return false;
|
||||
}
|
||||
|
||||
void NzTexture::SetTarget(bool isTarget)
|
||||
NzRenderTexture* NzTexture::GetRenderTexture() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraInternalError("Texture must be valid");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->renderTexture;
|
||||
}
|
||||
|
||||
void NzTexture::SetRenderTexture(NzRenderTexture* renderTexture)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraInternalError("Texture must be valid");
|
||||
|
|
@ -1626,5 +1552,5 @@ void NzTexture::SetTarget(bool isTarget)
|
|||
}
|
||||
#endif
|
||||
|
||||
m_impl->isTarget = isTarget;
|
||||
m_impl->renderTexture = renderTexture;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,28 +153,19 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
|
|||
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||
*attrib++ = parameters.minorVersion;
|
||||
|
||||
int flags = 0;
|
||||
|
||||
if (parameters.majorVersion >= 3)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||
if (parameters.compatibilityProfile)
|
||||
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||
else
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
|
||||
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||
}
|
||||
*attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
}
|
||||
|
||||
if (parameters.debugMode)
|
||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
|
||||
if (flags)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
|
||||
*attrib++ = flags;
|
||||
*attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
|
||||
// Les contextes forward-compatible ne sont plus utilisés pour cette raison :
|
||||
// http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile
|
||||
}
|
||||
|
||||
*attrib++ = 0;
|
||||
|
|
@ -210,13 +201,25 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
|
|||
void NzContextImpl::Destroy()
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
if (wglGetCurrentContext() == m_context)
|
||||
wglMakeCurrent(nullptr, nullptr);
|
||||
|
||||
wglDeleteContext(m_context);
|
||||
m_context = nullptr;
|
||||
}
|
||||
|
||||
if (m_deviceContext)
|
||||
{
|
||||
ReleaseDC(m_window, m_deviceContext);
|
||||
m_deviceContext = nullptr;
|
||||
}
|
||||
|
||||
if (m_ownsWindow)
|
||||
{
|
||||
DestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzContextImpl::SwapBuffers()
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ NzAnimation::~NzAnimation()
|
|||
Destroy();
|
||||
}
|
||||
|
||||
unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
|
||||
bool NzAnimation::AddSequence(const NzSequence& sequence)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Animation not created");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
|
|||
if (it != m_impl->sequenceMap.end())
|
||||
{
|
||||
NazaraError("Sequence name \"" + sequence.name + "\" is already used");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ unsigned int NzAnimation::AddSequence(const NzSequence& sequence)
|
|||
|
||||
m_impl->sequences.push_back(sequence);
|
||||
|
||||
return index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount)
|
||||
|
|
@ -86,6 +86,7 @@ bool NzAnimation::Create(nzAnimationType type, unsigned int frameCount)
|
|||
m_impl->frameCount = frameCount;
|
||||
m_impl->type = type;
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +94,8 @@ void NzAnimation::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
|
@ -206,6 +209,28 @@ unsigned int NzAnimation::GetSequenceCount() const
|
|||
return m_impl->sequences.size();
|
||||
}
|
||||
|
||||
int NzAnimation::GetSequenceIndex(const NzString& sequenceName) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Animation not created");
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto it = m_impl->sequenceMap.find(sequenceName);
|
||||
if (it == m_impl->sequenceMap.end())
|
||||
{
|
||||
NazaraError("Sequence not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
#else
|
||||
return m_impl->sequenceMap[sequenceName];
|
||||
#endif
|
||||
}
|
||||
|
||||
nzAnimationType NzAnimation::GetType() const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
|
|
@ -277,13 +302,13 @@ void NzAnimation::RemoveSequence(const NzString& identifier)
|
|||
auto it = m_impl->sequenceMap.find(identifier);
|
||||
if (it == m_impl->sequenceMap.end())
|
||||
{
|
||||
NazaraError("SubMesh not found");
|
||||
NazaraError("Sequence not found");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int index = it->second;
|
||||
int index = it->second;
|
||||
#else
|
||||
unsigned int index = m_impl->sequenceMap[identifier];
|
||||
int index = m_impl->sequenceMap[identifier];
|
||||
#endif
|
||||
|
||||
auto it2 = m_impl->sequences.begin();
|
||||
|
|
|
|||
|
|
@ -113,14 +113,16 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto
|
|||
m_storage = storage;
|
||||
m_usage = usage;
|
||||
|
||||
// Si on arrive ici c'est que tout s'est bien passé.
|
||||
return true;
|
||||
NotifyCreated();
|
||||
return true; // Si on arrive ici c'est que tout s'est bien passé.
|
||||
}
|
||||
|
||||
void NzBuffer::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
|
|
|||
|
|
@ -215,9 +215,6 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
|||
{
|
||||
ReleaseImage();
|
||||
|
||||
if (width == 0 || height == 0 || depth == 0)
|
||||
return true;
|
||||
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!NzPixelFormat::IsValid(format))
|
||||
{
|
||||
|
|
@ -225,6 +222,24 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
NazaraError("Width must be at least 1 (0)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (height == 0)
|
||||
{
|
||||
NazaraError("Height must be at least 1 (0)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (depth == 0)
|
||||
{
|
||||
NazaraError("Depth must be at least 1 (0)");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case nzImageType_1D:
|
||||
|
|
@ -315,11 +330,13 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
|||
|
||||
m_sharedImage = new SharedImage(1, type, format, levelCount, levels, width, height, depth);
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzImage::Destroy()
|
||||
{
|
||||
NotifyDestroy();
|
||||
ReleaseImage();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,27 +43,6 @@ namespace
|
|||
return false;
|
||||
}
|
||||
|
||||
// Les fichiers MD2 sont en little endian
|
||||
#if defined(NAZARA_BIG_ENDIAN)
|
||||
NzByteSwap(&header.ident, sizeof(nzUInt32));
|
||||
#endif
|
||||
|
||||
if (header.ident != md2Ident)
|
||||
{
|
||||
NazaraError("Invalid MD2 file");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(NAZARA_BIG_ENDIAN)
|
||||
NzByteSwap(&header.version, sizeof(nzUInt32));
|
||||
#endif
|
||||
|
||||
if (header.version != 8)
|
||||
{
|
||||
NazaraError("Bad version number (" + NzString::Number(header.version) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(NAZARA_BIG_ENDIAN)
|
||||
NzByteSwap(&header.skinwidth, sizeof(nzUInt32));
|
||||
NzByteSwap(&header.skinheight, sizeof(nzUInt32));
|
||||
|
|
@ -99,7 +78,7 @@ namespace
|
|||
else
|
||||
animated = false;
|
||||
|
||||
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait pas échouer
|
||||
if (!mesh->Create((animated) ? nzAnimationType_Keyframe : nzAnimationType_Static)) // Ne devrait jamais échouer
|
||||
{
|
||||
NazaraInternalError("Failed to create mesh");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
|
|||
unsigned int endFrame = NzClamp(parameters.animation.endFrame, 0U, static_cast<unsigned int>(header.num_frames-1));
|
||||
|
||||
m_frameCount = endFrame - startFrame + 1;
|
||||
m_vertexCount = header.num_tris*3;
|
||||
m_vertexCount = header.num_tris * 3;
|
||||
|
||||
/// Chargement des vertices
|
||||
std::vector<md2_texCoord> texCoords(header.num_st);
|
||||
|
|
@ -71,8 +71,9 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
|
|||
md2_frame frame;
|
||||
frame.vertices.resize(header.num_vertices);
|
||||
|
||||
// Pour que le modèle soit correctement aligné, on génère une matrice de rotation que nous appliquerons à chacune des vertices
|
||||
NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(90.f, -90.f, 0.f));
|
||||
// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
|
||||
NzQuaternionf rotationQuat = NzEulerAnglesf(-90.f, 90.f, 0.f);
|
||||
//NzMatrix4f rotationMatrix = NzMatrix4f::Rotate(NzEulerAnglesf(-90.f, -90.f, 0.f));
|
||||
|
||||
unsigned int stride = s_declaration.GetStride(nzElementStream_VertexData);
|
||||
|
||||
|
|
@ -94,7 +95,7 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
|
|||
NzByteSwap(&frame.translate.z, sizeof(float));
|
||||
#endif
|
||||
|
||||
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice de la normale plutôt que la normale (gain d'espace)
|
||||
m_frames[i].normal = new nzUInt8[m_vertexCount]; // Nous stockons l'indice MD2 de la normale plutôt que la normale (gain d'espace)
|
||||
m_frames[i].vertices = new NzVector3f[m_vertexCount];
|
||||
|
||||
NzVector3f max, min;
|
||||
|
|
@ -104,12 +105,16 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
|
|||
{
|
||||
const md2_vertex& vert = frame.vertices[triangles[t].vertices[v]];
|
||||
|
||||
NzVector3f vertex = rotationMatrix * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z);
|
||||
max.MakeCeil(vertex);
|
||||
min.MakeFloor(vertex);
|
||||
NzVector3f vertex = rotationQuat * NzVector3f(vert.x * frame.scale.x + frame.translate.x, vert.y * frame.scale.y + frame.translate.y, vert.z * frame.scale.z + frame.translate.z);
|
||||
|
||||
m_frames[i].normal[t*3+v] = vert.n;
|
||||
m_frames[i].vertices[t*3+v] = vertex;
|
||||
// On fait en sorte d'avoir deux vertices de délimitation, définissant un rectangle dans l'espace
|
||||
max.Maximize(vertex);
|
||||
min.Minimize(vertex);
|
||||
|
||||
// Le MD2 ne définit pas ses vertices dans le bon ordre, il nous faut donc les ajouter dans l'ordre inverse
|
||||
unsigned int index = m_vertexCount - (t*3 + v) - 1;
|
||||
m_frames[i].normal[index] = vert.n;
|
||||
m_frames[i].vertices[index] = vertex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,8 +133,8 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
// On avance jusqu'aux premières coordonnées de texture
|
||||
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset;
|
||||
// On avance jusqu'aux dernières coordonnées de texture et on les définit dans l'ordre inverse
|
||||
ptr += s_declaration.GetElement(nzElementStream_VertexData, nzElementUsage_TexCoord)->offset + stride * (m_vertexCount-1);
|
||||
for (unsigned int t = 0; t < header.num_tris; ++t)
|
||||
{
|
||||
for (unsigned int v = 0; v < 3; ++v)
|
||||
|
|
@ -140,7 +145,7 @@ bool NzMD2Mesh::Create(const md2_header& header, NzInputStream& stream, const Nz
|
|||
coords->x = texC.u / static_cast<float>(header.skinwidth);
|
||||
coords->y = 1.f - texC.v / static_cast<float>(header.skinheight);
|
||||
|
||||
ptr += stride;
|
||||
ptr -= stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,12 +59,6 @@ namespace
|
|||
return false;
|
||||
}
|
||||
|
||||
if (header.manufacturer != 0x0a)
|
||||
{
|
||||
NazaraError("Bad version number (" + NzString::Number(header.manufacturer) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(NAZARA_BIG_ENDIAN)
|
||||
// Les fichiers PCX sont en little endian
|
||||
NzByteSwap(&header.xmin, sizeof(nzUInt16));
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ bool NzMeshParams::IsValid() const
|
|||
|
||||
struct NzMeshImpl
|
||||
{
|
||||
std::map<NzString, nzUInt8> subMeshMap;
|
||||
std::deque<NzString> skins;
|
||||
std::map<NzString, unsigned int> subMeshMap;
|
||||
std::vector<NzSubMesh*> subMeshes;
|
||||
nzAnimationType animationType;
|
||||
NzAxisAlignedBox aabb;
|
||||
|
|
@ -44,19 +44,19 @@ NzMesh::~NzMesh()
|
|||
Destroy();
|
||||
}
|
||||
|
||||
unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
|
||||
bool NzMesh::AddSkin(const NzString& skin, bool setDefault)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Mesh not created");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skin.IsEmpty())
|
||||
{
|
||||
NazaraError("Skin is empty");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -65,71 +65,71 @@ unsigned int NzMesh::AddSkin(const NzString& skin, bool setDefault)
|
|||
else
|
||||
m_impl->skins.push_back(skin);
|
||||
|
||||
return m_impl->skins.size()-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
nzUInt8 NzMesh::AddSubMesh(NzSubMesh* subMesh)
|
||||
bool NzMesh::AddSubMesh(NzSubMesh* subMesh)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Mesh not created");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!subMesh)
|
||||
{
|
||||
NazaraError("Invalid submesh");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
subMesh->AddResourceReference();
|
||||
subMesh->AddResourceListener(this, m_impl->subMeshes.size());
|
||||
|
||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||
m_impl->subMeshes.push_back(subMesh);
|
||||
|
||||
return m_impl->subMeshes.size()-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
nzUInt8 NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh)
|
||||
bool NzMesh::AddSubMesh(const NzString& identifier, NzSubMesh* subMesh)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Mesh not created");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (identifier.IsEmpty())
|
||||
{
|
||||
NazaraError("Identifier is empty");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto it = m_impl->subMeshMap.find(identifier);
|
||||
if (it != m_impl->subMeshMap.end())
|
||||
{
|
||||
NazaraError("SubMesh identifier \"" + identifier + "\" is already used");
|
||||
return it->second;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!subMesh)
|
||||
{
|
||||
NazaraError("Invalid submesh");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
nzUInt8 index = m_impl->subMeshes.size();
|
||||
int index = m_impl->subMeshes.size();
|
||||
|
||||
subMesh->AddResourceReference();
|
||||
subMesh->AddResourceListener(this, index);
|
||||
|
||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||
m_impl->subMeshes.push_back(subMesh);
|
||||
m_impl->subMeshMap[identifier] = index;
|
||||
|
||||
return index;
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzMesh::Animate(unsigned int frameA, unsigned int frameB, float interpolation)
|
||||
|
|
@ -180,6 +180,8 @@ bool NzMesh::Create(nzAnimationType type)
|
|||
m_impl = new NzMeshImpl;
|
||||
m_impl->animationType = type;
|
||||
|
||||
NotifyCreated();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -187,11 +189,13 @@ void NzMesh::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
||||
if (m_impl->animation)
|
||||
m_impl->animation->RemoveResourceReference();
|
||||
m_impl->animation->RemoveResourceListener(this);
|
||||
|
||||
for (NzSubMesh* subMesh : m_impl->subMeshes)
|
||||
subMesh->RemoveResourceReference();
|
||||
subMesh->RemoveResourceListener(this);
|
||||
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
|
@ -316,7 +320,7 @@ NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier)
|
|||
#endif
|
||||
}
|
||||
|
||||
NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index)
|
||||
NzSubMesh* NzMesh::GetSubMesh(unsigned int index)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
|
|
@ -357,7 +361,7 @@ const NzSubMesh* NzMesh::GetSubMesh(const NzString& identifier) const
|
|||
#endif
|
||||
}
|
||||
|
||||
const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
|
||||
const NzSubMesh* NzMesh::GetSubMesh(unsigned int index) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
|
|
@ -376,7 +380,7 @@ const NzSubMesh* NzMesh::GetSubMesh(nzUInt8 index) const
|
|||
return m_impl->subMeshes[index];
|
||||
}
|
||||
|
||||
nzUInt8 NzMesh::GetSubMeshCount() const
|
||||
unsigned int NzMesh::GetSubMeshCount() const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
|
|
@ -389,6 +393,28 @@ nzUInt8 NzMesh::GetSubMeshCount() const
|
|||
return m_impl->subMeshes.size();
|
||||
}
|
||||
|
||||
int NzMesh::GetSubMeshIndex(const NzString& identifier) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Mesh not created");
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto it = m_impl->subMeshMap.find(identifier);
|
||||
if (it == m_impl->subMeshMap.end())
|
||||
{
|
||||
NazaraError("SubMesh not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
#else
|
||||
return m_impl->subMeshMap[identifier];
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int NzMesh::GetVertexCount() const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
|
|
@ -458,7 +484,7 @@ bool NzMesh::HasSubMesh(const NzString& identifier) const
|
|||
return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end();
|
||||
}
|
||||
|
||||
bool NzMesh::HasSubMesh(nzUInt8 index) const
|
||||
bool NzMesh::HasSubMesh(unsigned int index) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
|
|
@ -520,6 +546,7 @@ void NzMesh::RemoveSkin(unsigned int index)
|
|||
}
|
||||
#endif
|
||||
|
||||
// On accède à l'itérateur correspondant à l'entrée #index
|
||||
auto it = m_impl->skins.begin();
|
||||
std::advance(it, index);
|
||||
|
||||
|
|
@ -547,15 +574,18 @@ void NzMesh::RemoveSubMesh(const NzString& identifier)
|
|||
unsigned int index = m_impl->subMeshMap[identifier];
|
||||
#endif
|
||||
|
||||
// On déplace l'itérateur du début d'une distance de x
|
||||
auto it2 = m_impl->subMeshes.begin();
|
||||
std::advance(it2, index);
|
||||
std::advance(it, index);
|
||||
|
||||
// On libère la ressource
|
||||
(*it2)->RemoveResourceListener(this);
|
||||
m_impl->subMeshes.erase(it2);
|
||||
|
||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||
}
|
||||
|
||||
void NzMesh::RemoveSubMesh(nzUInt8 index)
|
||||
void NzMesh::RemoveSubMesh(unsigned int index)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
|
|
@ -571,9 +601,12 @@ void NzMesh::RemoveSubMesh(nzUInt8 index)
|
|||
}
|
||||
#endif
|
||||
|
||||
// On déplace l'itérateur du début de x
|
||||
auto it = m_impl->subMeshes.begin();
|
||||
std::advance(it, index);
|
||||
|
||||
// On libère la ressource
|
||||
(*it)->RemoveResourceListener(this);
|
||||
m_impl->subMeshes.erase(it);
|
||||
|
||||
m_impl->aabb.SetNull(); // On invalide l'AABB
|
||||
|
|
@ -599,7 +632,7 @@ bool NzMesh::SetAnimation(const NzAnimation* animation)
|
|||
return true;
|
||||
|
||||
if (m_impl->animation)
|
||||
m_impl->animation->RemoveResourceReference();
|
||||
m_impl->animation->RemoveResourceListener(this);
|
||||
|
||||
if (animation)
|
||||
{
|
||||
|
|
@ -611,13 +644,38 @@ bool NzMesh::SetAnimation(const NzAnimation* animation)
|
|||
}
|
||||
#endif
|
||||
|
||||
m_impl->animation = animation;
|
||||
m_impl->animation->AddResourceReference();
|
||||
animation->AddResourceListener(this);
|
||||
}
|
||||
else
|
||||
m_impl->animation = nullptr;
|
||||
|
||||
m_impl->animation = animation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzMesh::OnResourceCreated(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(index);
|
||||
|
||||
if (resource == m_impl->animation)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (m_impl->animation->GetType() != m_impl->animationType)
|
||||
{
|
||||
NazaraError("Animation's type must match mesh animation type");
|
||||
|
||||
m_impl->animation->RemoveResourceListener(this);
|
||||
m_impl->animation = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void NzMesh::OnResourceReleased(const NzResource* resource, int index)
|
||||
{
|
||||
if (resource == m_impl->animation)
|
||||
SetAnimation(nullptr);
|
||||
else
|
||||
RemoveSubMesh(index);
|
||||
}
|
||||
|
||||
NzMeshLoader::LoaderList NzMesh::s_loaders;
|
||||
|
|
|
|||
|
|
@ -38,28 +38,27 @@ bool NzStaticMesh::Create(const NzVertexDeclaration* vertexDeclaration, NzVertex
|
|||
#if NAZARA_UTILITY_SAFE
|
||||
if (!vertexDeclaration)
|
||||
{
|
||||
NazaraError("Vertex declaration is null");
|
||||
NazaraError("Invalid vertex declaration");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vertexBuffer)
|
||||
{
|
||||
NazaraError("Vertex buffer is null");
|
||||
NazaraError("Invalid vertex buffer");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (indexBuffer)
|
||||
{
|
||||
m_indexBuffer = indexBuffer;
|
||||
m_indexBuffer->AddResourceReference();
|
||||
}
|
||||
indexBuffer->AddResourceListener(this);
|
||||
|
||||
m_indexBuffer = indexBuffer;
|
||||
|
||||
m_vertexBuffer = vertexBuffer;
|
||||
m_vertexBuffer->AddResourceReference();
|
||||
m_vertexBuffer->AddResourceListener(this);
|
||||
|
||||
m_vertexDeclaration = vertexDeclaration;
|
||||
m_vertexDeclaration->AddResourceReference();
|
||||
m_vertexDeclaration->AddResourceListener(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -70,19 +69,19 @@ void NzStaticMesh::Destroy()
|
|||
|
||||
if (m_indexBuffer)
|
||||
{
|
||||
m_indexBuffer->RemoveResourceReference();
|
||||
m_indexBuffer->RemoveResourceListener(this);
|
||||
m_indexBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (m_vertexBuffer)
|
||||
{
|
||||
m_vertexBuffer->RemoveResourceReference();
|
||||
m_vertexBuffer->RemoveResourceListener(this);
|
||||
m_vertexBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (m_vertexDeclaration)
|
||||
{
|
||||
m_vertexDeclaration->RemoveResourceReference();
|
||||
m_vertexDeclaration->RemoveResourceListener(this);
|
||||
m_vertexDeclaration = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -184,3 +183,17 @@ void NzStaticMesh::AnimateImpl(unsigned int frameA, unsigned int frameB, float i
|
|||
// Le safe mode est censé nous protéger de cet appel
|
||||
NazaraError("Static mesh have no animation, please enable safe mode");
|
||||
}
|
||||
|
||||
void NzStaticMesh::OnResourceReleased(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(index);
|
||||
|
||||
if (resource == m_indexBuffer)
|
||||
m_indexBuffer = nullptr;
|
||||
else if (resource == m_vertexBuffer)
|
||||
m_vertexBuffer = nullptr;
|
||||
else if (resource == m_vertexDeclaration)
|
||||
m_vertexDeclaration = nullptr;
|
||||
else
|
||||
NazaraInternalError("Not listening to " + NzString::Pointer(resource));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,22 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
const unsigned int size[] =
|
||||
const unsigned int elementCount[] =
|
||||
{
|
||||
sizeof(nzUInt32), // nzElementType_Color
|
||||
4, // nzElementType_Color
|
||||
1, // nzElementType_Double1
|
||||
2, // nzElementType_Double2
|
||||
3, // nzElementType_Double3
|
||||
4, // nzElementType_Double4
|
||||
1, // nzElementType_Float1
|
||||
2, // nzElementType_Float2
|
||||
3, // nzElementType_Float3
|
||||
4 // nzElementType_Float4
|
||||
};
|
||||
|
||||
const unsigned int elementSize[] =
|
||||
{
|
||||
4*sizeof(nzUInt8), // nzElementType_Color
|
||||
1*sizeof(double), // nzElementType_Double1
|
||||
2*sizeof(double), // nzElementType_Double2
|
||||
3*sizeof(double), // nzElementType_Double3
|
||||
|
|
@ -143,7 +156,7 @@ bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int e
|
|||
if (impl->streamPos[current.stream] == -1)
|
||||
impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage)
|
||||
|
||||
impl->stride[current.stream] += size[current.type];
|
||||
impl->stride[current.stream] += elementSize[current.type];
|
||||
}
|
||||
|
||||
#if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
|
||||
|
|
@ -153,6 +166,7 @@ bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int e
|
|||
|
||||
m_sharedImpl = impl;
|
||||
|
||||
NotifyCreated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -161,6 +175,8 @@ void NzVertexDeclaration::Destroy()
|
|||
if (!m_sharedImpl)
|
||||
return;
|
||||
|
||||
NotifyDestroy();
|
||||
|
||||
NazaraMutexLock(m_sharedImpl->mutex);
|
||||
bool freeSharedImpl = (--m_sharedImpl->refCount == 0);
|
||||
NazaraMutexUnlock(m_sharedImpl->mutex);
|
||||
|
|
@ -344,3 +360,13 @@ NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declar
|
|||
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetElementCount(nzElementType type)
|
||||
{
|
||||
return elementCount[type];
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetElementSize(nzElementType type)
|
||||
{
|
||||
return elementSize[type];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
|
|||
{
|
||||
if (!mode.IsFullscreenValid())
|
||||
{
|
||||
NazaraWarning("Mode is not fullscreen valid");
|
||||
NazaraWarning("Video mode is not fullscreen valid");
|
||||
mode = NzVideoMode::GetFullscreenModes()[0];
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ void NzWindow::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
OnWindowDestroying();
|
||||
OnWindowDestroy();
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
|
|
@ -212,7 +212,7 @@ NzWindowHandle NzWindow::GetHandle() const
|
|||
if (m_impl)
|
||||
return m_impl->GetHandle();
|
||||
else
|
||||
return reinterpret_cast<NzWindowHandle>(0);
|
||||
return static_cast<NzWindowHandle>(0);
|
||||
}
|
||||
|
||||
unsigned int NzWindow::GetHeight() const
|
||||
|
|
@ -276,6 +276,11 @@ bool NzWindow::IsMinimized() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NzWindow::IsValid() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzWindow::IsVisible() const
|
||||
{
|
||||
if (m_impl)
|
||||
|
|
@ -483,15 +488,15 @@ bool NzWindow::WaitEvent(NzEvent* event)
|
|||
#endif
|
||||
}
|
||||
|
||||
void NzWindow::OnWindowDestroying()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzWindow::OnWindowCreated()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzWindow::OnWindowDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
void NzWindow::IgnoreNextMouseEvent(int mouseX, int mouseY) const
|
||||
{
|
||||
if (m_impl)
|
||||
|
|
|
|||
Loading…
Reference in New Issue