.bread

Open 3D file format · Draft specification · Apache-2.0Formato de archivo 3D abierto · Especificación en borrador · Apache-2.0

Specification draft — the full text will be published when version 1 is frozen.Especificación en borrador: el texto completo se publica cuando se congele la versión 1.

Every bit of the mesh. A twelfth of the size.Cada bit de la malla. Un doceavo del tamaño.

.bread is an open file format for triangle meshes and the scene that places them. A mesh read back is the mesh that was written: every coordinate bit for bit, every triangle in the same order, starting at the same corner. It is meant to replace STL wherever a model goes from one program, or one person, to another..bread es un formato de archivo abierto para mallas de triángulos y la escena que las ubica. La malla que se lee es la que se escribió: cada coordenada bit a bit, cada triángulo en el mismo orden y empezando por la misma esquina. Está pensado para reemplazar al STL donde sea que un modelo pase de un programa, o de una persona, a otra.

BREAD stands for Bit-exact Representation of Editable Assembly Data. It is also just bread: Breadslicer slices it, and the slices are the layers.BREAD quiere decir Bit-exact Representation of Editable Assembly Data. Y también es pan, nomás: Breadslicer lo rebana, y las rebanadas son las capas.

94.9MB

a 1.9 M triangle figure, as binary STLuna figura de 1,9 M de triángulos, en STL binario

7.6MB

the same figure, as .breadla misma figura, en .bread

0bits

lost on the wayperdidos en el camino

magic
versionversión
42
B
52
R
45
E
41
A
44
D
00
NUL
0D
CR
0A
LF
01
1
00
Every .bread file starts with these ten bytes · u16 little-endian · offsets 0–9Todo archivo .bread empieza con estos diez bytes · u16 little-endian · offsets 0–9

§ 01.bread

The numbersLos números

One figure of 1.9 million triangles and 950 thousand vertices, stored seven ways. Every one of them keeps the whole mesh; only one of them is small.Una figura de 1,9 millones de triángulos y 950 mil vértices, guardada de siete maneras. Todas guardan la malla entera; una sola es chica.

File size of a 1.9 M triangle figureTamaño de una figura de 1,9 M de triángulos

STL binary
94.9 MB
OBJ
73.1 MB
STL · zip
41.2 MB
STL · 7z
33.2 MB
OBJ · zstd 19
15.8 MB
.bread v1
8.5 MB
.bread v2
7.6 MB
Same mesh in every row, lossless · bars drawn to the same scale · .bread v2 is about 7.6 MBLa misma malla en cada fila, sin pérdida · barras a la misma escala · .bread v2 pesa unos 7,6 MB

Mesh version 2 against version 1 · same content, bit for bitMalla versión 2 contra versión 1 · mismo contenido, bit a bit

−24.7%

on a corpus of 22 meshes, 255 MB as STLen un corpus de 22 mallas, 255 MB en STL

5.9–9.1×

smaller than the STL, mesh by meshmás chico que el STL, malla por malla

−36%

on a large mesh of supportsen una malla grande de soportes

10–35%

smaller, on 15 real Breadslicer projectsmás chicos, en 15 proyectos reales de Breadslicer

By kind of model: −15 % on the 1.9 M figure, −19 to −27 % on sculptures, −1 to −8 % on CAD parts, whose flat faces leave little to predict.Por tipo de modelo: −15 % en la figura de 1,9 M, −19 a −27 % en esculturas, −1 a −8 % en piezas CAD, cuyas caras planas dejan poco para predecir.

Speed, determinism and weightVelocidad, determinismo y peso

~50ms

to open the 1.9 M figure, native, version 1para abrir la figura de 1,9 M, nativo, versión 1

205ms

to open it cold in WebAssembly, version 2para abrirla en frío en WebAssembly, versión 2

~0.5s

to save 2 million trianglespara guardar 2 millones de triángulos

62KB

the web reader, brotli; 119 KB with the writerel lector web, con brotli; 119 KB con el escritor

The same file comes out as the same bytes on Windows, Linux and WebAssembly. Measured on a desktop PC; WebAssembly in Node 26 on V8, the engine of Chrome.El mismo archivo sale con los mismos bytes en Windows, Linux y WebAssembly. Medido en una PC de escritorio; WebAssembly en Node 26 sobre V8, el motor de Chrome.

§ 02.bread

What it holdsQué guarda

Geometry, and only geometry, kept exactly. One file carries a whole kit of parts, with their names, ready for whoever opens it next.Geometría, y solo geometría, guardada exacta. Un archivo lleva un kit entero de partes, con sus nombres, listo para quien lo abra después.

KeptSe guarda

  • Every vertex coordinate, bit for bit: negative zero, subnormals and NaN payloads included.
  • Every triangle, in the same order, starting at the same corner: winding and first corner both survive.
  • A scene: named parts, groups, meshes shared between parts, copies of whole subtrees, and a transform on every node.
  • Room for a slicer: editable supports, hollowed models, paint on faces, a thumbnail and a preview of the supports.
  • Cada coordenada de cada vértice, bit a bit: el cero negativo, los subnormales y los NaN con su contenido incluidos.
  • Cada triángulo, en el mismo orden y empezando por la misma esquina: sobreviven el sentido de giro y la primera esquina.
  • Una escena: partes con nombre, grupos, mallas compartidas entre partes, copias de subárboles enteros y una transformación en cada nodo.
  • Lugar para un slicer: soportes editables, modelos ahuecados, pintura en las caras, una miniatura y una vista previa de los soportes.

Left out, on purposeSe deja afuera, a propósito

  • Colours, textures, UV coordinates, materials and animation. That is glTF's job, and .bread does not compete with it.
  • The facet normals an STL stores with every triangle. They are file data, not geometry: any program computes them from the corners.
  • Colores, texturas, coordenadas UV, materiales y animación. Eso es trabajo de glTF, y .bread no compite con él.
  • Las normales que el STL guarda con cada triángulo. Son datos del archivo, no geometría: cualquier programa las calcula desde las esquinas.

Who it is for. Designers who hand models to someone else, such as a client, and anyone who wants to take a pre-supported model out of a slicer with its supports still editable. It replaces STL; it is not another scene format for games or rendering.

Where it comes from. It started as the project file of Breadslicer, a resin slicer. It is now a format of its own, with its own specification and a reference implementation under the Apache-2.0 licence, while Breadslicer stays AGPL. The application chunks are Breadslicer's; any other program can skip them and still read the same meshes in the same scene.

Para quién es. Para diseñadores que le entregan modelos a otra persona, por ejemplo a un cliente, y para cualquiera que quiera sacar de un slicer un modelo presoportado con los soportes todavía editables. Reemplaza al STL; no es otro formato de escenas para juegos o render.

