mercredi 31 août 2011

Normal maps et Blender 2.5 - Créer un astéroïde

Le nouveau Blender ayant changé pas mal de choses, voici la version mise à jour de mon tutoriel sur les normal map, cette foi-ci pour créer un astéroïde.



Voici l'écran initial de Blender, après être passé à 4 vues (Ctrl-Alt-Q). Virons le cube (sélection avec bouton droit, puis DEL), et ajoutons une icosphère (Shift-A, Mesh => Icosphere).



L'on peut maintenant tortiller la sphère dans tous les sens: s + déplacements de souris pour changer sa taille, et s suivi de x, y ou z pour changer la taille dans une dimension seulement. L'on peut sélectionner les points individuellement en passant en mode vertex (TAB), et en sélectionnant les points avec le bouton droit. La touche g permet de déplacer les vertex, et l'on peut une fois de plus restreindre la dimension avec les touches x, y ou z. Formons donc un patatoïde.



Lequel patatoïde nous pouvons maintenant donner une forme plus douce, en y ajoutant le modifier "subdivisions". Dans le menu de droite, allez chercher le tab "Modifiers" (la petite clé à molette), et choisissez "Subdivision Surface". Mettons View et Render à 2.



L'on va ensuite rendre notre patatoïde tout doux: passez en mode vertex (TAB), selectionnez tout (a), et choisissez dans le menu "Mesh Tools" à gauche le shading "Smooth".



Allez chercher le tab "Material", et ajoutez un nouveau matériau.



Allez ensuite chercher le tab "Texture", et ajoutez une nouvelle texture. Pour donner un aspect rugueux à notre astéroïde, nous allons choisir une texture de type "Cloud", choisir un "noise" à "Hard", et changer son influence en désactivant "Colo" (pour couleur) et en activant "Nor" pour normales.



Ajustez vos couleurs, et admirez!



Maintenant, passons à la création de l'objet à exporter. D'abord, dupliquez l'astéroïde (Shift-D). Il est possible de renommer les objets en "high poly" et "low poly", par exemple, dans le menu "Object", histoire de ne pas se perdre. Enlevez le modifier de subdivisions afin de retrouver notre objet initial.



Ensuite, générez la texture UV (mode vertex, u, "Smart UV project"). Vous pouvez maintenant effectuer le rendu de la texture, en allant dans le tab "Render" (le petit appareil photo), et en allant tout en bas dans "Bake". Choisissez le bake mode "Normals", avec normal space "Object". Lancez le rendu avec "Bake".



Tout en haut, passez de la vue "Default" à la vue "UV editing" pour admirer votre œuvre. Sauvez l'image, puis exportez l'objet!



Avec OSG, je transforme l'objet exporté en Wavefront (.obj) vers un .osg, puis j'édite manuellement le .osg afin de dupliquer le noeud de texture, pour ajouter une deuxième texture avec un identifiant à 1. Je change ensuite les noms pour avoir ma texture de couleurs en 0, et ma texture de normales en 1, comme l'attend mon programme.

Et voilà le travail:


mardi 16 août 2011

1000 cubes

Un millier de cubes orbitant tranquillement. Le système monte gentiment en charge, avec une charge CPU à 125%, c'est à dire un proc à 100% pour afficher le plus d'images possible à la seconde, et 25% en calcul d'orbites et en passage de messages.

lundi 15 août 2011

Orbites

Il faut voir le cube tourner (je vais essayer de générer une vidéo), mais voilà déjà une image. Mon framework fonctionne, et devrait monter en charge facilement.

Cela représente donc un cube, doué d'une vitesse initiale, orbitant autour d'une masse pour l'instant non représentée. Cela devrait prouver ou pas la possibilité de mettre à jour des centaines d'objets, et de les représenter de façon fluide en recalculant "rarement" la position et la vitesse, puis en faisant une extrapolation à chaque image.


Week-end de folie chez Debian

La bonne vieille Wheezy prend du poil de la bête: non seulement nous sommes passés en noyau 3.0, mais en plus Iceweasel 5 est sorti! Au menu, un très bon support de Youtube en HTML5. Peut-être vais-je enfin pouvoir me débarrasser de Flash?

vendredi 12 août 2011

Mon compilo est intelligent

Brave g++!


#include <array>

int main()
{
std::array<int, 5> a = {1, 2, 3, 4};
std::array<int, 5> b = {1, 2, 3, 4, 5};
std::array<int, 5> c = {1, 2, 3, 4, 5, 6};

return 0;
}

Les tableaux a et b passent comme une lettre à la poste, mais le compilo hurle fort justement sur le tableau c, avec l'on ne peut plus explicite message:

array.cpp:9:43: error: too many initializers for ‘std::array<int, 5ul>’

Je n'en attendais pas tant. Magnifique!

mercredi 10 août 2011

Événements

Je suis en train d'essayer de construire un truc qui se tient autour de boost::asio et de la programmation orientée événements. L'idée est de construire quelques briques de plus haut niveau autour d'asio, et d'en tirer quelque chose d'utilisable.

Tout tourne autour d'un boost::asio::io_service::strand, que j'ai collé dans une classe de base. J'en dérive (virtuellement!) ensuite des classes d'utilitaires tels un timer, ou un notifier / listener. Ensuite, il ne reste qu'à dériver sa classe depuis les classes d'utilitaires: l'on veut écouter tel type d'événements, recevoir un signal toutes les secondes, etc. Tout passer par le strand unique à la classe (d'où l'héritage virtuel), ce qui permet de s'affranchir complétement des locks.

Cela veut également dire que l'état de l'objet ne doit être modifié que depuis le strand, ce qui n'est aucunement garanti lorsque l'on appelle une méthode de l'objet. Il faut donc réexpédier tous les appels de méthodes publiques vers une méthode privée correspondante, à travers le strand. Vu que l'on passe alors un message, il n'est plus possible d'obtenir des valeurs de retour, uniquement des callbacks ou des objets protégés.



Bien évidemment, ce genre d'approche n'est utile que pour une classe limitée de problèmes. Écrire un raytracer orienté événement n'est probablement pas une bonne idée. En revanche, ces techniques pourraient bien se prêter aux jeux.

mercredi 3 août 2011

Iceweasel 5 bientôt dans Squeeze!

La page d'"excuses" de Debian:

Too young, only 3 of 10 days old

Il y a quelques autres points, mais j'ai bien l'impression qu'on se dirige vers un Firefox un poil moderne pour dans une semaine. Chouette!

lundi 1 août 2011

Et moi qui vous délaisse!

C'est que, entre le recrutement d'espions britanniques cherchant à se recaser (eh oui), les batailles incessantes avec un système de middleware dont le nom commence par Tib et finit par Co, et le passage une fois de plus de la souris de la main droite à la main gauche pour des raisons de santé, il faut encore que j'arrive à caser du code à moi.

Le système d'update callbacks pour faire mon système de navigation à l'estime marche d'enfer: je puis passer entre mon système graphique, tournant à plusieurs centaines d'images par seconde, et le système de gamplay, tournant lui à 20 cycles, voire moins, par seconde, sans risquer ni de hacher l'un ni d'envahir l'autre.

En revanche, ma nième tentative pour obtenir un bump mapping dans l'espace tangent s'est achevé par une cuisante défaite. Je n'y arrive simplement pas. Je vais donc rester aux normales dans l'espace objet, telles que je les ai gérées jusqu'à présent.