fabriks 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fabriks/__init__.py +244 -0
- fabriks/build.py +611 -0
- fabriks/codecs/__init__.py +85 -0
- fabriks/codecs/blobs.py +177 -0
- fabriks/codecs/compression.py +50 -0
- fabriks/codecs/meshopt.py +115 -0
- fabriks/codecs/protocol.py +66 -0
- fabriks/codecs/raw.py +75 -0
- fabriks/errors.py +33 -0
- fabriks/frames.py +260 -0
- fabriks/geometry.py +368 -0
- fabriks/manifest.py +498 -0
- fabriks/octree.py +94 -0
- fabriks/planner.py +213 -0
- fabriks/py.typed +0 -0
- fabriks/reader.py +787 -0
- fabriks/simplifiers/__init__.py +64 -0
- fabriks/simplifiers/greedy.py +65 -0
- fabriks/simplifiers/measure.py +84 -0
- fabriks/simplifiers/protocol.py +72 -0
- fabriks/simplifiers/quadric.py +119 -0
- fabriks/simplifiers/registry.py +110 -0
- fabriks/sources.py +126 -0
- fabriks/stores/__init__.py +74 -0
- fabriks/stores/access.py +146 -0
- fabriks/stores/directory.py +72 -0
- fabriks/stores/file.py +153 -0
- fabriks/stores/memory.py +48 -0
- fabriks/stores/protocol.py +101 -0
- fabriks/verify.py +757 -0
- fabriks/writer.py +237 -0
- fabriks-1.0.0.dist-info/METADATA +378 -0
- fabriks-1.0.0.dist-info/RECORD +34 -0
- fabriks-1.0.0.dist-info/WHEEL +4 -0
fabriks/__init__.py
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"""fabriks: a level-of-detail mesh wire format.
|
|
2
|
+
|
|
3
|
+
A mesh collection is an **octree of surfaces** written as one self-describing tree, so a
|
|
4
|
+
renderer can fetch the detail it needs for the view it has instead of the whole thing::
|
|
5
|
+
|
|
6
|
+
<prefix>/
|
|
7
|
+
fabriks.json <- the manifest, written LAST
|
|
8
|
+
catalog/cells.parquet <- the spatial index, one row per (level, cell)
|
|
9
|
+
catalog/objects.parquet <- the identity index, one row per object
|
|
10
|
+
level=0/part-00000.parquet <- the geometry, finest level
|
|
11
|
+
level=1/part-00000.parquet
|
|
12
|
+
level=2/part-00000.parquet
|
|
13
|
+
|
|
14
|
+
Writing one::
|
|
15
|
+
|
|
16
|
+
import trimesh
|
|
17
|
+
from obstore.store import LocalStore
|
|
18
|
+
import fabriks
|
|
19
|
+
|
|
20
|
+
objects = {1: trimesh.creation.icosphere(radius=4.0), 2: ...}
|
|
21
|
+
manifest = fabriks.write_meshes(
|
|
22
|
+
objects,
|
|
23
|
+
LocalStore("/data"), # or an S3Store, or fabriks.DirectoryStore
|
|
24
|
+
prefix="my-collection",
|
|
25
|
+
cell_size=(128, 128, 64), # in voxels, in your data's own component order
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
Reading it back::
|
|
29
|
+
|
|
30
|
+
collection = fabriks.open_collection(LocalStore("/data"), "my-collection")
|
|
31
|
+
for entry in collection.plan(camera=fabriks.Camera.perspective((0, 0, 500), fov_y=0.8, viewport_height=1080)):
|
|
32
|
+
cell = collection.read_cell(entry.level, entry.cell)
|
|
33
|
+
draw(cell.vertices, cell.faces)
|
|
34
|
+
|
|
35
|
+
sphere = collection.object_mesh(1) # one object, reassembled across its cells
|
|
36
|
+
|
|
37
|
+
Coordinates
|
|
38
|
+
-----------
|
|
39
|
+
**fabriks addresses components by position, never by name.** Vertices, ``cell_size`` and the
|
|
40
|
+
``bbox_*`` columns are components 0, 1 and 2, and nothing in the writer, the octree or the
|
|
41
|
+
planner asks what they mean. Feed them in whatever order your data already has -- meshes off a
|
|
42
|
+
``(z, y, x)`` volume stay ``(z, y, x)`` -- as long as you feed them *consistently*, and the
|
|
43
|
+
octree comes out the same either way.
|
|
44
|
+
|
|
45
|
+
The ``x``/``y``/``z`` in the ``bbox_min_x`` column names are labels for those three slots,
|
|
46
|
+
fixed by the Parquet schema a server checks. They are not a claim about which physical axis
|
|
47
|
+
each slot holds, and the format makes no such claim anywhere: naming these axes is a statement
|
|
48
|
+
about how the collection relates to the image it came from or the coordinate graph it sits in,
|
|
49
|
+
which belongs to whatever owns that coordinate system rather than to `fabriks.json`.
|
|
50
|
+
|
|
51
|
+
An order mistake here cannot misplace geometry: clipping and quantization read the same
|
|
52
|
+
``cell_size``, so a mismatched one yields a differently *shaped* octree rather than displaced
|
|
53
|
+
vertices. Still worth matching ``cell_size`` to the source array's chunk shape, in whatever
|
|
54
|
+
order that shape is in -- a cell that matches the chunking means a viewer fetching image chunks
|
|
55
|
+
and mesh cells pulls the same regions.
|
|
56
|
+
|
|
57
|
+
Simplification
|
|
58
|
+
--------------
|
|
59
|
+
A coarse level is made by a pluggable backend, named the way a codec is: ``"QUADRIC"`` is the
|
|
60
|
+
default, backed by ``fast-simplification`` -- it collapses to the quadric-optimal shape while
|
|
61
|
+
pinning every vertex on the cut boundary at exactly its input position, which is what makes
|
|
62
|
+
``boundary: LOCKED`` provable rather than intended. ``"GREEDY"`` is a pure-numpy alternative,
|
|
63
|
+
useful where a heavily pinned boundary stops the quadric collapse reaching a budget::
|
|
64
|
+
|
|
65
|
+
fabriks.build_collection(objects, cell_size=..., simplifier="GREEDY")
|
|
66
|
+
fabriks.build_collection(objects, cell_size=..., simplifier=fabriks.GreedyEdgeCollapse())
|
|
67
|
+
fabriks.build_collection(objects, cell_size=..., decimation=fabriks.Decimation.half())
|
|
68
|
+
|
|
69
|
+
Pass the name to pick a backend, an instance to configure one, or your own object providing
|
|
70
|
+
``simplify`` -- see :mod:`fabriks.simplifiers`.
|
|
71
|
+
|
|
72
|
+
How much survives each level is :class:`Decimation`, defaulting to a quarter. Whatever it is,
|
|
73
|
+
the manifest declares what was actually done: a ratio and its declaration are required to
|
|
74
|
+
agree, because nothing downstream can re-derive one from the other.
|
|
75
|
+
|
|
76
|
+
The byte format is documented in :mod:`fabriks.codecs`; the boundary and decimation arguments in
|
|
77
|
+
:mod:`fabriks.geometry`; the tree layout in :mod:`fabriks.manifest`.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
from fabriks.build import MeshCollection, build_collection, choose_cell_size
|
|
81
|
+
from fabriks.codecs import (
|
|
82
|
+
QUANT_MAX,
|
|
83
|
+
BlobCodec,
|
|
84
|
+
MeshoptCodec,
|
|
85
|
+
RawCodec,
|
|
86
|
+
codec_for,
|
|
87
|
+
decode_indices,
|
|
88
|
+
decode_positions,
|
|
89
|
+
encode_indices,
|
|
90
|
+
encode_positions,
|
|
91
|
+
)
|
|
92
|
+
from fabriks.errors import (
|
|
93
|
+
FabriksError,
|
|
94
|
+
FormatError,
|
|
95
|
+
MissingExtraError,
|
|
96
|
+
PartitioningError,
|
|
97
|
+
UnfinishedCollectionError,
|
|
98
|
+
)
|
|
99
|
+
from fabriks.frames import (
|
|
100
|
+
DEFAULT_ROW_GROUP_BYTES,
|
|
101
|
+
REQUIRED_COLUMNS,
|
|
102
|
+
arrow_schemas,
|
|
103
|
+
validate_columns,
|
|
104
|
+
)
|
|
105
|
+
from fabriks.geometry import decimate_fixed, snap_boundary
|
|
106
|
+
from fabriks.manifest import (
|
|
107
|
+
BOUNDARY_LOCKED,
|
|
108
|
+
CELL_CATALOG_PATH,
|
|
109
|
+
CODEC_MESHOPT,
|
|
110
|
+
CODEC_NONE,
|
|
111
|
+
COMPRESSION_NONE,
|
|
112
|
+
COMPRESSION_ZSTD,
|
|
113
|
+
DECIMATION_CUSTOM,
|
|
114
|
+
DECIMATION_EIGHTH,
|
|
115
|
+
DECIMATION_HALF,
|
|
116
|
+
DECIMATION_QUARTER,
|
|
117
|
+
INDICES_UINT32,
|
|
118
|
+
MANIFEST_NAME,
|
|
119
|
+
OBJECT_CATALOG_PATH,
|
|
120
|
+
POSITIONS_UINT16_QUANTIZED_PER_CELL,
|
|
121
|
+
SPEC_VERSION,
|
|
122
|
+
Decimation,
|
|
123
|
+
Encoding,
|
|
124
|
+
FileEntry,
|
|
125
|
+
Grid,
|
|
126
|
+
Manifest,
|
|
127
|
+
level_part_path,
|
|
128
|
+
level_prefix,
|
|
129
|
+
)
|
|
130
|
+
from fabriks.octree import cell_box, morton_decode, morton_encode, morton_encode_one
|
|
131
|
+
from fabriks.planner import Camera, plan_cells
|
|
132
|
+
from fabriks.reader import (
|
|
133
|
+
CellEntry,
|
|
134
|
+
Collection,
|
|
135
|
+
DecodedCell,
|
|
136
|
+
ObjectEntry,
|
|
137
|
+
aopen_collection,
|
|
138
|
+
open_collection,
|
|
139
|
+
)
|
|
140
|
+
from fabriks.simplifiers import (
|
|
141
|
+
SIMPLIFICATION_DEFAULT,
|
|
142
|
+
SIMPLIFICATION_GREEDY,
|
|
143
|
+
SIMPLIFICATION_QUADRIC,
|
|
144
|
+
GreedyEdgeCollapse,
|
|
145
|
+
QuadricSimplifier,
|
|
146
|
+
Simplified,
|
|
147
|
+
Simplifier,
|
|
148
|
+
simplifier_for,
|
|
149
|
+
)
|
|
150
|
+
from fabriks.sources import HasVerticesAndFaces, Mesh, MeshSource, coerce_mesh
|
|
151
|
+
from fabriks.stores import (
|
|
152
|
+
AsyncReadable,
|
|
153
|
+
DirectoryStore,
|
|
154
|
+
FabriksStore,
|
|
155
|
+
MemoryStore,
|
|
156
|
+
RangeReadable,
|
|
157
|
+
StoreFile,
|
|
158
|
+
)
|
|
159
|
+
from fabriks.verify import Check, VerifyReport, verify
|
|
160
|
+
from fabriks.writer import awrite_collection, write_collection, write_meshes
|
|
161
|
+
|
|
162
|
+
__all__ = [
|
|
163
|
+
"BOUNDARY_LOCKED",
|
|
164
|
+
"CELL_CATALOG_PATH",
|
|
165
|
+
"CODEC_MESHOPT",
|
|
166
|
+
"CODEC_NONE",
|
|
167
|
+
"COMPRESSION_NONE",
|
|
168
|
+
"COMPRESSION_ZSTD",
|
|
169
|
+
"DECIMATION_CUSTOM",
|
|
170
|
+
"DECIMATION_EIGHTH",
|
|
171
|
+
"DECIMATION_HALF",
|
|
172
|
+
"DECIMATION_QUARTER",
|
|
173
|
+
"DEFAULT_ROW_GROUP_BYTES",
|
|
174
|
+
"INDICES_UINT32",
|
|
175
|
+
"MANIFEST_NAME",
|
|
176
|
+
"OBJECT_CATALOG_PATH",
|
|
177
|
+
"POSITIONS_UINT16_QUANTIZED_PER_CELL",
|
|
178
|
+
"QUANT_MAX",
|
|
179
|
+
"REQUIRED_COLUMNS",
|
|
180
|
+
"SIMPLIFICATION_DEFAULT",
|
|
181
|
+
"SIMPLIFICATION_GREEDY",
|
|
182
|
+
"SIMPLIFICATION_QUADRIC",
|
|
183
|
+
"SPEC_VERSION",
|
|
184
|
+
"AsyncReadable",
|
|
185
|
+
"BlobCodec",
|
|
186
|
+
"Camera",
|
|
187
|
+
"CellEntry",
|
|
188
|
+
"Check",
|
|
189
|
+
"Collection",
|
|
190
|
+
"Decimation",
|
|
191
|
+
"DecodedCell",
|
|
192
|
+
"DirectoryStore",
|
|
193
|
+
"Encoding",
|
|
194
|
+
"FabriksError",
|
|
195
|
+
"FabriksStore",
|
|
196
|
+
"FileEntry",
|
|
197
|
+
"FormatError",
|
|
198
|
+
"GreedyEdgeCollapse",
|
|
199
|
+
"Grid",
|
|
200
|
+
"HasVerticesAndFaces",
|
|
201
|
+
"Manifest",
|
|
202
|
+
"MemoryStore",
|
|
203
|
+
"Mesh",
|
|
204
|
+
"MeshCollection",
|
|
205
|
+
"MeshSource",
|
|
206
|
+
"MeshoptCodec",
|
|
207
|
+
"MissingExtraError",
|
|
208
|
+
"ObjectEntry",
|
|
209
|
+
"PartitioningError",
|
|
210
|
+
"QuadricSimplifier",
|
|
211
|
+
"RangeReadable",
|
|
212
|
+
"RawCodec",
|
|
213
|
+
"Simplified",
|
|
214
|
+
"Simplifier",
|
|
215
|
+
"StoreFile",
|
|
216
|
+
"UnfinishedCollectionError",
|
|
217
|
+
"VerifyReport",
|
|
218
|
+
"aopen_collection",
|
|
219
|
+
"arrow_schemas",
|
|
220
|
+
"awrite_collection",
|
|
221
|
+
"build_collection",
|
|
222
|
+
"cell_box",
|
|
223
|
+
"choose_cell_size",
|
|
224
|
+
"codec_for",
|
|
225
|
+
"coerce_mesh",
|
|
226
|
+
"decimate_fixed",
|
|
227
|
+
"decode_indices",
|
|
228
|
+
"decode_positions",
|
|
229
|
+
"encode_indices",
|
|
230
|
+
"encode_positions",
|
|
231
|
+
"level_part_path",
|
|
232
|
+
"level_prefix",
|
|
233
|
+
"morton_decode",
|
|
234
|
+
"morton_encode",
|
|
235
|
+
"morton_encode_one",
|
|
236
|
+
"open_collection",
|
|
237
|
+
"plan_cells",
|
|
238
|
+
"simplifier_for",
|
|
239
|
+
"snap_boundary",
|
|
240
|
+
"validate_columns",
|
|
241
|
+
"verify",
|
|
242
|
+
"write_collection",
|
|
243
|
+
"write_meshes",
|
|
244
|
+
]
|