De dónde viene. Empezó como el archivo de proyecto de Breadslicer, un slicer de resina. Hoy es un formato propio, con su especificación y una implementación de referencia bajo licencia Apache-2.0, mientras que Breadslicer sigue siendo AGPL. Los chunks de aplicación son los de Breadslicer; cualquier otro programa puede saltearlos y leer igual las mismas mallas en la misma escena.

§ 03.bread

Anatomy of a fileAnatomía de un archivo

A ten-byte header, then chunks, one after another, until the file ends. No index, no end marker, no padding.Una cabecera de diez bytes y después chunks, uno detrás de otro, hasta que termina el archivo. Sin índice, sin marca de fin, sin relleno.

The magic is built the way PNG's is. BREAD names the format to anyone looking at the bytes. The NUL byte makes tools that guess whether a file is text treat it as binary. CR LF catches a file that went through a text-mode transfer: turning line endings into LF, or into CR LF, changes the magic. Anything a transfer breaks further on is caught by the chunk checksums.

Each chunk carries a four-byte tag that says what it holds, a version of its own, and a payload that is compressed and guarded by a checksum. All numbers are little-endian, with no padding or alignment.

El magic está armado como el de PNG. BREAD le dice el formato a cualquiera que mire los bytes. El byte NUL hace que las herramientas que adivinan si un archivo es texto lo traten como binario. CR LF detecta un archivo que pasó por una transferencia en modo texto: pasar los finales de línea a LF, o a CR LF, cambia el magic. Lo que una transferencia rompa más adelante lo detectan los checksums de los chunks.

Cada chunk lleva un tag de cuatro bytes que dice qué guarda, una versión propia y un payload comprimido y protegido por un checksum. Todos los números son little-endian, sin relleno ni alineación.

tag
what it holdsqué guarda
version
of this chunkde este chunk
lengths
raw and storedcrudo y guardado
CRC-32
of the stored bytesde los bytes guardados
payload · zstd
the data itself, compressedlos datos, comprimidos
One chunk: a short header, then the payload compressed with zstd · the next chunk starts right after itUn chunk: una cabecera corta y después el payload comprimido con zstd · el chunk siguiente empieza justo después

Stored bytes. One Zstandard frame (RFC 8878) that decompresses to the payload: no dictionary, and a window of at most 8 MB, so every decoder can read it. The compression level is the writer's choice; two writers may store the same payload as different bytes. The checksum is the CRC-32 of zlib, gzip and PNG, over the stored bytes only, and stored little-endian like everything else:

Bytes guardados. Un frame de Zstandard (RFC 8878) que descomprime al payload: sin diccionario y con una ventana de 8 MB como mucho, para que cualquier decodificador lo pueda leer. El nivel de compresión lo elige quien escribe; dos escritores pueden guardar el mismo payload con bytes distintos. El checksum es el CRC-32 de zlib, gzip y PNG, solo sobre los bytes guardados, y se guarda en little-endian como todo lo demás:

4.3
g(x)=0x04C11DB7  (reflected: 0xEDB88320),init=xorout=0xFFFFFFFFCRC-32⁡("123456789")=0xCBF43926\begin{array}{l} g(x) = \texttt{0x04C11DB7}\ \ (\text{reflected: } \texttt{0xEDB88320}),\qquad \text{init} = \text{xorout} = \texttt{0xFFFFFFFF} \\[6pt] \crc(\texttt{"123456789"}) = \texttt{0xCBF43926} \end{array}
g(x)=0x04C11DB7  (reflejado: 0xEDB88320),init=xorout=0xFFFFFFFFCRC-32⁡("123456789")=0xCBF43926\begin{array}{l} g(x) = \texttt{0x04C11DB7}\ \ (\text{reflejado: } \texttt{0xEDB88320}),\qquad \text{init} = \text{xorout} = \texttt{0xFFFFFFFF} \\[6pt] \crc(\texttt{"123456789"}) = \texttt{0xCBF43926} \end{array}

What a reader must doQué tiene que hacer un lector

It findsIt must
fewer than 8 bytes, or 8 bytes that are not the magicrefuse: it is not a .bread file
a container version newer than the reader knowsrefuse the file
the file ends inside a header or inside stored bytesrefuse: it is cut short
a CRC that does not match, in any chunkrefuse: it is damaged
a tag the reader does not knowskip the chunk and go on
a known tag at a newer chunk versionrefuse the file
stored bytes that are not one valid frame, or that do not decompress to exactly the raw lengthrefuse: it is damaged
EncuentraTiene que
menos de 8 bytes, u 8 bytes que no son el magicrechazar: no es un archivo .bread
una versión de contenedor más nueva que las que conoce el lectorrechazar el archivo
el archivo termina dentro de una cabecera o de los bytes guardadosrechazar: está cortado
un CRC que no coincide, en cualquier chunkrechazar: está dañado
un tag que el lector no conocesaltear el chunk y seguir
un tag conocido con una versión de chunk más nuevarechazar el archivo
bytes guardados que no son un frame válido, o que no descomprimen a exactamente el largo crudorechazar: está dañado

Skipping unknown tags is how new kinds of chunks arrive without breaking old readers. Refusing a known tag at a newer version is the other half: skipping it could lose data the rest of the file depends on.Saltear los tags desconocidos es lo que permite sumar chunks nuevos sin romper lectores viejos. Rechazar un tag conocido en una versión más nueva es la otra mitad: saltearlo podría perder datos de los que depende el resto del archivo.

The chunk registryEl registro de chunks

TagVersionVersiónPer filePor archivoHoldsGuarda
SCNE1exactly oneexactamente unothe scene: nodes, transforms and the meshes they usela escena: nodos, transformaciones y las mallas que usan
MESH2any numbercualquier cantidadone triangle mesh; version 1 is still readuna malla de triángulos; la versión 1 se sigue leyendo
THMB1at most onea lo sumo unoa thumbnail, as a PNG of up to 512 × 512una miniatura, como PNG de hasta 512 × 512
PROJ1at most onea lo sumo unoapplication data: project settingsdatos de aplicación: ajustes del proyecto
SUPP2at most onea lo sumo unoapplication data: editable supportsdatos de aplicación: soportes editables
HOLW2at most onea lo sumo unoapplication data: hollowed modelsdatos de aplicación: modelos ahuecados
SPRV1at most onea lo sumo unoa preview of the supports, for readers that skip SUPPuna vista previa de los soportes, para lectores que saltean SUPP
SURF1at most onea lo sumo unopaint on the faces of modelspintura en las caras de los modelos

A tag is four ASCII letters or digits, and the case of its first letter says who owns it: uppercase tags are official and listed here; lowercase tags are private, for a program's own data, and no official chunk will ever use one. A private chunk may not change what the official chunks mean, so a reader that skips it still reads the same meshes in the same scene.

