Spécifications de format des tracés
Cette page décrit le format Tracés et fournit des instructions sur la manipulation des données dans ce format à l’aide des fonctions incluses dans les outils Tracés.
Spécifications de format
Soit *uv\_pos* une adresse 2D (telle que $pos) d’un pixel de la partie supérieure.
Dans la suite de ce document :
- top[uv_pos].XYZW fera référence aux 4 flotteurs stockés dans le pixel de la partie supérieure.
top[uv_pos] == sample_color(paths, uv_pos) - bottom[uv_pos].XYZW fera référence aux 4 flotteurs stockés dans le pixel correspondant de la partie inférieure.
bottom[uv_pos] == sample_color(paths, uv_pos + Flottant 2(0, 0.5))
top[uv_pos] et bottom[uv_pos] forment ensemble une unité sémantique U[uv_pos] du document, composée de 8 flotteurs.
En-tête de document
Chaque document Tracés commence par un en-tête de document. Il s’agit de la toute première unité sémantique U[(0,0)]:
Le nombre de tracés (doit être un entier positif dans [0 ; 16777216]).
Si certains tracés sont vides, ils comptent toujours ici. Vous pouvez donc l’envisager comme un « nombre d’en-têtes de chemins à décoder ».
YZ
Taille de pixel de ce document (c’est-à-dire exactement Float2(1,1) / $size).
Cela est utile lors de la lecture des tracés à partir d’un Processeur de pixels ou d’un Fx-Map, par exemple, dont la taille de sortie est différente.
W
1/16 = 0,0625 (indicateur d’en-tête)
Adresse du dernier vertex défini dans ce document. Ceci est utile pour ajouter de nouvelles données.
Il peut donc s’agir en fait de toute adresse supérieure (par ordre de balayage) à l’adresse du dernier vertex. Il doit être compris entre ]0, 1[×]0,.5[
ZW
Inutilisé, doit être Flottant 2(0, 1)
En-têtes de tracé
L’en-tête du document est immédiatement suivi de number-of-paths = top[(0,0)].X path-headers, one by semantic unit.
E.g. s’il y a 3 tracés dans le document, ils seront stockés en U[(0,1)*pixel_size], U[(0,2)*pixel_size] et U[(0,3)*pixel_size] (avec pixel_size = top[(0,0)].YZ).
S’il y a plus de tracés que ce qu’une ligne de pixels peut contenir, les en-têtes de tracé restants sont écrits sur la ou les lignes suivantes, dans l’ordre des lignes de numérisation.
Il est autorisé d’avoir des en-têtes de chemin d’accès nuls (top[...].XYZW = Float4(0,0,0,0)) ; un tel chemin d’accès peut toujours être vide.
L’en-tête de chemin du Nième chemin sera défini à l’adresse path\_addr comme :
Nombre de vertex dans ce chemin. Doit être compris dans la plage [0, 16777216].
Si les vertex de début et de fin d’un tracé fermé se trouvent à la même position, ils comptent toujours pour 2 vertex.
Un chemin avec 0 vertex est un chemin valide.
Y
Indicateur Est_fermé : 1 si le tracé est fermé (par exemple, un cercle), 0 dans le cas contraire (par exemple, une ligne droite).
Z
L’index de chemin N. Il doit absolument correspondre à path_addr (voir remarque ci-dessous).
W
Indicateur d’en-tête : 1/16 = 0,0625.
Adresse de début (ou première) du vertex.
ZW
Fin (ou dernière) adresse du vertex.
path\_addr à partir de N à l'aide de la fonction Utils/pixel\_index\_to\_position dans paths_tools.sbs : path\_addr = pixel\_index\_to\_position(N+1)informations sur les vertex
Les vertex se trouvent n’importe où dans l’image après les en-têtes (en-têtes de document ou de chemin). Les vertex peuvent être de différents « types » (Début, Milieu ou Fin) et ils sont explicitement liés entre eux à l’aide de 2 pointeurs d’adresse (« liens »).
Les vertex Début et Fin sont spéciaux à cet égard : pour permettre la représentation de tracés fermés ou d’un réseau arbitraire de tracés liés entre eux, l’un des liens est en fait utilisé pour constituer une liste circulaire avant liée de tous les autres vertex Début ou Fin qui représentent le même vertex. Ces vertex qui se correspondent sont appelés « frères et sœurs ». [Illustration accueillie]
Formellement, chaque vertex à l’adresse *vert\_addr* est défini comme ceci :
La position vertex. Les coordonnées peuvent être n’importe quelle valeur flottante autre que NaN ou ±inf. Il n’y a pas de notion de répétition à ce niveau (elle peut être gérée ou non par la mise en œuvre de chaque filtre), les chemins sont donc supposés être définis sur le plan euclidien.
Z
Index de chemin de vertex. Un vertex ne peut appartenir qu’à un seul chemin. (Comme mentionné précédemment, les vertex de début et de fin peuvent toutefois avoir des frères.) L’index de chemin peut être utilisé pour récupérer l’en-tête de chemin (voir la section En-têtes de chemin de section ci-dessus). Assurez-vous donc qu’il est synchronisé.
W
type de vertex. Il est divisé entre le signe de la valeur et sa valeur absolue :
Sur la partie signe, une valeur de 0 signifierait qu’il n’y a pas de vertex ici en fait (tous les autres composants devraient également être 0). Une valeur négative signifie que le vertex est marqué comme un « coin » ; une valeur positive signifie que le vertex est « lisse ». Le vertex d’arrondi et le calque d’arrondi sont des attributs purs et isolés qui n’ont aucun impact ni aucune signification sur le codage des autres tracés.
Sur la partie valeur absolue, le type de pixel (Début, Milieu ou Fin) et un autre drapeau (trivial_link) sont codés:
-
0.125 : vertex de fin (dernier vertex de la forme ; liens toujours non triviaux, voir ci-dessous)
-
0.25 : vertex de début (premier vertex de la forme ; liens toujours non triviaux, voir ci-dessous)
-
0.5 : vertex moyen avec des liens non triviaux
-
1 : milieu de vertex avec des liens insignifiants
Par « liens non triviaux », on entend le fait que les vertex précédent et suivant (dans la liste des vertex du tracé courant) sont stockés respectivement dans le pixel à gauche (vert_addr-(0,pixel_size)) et à droite (vert_addr+(0,pixel_size)), tandis que par « liens non triviaux », on entend qu’au moins l’un d’entre eux est stocké ailleurs.
Indépendamment de la « banalité » des liens, les valeurs fiables des liens sont stockées dans la partie inférieure :
XY
Adresse du vertex précédent de ce chemin. Pour les vertex de démarrage, cette option pointe vers le vertex apparenté suivant.
si |top[vert_addr].W| = 1, puis bottom[vert_addr].XY = vert_addr - (0,pixel_size)
ZW
Adresse du vertex suivant de ce chemin. Pour les vertex d’extrémité, cette option pointe vers le vertex apparenté suivant.
si |top[vert_addr].W| = 1, puis bottom[vert_addr].ZW = vert_addr + (0,pixel_size)
Informations sur les chemins de lecture et d’écriture
Si vous souhaitez créer vos propres nœuds de traitement des tracés, vous disposez de plusieurs outils.
Les bases sont fournies par les nœuds Processeur de Vertex de tracés et Processeur de Vertex de tracés simple, qui peuvent être utilisés de la même manière qu’un Processeur de pixels.
Si vous avez besoin de fonctionnalités au-delà de ce que proposent les nœuds du processeur de Vertex Paths (plus de textures d’entrée, ou plus de vertex précédents ou suivants), la copie de l’implémentation de ce graphe peut être un bon point de départ (en supposant que vous remplacez le nœud Get(« %perVertex ») par votre traitement personnalisé).
Mais au cas où vous voudriez faire quelque chose de plus étrange que l’application d’une fonction par vertex, voici une explication détaillée des outils que vous pouvez utiliser. Il s’agit généralement de petites fonctions d’assistant qui se trouvent dans le même package que les autres nœuds Paths (paths_tools.sbs). (Ces fonctions ne sont pas exposées dans le menu Bibliothèque et le menu Nœud.)
Fonctions de lecture
Sous le dossier Read, vous trouverez plusieurs de ces éléments, utiles pour collecter des informations sur les Chemins :
Certains peuvent vous donner des informations sur un pixel donné. Ils prennent tous la valeur Flottant 4 échantillonnée dans la partie *top* comme entrée. Si vous regardez leur mise en œuvre, ils sont super-simples. Leur but est de donner plus de sens que de simples noeuds atomiques :
is\_header et que current\_pixel\_is\_document\_header a renvoyé la valeur false.is\_vertex).is\_vertex).is\_vertex).is\_start\_vertex || is\_mid\_vertex. Plus utile pour le traitement basé sur Fx-Map, pour traiter chaque segment au plus une fois.is\_vertex : si la réponse est vraie, vous êtes sur un vertex pour sûr). Rappelez-vous que cet indicateur n’est pas encore pris en charge par les nœuds officiels.S’il s’agit d’un vertex, indique si vous pouvez facilement déduire la position des vertex précédent et suivant sans échantillonner la partie inférieure. (Remarque : un non-vertex renvoie toujours la valeur false.)
Vous ne voulez probablement pas l’utiliser directement, mais utilisez plutôt l’une des fonctions sample\_next\* ou sample\_prev\*, qui s’en occupent pour vous.
Compte tenu de la valeur échantillonnée de la partie supérieure *sampled* et de sa position *sampled\_position*, renvoie la valeur échantillonnée de la partie supérieure du vertex suivante (respectivement précédente) et Définit une variable Flottant 2 *next\_sampled\_pos* à la position (dans la partie supérieure) de ce voisin (c’est-à-dire <valeur renvoyée> = SampleColor(next_sampl_pos, image0)). *input0PixSize*doit être égal à la taille en pixels du tracé (top[(0,0)].YZ).
Si le pixel actif (*sampled*) est un vertex Début, sample_prev renvoie le frère suivant de ce vertex. De même, s’il s’agit d’un vertex Fin, sample_next renvoie le frère suivant de ce vertex (ce qui n’est peut-être pas ce que vous voulez). Voir *sample\_next\_advanced* et *sample\_prev\_advanced* ci-dessous pour résoudre ce problème.
Veuillez noter que pour plus de simplicité, les informations sur les chemins d’accès sont supposées être stockées dans input0 ! En outre, contrairement à ce qu’indique le document de la fonction, vous n’avez pas besoin de déclarer préalablement *next\_sampled\_pos*. *[out]next\_sampled\_pos* est un paramètre fictif pour vous rappeler que cette deuxième « valeur renvoyée » existe.
Vous pouvez vérifier le *paths\_trace* Fx-Map, dans le paramètre Itérations du troisième nœud d’itération, pour obtenir un exemple d’utilisation.
Fonctions ‘Write’
Sous le dossier Write, vous trouverez de petits assistants qui créent un Flottant 4 prêt à être écrit par un Fx-Map.
En effet, la Fx-Map multiplie le RGB par Alpha avant de dessiner, de sorte que les valeurs réelles ne sont pas prémultipliées pour compenser. Si vous souhaitez utiliser ces fonctions, par exemple dans un Processeur de pixels, nous vous recommandons de réappliquer la prémultiplication vous-même ou d’écrire une version personnalisée (plus optimisée pour votre cas d’utilisation et plus facile à utiliser).
*nbVertices*, de l’indicateur *isClosed* et de l’indicateur *pathIndex*.Crée la partie supérieure d’un vertex, en définissant la position, le texte et d’autres options en conséquence.
Environ mid_vertex et le paramètre hasTrivialLinks : idéalement, vous devez définir la valeur appropriée, mais si, pour une raison quelconque, vous ne parvenez pas à dire si les liens seront triviaux ou non, vous pouvez sans danger la définir sur false (au prix d’un traitement plus lent de votre chemin généré).
Il n’existe pas de générateur de partie inférieure pour les en-têtes de tracé ou les vertex : les deux codent deux liens vers la partie supérieure, de sorte que cette fonction serait essentiellement un constructeur Vecteur flottant4 de deux Flottant 2. N’oubliez pas de diviser XYZ par W si vous écrivez à l’aide d’une Fx-Map (W étant le Y d’une adresse, elle ne doit jamais être nulle).
Vous trouverez un exemple pertinent d’utilisation de ces fonctions dans le package chemins_polygon.sbs hébergeant le nœud polygone des chemins.
Procédés de traitement de tracés
Vous utiliserez probablement un Processeur de pixels ou un Fx-Map pour mettre en œuvre votre traitement personnalisé, chacun ayant sa force et ses faiblesses :
La solution basée sur Fx-Map est généralement préférée lors de l’exécution d’opérations de haut niveau nécessitant une connaissance globale de l’ensemble du (ou des) chemin(s), ou d’une connaissance cumulative (par exemple, le reconditionnement des vertex après décimation ou tessellation). Il s’agit également de l’approche la plus simple. Par conséquent, si vous effectuez un traitement personnalisé pour la première fois, vous pouvez utiliser une Fx-Map, même si est peut-être plus lent.
Vous devez d’abord vous familiariser avec Fx-Map. Si ce n’est pas le cas, consultez la documentation spécifique.
Nous vous recommandons d’examiner l’implémentation des chemins d’aperçu dans chemins_trace.sbs et du polygone des chemins dans chemins_polygone.sbs pour vous faire une idée de la lecture et de l’écriture (respectivement) d’un chemin à l’aide d’une Fx-Map.
La solution Processeur de pixels conviendra si vous avez uniquement besoin d’informations « locales ». Ici, nous voulons dire « local » non pas spatialement (la distance entre les éléments) mais plutôt topologiquement (les vertex liés entre eux). C’est ainsi que le processeur de Vertex est implémenté. Le Processeur de pixels est généralement plus rapide que la Fx-Map pour ce type d’opération, car la fonction de chaque pixel est évaluée en parallèle, alors que seule une quantité limitée de données est accessible. L’effort d’implémentation peut être beaucoup plus important, car vous ne pouvez modifier que le pixel actuel.
Nous n’entrerons pas dans les détails, car il y a tant à dire en fonction de votre cas d’utilisation spécifique, mais la première chose à faire est de vérifier où vous êtes :
Êtes-vous dans la partie supérieure ($pos.y < 0,5) ou inférieure ($pos.y > 0,5) ? Nous vous recommandons de ne pas oublier que dans une variable dédiée (par exemple, *isTop*) et de créer un Flottant 2 *vert.addr*, cette valeur est *$pos* pour la partie supérieure et $pos - (0,0.5) pour la partie inférieure.
Qu’en est-il à vert.addr ? Échantillonnez-le et vérifiez s’il y a quelque chose (W != 0), puis, s’il y en a, quoi exactement. Un en-tête (W = 0,0625) (cochez avec *Read/is\_header*) ou un vertex (cochez avec Read/is\_vertex) ? S’il s’agit d’un en-tête, est-ce l’en-tête du document ou un en-tête Chemin ? (Vous pouvez utiliser *Read/current\_pixel\_is\_document\_header* pour vérifier cela.) Utilisez une ou plusieurs fonctions d’assistant pour trouver ce qui vous intéresse.