Especificaciones de formato de trazados
Esta página describe el formato de trazados y proporciona instrucciones para manipular los datos en ese formato mediante las funciones incluidas en las herramientas de trazados.
Especificaciones de formato
Permita que *uv\_pos* sea una dirección 2D (como $pos) de un píxel de la parte ‘superior’.
En el resto de este documento:
- top[uv_pos].XYZW hará referencia a los 4 elementos flotantes almacenados en el píxel de la parte superior.
top[uv_pos] == muestra_color(rutas, uv_pos) - bottom[uv_pos].XYZW hará referencia a los 4 elementos flotantes almacenados en el píxel coincidente de la parte inferior.
bottom[uv_pos] == muestra_color(rutas, uv_pos + Flotante2(0, 0.5))
top[uv_pos] y bottom[uv_pos] juntos forman una unidad semántica U[uv_pos] del documento, compuesta por 8 flotantes.
Encabezado del documento
Cada documento de Paths comienza con un encabezado de documento. Es la primera unidad semántica U[(0,0)]:
El número de rutas (debe ser un entero positivo en [0; 16777216]).
Si algunos trazados están vacíos, todavía cuentan aquí. Por lo tanto, puede pensarlo como un “número de encabezados de trazados que se deben decodificar”.
YZ
El tamaño de píxel de este documento (es decir, exactamente Float2(1,1) / $size).
Esto es útil cuando se leen las rutas de acceso desde un procesador de píxeles o un mapa de píxeles, por ejemplo, cuyo tamaño de salida es diferente.
W
1/16 = 0,0625 (indicador de encabezado)
La dirección del último vértice definido en este documento. Esto resulta útil para anexar nuevos datos.
Por lo tanto, puede ser realmente cualquier dirección mayor (en orden de escaneado) que la dirección del último vértice. Debe estar en el intervalo ]0, 1[×]0, .5[
ZW
No utilizado, debe ser Float2(0, 1)
Encabezados de ruta
El encabezado del documento va seguido inmediatamente de los encabezados de número de rutas = top[(0,0)].X, uno por unidad semántica.
E.g. si hay 3 rutas en el documento, se almacenarán en U[(0,1)*pixel_size], U[(0,2)*pixel_size] y U[(0,3)*pixel_size] (con pixel_size = top[(0,0)].YZ).
Si hay más trazados de los que puede contener una línea de píxeles, los encabezados de trazado restantes se escriben en la siguiente línea o líneas, en orden de escaneado.
Se permite tener encabezados de ruta de acceso null (top[...].XYZW = Float4(0,0,0,0)); dicho trazado podría seguir siendo un único trazado vacío.
El encabezado de ruta de acceso de la ruta de acceso N se definirá en la dirección path\_addr y se definirá como:
Número de vértices de este trazado. Debe estar en el intervalo [0, 1677216].
Si los vértices inicial y final de un trazado cerrado están en la misma posición, todavía cuentan para 2 vértices.
Una ruta con 0 vértices es una ruta válida de todos modos.
Y
Indicador Is_closed: 1 si el trazado está cerrado (por ejemplo, un círculo), 0 en caso contrario (por ejemplo, una línea recta).
Z
El índice de la ruta N. Debe coincidir absolutamente con path_addr (consulte la nota siguiente).
W
El indicador de encabezado: 1/16 = 0,0625.
Dirección de vértice inicial (o primera).
ZW
Dirección de fin (o último) vértice.
path\_addr desde N mediante la función Utils/pixel\_index\_to\_position en rutas_tools.sbs: path\_addr = pixel\_index\_to\_position(N+1)Información de vértices
Los vértices se pueden encontrar en cualquier parte de la imagen después de los encabezados (encabezados de documento o de ruta). Los vértices pueden ser de varios “tipos” (Inicio, Medio o Fin) y se vinculan explícitamente entre sí mediante 2 punteros de dirección (“vínculos”).
Los vértices Inicio y Fin son especiales en este sentido: Para permitir la representación de trazados cerrados o de una red arbitraria de trazados enlazados entre sí, uno de los enlaces se utiliza realmente para formar una lista circular enlazada hacia delante de todos los demás vértices de Inicio o Fin que representan el mismo vértice. Tales vértices que coinciden entre sí se llaman “hermanos”. [Ilustración bienvenida]
Formalmente, cada vértice de la dirección *vert\_addr* se define así:
La posición del vértice. Las coordenadas pueden ser cualquier valor flotante que no sea NaN o ±inf. No existe la noción de mosaico en este nivel (puede ser manejado o no por la implementación de cada filtro), por lo que se supone que los trazados deben ser definidos en el plano euclidiano.
Z
El índice de trazado de vértice. Un vértice solo puede pertenecer a un trazado. (Como se mencionó anteriormente, los vértices inicial y final pueden tener hermanos). El índice de ruta se puede utilizar para recuperar el encabezado de ruta (consulte Encabezados de ruta de sección más arriba), por lo que debe estar sincronizado.
W
Tipo de vértice. Se divide entre el signo del valor y su valor absoluto:
En la parte de signo, un valor de 0 significaría que no hay ningún vértice aquí en realidad (todos los demás componentes deben ser 0 también). Un valor negativo significa que el vértice está marcado como una “esquina”; uno positivo que el vértice es “liso”. El vértice de vértice frente a vértice suave es un atributo puro y aislado y no tiene ningún impacto ni significado en el resto de la codificación de Trazados.
En la parte de valor absoluto, el tipo de píxel (Inicio, Medio o Fin) y otro indicador (trivial_link) están codificados:
-
0,125: Vértice del extremo (el último vértice de la forma; enlaces siempre no triviales, ver a continuación)
-
0,25: Vértice inicial (el primer vértice de la forma; enlaces siempre no triviales, ver a continuación)
-
0,5: Vértice medio con vínculos no triviales
-
1: Vértice medio con vínculos triviales
“Vínculos triviales” se refiere al hecho de que los vértices anterior y siguiente (en la lista de vértices del trazado actual) se almacenan en el píxel a la izquierda (vert_addr-(0,pixel_size)) y a la derecha (vert_addr+(0,pixel_size) respectivamente, mientras que “vínculos no triviales” significa que al menos uno de estos se almacena en otro lugar.
Independientemente de la “trivialidad” de los vínculos, los valores de confianza de los vínculos se almacenan en la parte inferior:
XY
La dirección del vértice anterior de esta ruta. Para los vértices de inicio, esto señala al siguiente vértice del mismo nivel.
si |top[vert_addr].W| = 1, then bottom[vert_addr].XY = vert_addr - (0,pixel_size)
ZW
La dirección del siguiente vértice de esta ruta. Para los vértices finales, esto apunta al siguiente vértice del mismo nivel.
si |top[vert_addr].W| = 1, then bottom[vert_addr].ZW = vert_addr + (0,pixel_size)
Leer y escribir información de trazados
Si desea crear sus propios nodos de procesamiento de trazados, dispone de varias herramientas.
Los conceptos básicos los proporcionan los nodos Paths Vertex Processor y Paths Vertex Processor Simple, que básicamente se pueden usar de la misma manera que un Procesador de píxeles.
Si necesita características más allá de lo que ofrecen los nodos del procesador de vértices de rutas (más texturas de entrada, o más vértices anteriores o siguientes), copiar la implementación de este gráfico podría ser un buen punto de partida (suponiendo que reemplace el nodo Get(“%perVertex”) por su procesamiento personalizado).
Pero en caso de que quieras hacer algo más extraterrestre que aplicar una función por vértice, aquí hay una explicación detallada de las herramientas que puedes usar. Estas suelen ser pequeñas funciones auxiliares que se pueden encontrar en el mismo paquete que los otros nodos de rutas (rutas_tools.sbs). (Estas funciones no se exponen en el menú Biblioteca y Nodo.)
Funciones de ‘Lectura’
En la carpeta Read, puede encontrar varias de estas, útiles para recopilar información sobre las rutas:
Algunos pueden proporcionarle información sobre un píxel determinado. Todos toman como entrada el valor Float4 muestreado en la parte *top*. Si se fijan en su implementación, son súper simples. Su objetivo es transmitir más significado que los nodos atómicos:
is\_header y que current\_pixel\_is\_document\_header devolvió false.is\_vertex primero).is\_vertex primero).is\_vertex primero).is\_start\_vertex || is\_mid\_vertex. Es más útil para el procesamiento basado en Fx-Map, para procesar cada segmento como máximo una vez.is\_vertex primero: si la respuesta es verdadera, usted está en un vértice seguro). Por favor recuerde que esta bandera no está soportada aún por nodos oficiales.Si se trata de un vértice, indica si se puede deducir fácilmente la posición de los vértices anterior y siguiente sin muestrear la parte inferior. (Nota: Un elemento que no sea un vértice siempre devolverá false.)
Probablemente no desee usar esto directamente, sino más bien usar una de las funciones sample\_next\* o sample\_prev\*, que se encargan de ello por usted.
Dado el valor muestreado de la parte superior *sampled* y su posición *sampled\_position*, devuelve el valor muestreado de la parte superior del vértice siguiente (respectivamente anterior) y establece una variable Flotante2 *next\_sampled\_pos* en la posición (en la parte superior) de este vecino (es decir, <valor devuelto> = SampleColor(next_sampled_pos, image0). *input0PixSize* debe ser igual al tamaño de píxel del trazado (top[(0,0)].YZ).
Si el píxel actual (*sampled*) es un vértice Start, sample_prev devolverá el siguiente elemento relacionado de este vértice; del mismo modo, si es un vértice End, sample_next devolverá el siguiente hermano de este vértice (es decir, tal vez no sea lo que desee). Consulte *sample\_next\_advanced* y *sample\_prev\_advanced* a continuación para resolver este problema.
Tenga en cuenta que para simplificar, se supone que la información de rutas se almacena en input0! Además, a diferencia de lo que indica el documento de la función, no es necesario declarar previamente *next\_sampled\_pos*. *[out]next\_sampled\_pos* es un parámetro ficticio para recordarle que este segundo “valor devuelto” existe.
Puede comprobar *paths\_trace* Fx-Map, en el parámetro Iteraciones del tercer nodo iterado, para obtener un ejemplo de cómo usarlo.
Funciones de ‘escritura’
En la carpeta Write, encontrará pequeños ayudantes que crean un Flotante4 listo para ser escrito por un Fx-Map.
De hecho, Fx-Map multiplica RGB por Alpha antes de dibujar, por lo que los valores reales no se premultiplican para compensar eso. Si desea utilizar estas funciones, por ejemplo, en un Procesador de píxeles, le recomendamos que aplique de nuevo la premultiplicación o que escriba una versión personalizada (más optimizada para su caso de uso y más fácil de usar).
*nbVertices*, el indicador *isClosed* y *pathIndex*.Crea la parte superior de un vértice, estableciendo la posición, el texto y otras opciones en consecuencia.
Acerca de mid_vertex y el parámetro hasTrivialLinks: Lo ideal sería establecer el valor adecuado, pero si por cualquier razón no se puede saber si los vínculos serán triviales o no, se puede establecer con seguridad en false (a costa de un procesamiento más lento de la ruta generada).
No hay ningún generador de partes inferiores para encabezados de ruta ni vértices: ambos codifican dos vínculos en la parte superior, por lo que esta función sería esencialmente un constructor Flotante de vector4 de dos Flotante2. No olvide dividir XYZ por W si está escribiendo con Fx-Map (dado que W es la Y de una dirección, nunca debe ser null).
Encontrará un ejemplo pertinente de cómo usar estas funciones en el paquete paths_polygon.sbs que aloja el nodo Paths Polygon.
Métodos para procesar rutas
Es probable que utilice un Procesador de píxeles o un Fx-Map para implementar su procesamiento personalizado, cada uno de los cuales tiene sus fortalezas y debilidades:
La solución basada en Fx-Map suele ser la preferida cuando se realizan operaciones de alto nivel que requieren un conocimiento global de toda la ruta (o rutas) o una acumulativa (por ejemplo, reempaquetar los vértices después de la diezmación o teselación). También es la forma más sencilla de abordarlo, por lo que si está realizando un procesamiento personalizado por primera vez, puede que desee utilizar un mapa de efectos, a pesar de que puede ser más lento.
En primer lugar, debe estar familiarizado con Fx-Map. Si no es así, consulte la documentación específica.
Le recomendamos que examine la implementación de Rutas de vista previa en rutas_trace.sbs y Rutas polígono en rutas_polygon.sbs para tener una idea sobre cómo leer y escribir (respectivamente) una ruta usando un mapa de efectos.
La solución Procesador de píxeles se ajustará si solo necesitas información “local”. Aquí queremos decir “local” no espacialmente (la distancia entre el elemento) sino topológicamente (vértices unidos). Así es como se implementa el procesador de vértices. El Procesador de píxeles suele ser más rápido que el Fx-Map para este tipo de operaciones, ya que la función de cada píxel se evalúa en paralelo, mientras que solo se accede a una cantidad limitada de datos. Sin embargo, el esfuerzo de implementación podría ser mucho más importante, ya que solo puede modificar el píxel actual.
No entraremos en detalles, ya que hay mucho que decir dependiendo de su caso de uso específico, pero lo primero que hay que hacer es comprobar dónde se encuentra:
¿Está en la parte superior ($pos.y < 0.5) o inferior ($pos.y > 0.5)? Recomendamos que recuerde que en una variable dedicada (p.ej. *isTop*), y que crea un Flotante *vert.addr*, cuyo valor es *$pos* para la parte superior y $pos - (0,0.5) para la parte inferior.
¿Qué hay en vert.addr? Muéstrelo y compruebe si hay algo (W != 0) entonces, si lo hay, qué exactamente. ¿Un encabezado (W = 0,0625) (comprobar con *Read/is\_header*) o un vértice (comprobar con Read/is\_vertex)? Y si es un encabezado, ¿es el encabezado del documento o un encabezado de ruta? (Puede usar *Read/current\_pixel\_is\_document\_header* para comprobarlo). Utilice una o varias de las funciones auxiliares para que coincidan con lo que le resulte interesante.