Un tag son cuatro letras o dígitos ASCII, y la mayúscula o minúscula de la primera letra dice de quién es: los tags en mayúscula son oficiales y están en esta lista; los de minúscula son privados, para datos propios de un programa, y ningún chunk oficial va a usar uno. Un chunk privado no puede cambiar lo que significan los oficiales, así que un lector que lo saltea lee las mismas mallas en la misma escena.

§ 04.bread

The sceneLa escena

A tree of groups and leaves. Every node has a transform, every leaf shows one mesh, and anything used twice is stored once.Un árbol de grupos y hojas. Cada nodo tiene una transformación, cada hoja muestra una malla, y lo que se usa dos veces se guarda una.

roots
└─ group      "kit"
   ├─ leaf    "base"            → mesh 0
   ├─ leaf    "arm L"           → mesh 1
   ├─ leaf    "arm R"   M = −x  → mesh 1
   ├─ reference          T₁  → subtree 0
   └─ reference          T₂  → subtree 0

subtree 0
└─ group      "bolt"
   └─ leaf    "thread"          → mesh 2
A kit of parts as a scene · arm R shows the same mesh as arm L, mirrored, and it is stored once · each reference places one more boltUn kit de partes como escena · arm R muestra la misma malla que arm L, espejada, y se guarda una vez · cada referencia pone un tornillo más

group

holds other nodes, in orderagrupa otros nodos, en orden

leaf

shows one meshmuestra una malla

shared leaf

shows a mesh kept as shared on purpose: editing it changes every leaf that shows itmuestra una malla compartida a propósito: editarla cambia todas las hojas que la muestran

reference

places one more copy of a whole subtreepone una copia más de un subárbol entero

The result of an operation on several meshes, such as a boolean difference, is stored as a leaf that shows the resulting mesh.El resultado de una operación entre mallas, como una diferencia booleana, se guarda como una hoja que muestra la malla resultante.

Transforms. A node's transform is a 3 × 3 matrix MM and a translation tt, in f64. It takes a point from the node's own space to its parent's:

Transformaciones. La transformación de un nodo es una matriz MM de 3 × 3 y una traslación tt, en f64. Lleva un punto del espacio del nodo al de su padre:

5.2
p′=M p+t⟺(x′y′z′)=(m00m01m02m10m11m12m20m21m22)(xyz)+(txtytz)p' = M\,p + t \qquad\Longleftrightarrow\qquad \begin{pmatrix} x' \\ y' \\ z' \end{pmatrix} = \begin{pmatrix} m_{00} & m_{01} & m_{02} \\ m_{10} & m_{11} & m_{12} \\ m_{20} & m_{21} & m_{22} \end{pmatrix} \begin{pmatrix} x \\ y \\ z \end{pmatrix} + \begin{pmatrix} t_x \\ t_y \\ t_z \end{pmatrix}

Walking down from each root, starting with the identity, every node's world transform is its parent's composed with its own, and a leaf sends each vertex vv of its mesh to W(leaf)(v)W(\text{leaf})(v). A reference continues into its subtree as if it were its only child.

Bajando desde cada raíz y empezando por la identidad, la transformación de mundo de cada nodo es la de su padre compuesta con la propia, y una hoja manda cada vértice vv de su malla a W(hoja)(v)W(\text{hoja})(v). Una referencia sigue por su subárbol como si fuera su único hijo.

5.4
W(node)=W(parent)∘T(node),(A∘B)(p)=A(B(p))W(\text{node}) = W(\text{parent}) \circ T(\text{node}),\qquad (A \circ B)(p) = A\big(B(p)\big)
W(nodo)=W(padre)∘T(nodo),(A∘B)(p)=A(B(p))W(\text{nodo}) = W(\text{padre}) \circ T(\text{nodo}),\qquad (A \circ B)(p) = A\big(B(p)\big)

Transforms are f64 and vertices f32, so world positions are computed in f64 and rounded to f32 only at the end, if at all.

No cycles, without checking for them. Nodes are listed children first: every node names only nodes, meshes and subtrees listed before it. So no node can contain itself and no subtree can reach itself through references, and a reader proves it just by reading in order. It still checks that each node has at most one place: one group's child, a root, or a subtree's root.

Las transformaciones son f64 y los vértices f32, así que las posiciones de mundo se calculan en f64 y se redondean a f32 recién al final, si hace falta.

Sin ciclos, sin buscarlos. Los nodos van con los hijos primero: cada nodo nombra solo nodos, mallas y subárboles listados antes. Así ningún nodo puede contenerse a sí mismo y ningún subárbol puede llegar a sí mismo por referencias, y un lector lo demuestra con solo leer en orden. Igual verifica que cada nodo tenga a lo sumo un lugar: hijo de un grupo, raíz, o raíz de un subárbol.

§ 05.bread

The meshLa malla

Vertices and the triangles that name them. A writer may not reorder anything to compress better: it has to find another way.Vértices y los triángulos que los nombran. Quien escribe no puede reordenar nada para comprimir mejor: tiene que encontrar otra manera.

Version 1 stands on two published bitstreams, the ones meshoptimizer wrote for glTF. Vertices, three f32 each, go through the attribute codec of KHR_meshopt_compression. It works on bytes and keeps every one, so it keeps every bit of every coordinate. Triangles go through its triangle codec.

The triangle codec may hand a triangle back starting at another corner: (a,b,c)(a,b,c) can come back as (b,c,a)(b,c,a) or (c,a,b)(c,a,b), with the same winding. A list of rotations names those triangles and the corner each one starts at, and turns them back:

La versión 1 se apoya en dos bitstreams publicados, los que meshoptimizer escribió para glTF. Los vértices, tres f32 cada uno, pasan por el códec de atributos de KHR_meshopt_compression. Trabaja sobre bytes y los guarda todos, así que guarda cada bit de cada coordenada. Los triángulos pasan por su códec de triángulos.

El códec de triángulos puede devolver un triángulo empezando por otra esquina: (a,b,c)(a,b,c) puede volver como (b,c,a)(b,c,a) o (c,a,b)(c,a,b), con el mismo sentido de giro. Una lista de rotaciones nombra esos triángulos y la esquina por la que empieza cada uno, y los da vuelta:

6.5
(s0, s1, s2) → c  (sc, s(c+1) mod 3, s(c+2) mod 3),c∈{1,2}(s_0,\,s_1,\,s_2)\ \xrightarrow{\ c\ }\ \big(s_{c},\ s_{(c+1) \bmod 3},\ s_{(c+2) \bmod 3}\big),\qquad c \in \{1, 2\}

Version 2 · trianglesVersión 2 · triángulos

Connectivity A, in their own order, or B, in the codec's order with a permutation back.Conectividad A, en su orden, o B, en el orden del códec con una permutación de vuelta.

Version 2 · verticesVersión 2 · vértices

The meshopt codec as in version 1, or a prediction plus its residuals, coded with rANS or as byte planes.El códec de meshopt como en la versión 1, o una predicción más sus residuos, codificados con rANS o como planos de bytes.

Version 2 keeps the same mesh in fewer bytes, two ways: triangles can be stored in an order the codec likes, with the way back to their own order, and vertices can be predicted from the triangles around them, so that only the difference is stored. Some parts are bit streams: values packed least significant bit first, exactly as long as their bits need, with the unused bits of the last byte at zero. A reader refuses any other length.

La versión 2 guarda la misma malla en menos bytes, de dos maneras: los triángulos se pueden guardar en un orden que al códec le conviene, con el camino de vuelta a su orden, y los vértices se pueden predecir desde los triángulos que los rodean, para guardar solo la diferencia. Algunas partes son bit streams: valores empaquetados desde el bit menos significativo, exactamente tan largos como piden sus bits, con los bits sobrantes del último byte en cero. Un lector rechaza cualquier otro largo.

§ 06.bread

Triangle orderEl orden de los triángulos

The triangle codec compresses best in an order of its own. Version 2 lets it have that order, and stores the way back in a few bits per triangle.El códec de triángulos comprime mejor en un orden propio. La versión 2 le deja ese orden y guarda el camino de vuelta en pocos bits por triángulo.

The decoding order is the order triangles are stored in. A corners part, 2 bits per triangle, says which corner of each decoded triangle comes first; the value 3 is refused:

El orden de decodificación es el orden en que se guardan los triángulos. Una parte de esquinas, 2 bits por triángulo, dice qué esquina de cada triángulo decodificado va primero; el valor 3 se rechaza:

6.7
(s0, s1, s2) → r  (sr, s(r+1) mod 3, s(r+2) mod 3),r∈{0,1,2}(s_0,\,s_1,\,s_2)\ \xrightarrow{\ r\ }\ \big(s_{r},\ s_{(r+1) \bmod 3},\ s_{(r+2) \bmod 3}\big),\qquad r \in \{0, 1, 2\}

Connectivity AConectividad A

Triangles in their own order, vertices numbered as the mesh numbers them. Works for any mesh.Los triángulos en su orden, los vértices numerados como los numera la malla. Sirve para cualquier malla.

Connectivity BConectividad B

Triangles in the order the writer picked, usually meshoptimizer's vertex cache order, plus a permutation back.Los triángulos en el orden que eligió quien escribe, casi siempre el de la caché de vértices de meshoptimizer, más una permutación de vuelta.

DECODING ORDER jOWN ORDER pⱼ0p=301p=012p=423p=134p=545p=25
Connectivity B · the codec stores triangles in its favourite order; the permutation puts each one back where it wasConectividad B · el códec guarda los triángulos en el orden que más le conviene; la permutación devuelve cada uno a su lugar

The permutation is a bit stream with one value pjp_j per decoded triangle, the triangle's index in its own order, each in just enough bits for tt triangles:

La permutación es un bit stream con un valor pjp_j por triángulo decodificado, el índice del triángulo en su orden, cada uno en los bits justos para tt triángulos:

6.7
w=bitlen⁡ ⁣(max⁡(t, 2)−1) bits per triangle,pj<t,pj≠pk for j≠kw = \bitlen\!\big(\max(t,\,2) - 1\big)\ \text{bits per triangle},\qquad p_j < t,\quad p_j \ne p_k \text{ for } j \ne k
w=bitlen⁡ ⁣(max⁡(t, 2)−1) bits por triaˊngulo,pj<t,pj≠pk para j≠kw = \bitlen\!\big(\max(t,\,2) - 1\big)\ \text{bits por triángulo},\qquad p_j < t,\quad p_j \ne p_k \text{ para } j \ne k
  1. Put each decoded triangle jj, turned by its corner, at index pjp_j.
  2. Number the vertices by first use: walk the triangles in their own order, corners in order; the first vertex met is 0, the next new one 1, and so on.
  3. Give each vertex that number, keeping its coordinates, and rename the corners the same way.

So B only round-trips a mesh whose vertices were already numbered by first use, every vertex used, and a writer may use it for nothing else. Meshes welded from an STL are numbered exactly that way. A writer picks B only when A's index buffer takes more than 2 bytes per triangle and B stores the triangles smaller.

  1. Poner cada triángulo decodificado jj, girado según su esquina, en el índice pjp_j.
  2. Numerar los vértices por primer uso: recorrer los triángulos en su orden y sus esquinas en orden; el primer vértice que aparece es el 0, el siguiente nuevo el 1, y así.
  3. Darle a cada vértice ese número, con sus coordenadas, y renombrar las esquinas igual.

Así, B solo devuelve intacta una malla cuyos vértices ya estaban numerados por primer uso, todos usados, y quien escribe no puede usarla para otra cosa. Las mallas soldadas desde un STL están numeradas justo así. Se elige B solo cuando el buffer de índices de A ocupa más de 2 bytes por triángulo y B guarda los triángulos más chicos.

§ 07.bread

Predicting verticesPredecir vértices

Most of a mesh is coordinates, and most coordinates sit almost where their neighbours say they should. Version 2 stores only how far off they are.Casi toda una malla son coordenadas, y casi todas están casi donde sus vecinos dicen que deberían estar. La versión 2 guarda solo cuánto se corren.

Vertices are decoded in increasing number, so vertex vv is predicted from vertices 0…v−10 \ldots v-1 and the triangles, turned by their corners. Every triangle that has vv as a corner is visited once, in increasing order. Let aa and bb be the two corners after vv, with coordinates AA and BB. Three sums collect what the known neighbours say:

Los vértices se decodifican en número creciente, así que el vértice vv se predice a partir de los vértices 0…v−10 \ldots v-1 y de los triángulos, girados según sus esquinas. Cada triángulo que tiene a vv como esquina se visita una vez, en orden creciente. Sean aa y bb las dos esquinas que siguen a vv, con coordenadas AA y BB. Tres sumas juntan lo que dicen los vecinos conocidos:

1 · para

A+B−CA + B - C

when a, b < v and another triangle across edge ab has a known third corner ccuando a, b < v y otro triángulo del otro lado de la arista ab tiene una tercera esquina c conocida

2 · mid

12(A+B)\tfrac{1}{2}(A + B)

when a, b < v but nothing known lies across the edgecuando a, b < v pero del otro lado de la arista no hay nada conocido

3 · near

A  (a<v),B  (b<v)A\ \ (a < v),\qquad B\ \ (b < v)

every known corner, alonecada esquina conocida, sola

ABC½(A+B)P = A+B−Cv
Parallelogram prediction · the new triangle ABv mirrors the known triangle ABC across their shared edge · only the gap between v and P is storedPredicción por paralelogramo · el triángulo nuevo ABv refleja al conocido ABC a través de la arista que comparten · solo se guarda la distancia entre v y P

The prediction is the average of the first sum that got anything, in that order. If none did, it is the previous vertex, or the origin for vertex 0:

La predicción es el promedio de la primera suma que recibió algo, en ese orden. Si ninguna recibió nada, es el vértice anterior, o el origen para el vértice 0:

6.8
P(v)={1∣P∣∑P(A+B−C)P≠∅1∣M∣∑M12(A+B)P=∅, M≠∅1∣N∣∑NXP=M=∅, N≠∅xv−1  or  (0,0,0)otherwisep^=f32⁡(P(v))P(v) = \begin{cases} \dfrac{1}{|\mathcal{P}|}\displaystyle\sum_{\mathcal{P}} (A + B - C) & \mathcal{P} \neq \varnothing \\[10pt] \dfrac{1}{|\mathcal{M}|}\displaystyle\sum_{\mathcal{M}} \tfrac{1}{2}(A + B) & \mathcal{P} = \varnothing,\ \mathcal{M} \neq \varnothing \\[10pt] \dfrac{1}{|\mathcal{N}|}\displaystyle\sum_{\mathcal{N}} X & \mathcal{P} = \mathcal{M} = \varnothing,\ \mathcal{N} \neq \varnothing \\[10pt] x_{v-1} \ \text{ or } \ (0,0,0) & \text{otherwise} \end{cases} \qquad \hat{p} = \operatorname{f32}\big(P(v)\big)
P(v)={1∣P∣∑P(A+B−C)P≠∅1∣M∣∑M12(A+B)P=∅, M≠∅1∣N∣∑NXP=M=∅, N≠∅xv−1  o  (0,0,0)si nop^=f32⁡(P(v))P(v) = \begin{cases} \dfrac{1}{|\mathcal{P}|}\displaystyle\sum_{\mathcal{P}} (A + B - C) & \mathcal{P} \neq \varnothing \\[10pt] \dfrac{1}{|\mathcal{M}|}\displaystyle\sum_{\mathcal{M}} \tfrac{1}{2}(A + B) & \mathcal{P} = \varnothing,\ \mathcal{M} \neq \varnothing \\[10pt] \dfrac{1}{|\mathcal{N}|}\displaystyle\sum_{\mathcal{N}} X & \mathcal{P} = \mathcal{M} = \varnothing,\ \mathcal{N} \neq \varnothing \\[10pt] x_{v-1} \ \text{ o } \ (0,0,0) & \text{si no} \end{cases} \qquad \hat{p} = \operatorname{f32}\big(P(v)\big)

Exact on every machine. Every value is an IEEE 754 binary64, every operation rounds to nearest, ties to even, in the order written, with no fused multiply-add. The average is rounded to f32 once, at the end, and a component that is not finite becomes +0+0. That is what lets a writer on Windows and a reader in a browser compute the same prediction, bit for bit.

Exacto en cualquier máquina. Cada valor es un binary64 de IEEE 754, cada operación redondea al más cercano, con empates al par, en el orden escrito, sin multiplicación-suma fusionada. El promedio se redondea a f32 una sola vez, al final, y una componente que no es finita pasa a +0+0. Eso es lo que permite que quien escribe en Windows y quien lee en un navegador calculen la misma predicción, bit a bit.

The residualEl residuo

The difference is not taken between floats, which could round, but between their bits. ord⁡\ord maps the 32 bits uu of an f32 to an unsigned integer that orders the way the values do; the gap between the two is then folded so that small gaps, either way, become small numbers:

La diferencia no se toma entre floats, que podrían redondear, sino entre sus bits. ord⁡\ord lleva los 32 bits uu de un f32 a un entero sin signo que se ordena como los valores; la distancia entre los dos se pliega para que las distancias chicas, para cualquier lado, sean números chicos:

6.8
ord⁡(u)={¬uif the sign bit of u is setu∨231otherwised=(ord⁡(x)−ord⁡(p^)) mod 232r=zigzag⁡(d)={2dd≥0−2d−1d<0(d read as an i32)\begin{aligned} \ord(u) &= \begin{cases} \lnot u & \text{if the sign bit of } u \text{ is set} \\ u \lor 2^{31} & \text{otherwise} \end{cases} \\[6pt] d &= \big(\ord(x) - \ord(\hat p)\big) \bmod 2^{32} \\[4pt] r &= \zz(d) = \begin{cases} 2d & d \ge 0 \\ -2d - 1 & d < 0 \end{cases} \quad (d \text{ read as an } \texttt{i32}) \end{aligned}
ord⁡(u)={¬usi u tiene el bit de signo prendidou∨231si nod=(ord⁡(x)−ord⁡(p^)) mod 232r=zigzag⁡(d)={2dd≥0−2d−1d<0(d leıˊdo como i32)\begin{aligned} \ord(u) &= \begin{cases} \lnot u & \text{si } u \text{ tiene el bit de signo prendido} \\ u \lor 2^{31} & \text{si no} \end{cases} \\[6pt] d &= \big(\ord(x) - \ord(\hat p)\big) \bmod 2^{32} \\[4pt] r &= \zz(d) = \begin{cases} 2d & d \ge 0 \\ -2d - 1 & d < 0 \end{cases} \quad (d \text{ leído como } \texttt{i32}) \end{aligned}

A reader undoes both steps: xx is the f32 whose ord⁡\ord is (ord⁡(p^)+d) mod 232(\ord(\hat p) + d) \bmod 2^{32}. Every residual gives back some f32, NaN payloads and −0.0-0.0 included, so coordinates come back bit for bit, however bad the prediction was. Try it:

Un lector deshace los dos pasos: xx es el f32 cuyo ord⁡\ord es (ord⁡(p^)+d) mod 232(\ord(\hat p) + d) \bmod 2^{32}. Cualquier residuo devuelve algún f32, los NaN con su contenido y el −0.0-0.0 incluidos, así que las coordenadas vuelven bit a bit, por mala que haya sido la predicción. Probalo:

Both are rounded to f32 first, as the file stores them. Try a negative p, or −0.Las dos se redondean primero a f32, como las guarda el archivo. Probá una p negativa, o −0.

x · f3210.3699999 0x4125EB85
p · f3210.3650999 0x4125D773
ord(x)0xC125EB85
ord(p)0xC125D773
d = ord(x) − ord(p)5138
zigzag(d)10,276
bitlen14 bits

§ 08.bread

Entropy codingCodificación de entropía

Residuals are small and lopsided: exactly what an entropy coder eats. Version 2 codes them with static rANS, in 102 contexts.Los residuos son chicos y desparejos: justo lo que come un codificador de entropía. La versión 2 los codifica con rANS estático, en 102 contextos.

Symbols. A residual rr can take any of 2³² values, too many for a table. So it is split: its bit length and its top bits become one of 132 symbols, and the bits below go out raw. With L=bitlen⁡(r)L = \bitlen(r):

Símbolos. Un residuo rr puede valer cualquiera de 2³² valores, demasiados para una tabla. Entonces se parte: su largo en bits y sus bits de arriba forman uno de 132 símbolos, y los bits de abajo van crudos. Con L=bitlen⁡(r)L = \bitlen(r):

6.9
L≤1:s=4L, no raw bitsL≥2:n=L−1,h=min⁡(n,2),m=n−hs=4L+((⌊r/2m⌋ mod 2h)≪(2−h)),raw=r mod 2mback:r=2n+(((s mod 4)≫(2−h))≪m)+raw\begin{aligned} L \le 1:&\quad s = 4L,\ \text{no raw bits} \\[4pt] L \ge 2:&\quad n = L - 1,\quad h = \min(n, 2),\quad m = n - h \\ &\quad s = 4L + \Big( \big(\lfloor r / 2^{m} \rfloor \bmod 2^{h}\big) \ll (2 - h) \Big),\qquad \text{raw} = r \bmod 2^{m} \\[4pt] \text{back:}&\quad r = 2^{n} + \Big( \big((s \bmod 4) \gg (2 - h)\big) \ll m \Big) + \text{raw} \end{aligned}
L≤1:s=4L, sin bits crudosL≥2:n=L−1,h=min⁡(n,2),m=n−hs=4L+((⌊r/2m⌋ mod 2h)≪(2−h)),crudos=r mod 2mvuelta:r=2n+(((s mod 4)≫(2−h))≪m)+crudos\begin{aligned} L \le 1:&\quad s = 4L,\ \text{sin bits crudos} \\[4pt] L \ge 2:&\quad n = L - 1,\quad h = \min(n, 2),\quad m = n - h \\ &\quad s = 4L + \Big( \big(\lfloor r / 2^{m} \rfloor \bmod 2^{h}\big) \ll (2 - h) \Big),\qquad \text{crudos} = r \bmod 2^{m} \\[4pt] \text{vuelta:}&\quad r = 2^{n} + \Big( \big((s \bmod 4) \gg (2 - h)\big) \ll m \Big) + \text{crudos} \end{aligned}
10110110
■ leading 1, implied by L1 inicial, implícito en L■ h bits, into the symbolh bits, al símbolo■ m raw bits, stored as they arem bits crudos, tal cual
L = bitlen(r)8
n = L − 17
h = min(n, 2)2
m = n − h5
symbol33 / 131
raw bits10110
s mod 401
decode182 ✓

A reader refuses a symbol no residual gives: one with L≤1L \le 1 and s mod 4≠0s \bmod 4 \ne 0, or one whose lowest 2−h2-h bits are not zero.

Contexts. Residuals are coded vertex by vertex, x then y then z, and each one in a context that says how big its neighbours were, because big residuals come in clumps. Component cc (0 x, 1 y, 2 z) gets context:

Un lector rechaza un símbolo que ningún residuo da: uno con L≤1L \le 1 y s mod 4≠0s \bmod 4 \ne 0, o uno cuyos 2−h2-h bits más bajos no son cero.

Contextos. Los residuos se codifican vértice por vértice, x, después y, después z, y cada uno en un contexto que dice qué tan grandes fueron sus vecinos, porque los residuos grandes vienen juntos. La componente cc (0 x, 1 y, 2 z) usa el contexto:

6.9
κ=34c+{max⁡(bitlen⁡rx′, bitlen⁡ry′, bitlen⁡rz′)c=0(the vertex before; 0 for vertex 0)bitlen⁡rxc=1⌈(bitlen⁡rx+bitlen⁡ry)/2⌉c=2κ∈[0,101]\kappa = 34c + \begin{cases} \max\big(\bitlen r_x',\ \bitlen r_y',\ \bitlen r_z'\big) & c = 0 \quad (\text{the vertex before; } 0 \text{ for vertex } 0) \\ \bitlen r_x & c = 1 \\ \big\lceil (\bitlen r_x + \bitlen r_y) / 2 \big\rceil & c = 2 \end{cases} \qquad \kappa \in [0, 101]
κ=34c+{max⁡(bitlen⁡rx′, bitlen⁡ry′, bitlen⁡rz′)c=0(el veˊrtice anterior; 0 para el veˊrtice 0)bitlen⁡rxc=1⌈(bitlen⁡rx+bitlen⁡ry)/2⌉c=2κ∈[0,101]\kappa = 34c + \begin{cases} \max\big(\bitlen r_x',\ \bitlen r_y',\ \bitlen r_z'\big) & c = 0 \quad (\text{el vértice anterior; } 0 \text{ para el vértice } 0) \\ \bitlen r_x & c = 1 \\ \big\lceil (\bitlen r_x + \bitlen r_y) / 2 \big\rceil & c = 2 \end{cases} \qquad \kappa \in [0, 101]

Tables. A bit stream: for each context, one bit saying whether it has a table; a table gives each of the 132 symbols one bit, and a frequency minus 1 in 12 bits when the bit is set. Each table's frequencies add up to exactly 212=40962^{12} = 4096, and a symbol owns the 4096 slots from the sum of the frequencies before it.

Tablas. Un bit stream: por cada contexto, un bit que dice si tiene tabla; una tabla le da a cada uno de los 132 símbolos un bit, y una frecuencia menos 1 en 12 bits cuando el bit está prendido. Las frecuencias de cada tabla suman exactamente 212=40962^{12} = 4096, y cada símbolo es dueño de los slots que empiezan en la suma de las frecuencias anteriores.

Decoding one symbolDecodificar un símbolo

slot=x mod 4096x←f⋅⌊x/212⌋+slot−startwhile x<223:  x←256 x+next byte\begin{array}{l} \text{slot} = x \bmod 4096 \\ x \leftarrow f \cdot \lfloor x / 2^{12} \rfloor + \text{slot} - \text{start} \\ \textbf{while } x < 2^{23}:\ \ x \leftarrow 256\,x + \text{next byte} \end{array}
slot=x mod 4096x←f⋅⌊x/212⌋+slot−startmientras x<223:  x←256 x+byte siguiente\begin{array}{l} \text{slot} = x \bmod 4096 \\ x \leftarrow f \cdot \lfloor x / 2^{12} \rfloor + \text{slot} - \text{start} \\ \textbf{mientras } x < 2^{23}:\ \ x \leftarrow 256\,x + \text{byte siguiente} \end{array}

Encoding, in reverseCodificar, al revés

x0=223while x≥219f:  emit x mod 256,  x←⌊x/256⌋x←4096⌊x/f⌋+start+(x mod f)\begin{array}{l} x_0 = 2^{23} \\ \textbf{while } x \ge 2^{19} f:\ \ \text{emit } x \bmod 256,\ \ x \leftarrow \lfloor x / 256 \rfloor \\ x \leftarrow 4096 \lfloor x / f \rfloor + \text{start} + (x \bmod f) \end{array}
x0=223mientras x≥219f:  emitir x mod 256,  x←⌊x/256⌋x←4096⌊x/f⌋+start+(x mod f)\begin{array}{l} x_0 = 2^{23} \\ \textbf{mientras } x \ge 2^{19} f:\ \ \text{emitir } x \bmod 256,\ \ x \leftarrow \lfloor x / 256 \rfloor \\ x \leftarrow 4096 \lfloor x / f \rfloor + \text{start} + (x \bmod f) \end{array}

The state is 32 bits and starts as the first four bytes, big-endian. The writer codes the symbols last to first and reverses its bytes, so the reader goes first to last. A stream must end with no bytes left and the state back at exactly 2232^{23}: a free check that the whole stream was read.

The other codings. Coding 0 stores the vertices with the meshopt attribute codec, as in version 1. Coding 2 stores the residuals as 12 byte planes, plane 4c+i4c + i holding byte ii of every residual of component cc, and lets the chunk's zstd squeeze them. A writer may use any coding the mesh meets the rules of, and should keep whichever comes out smallest once compressed.

El estado es de 32 bits y arranca con los primeros cuatro bytes, en big-endian. Quien escribe codifica los símbolos del último al primero y da vuelta sus bytes, así quien lee va del primero al último. Un stream tiene que terminar sin bytes sobrantes y con el estado de vuelta en exactamente 2232^{23}: un control gratis de que se leyó el stream entero.

Las otras codificaciones. La 0 guarda los vértices con el códec de atributos de meshopt, como en la versión 1. La 2 guarda los residuos como 12 planos de bytes, con el plano 4c+i4c + i llevando el byte ii de cada residuo de la componente cc, y deja que el zstd del chunk los apriete. Quien escribe puede usar cualquier codificación cuyas reglas cumpla la malla, y debería quedarse con la que salga más chica una vez comprimida.

§ 09.bread

Safe by arithmeticSeguro por aritmética

Lengths come from the file, so a damaged one can be enormous: one flipped bit in a length asks for 2⁶³ bytes. No count in a .bread file can make a reader ask for more memory than the file could fill.Los largos salen del archivo, así que uno dañado puede ser enorme: un bit dado vuelta en un largo pide 2⁶³ bytes. Ningún conteo de un archivo .bread puede hacer que un lector pida más memoria de la que el archivo podría llenar.

The rule is one inequality, checked before allocating anything: items that take at least kk bytes each cannot number more than the bytes left, divided by kk. Every structure in the format comes with its kk:

La regla es una desigualdad, que se verifica antes de reservar nada: elementos que ocupan al menos kk bytes cada uno no pueden ser más que los bytes que quedan, divididos por kk. Cada estructura del formato trae su kk:

3.3
count  ≤  ⌊bytes leftk⌋\text{count} \;\le\; \left\lfloor \frac{\text{bytes left}}{k} \right\rfloor
conteo  ≤  ⌊bytes restantesk⌋\text{conteo} \;\le\; \left\lfloor \frac{\text{bytes restantes}}{k} \right\rfloor
WhatQuéBoundCotaWhyPor qué
vertices, attribute codecvértices, códec de atributos3n<256 L3n < 256\,Levery block of up to 256 vertices starts with a 3-byte headercada bloque de hasta 256 vértices empieza con una cabecera de 3 bytes
triangles, triangle codectriángulos, códec de triángulost≤L−17t \le L - 17at least one byte per triangle, past the first byte and a 16-byte tailal menos un byte por triángulo, más el primer byte y una cola de 16
vertices, rANS codingvértices, codificación rANSn≤3tn \le 3ta small payload cannot ask for a large meshun payload chico no puede pedir una malla grande

L: the bytes of the buffer · n: vertices · t: trianglesL: los bytes del buffer · n: vértices · t: triángulos

The same goes for the container. Stored bytes are read as they arrive, or checked against what is left of the file. Payloads are decompressed as a stream that stops the moment it passes the raw length, instead of allocating the raw length up front; the content size a Zstandard frame records is just as untrusted.

So memory grows with what a file really holds once decompressed, never with what a damaged length claims. A file crafted on purpose cannot make the reference reader ask for huge amounts of memory, or hang it. A reader may still set limits of its own, and should then say the file is too large for it, not that it is damaged.

Lo mismo vale para el contenedor. Los bytes guardados se leen a medida que llegan, o se comparan con lo que queda del archivo. Los payloads se descomprimen como un stream que frena apenas se pasa del largo crudo, en vez de reservar el largo crudo de entrada; el tamaño que anota un frame de Zstandard es igual de poco confiable.

Así, la memoria crece con lo que el archivo de verdad tiene una vez descomprimido, nunca con lo que dice un largo dañado. Un archivo armado a propósito no puede hacer que el lector de referencia pida memoria enorme, ni colgarlo. Un lector puede igual poner límites propios, y entonces tiene que decir que el archivo es demasiado grande para él, no que está dañado.

§ 10.bread

Slicer dataDatos de slicer

What turns a mesh into a print job. Any program can skip all of it and still show the same models in the same places.Lo que convierte una malla en un trabajo de impresión. Cualquier programa puede saltearlo entero y mostrar igual los mismos modelos en los mismos lugares.

SUPP

Editable supports. Each entry names a model and the leaf that shows its supports; the document holds tips, trunks, joints, rafts and the settings they were built with. The support leaf is stored with an empty mesh and rebuilt from the document, so the supports stay editable.Soportes editables. Cada entrada nombra un modelo y la hoja que muestra sus soportes; el documento guarda puntas, troncos, uniones, balsas y los ajustes con que se armaron. La hoja de soportes se guarda con una malla vacía y se reconstruye desde el documento, así los soportes siguen siendo editables.

HOLW

Hollowed models. The model's leaf shows the hollow, which is what prints; the entry names the original mesh, and the document keeps the hollowing settings and the drain holes, so the model can be hollowed again with new ones.Modelos ahuecados. La hoja del modelo muestra el hueco, que es lo que se imprime; la entrada nombra la malla original, y el documento guarda los ajustes del ahuecado y los agujeros de drenaje, para poder ahuecarlo de nuevo con otros.

SPRV

A preview of the supports: their mesh as it was when the file was written, so a viewer or a shop that cannot rebuild supports still shows them. It is for showing, never for editing.Una vista previa de los soportes: su malla tal como estaba al guardar el archivo, para que un visor o una tienda que no sabe reconstruir soportes igual los muestre. Es para mostrar, nunca para editar.

SURF

Paint on faces: details to keep, or where supports must or must not touch. One mask per leaf and kind, as runs of a value from 0 to 255 over the triangles, with the soft brush in between.Pintura en las caras: detalles para cuidar, o dónde los soportes tienen que tocar o no. Una máscara por hoja y tipo, como tramos de un valor de 0 a 255 sobre los triángulos, con el pincel suave en el medio.

THMB

A thumbnail: a PNG of up to 512 × 512 in sRGB, written first so that a file manager reads one chunk and stops.Una miniatura: un PNG de hasta 512 × 512 en sRGB, escrito primero para que un explorador de archivos lea un chunk y pare.

PROJ

Breadslicer's project settings, as a versioned TOML document: printer, resin and export format.Los ajustes de proyecto de Breadslicer, como un documento TOML con versión: impresora, resina y formato de exportación.

Paint never lands on the wrong mesh. Every paint mask carries the triangle count and a fingerprint of the mesh it was painted on: a SHA-384 over its geometry, all little-endian, without its name. If the leaf's mesh has changed, the fingerprint no longer matches and the paint is ignored, never misplaced.

La pintura nunca cae en la malla equivocada. Cada máscara lleva la cantidad de triángulos y una huella de la malla sobre la que se pintó: un SHA-384 de su geometría, todo en little-endian, sin el nombre. Si la malla de la hoja cambió, la huella deja de coincidir y la pintura se ignora, nunca se corre de lugar.

10.1
fingerprint=SHA-384⁡( nu64  ∥  ⨀i<n(xi, yi, zi)u32 bits  ∥  tu64  ∥  ⨀j<t(cj,0, cj,1, cj,2)u32)∑klengthk=t\begin{array}{l} \text{fingerprint} = \sha\Big(\, n_{\texttt{u64}} \;\Vert\; \textstyle\bigodot_{i<n} \big(x_i,\, y_i,\, z_i\big)_{\texttt{u32 bits}} \;\Vert\; t_{\texttt{u64}} \;\Vert\; \textstyle\bigodot_{j<t} \big(c_{j,0},\, c_{j,1},\, c_{j,2}\big)_{\texttt{u32}} \Big) \\[4pt] \textstyle\sum_k \text{length}_k = t \end{array}
huella=SHA-384⁡( nu64  ∥  ⨀i<n(xi, yi, zi)bits u32  ∥  tu64  ∥  ⨀j<t(cj,0, cj,1, cj,2)u32)∑klargok=t\begin{array}{l} \text{huella} = \sha\Big(\, n_{\texttt{u64}} \;\Vert\; \textstyle\bigodot_{i<n} \big(x_i,\, y_i,\, z_i\big)_{\text{bits }\texttt{u32}} \;\Vert\; t_{\texttt{u64}} \;\Vert\; \textstyle\bigodot_{j<t} \big(c_{j,0},\, c_{j,1},\, c_{j,2}\big)_{\texttt{u32}} \Big) \\[4pt] \textstyle\sum_k \text{largo}_k = t \end{array}

§ 11.bread

ConformanceConformidad

A format is what a second implementation can read. Every rule above comes with files that prove a reader follows it.Un formato es lo que puede leer una segunda implementación. Cada regla de arriba viene con archivos que prueban que un lector la cumple.

18

valid files, each with a JSON of what it holdsarchivos válidos, cada uno con un JSON de lo que guarda

17

invalid files, each with the code a reader must refuse it witharchivos inválidos, cada uno con el código con que hay que rechazarlo

15

real projects that open, save and come back bit for bitproyectos reales que abren, se guardan y vuelven bit a bit

3

platforms writing identical bytes: Windows, Linux, WebAssemblyplataformas que escriben los mismos bytes: Windows, Linux, WebAssembly

The reference implementation is a Rust crate, bread-format, the same code compiled to WebAssembly for JavaScript. Every change runs its tests on Linux and on Windows before it is merged.

La implementación de referencia es un crate de Rust, bread-format, y el mismo código compilado a WebAssembly para JavaScript. Cada cambio corre sus tests en Linux y en Windows antes de entrar.

§ 12.bread

StatusEstado

A draft, and close. This page explains it; the full text comes out with version 1.Un borrador, y cerca. Esta página lo explica; el texto completo sale con la versión 1.

Specification draft — the full text will be published when version 1 is frozen.Especificación en borrador: el texto completo se publica cuando se congele la versión 1.

Before version 1 is frozenAntes de congelar la versión 1

  • Settle units and axes, so every program agrees on what a millimetre and “up” are.
  • A second reader, written from the specification alone, that reads every conformance file the same way.
  • Breadslicer moving to the reference implementation for its own files.
  • Definir unidades y ejes, para que todos los programas coincidan en qué es un milímetro y dónde es “arriba”.
  • Un segundo lector, escrito solo a partir de la especificación, que lea igual cada archivo de conformidad.
  • Que Breadslicer pase a usar la implementación de referencia para sus propios archivos.
ExtensionExtensión.bread
MagicMagic42 52 45 41 44 00 0D 0A
ContainerContenedorversion 1versión 1
ChunksChunksSCNE 1 · MESH 2 · THMB 1 · PROJ 1 · SUPP 2 · HOLW 2 · SPRV 1 · SURF 1
SpecificationEspecificacióndraft, not frozen yetborrador, todavía sin congelar
Reference implementationImplementación de referencia0.2.0, 11 Nov 2026 · 0.1.0, 30 Oct 20260.2.0, 11 nov 2026 · 0.1.0, 30 oct 2026
LicenceLicenciaApache-2.0

Standing on. Zstandard (RFC 8878) for the container; the attribute and triangle codecs of meshoptimizer, by Arseny Kapoulkine, as published in glTF's KHR_meshopt_compression; CRC-32 as in zlib and PNG; the requirement words of RFC 2119 and RFC 8174.

Sobre hombros de. Zstandard (RFC 8878) para el contenedor; los códecs de atributos y de triángulos de meshoptimizer, de Arseny Kapoulkine, como los publica KHR_meshopt_compression de glTF; el CRC-32 de zlib y PNG; las palabras de requisito de RFC 2119 y RFC 8174.