Lucasgitguy-co commited on
Commit
e80b8d8
·
verified ·
1 Parent(s): 653feb2

Publish evaluated Forma3D-Tiny v0.2

Browse files
ATTRIBUTIONS.json ADDED
@@ -0,0 +1,1314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "repo": "scenario-labs/3d-collection",
4
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
5
+ "path": "assets/scenario_asset_j69T8oBpnATHCfYAAaa9tHQm/output.glb",
6
+ "sha256": "5a99d51a3a1765cddffb545fb80970bda9eb83ca64382788bd064ff8239782d7",
7
+ "asset_id": "scenario:asset_j69T8oBpnATHCfYAAaa9tHQm",
8
+ "license": "cc-by-4.0",
9
+ "author": "Scenario",
10
+ "title": "scenario:asset_j69T8oBpnATHCfYAAaa9tHQm",
11
+ "source_model": "model_scenario-claude-opus-5-5-3d",
12
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
13
+ "object_id": "scenario-0f2e19a4898f95756a1a",
14
+ "source_object_id": "scenario-0f2e19a4898f95756a1a"
15
+ },
16
+ {
17
+ "repo": "scenario-labs/3d-collection",
18
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
19
+ "path": "assets/scenario_asset_j5kkiUz5G8bpJX78kwkJCvZs/output.glb",
20
+ "sha256": "8c9121b558f19a067aa76a6940c98252765ef79b45d651e922d99ffc8f23f44f",
21
+ "asset_id": "scenario:asset_j5kkiUz5G8bpJX78kwkJCvZs",
22
+ "license": "cc-by-4.0",
23
+ "author": "Scenario",
24
+ "title": "scenario:asset_j5kkiUz5G8bpJX78kwkJCvZs",
25
+ "source_model": "model_pixal3d",
26
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
27
+ "object_id": "scenario-63ee5f1041b51dbdca56",
28
+ "source_object_id": "scenario-63ee5f1041b51dbdca56"
29
+ },
30
+ {
31
+ "repo": "scenario-labs/3d-collection",
32
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
33
+ "path": "assets/scenario_asset_ecawy76SCymJthaVd38SvNPT/output.glb",
34
+ "sha256": "871a1cc7bbe5ea9605d31f6f9c213696c202c51ace4fedd6114c4535b616ea4d",
35
+ "asset_id": "scenario:asset_ecawy76SCymJthaVd38SvNPT",
36
+ "license": "cc-by-4.0",
37
+ "author": "Scenario",
38
+ "title": "scenario:asset_ecawy76SCymJthaVd38SvNPT",
39
+ "source_model": "model_tripo-v2-5-image-to-3d",
40
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
41
+ "object_id": "scenario-cddc1d43d8bf54b84aeb",
42
+ "source_object_id": "scenario-cddc1d43d8bf54b84aeb"
43
+ },
44
+ {
45
+ "repo": "scenario-labs/3d-collection",
46
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
47
+ "path": "assets/scenario_asset_uKgWMW27HVuHYKfb21S9pP1V/output.glb",
48
+ "sha256": "d67442b0ad2828b743efa43058e0a773521dd53b1c92ba4e8e445e4f4f198e23",
49
+ "asset_id": "scenario:asset_uKgWMW27HVuHYKfb21S9pP1V",
50
+ "license": "cc-by-4.0",
51
+ "author": "Scenario",
52
+ "title": "scenario:asset_uKgWMW27HVuHYKfb21S9pP1V",
53
+ "source_model": "model_scenario-gpt6-astra-3d",
54
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
55
+ "object_id": "scenario-149583b9bacab13e8588",
56
+ "source_object_id": "scenario-149583b9bacab13e8588"
57
+ },
58
+ {
59
+ "repo": "scenario-labs/3d-collection",
60
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
61
+ "path": "assets/scenario_asset_xyRDpvBmjLJKoZtU8utx9gRH/output.glb",
62
+ "sha256": "6695720343b20ee12e87a196becbf8aca22463c7b725b42571fae32ef1c6fd57",
63
+ "asset_id": "scenario:asset_xyRDpvBmjLJKoZtU8utx9gRH",
64
+ "license": "cc-by-4.0",
65
+ "author": "Scenario",
66
+ "title": "scenario:asset_xyRDpvBmjLJKoZtU8utx9gRH",
67
+ "source_model": "model_tripo-v2-5-image-to-3d",
68
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
69
+ "object_id": "scenario-74b4c6a58a7a9fd27185",
70
+ "source_object_id": "scenario-74b4c6a58a7a9fd27185"
71
+ },
72
+ {
73
+ "repo": "scenario-labs/3d-collection",
74
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
75
+ "path": "assets/scenario_asset_Lfd5tqLimGQtrD7ifXzKcmjG/output.glb",
76
+ "sha256": "32d6fab78c142a58a462a3a28bc4f03eded415e5553a1177f4c487cc25ec8d9f",
77
+ "asset_id": "scenario:asset_Lfd5tqLimGQtrD7ifXzKcmjG",
78
+ "license": "cc-by-4.0",
79
+ "author": "Scenario",
80
+ "title": "scenario:asset_Lfd5tqLimGQtrD7ifXzKcmjG",
81
+ "source_model": "model_rodin-hyper3d",
82
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
83
+ "object_id": "scenario-5a5f6e10b1f1d1adb638",
84
+ "source_object_id": "scenario-5a5f6e10b1f1d1adb638"
85
+ },
86
+ {
87
+ "repo": "scenario-labs/3d-collection",
88
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
89
+ "path": "assets/scenario_asset_8i2h2wUfLzme7LUYLWU5AWDv/output.glb",
90
+ "sha256": "598e38def4f3868c7b9782daae80a462b759f4ad2f6abf074b5c22f435521acb",
91
+ "asset_id": "scenario:asset_8i2h2wUfLzme7LUYLWU5AWDv",
92
+ "license": "cc-by-4.0",
93
+ "author": "Scenario",
94
+ "title": "scenario:asset_8i2h2wUfLzme7LUYLWU5AWDv",
95
+ "source_model": "model_trellis",
96
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
97
+ "object_id": "scenario-d7e8f8b03a4a6207bc64",
98
+ "source_object_id": "scenario-d7e8f8b03a4a6207bc64"
99
+ },
100
+ {
101
+ "repo": "scenario-labs/3d-collection",
102
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
103
+ "path": "assets/scenario_asset_GN2PtfF8pL61mgLoYHPMs2Ns/output.glb",
104
+ "sha256": "d8ff52ff8eb4c2dcf1b67e89979d1e66eccb069f404d6b9e75b84221e4830392",
105
+ "asset_id": "scenario:asset_GN2PtfF8pL61mgLoYHPMs2Ns",
106
+ "license": "cc-by-4.0",
107
+ "author": "Scenario",
108
+ "title": "scenario:asset_GN2PtfF8pL61mgLoYHPMs2Ns",
109
+ "source_model": "model_meshy-txt23d",
110
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
111
+ "object_id": "scenario-8e7c4a687ffbe178d8d7",
112
+ "source_object_id": "scenario-8e7c4a687ffbe178d8d7"
113
+ },
114
+ {
115
+ "repo": "scenario-labs/3d-collection",
116
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
117
+ "path": "assets/scenario_asset_PxbXeyqvNysMiYub8zn3C2eR/output.glb",
118
+ "sha256": "40be851ac7ceacaf3cad1227e0a65ff5da312769a7f4a4f0865fc80878a18bb9",
119
+ "asset_id": "scenario:asset_PxbXeyqvNysMiYub8zn3C2eR",
120
+ "license": "cc-by-4.0",
121
+ "author": "Scenario",
122
+ "title": "scenario:asset_PxbXeyqvNysMiYub8zn3C2eR",
123
+ "source_model": "model_meshy-7-1-img23d",
124
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
125
+ "object_id": "scenario-8a32f2baa95a557b9d61",
126
+ "source_object_id": "scenario-8a32f2baa95a557b9d61"
127
+ },
128
+ {
129
+ "repo": "scenario-labs/3d-collection",
130
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
131
+ "path": "assets/scenario_asset_odL4YXhQCEFB3NwywcT6W9LV/output.glb",
132
+ "sha256": "6d942ea2f2b3115a33ceb4510fe32461e0d152612d7f80563695e23600fd2fbb",
133
+ "asset_id": "scenario:asset_odL4YXhQCEFB3NwywcT6W9LV",
134
+ "license": "cc-by-4.0",
135
+ "author": "Scenario",
136
+ "title": "scenario:asset_odL4YXhQCEFB3NwywcT6W9LV",
137
+ "source_model": "model_reconviagen-0-5",
138
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
139
+ "object_id": "scenario-34ba20395fdf508cd9cc",
140
+ "source_object_id": "scenario-34ba20395fdf508cd9cc"
141
+ },
142
+ {
143
+ "repo": "scenario-labs/3d-collection",
144
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
145
+ "path": "assets/75f5c6b128053234/6e44e427eff9329f.glb",
146
+ "sha256": "a15e441f40d6b36c61bdfcc665f4aed4c01b108998e00b8ee1ad261d6cf39271",
147
+ "asset_id": "75f5c6b128053234",
148
+ "license": "cc-by-4.0",
149
+ "author": "Scenario",
150
+ "title": "75f5c6b128053234",
151
+ "source_model": "gpt-6-astra",
152
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
153
+ "object_id": "scenario-5b9e2bb00fd7fde9af1e",
154
+ "source_object_id": "scenario-5b9e2bb00fd7fde9af1e"
155
+ },
156
+ {
157
+ "repo": "scenario-labs/3d-collection",
158
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
159
+ "path": "assets/scenario_asset_GPuZMdobUQDpkGtBzDfoEvnU/output.glb",
160
+ "sha256": "881c8f3e5de7478d46efd0fbaf1bc91062d9f1dd6805ab63eee8b7a7b106a5e1",
161
+ "asset_id": "scenario:asset_GPuZMdobUQDpkGtBzDfoEvnU",
162
+ "license": "cc-by-4.0",
163
+ "author": "Scenario",
164
+ "title": "scenario:asset_GPuZMdobUQDpkGtBzDfoEvnU",
165
+ "source_model": "model_tripo-p1-multiview-to-3d",
166
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
167
+ "object_id": "scenario-ade571817876d8668a6e",
168
+ "source_object_id": "scenario-ade571817876d8668a6e"
169
+ },
170
+ {
171
+ "repo": "scenario-labs/3d-collection",
172
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
173
+ "path": "assets/scenario_asset_eTuW5Zb3UH1tnPFfpf62eEJf/output.glb",
174
+ "sha256": "30e63f0028f5e08dc6e7f94546f47630a77993b5bdcc0f9129c58ecf16306f0a",
175
+ "asset_id": "scenario:asset_eTuW5Zb3UH1tnPFfpf62eEJf",
176
+ "license": "cc-by-4.0",
177
+ "author": "Scenario",
178
+ "title": "scenario:asset_eTuW5Zb3UH1tnPFfpf62eEJf",
179
+ "source_model": "model_tripo-p1-multiview-to-3d",
180
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
181
+ "object_id": "scenario-466d0be00c0e012fb542",
182
+ "source_object_id": "scenario-466d0be00c0e012fb542"
183
+ },
184
+ {
185
+ "repo": "scenario-labs/3d-collection",
186
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
187
+ "path": "assets/scenario_asset_pULm1d2Z2udMAY1oUnhVckjr/output.glb",
188
+ "sha256": "e5fc737f3e8e00b25c926777a3062c227e017d14d9126283ee3b10040126fb49",
189
+ "asset_id": "scenario:asset_pULm1d2Z2udMAY1oUnhVckjr",
190
+ "license": "cc-by-4.0",
191
+ "author": "Scenario",
192
+ "title": "scenario:asset_pULm1d2Z2udMAY1oUnhVckjr",
193
+ "source_model": "model_csm-multiview-to-3d",
194
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
195
+ "object_id": "scenario-d147580bd3107d1a4eb8",
196
+ "source_object_id": "scenario-d147580bd3107d1a4eb8"
197
+ },
198
+ {
199
+ "repo": "scenario-labs/3d-collection",
200
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
201
+ "path": "assets/scenario_asset_6wkTbVyWTk8kTaFA36P7eXLK/output.glb",
202
+ "sha256": "00923c07b521a7cd3d16904204c55e67a7a15e855001f9fa16677411d9bdfb21",
203
+ "asset_id": "scenario:asset_6wkTbVyWTk8kTaFA36P7eXLK",
204
+ "license": "cc-by-4.0",
205
+ "author": "Scenario",
206
+ "title": "scenario:asset_6wkTbVyWTk8kTaFA36P7eXLK",
207
+ "source_model": "model_hitem-3d-3-0",
208
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
209
+ "object_id": "scenario-466d0be00c0e012fb542",
210
+ "source_object_id": "scenario-466d0be00c0e012fb542"
211
+ },
212
+ {
213
+ "repo": "scenario-labs/3d-collection",
214
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
215
+ "path": "assets/scenario_asset_fXLLwifmNEiarzDHvU9qR9c6/output.glb",
216
+ "sha256": "8a5c966299b8ba69a36afcf86164606b9d5e2c0dda209c668180396721c1b80f",
217
+ "asset_id": "scenario:asset_fXLLwifmNEiarzDHvU9qR9c6",
218
+ "license": "cc-by-4.0",
219
+ "author": "Scenario",
220
+ "title": "scenario:asset_fXLLwifmNEiarzDHvU9qR9c6",
221
+ "source_model": "model_rodin-hyper3d-v2-5",
222
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
223
+ "object_id": "scenario-b5f455653965ad70ef61",
224
+ "source_object_id": "scenario-b5f455653965ad70ef61"
225
+ },
226
+ {
227
+ "repo": "scenario-labs/3d-collection",
228
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
229
+ "path": "assets/scenario_asset_jXUrm3QeKHsQSzwaRAVpAdNn/output.glb",
230
+ "sha256": "0ab33363f3b705073b28486e9f795cef48ee3931f21cf3d8d9232fa0f5062c86",
231
+ "asset_id": "scenario:asset_jXUrm3QeKHsQSzwaRAVpAdNn",
232
+ "license": "cc-by-4.0",
233
+ "author": "Scenario",
234
+ "title": "scenario:asset_jXUrm3QeKHsQSzwaRAVpAdNn",
235
+ "source_model": "model_rodin-hyper3d",
236
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
237
+ "object_id": "scenario-28ce44f5fbb0c0e011cd",
238
+ "source_object_id": "scenario-28ce44f5fbb0c0e011cd"
239
+ },
240
+ {
241
+ "repo": "scenario-labs/3d-collection",
242
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
243
+ "path": "assets/scenario_asset_2Ro5Mui16ixub1zqw2BiqKaR/output.glb",
244
+ "sha256": "6318af422fbbf062c37484418e866c8fd459df2b98e1bb1e25d933425d60d5ef",
245
+ "asset_id": "scenario:asset_2Ro5Mui16ixub1zqw2BiqKaR",
246
+ "license": "cc-by-4.0",
247
+ "author": "Scenario",
248
+ "title": "scenario:asset_2Ro5Mui16ixub1zqw2BiqKaR",
249
+ "source_model": "model_trellis",
250
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
251
+ "object_id": "scenario-4a5266cce3f49719090d",
252
+ "source_object_id": "scenario-4a5266cce3f49719090d"
253
+ },
254
+ {
255
+ "repo": "scenario-labs/3d-collection",
256
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
257
+ "path": "assets/scenario_asset_BRRWVciFtq3RwW3iv11W6DvT/output.glb",
258
+ "sha256": "ef8fc714c4404fb9390fa8c61074b1b1fe7ed469da4712c5b66bacb46c559133",
259
+ "asset_id": "scenario:asset_BRRWVciFtq3RwW3iv11W6DvT",
260
+ "license": "cc-by-4.0",
261
+ "author": "Scenario",
262
+ "title": "scenario:asset_BRRWVciFtq3RwW3iv11W6DvT",
263
+ "source_model": "model_tripo-p2-multiview-to-3d",
264
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
265
+ "object_id": "scenario-c0a3cbf459276cc685ae",
266
+ "source_object_id": "scenario-c0a3cbf459276cc685ae"
267
+ },
268
+ {
269
+ "repo": "scenario-labs/3d-collection",
270
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
271
+ "path": "assets/scenario_asset_eDVxQybk45x7XjuFeTXKSScc/output.glb",
272
+ "sha256": "00ef0a0908ec20bec84e35b1b0865d5e14a877122525cda1693351cb22ae0c62",
273
+ "asset_id": "scenario:asset_eDVxQybk45x7XjuFeTXKSScc",
274
+ "license": "cc-by-4.0",
275
+ "author": "Scenario",
276
+ "title": "scenario:asset_eDVxQybk45x7XjuFeTXKSScc",
277
+ "source_model": "model_pixal3d",
278
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
279
+ "object_id": "scenario-fc68b47a345c9d6e4963",
280
+ "source_object_id": "scenario-fc68b47a345c9d6e4963"
281
+ },
282
+ {
283
+ "repo": "scenario-labs/3d-collection",
284
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
285
+ "path": "assets/scenario_asset_6ZWKZ6Rzri1Vxy8cSUq2cZTs/output.glb",
286
+ "sha256": "fec06cf24094a4f99ef6e5bae69db44c9d681c97479b68476f4fb741ddb76a9c",
287
+ "asset_id": "scenario:asset_6ZWKZ6Rzri1Vxy8cSUq2cZTs",
288
+ "license": "cc-by-4.0",
289
+ "author": "Scenario",
290
+ "title": "scenario:asset_6ZWKZ6Rzri1Vxy8cSUq2cZTs",
291
+ "source_model": "model_pixal3d",
292
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
293
+ "object_id": "scenario-085e1963fcccdc9d5b3f",
294
+ "source_object_id": "scenario-085e1963fcccdc9d5b3f"
295
+ },
296
+ {
297
+ "repo": "scenario-labs/3d-collection",
298
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
299
+ "path": "assets/scenario_asset_bxgKgzWypCUMwx3uoum89c8f/output.glb",
300
+ "sha256": "08fd1ab1a1d9f5d96ff96c590d15233183a0628ee0c7da7cbc0f94c30934f7aa",
301
+ "asset_id": "scenario:asset_bxgKgzWypCUMwx3uoum89c8f",
302
+ "license": "cc-by-4.0",
303
+ "author": "Scenario",
304
+ "title": "scenario:asset_bxgKgzWypCUMwx3uoum89c8f",
305
+ "source_model": "model_tripo-p2-image-to-3d",
306
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
307
+ "object_id": "scenario-957a1644ed775a4ba828",
308
+ "source_object_id": "scenario-957a1644ed775a4ba828"
309
+ },
310
+ {
311
+ "repo": "scenario-labs/3d-collection",
312
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
313
+ "path": "assets/scenario_asset_SHLHdYJU8ZZcD1RLBoZRN4Dh/output.glb",
314
+ "sha256": "ce0f34aa1819c54a82b5994217c78017502e0cb8da977904bf7a7eaa98aaa01b",
315
+ "asset_id": "scenario:asset_SHLHdYJU8ZZcD1RLBoZRN4Dh",
316
+ "license": "cc-by-4.0",
317
+ "author": "Scenario",
318
+ "title": "scenario:asset_SHLHdYJU8ZZcD1RLBoZRN4Dh",
319
+ "source_model": "model_direct3d-s2",
320
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
321
+ "object_id": "scenario-bac8263386b13cb2ba13",
322
+ "source_object_id": "scenario-bac8263386b13cb2ba13"
323
+ },
324
+ {
325
+ "repo": "scenario-labs/3d-collection",
326
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
327
+ "path": "assets/e8aa5080a9e1176b/61031a4d47639ab5.glb",
328
+ "sha256": "d4119d2b44452f2014d27b3013519eb609eb2355911ad5fe340de258fa8adc84",
329
+ "asset_id": "e8aa5080a9e1176b",
330
+ "license": "cc-by-4.0",
331
+ "author": "Scenario",
332
+ "title": "e8aa5080a9e1176b",
333
+ "source_model": "gpt-6-astra",
334
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
335
+ "object_id": "scenario-5159f9b4437c7798221b",
336
+ "source_object_id": "scenario-5159f9b4437c7798221b"
337
+ },
338
+ {
339
+ "repo": "scenario-labs/3d-collection",
340
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
341
+ "path": "assets/scenario_asset_kFom3by1MoaqECxbVDNLhjm9/output.glb",
342
+ "sha256": "eb02e67db9d6e0787b0600415d7ee00f045834596f24ec741cb0133c659a67a6",
343
+ "asset_id": "scenario:asset_kFom3by1MoaqECxbVDNLhjm9",
344
+ "license": "cc-by-4.0",
345
+ "author": "Scenario",
346
+ "title": "scenario:asset_kFom3by1MoaqECxbVDNLhjm9",
347
+ "source_model": "model_meta-sam-3d-body",
348
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
349
+ "object_id": "scenario-747f6b9cd38dbcf69503",
350
+ "source_object_id": "scenario-747f6b9cd38dbcf69503"
351
+ },
352
+ {
353
+ "repo": "scenario-labs/3d-collection",
354
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
355
+ "path": "assets/scenario_asset_rc9vDsejZEnGMXSBSssE8idQ/output.glb",
356
+ "sha256": "be499e4f5f18ade7908834c95dc221c8dc2224a26e96a2da9ec29553c724873a",
357
+ "asset_id": "scenario:asset_rc9vDsejZEnGMXSBSssE8idQ",
358
+ "license": "cc-by-4.0",
359
+ "author": "Scenario",
360
+ "title": "scenario:asset_rc9vDsejZEnGMXSBSssE8idQ",
361
+ "source_model": "model_rodin-hyper3d",
362
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
363
+ "object_id": "scenario-5b991601f627db98fbf1",
364
+ "source_object_id": "scenario-5b991601f627db98fbf1"
365
+ },
366
+ {
367
+ "repo": "scenario-labs/3d-collection",
368
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
369
+ "path": "assets/scenario_asset_ZMCWJUkPNZ3q2DMUnCZCELoZ/output.glb",
370
+ "sha256": "e8eeec0085132206599009152b4eda705eeea6810e8767270c515be18d4296d5",
371
+ "asset_id": "scenario:asset_ZMCWJUkPNZ3q2DMUnCZCELoZ",
372
+ "license": "cc-by-4.0",
373
+ "author": "Scenario",
374
+ "title": "scenario:asset_ZMCWJUkPNZ3q2DMUnCZCELoZ",
375
+ "source_model": "model_csm-multiview-to-3d",
376
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
377
+ "object_id": "scenario-54f1fab77a40c2cf9628",
378
+ "source_object_id": "scenario-54f1fab77a40c2cf9628"
379
+ },
380
+ {
381
+ "repo": "scenario-labs/3d-collection",
382
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
383
+ "path": "assets/scenario_asset_hBi4aoD5QT99pZuVv5YRwzjn/output.glb",
384
+ "sha256": "fb9dbc5a294d47809a60bacf2672df5f3ffeb465a99eb544ddf63211cd310b91",
385
+ "asset_id": "scenario:asset_hBi4aoD5QT99pZuVv5YRwzjn",
386
+ "license": "cc-by-4.0",
387
+ "author": "Scenario",
388
+ "title": "scenario:asset_hBi4aoD5QT99pZuVv5YRwzjn",
389
+ "source_model": "model_meshy-smart-topology",
390
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
391
+ "object_id": "scenario-281ba76c64b84df68cb5",
392
+ "source_object_id": "scenario-281ba76c64b84df68cb5"
393
+ },
394
+ {
395
+ "repo": "scenario-labs/3d-collection",
396
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
397
+ "path": "assets/scenario_asset_FYB55Mi6cHwTMsdLv4WgKBhe/output.glb",
398
+ "sha256": "b1b16b0410aa55cf84b4f4d68265de10b4a8f28bcfa1f43d16e8faaa1d9072ae",
399
+ "asset_id": "scenario:asset_FYB55Mi6cHwTMsdLv4WgKBhe",
400
+ "license": "cc-by-4.0",
401
+ "author": "Scenario",
402
+ "title": "scenario:asset_FYB55Mi6cHwTMsdLv4WgKBhe",
403
+ "source_model": "model_direct3d-s2",
404
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
405
+ "object_id": "scenario-1fe51bab97a9f112d73a",
406
+ "source_object_id": "scenario-1fe51bab97a9f112d73a"
407
+ },
408
+ {
409
+ "repo": "scenario-labs/3d-collection",
410
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
411
+ "path": "assets/scenario_asset_dD4bnfT5Uk2mdeeCf7tJjeF3/output.glb",
412
+ "sha256": "fbd3c54488095c88be9585aa31a4f12651ff93722d56d210b56f62f51e796179",
413
+ "asset_id": "scenario:asset_dD4bnfT5Uk2mdeeCf7tJjeF3",
414
+ "license": "cc-by-4.0",
415
+ "author": "Scenario",
416
+ "title": "scenario:asset_dD4bnfT5Uk2mdeeCf7tJjeF3",
417
+ "source_model": "model_yvo3d-image-to-3d",
418
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
419
+ "object_id": "scenario-8a1bf58a7e151b7669d4",
420
+ "source_object_id": "scenario-8a1bf58a7e151b7669d4"
421
+ },
422
+ {
423
+ "repo": "scenario-labs/3d-collection",
424
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
425
+ "path": "assets/235d9bb960353a38/056f751264889193.glb",
426
+ "sha256": "b2e4672cd74e52046e7fc96eaf04efcdff2c45676548aeb8602a56edc55e41f4",
427
+ "asset_id": "235d9bb960353a38",
428
+ "license": "cc-by-4.0",
429
+ "author": "Scenario",
430
+ "title": "235d9bb960353a38",
431
+ "source_model": "gpt-6-astra",
432
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
433
+ "object_id": "scenario-387c8e1e591b785054e6",
434
+ "source_object_id": "scenario-387c8e1e591b785054e6"
435
+ },
436
+ {
437
+ "repo": "scenario-labs/3d-collection",
438
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
439
+ "path": "assets/scenario_asset_nKd9y67AGcwgNu93YFAWtuKC/output.glb",
440
+ "sha256": "5a2d35f584bf626d96dc7aa427970b06d9d856d3ecf919707d374dd02670ea69",
441
+ "asset_id": "scenario:asset_nKd9y67AGcwgNu93YFAWtuKC",
442
+ "license": "cc-by-4.0",
443
+ "author": "Scenario",
444
+ "title": "scenario:asset_nKd9y67AGcwgNu93YFAWtuKC",
445
+ "source_model": "model_meshy-img23d",
446
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
447
+ "object_id": "scenario-e88dc70a195271498d23",
448
+ "source_object_id": "scenario-e88dc70a195271498d23"
449
+ },
450
+ {
451
+ "repo": "scenario-labs/3d-collection",
452
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
453
+ "path": "assets/scenario_asset_TmBXvPuDDd6hQohRKc2xA7CD/output.glb",
454
+ "sha256": "040613d474db9d2ac51dfe9cf5cae6f0add07fd2cd9a162a8a257ef2c1216a2d",
455
+ "asset_id": "scenario:asset_TmBXvPuDDd6hQohRKc2xA7CD",
456
+ "license": "cc-by-4.0",
457
+ "author": "Scenario",
458
+ "title": "scenario:asset_TmBXvPuDDd6hQohRKc2xA7CD",
459
+ "source_model": "model_tripo-p1-image-to-3d",
460
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
461
+ "object_id": "scenario-7f98b44563b6a2b1e0a3",
462
+ "source_object_id": "scenario-7f98b44563b6a2b1e0a3"
463
+ },
464
+ {
465
+ "repo": "scenario-labs/3d-collection",
466
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
467
+ "path": "assets/c908eeca2605ca5a/d646af767b201652.glb",
468
+ "sha256": "400c5e6d8cc1e37a7e23bce93cdb3da57f621a6a7e51f7e4c8f4c875ec53e4bd",
469
+ "asset_id": "c908eeca2605ca5a",
470
+ "license": "cc-by-4.0",
471
+ "author": "Scenario",
472
+ "title": "c908eeca2605ca5a",
473
+ "source_model": "claude-opus-5-5",
474
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
475
+ "object_id": "scenario-9f90af50ddf3cc3b8dc9",
476
+ "source_object_id": "scenario-9f90af50ddf3cc3b8dc9"
477
+ },
478
+ {
479
+ "repo": "scenario-labs/3d-collection",
480
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
481
+ "path": "assets/scenario_asset_VdvKmv8rbL34DQdbFQGRCTWQ/output.glb",
482
+ "sha256": "27108c11ba8cc8453c38a835af0c83c3cfef0a7d5e1bdebc8e537bf6be9eb0f0",
483
+ "asset_id": "scenario:asset_VdvKmv8rbL34DQdbFQGRCTWQ",
484
+ "license": "cc-by-4.0",
485
+ "author": "Scenario",
486
+ "title": "scenario:asset_VdvKmv8rbL34DQdbFQGRCTWQ",
487
+ "source_model": "model_trellis",
488
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
489
+ "object_id": "scenario-8e087edc87eb198f7358",
490
+ "source_object_id": "scenario-8e087edc87eb198f7358"
491
+ },
492
+ {
493
+ "repo": "scenario-labs/3d-collection",
494
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
495
+ "path": "assets/scenario_asset_nqVfuhFbnZ6zRdqoJLrRAY4s/output.glb",
496
+ "sha256": "20c2803ec33018117126ac9dfb7f79443c87aa52aacb1890c33f5e548ae044c7",
497
+ "asset_id": "scenario:asset_nqVfuhFbnZ6zRdqoJLrRAY4s",
498
+ "license": "cc-by-4.0",
499
+ "author": "Scenario",
500
+ "title": "scenario:asset_nqVfuhFbnZ6zRdqoJLrRAY4s",
501
+ "source_model": "model_tripo-v2-5-image-to-3d",
502
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
503
+ "object_id": "scenario-c4c39624a27e365901c5",
504
+ "source_object_id": "scenario-c4c39624a27e365901c5"
505
+ },
506
+ {
507
+ "repo": "scenario-labs/3d-collection",
508
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
509
+ "path": "assets/scenario_asset_95NZSL5PxdZjEMQL4QpoWaz7/output.glb",
510
+ "sha256": "64dbc21511a56e9ea3079608348ea56be17b6a62599e93d0a66a13207247ca02",
511
+ "asset_id": "scenario:asset_95NZSL5PxdZjEMQL4QpoWaz7",
512
+ "license": "cc-by-4.0",
513
+ "author": "Scenario",
514
+ "title": "scenario:asset_95NZSL5PxdZjEMQL4QpoWaz7",
515
+ "source_model": "model_pixal3d",
516
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
517
+ "object_id": "scenario-b490750daeb4998c0d16",
518
+ "source_object_id": "scenario-b490750daeb4998c0d16"
519
+ },
520
+ {
521
+ "repo": "scenario-labs/3d-collection",
522
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
523
+ "path": "assets/ad02587cc65da156/f07ca6f5eea265f5.glb",
524
+ "sha256": "7946af4eef28801c74f11cda843b63d4b68164f7288638346302c4877639c2a6",
525
+ "asset_id": "ad02587cc65da156",
526
+ "license": "cc-by-4.0",
527
+ "author": "Scenario",
528
+ "title": "ad02587cc65da156",
529
+ "source_model": "gpt-6-astra",
530
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
531
+ "object_id": "scenario-b1799ce46eb1de635b7e",
532
+ "source_object_id": "scenario-b1799ce46eb1de635b7e"
533
+ },
534
+ {
535
+ "repo": "scenario-labs/3d-collection",
536
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
537
+ "path": "assets/scenario_asset_UDpDkhXVXMnWn3HrU2Ce7fVq/output.glb",
538
+ "sha256": "fb13692795060bf3ed8b95ea121be28266d6de184d4997269d8ad67b54189ccd",
539
+ "asset_id": "scenario:asset_UDpDkhXVXMnWn3HrU2Ce7fVq",
540
+ "license": "cc-by-4.0",
541
+ "author": "Scenario",
542
+ "title": "scenario:asset_UDpDkhXVXMnWn3HrU2Ce7fVq",
543
+ "source_model": "model_meshy-7-img23d",
544
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
545
+ "object_id": "scenario-e602d47f161992c903e0",
546
+ "source_object_id": "scenario-e602d47f161992c903e0"
547
+ },
548
+ {
549
+ "repo": "scenario-labs/3d-collection",
550
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
551
+ "path": "assets/scenario_asset_TYoJxpMFMogTsnBocoU4ne6K/output.glb",
552
+ "sha256": "53c22d8d14999c69660023d7770abc4416181c5ad7b066d584e44172c5f1bbae",
553
+ "asset_id": "scenario:asset_TYoJxpMFMogTsnBocoU4ne6K",
554
+ "license": "cc-by-4.0",
555
+ "author": "Scenario",
556
+ "title": "scenario:asset_TYoJxpMFMogTsnBocoU4ne6K",
557
+ "source_model": "model_rodin-hyper3d",
558
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
559
+ "object_id": "scenario-41224d499165d1141c8a",
560
+ "source_object_id": "scenario-41224d499165d1141c8a"
561
+ },
562
+ {
563
+ "repo": "scenario-labs/3d-collection",
564
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
565
+ "path": "assets/scenario_asset_iRyoVbKAE1hwoq7rmZXxm9Rc/output.glb",
566
+ "sha256": "bacf1d43989eb16af64f1ab47b60d5eeaf951daf7cf7ba3350d8fa69b424f8c2",
567
+ "asset_id": "scenario:asset_iRyoVbKAE1hwoq7rmZXxm9Rc",
568
+ "license": "cc-by-4.0",
569
+ "author": "Scenario",
570
+ "title": "scenario:asset_iRyoVbKAE1hwoq7rmZXxm9Rc",
571
+ "source_model": "model_reconviagen-0-5",
572
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
573
+ "object_id": "scenario-464c65411e1df43484b6",
574
+ "source_object_id": "scenario-464c65411e1df43484b6"
575
+ },
576
+ {
577
+ "repo": "scenario-labs/3d-collection",
578
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
579
+ "path": "assets/scenario_asset_vP1MjicPiq34ia4KFb2U9wXJ/output.glb",
580
+ "sha256": "0946534bdc34a44802500aa58dd509679bc1742ea27770807b0b84e524e221fd",
581
+ "asset_id": "scenario:asset_vP1MjicPiq34ia4KFb2U9wXJ",
582
+ "license": "cc-by-4.0",
583
+ "author": "Scenario",
584
+ "title": "scenario:asset_vP1MjicPiq34ia4KFb2U9wXJ",
585
+ "source_model": "model_tripo-v3-1-image-to-3d",
586
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
587
+ "object_id": "scenario-7f98b44563b6a2b1e0a3",
588
+ "source_object_id": "scenario-7f98b44563b6a2b1e0a3"
589
+ },
590
+ {
591
+ "repo": "scenario-labs/3d-collection",
592
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
593
+ "path": "assets/scenario_asset_QiggxN9z1LL9vXvCsWe5cbfJ/output.glb",
594
+ "sha256": "8861690497c5460bb5d70a0f7af65921673f86d3c82d6d30580d911bc928c74d",
595
+ "asset_id": "scenario:asset_QiggxN9z1LL9vXvCsWe5cbfJ",
596
+ "license": "cc-by-4.0",
597
+ "author": "Scenario",
598
+ "title": "scenario:asset_QiggxN9z1LL9vXvCsWe5cbfJ",
599
+ "source_model": "model_rodin-hyper3d",
600
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
601
+ "object_id": "scenario-556b7a1414e71aade568",
602
+ "source_object_id": "scenario-556b7a1414e71aade568"
603
+ },
604
+ {
605
+ "repo": "scenario-labs/3d-collection",
606
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
607
+ "path": "assets/scenario_asset_VKKCk5EX1kBuk9FwTGzQsd8w/output.glb",
608
+ "sha256": "534f66fdc4ca2cf4129aaa73d0a29618e12e71e693120014f6127f9eaa1c0224",
609
+ "asset_id": "scenario:asset_VKKCk5EX1kBuk9FwTGzQsd8w",
610
+ "license": "cc-by-4.0",
611
+ "author": "Scenario",
612
+ "title": "scenario:asset_VKKCk5EX1kBuk9FwTGzQsd8w",
613
+ "source_model": "model_meshy-smart-topology",
614
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
615
+ "object_id": "scenario-de5c3a8b834fa12da88c",
616
+ "source_object_id": "scenario-de5c3a8b834fa12da88c"
617
+ },
618
+ {
619
+ "repo": "scenario-labs/3d-collection",
620
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
621
+ "path": "assets/scenario_asset_HLWZjA2B6KKDGpYGaXLvmYHq/output.glb",
622
+ "sha256": "037ef71f93039723386cb4f948f9bf4f429e74c7ece6788f51d231caded0811e",
623
+ "asset_id": "scenario:asset_HLWZjA2B6KKDGpYGaXLvmYHq",
624
+ "license": "cc-by-4.0",
625
+ "author": "Scenario",
626
+ "title": "scenario:asset_HLWZjA2B6KKDGpYGaXLvmYHq",
627
+ "source_model": "model_trellis",
628
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
629
+ "object_id": "scenario-53e1e59a0ec494d5c59a",
630
+ "source_object_id": "scenario-53e1e59a0ec494d5c59a"
631
+ },
632
+ {
633
+ "repo": "scenario-labs/3d-collection",
634
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
635
+ "path": "assets/scenario_asset_oLL5ToAk9mAH3dVwfBfButdP/output.glb",
636
+ "sha256": "188bc3a4455a767baaafc73bcdae8a6a1ccdfa0fff5a0cc91b77dfb99601b9dc",
637
+ "asset_id": "scenario:asset_oLL5ToAk9mAH3dVwfBfButdP",
638
+ "license": "cc-by-4.0",
639
+ "author": "Scenario",
640
+ "title": "scenario:asset_oLL5ToAk9mAH3dVwfBfButdP",
641
+ "source_model": "model_meshy-smart-topology",
642
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
643
+ "object_id": "scenario-70507811046725a3d969",
644
+ "source_object_id": "scenario-70507811046725a3d969"
645
+ },
646
+ {
647
+ "repo": "scenario-labs/3d-collection",
648
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
649
+ "path": "assets/scenario_asset_KYwfc9pAw1JEVFaBHSTb194Z/output.glb",
650
+ "sha256": "81ce08dca927c9ee473e09f57fd8388f4213bafaf9f32247b08a080a72651f04",
651
+ "asset_id": "scenario:asset_KYwfc9pAw1JEVFaBHSTb194Z",
652
+ "license": "cc-by-4.0",
653
+ "author": "Scenario",
654
+ "title": "scenario:asset_KYwfc9pAw1JEVFaBHSTb194Z",
655
+ "source_model": "model_yvo3d-image-to-3d",
656
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
657
+ "object_id": "scenario-d6f9d904d7bfb3c27844",
658
+ "source_object_id": "scenario-d6f9d904d7bfb3c27844"
659
+ },
660
+ {
661
+ "repo": "scenario-labs/3d-collection",
662
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
663
+ "path": "assets/scenario_asset_ji6pZ3cCx1yx6AoL2UUzMRwn/output.glb",
664
+ "sha256": "9d8b9a2928de97a17c4e1c1a456e03cdd950df31d32c5217009f44b0e998f55a",
665
+ "asset_id": "scenario:asset_ji6pZ3cCx1yx6AoL2UUzMRwn",
666
+ "license": "cc-by-4.0",
667
+ "author": "Scenario",
668
+ "title": "scenario:asset_ji6pZ3cCx1yx6AoL2UUzMRwn",
669
+ "source_model": "model_tripo-p1-image-to-3d",
670
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
671
+ "object_id": "scenario-085e1963fcccdc9d5b3f",
672
+ "source_object_id": "scenario-085e1963fcccdc9d5b3f"
673
+ },
674
+ {
675
+ "repo": "scenario-labs/3d-collection",
676
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
677
+ "path": "assets/4f43cf75a8660b1c/187a1d9ef36591e9.glb",
678
+ "sha256": "94dad0e2be58d23bb9282f84bed8f753d779f7ca6d6b7cd442ab6e3d25d46778",
679
+ "asset_id": "4f43cf75a8660b1c",
680
+ "license": "cc-by-4.0",
681
+ "author": "Scenario",
682
+ "title": "4f43cf75a8660b1c",
683
+ "source_model": "claude-opus-5-5",
684
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
685
+ "object_id": "scenario-798f7b2b5e4ec95fba0f",
686
+ "source_object_id": "scenario-798f7b2b5e4ec95fba0f"
687
+ },
688
+ {
689
+ "repo": "scenario-labs/3d-collection",
690
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
691
+ "path": "assets/scenario_asset_S8uTvDr43t5chE48nznNmrAc/output.glb",
692
+ "sha256": "b97c45d970d58ff0b6b707b409a3dafd55fe9c91db878e874d83705a6c74b34f",
693
+ "asset_id": "scenario:asset_S8uTvDr43t5chE48nznNmrAc",
694
+ "license": "cc-by-4.0",
695
+ "author": "Scenario",
696
+ "title": "scenario:asset_S8uTvDr43t5chE48nznNmrAc",
697
+ "source_model": "model_csm-multiview-to-3d",
698
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
699
+ "object_id": "scenario-991595188cc901f110dc",
700
+ "source_object_id": "scenario-991595188cc901f110dc"
701
+ },
702
+ {
703
+ "repo": "scenario-labs/3d-collection",
704
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
705
+ "path": "assets/scenario_asset_6gKbavLEWZCCv1VWDCa8efhu/output.glb",
706
+ "sha256": "e74e06e961cee0a0783153ca415c9f2149208eb79deb2e3dd228fdd45807f501",
707
+ "asset_id": "scenario:asset_6gKbavLEWZCCv1VWDCa8efhu",
708
+ "license": "cc-by-4.0",
709
+ "author": "Scenario",
710
+ "title": "scenario:asset_6gKbavLEWZCCv1VWDCa8efhu",
711
+ "source_model": "model_rodin-hyper3d",
712
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
713
+ "object_id": "scenario-f2efa588b531d1fb9ec3",
714
+ "source_object_id": "scenario-f2efa588b531d1fb9ec3"
715
+ },
716
+ {
717
+ "repo": "scenario-labs/3d-collection",
718
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
719
+ "path": "assets/scenario_asset_VfmiL7nFMC3bvSKTkSa7tFuh/output.glb",
720
+ "sha256": "e67a94a1d0870235f8e6081cf56d2bc70e6d61fd9b367f6388d3ab9fba8a30e3",
721
+ "asset_id": "scenario:asset_VfmiL7nFMC3bvSKTkSa7tFuh",
722
+ "license": "cc-by-4.0",
723
+ "author": "Scenario",
724
+ "title": "scenario:asset_VfmiL7nFMC3bvSKTkSa7tFuh",
725
+ "source_model": "model_direct3d-s2",
726
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
727
+ "object_id": "scenario-3431919e57b5420df888",
728
+ "source_object_id": "scenario-3431919e57b5420df888"
729
+ },
730
+ {
731
+ "repo": "scenario-labs/3d-collection",
732
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
733
+ "path": "assets/scenario_asset_8pyMRPstPsnCVsYAf3kz1VQh/output.glb",
734
+ "sha256": "6cc9d5df11152518f71d497d70fb83a6fc64a9cd5179daa082d6de3ab037517c",
735
+ "asset_id": "scenario:asset_8pyMRPstPsnCVsYAf3kz1VQh",
736
+ "license": "cc-by-4.0",
737
+ "author": "Scenario",
738
+ "title": "scenario:asset_8pyMRPstPsnCVsYAf3kz1VQh",
739
+ "source_model": "model_scenario-claude-opus-5-5-3d",
740
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
741
+ "object_id": "scenario-c4613bfdc2da9e7b12e3",
742
+ "source_object_id": "scenario-c4613bfdc2da9e7b12e3"
743
+ },
744
+ {
745
+ "repo": "scenario-labs/3d-collection",
746
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
747
+ "path": "assets/scenario_asset_CpMtjRFkYf4qJFqWXfYUhkgG/output.glb",
748
+ "sha256": "a0403f578ddc56ffe4822861076589d55bf136395f66fa1294740113ff7c79e6",
749
+ "asset_id": "scenario:asset_CpMtjRFkYf4qJFqWXfYUhkgG",
750
+ "license": "cc-by-4.0",
751
+ "author": "Scenario",
752
+ "title": "scenario:asset_CpMtjRFkYf4qJFqWXfYUhkgG",
753
+ "source_model": "model_yvo3d-image-to-3d",
754
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
755
+ "object_id": "scenario-bf6ef83e0415cbcaef42",
756
+ "source_object_id": "scenario-bf6ef83e0415cbcaef42"
757
+ },
758
+ {
759
+ "repo": "scenario-labs/3d-collection",
760
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
761
+ "path": "assets/scenario_asset_TtQmB4yb5GmPs2XoMhEoTbXt/output.glb",
762
+ "sha256": "6e3ea0ad4208a4f0b55d981218756ab9aabcfd335456b49d66c57989d8ac7932",
763
+ "asset_id": "scenario:asset_TtQmB4yb5GmPs2XoMhEoTbXt",
764
+ "license": "cc-by-4.0",
765
+ "author": "Scenario",
766
+ "title": "scenario:asset_TtQmB4yb5GmPs2XoMhEoTbXt",
767
+ "source_model": "model_trellis",
768
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
769
+ "object_id": "scenario-7230f13fded428b3dd03",
770
+ "source_object_id": "scenario-7230f13fded428b3dd03"
771
+ },
772
+ {
773
+ "repo": "scenario-labs/3d-collection",
774
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
775
+ "path": "assets/scenario_asset_RgnwiEnHczYcZ4jJ9TLc3eE4/output.glb",
776
+ "sha256": "8b8ac09c744ed38bc9f70262021334cfa0c89fe0653c8375fe1ceeb77cc71e21",
777
+ "asset_id": "scenario:asset_RgnwiEnHczYcZ4jJ9TLc3eE4",
778
+ "license": "cc-by-4.0",
779
+ "author": "Scenario",
780
+ "title": "scenario:asset_RgnwiEnHczYcZ4jJ9TLc3eE4",
781
+ "source_model": "model_rodin-hyper3d-v2-5-fast",
782
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
783
+ "object_id": "scenario-4e2e45c882aa9d2e2716",
784
+ "source_object_id": "scenario-4e2e45c882aa9d2e2716"
785
+ },
786
+ {
787
+ "repo": "scenario-labs/3d-collection",
788
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
789
+ "path": "assets/scenario_asset_P2nUBx2nK3xNKJFMBh8P3SbT/output.glb",
790
+ "sha256": "708543146174141e5f95d32283649fd0504394d53c8722bd7a0c39e2bef12a72",
791
+ "asset_id": "scenario:asset_P2nUBx2nK3xNKJFMBh8P3SbT",
792
+ "license": "cc-by-4.0",
793
+ "author": "Scenario",
794
+ "title": "scenario:asset_P2nUBx2nK3xNKJFMBh8P3SbT",
795
+ "source_model": "model_meta-sam-3d-body",
796
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
797
+ "object_id": "scenario-05a748c9c86f615a9506",
798
+ "source_object_id": "scenario-05a748c9c86f615a9506"
799
+ },
800
+ {
801
+ "repo": "scenario-labs/3d-collection",
802
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
803
+ "path": "assets/4d54a50094e52d2b/abe7aea7e42e2cfa.glb",
804
+ "sha256": "24971a53f2651f66e92c2da539675222bed38d2a08a027e135268de7926729f8",
805
+ "asset_id": "4d54a50094e52d2b",
806
+ "license": "cc-by-4.0",
807
+ "author": "Scenario",
808
+ "title": "4d54a50094e52d2b",
809
+ "source_model": "gpt-6-astra",
810
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
811
+ "object_id": "scenario-a0ab890ab088491fcbe7",
812
+ "source_object_id": "scenario-a0ab890ab088491fcbe7"
813
+ },
814
+ {
815
+ "repo": "scenario-labs/3d-collection",
816
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
817
+ "path": "assets/d53af1d69a7df48e/b617bf376be6deca.glb",
818
+ "sha256": "a0f629173fd79615e898d214d91b1007df0b7211ab0d77070b5a32b701e9dbc7",
819
+ "asset_id": "d53af1d69a7df48e",
820
+ "license": "cc-by-4.0",
821
+ "author": "Scenario",
822
+ "title": "d53af1d69a7df48e",
823
+ "source_model": "gpt-6-astra",
824
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
825
+ "object_id": "scenario-65648f8af659f2626c9a",
826
+ "source_object_id": "scenario-65648f8af659f2626c9a"
827
+ },
828
+ {
829
+ "repo": "scenario-labs/3d-collection",
830
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
831
+ "path": "assets/scenario_asset_gA89x3a9cy4cUzVGN3KDA4W9/output.glb",
832
+ "sha256": "fc73c6cf8fb66a90d4ce4e707d876f2bfc0b87bc5cfaaa20215866fab1334ab2",
833
+ "asset_id": "scenario:asset_gA89x3a9cy4cUzVGN3KDA4W9",
834
+ "license": "cc-by-4.0",
835
+ "author": "Scenario",
836
+ "title": "scenario:asset_gA89x3a9cy4cUzVGN3KDA4W9",
837
+ "source_model": "model_yvo3d-image-to-3d",
838
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
839
+ "object_id": "scenario-a1125b61956d2b157da5",
840
+ "source_object_id": "scenario-a1125b61956d2b157da5"
841
+ },
842
+ {
843
+ "repo": "scenario-labs/3d-collection",
844
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
845
+ "path": "assets/scenario_asset_fzZEg2u24taWgTTRTMkY2hiK/output.glb",
846
+ "sha256": "73a20bfd87f97278d20e4fadcbc999dcfe698b7d8d6db89ac0a68c7ca7edf881",
847
+ "asset_id": "scenario:asset_fzZEg2u24taWgTTRTMkY2hiK",
848
+ "license": "cc-by-4.0",
849
+ "author": "Scenario",
850
+ "title": "scenario:asset_fzZEg2u24taWgTTRTMkY2hiK",
851
+ "source_model": "model_rodin-hyper3d-v2-5-fast",
852
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
853
+ "object_id": "scenario-085e1963fcccdc9d5b3f",
854
+ "source_object_id": "scenario-085e1963fcccdc9d5b3f"
855
+ },
856
+ {
857
+ "repo": "allenai/objaverse",
858
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
859
+ "path": "glbs/000-000/04bd8f55740342429cbf34ca9a5b9792.glb",
860
+ "asset_id": "04bd8f55740342429cbf34ca9a5b9792",
861
+ "object_id": "objaverse-04bd8f55740342429cbf34ca9a5b9792",
862
+ "license": "cc0-1.0",
863
+ "author": "Digital Atlas of Ancient Life",
864
+ "title": "Gastropod: Ecphora quadricostata (PRI 70750)",
865
+ "source_url": "https://sketchfab.com/3d-models/04bd8f55740342429cbf34ca9a5b9792",
866
+ "sha256": "fb11df227261356a902fa0f725690902c7297e7eb6b92157f460e3f0b93f9a68",
867
+ "source_object_id": "objaverse-04bd8f55740342429cbf34ca9a5b9792"
868
+ },
869
+ {
870
+ "repo": "allenai/objaverse",
871
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
872
+ "path": "glbs/000-000/1a57a0d6609145b486ed5b1d3e9ec7fb.glb",
873
+ "asset_id": "1a57a0d6609145b486ed5b1d3e9ec7fb",
874
+ "object_id": "objaverse-1a57a0d6609145b486ed5b1d3e9ec7fb",
875
+ "license": "cc0-1.0",
876
+ "author": "Cleveland Museum of Art",
877
+ "title": "1997.11 Standing Bodhisattva",
878
+ "source_url": "https://sketchfab.com/3d-models/1a57a0d6609145b486ed5b1d3e9ec7fb",
879
+ "sha256": "52825f9bc6ab3f301107a766c23efc346157702952b7d929144881d43ae33965",
880
+ "source_object_id": "objaverse-1a57a0d6609145b486ed5b1d3e9ec7fb"
881
+ },
882
+ {
883
+ "repo": "allenai/objaverse",
884
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
885
+ "path": "glbs/000-000/d8c7caeb4497447ba801ed4479575d12.glb",
886
+ "asset_id": "d8c7caeb4497447ba801ed4479575d12",
887
+ "object_id": "objaverse-d8c7caeb4497447ba801ed4479575d12",
888
+ "license": "cc0-1.0",
889
+ "author": "Digital Atlas of Ancient Life",
890
+ "title": "Gastropod: Diodora sp. (PRI 76791)",
891
+ "source_url": "https://sketchfab.com/3d-models/d8c7caeb4497447ba801ed4479575d12",
892
+ "sha256": "26809d92313f7a569a29f8fd1cebb1b0277d866ade5449fd80b515cd2704e9ab",
893
+ "source_object_id": "objaverse-d8c7caeb4497447ba801ed4479575d12"
894
+ },
895
+ {
896
+ "repo": "allenai/objaverse",
897
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
898
+ "path": "glbs/000-000/521be39e2ea94bbaa1f06f3e89b0ad97.glb",
899
+ "asset_id": "521be39e2ea94bbaa1f06f3e89b0ad97",
900
+ "object_id": "objaverse-521be39e2ea94bbaa1f06f3e89b0ad97",
901
+ "license": "cc0-1.0",
902
+ "author": "Virtual Museums of Ma\u0142opolska",
903
+ "title": "Cauldron",
904
+ "source_url": "https://sketchfab.com/3d-models/521be39e2ea94bbaa1f06f3e89b0ad97",
905
+ "sha256": "db9d04dd646f6b162fcd9ed3411b721f042007b468e6e7fd3fb933c1663e5183",
906
+ "source_object_id": "objaverse-521be39e2ea94bbaa1f06f3e89b0ad97"
907
+ },
908
+ {
909
+ "repo": "allenai/objaverse",
910
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
911
+ "path": "glbs/000-001/8a9782ade2764984a792f3fb553e27e5.glb",
912
+ "asset_id": "8a9782ade2764984a792f3fb553e27e5",
913
+ "object_id": "objaverse-8a9782ade2764984a792f3fb553e27e5",
914
+ "license": "cc0-1.0",
915
+ "author": "Virtual Museums of Ma\u0142opolska",
916
+ "title": "Perfume bottle in the case",
917
+ "source_url": "https://sketchfab.com/3d-models/8a9782ade2764984a792f3fb553e27e5",
918
+ "sha256": "6ac1a0928f516698df9e61647546fb77e342a56e15938fadbe3320a8fd605b2e",
919
+ "source_object_id": "objaverse-8a9782ade2764984a792f3fb553e27e5"
920
+ },
921
+ {
922
+ "repo": "allenai/objaverse",
923
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
924
+ "path": "glbs/000-000/d1fe37e659c84bacbbfeb54ab2fbbd6e.glb",
925
+ "asset_id": "d1fe37e659c84bacbbfeb54ab2fbbd6e",
926
+ "object_id": "objaverse-d1fe37e659c84bacbbfeb54ab2fbbd6e",
927
+ "license": "cc0-1.0",
928
+ "author": "Museum f\u00fcr Kunst und Gewerbe Hamburg",
929
+ "title": "Jug",
930
+ "source_url": "https://sketchfab.com/3d-models/d1fe37e659c84bacbbfeb54ab2fbbd6e",
931
+ "sha256": "f04a2890238f3ba40dcf13cd78fc97c376de0cb14cfa46fbc6504866c77fd20c",
932
+ "source_object_id": "objaverse-d1fe37e659c84bacbbfeb54ab2fbbd6e"
933
+ },
934
+ {
935
+ "repo": "allenai/objaverse",
936
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
937
+ "path": "glbs/000-001/5f2b9bd73ce64fbfbc8dc4309d429b1e.glb",
938
+ "asset_id": "5f2b9bd73ce64fbfbc8dc4309d429b1e",
939
+ "object_id": "objaverse-5f2b9bd73ce64fbfbc8dc4309d429b1e",
940
+ "license": "cc0-1.0",
941
+ "author": "Digital Atlas of Ancient Life",
942
+ "title": "Bivalve: Isognomon maxillata (PRI 76763)",
943
+ "source_url": "https://sketchfab.com/3d-models/5f2b9bd73ce64fbfbc8dc4309d429b1e",
944
+ "sha256": "70d31c2792ffc229285630d478ae5d27372f6f8583f33c4e068b76f011ab0ceb",
945
+ "source_object_id": "objaverse-5f2b9bd73ce64fbfbc8dc4309d429b1e"
946
+ },
947
+ {
948
+ "repo": "allenai/objaverse",
949
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
950
+ "path": "glbs/000-001/1b640e4be73d461abd24eee5e1b61301.glb",
951
+ "asset_id": "1b640e4be73d461abd24eee5e1b61301",
952
+ "object_id": "objaverse-1b640e4be73d461abd24eee5e1b61301",
953
+ "license": "cc0-1.0",
954
+ "author": "Virtual Museums of Ma\u0142opolska",
955
+ "title": "Sculpture of man and woman",
956
+ "source_url": "https://sketchfab.com/3d-models/1b640e4be73d461abd24eee5e1b61301",
957
+ "sha256": "d723ed8842843bb49c04f4eecc73a36d48985b991b96a7ec0938f9680bad4727",
958
+ "source_object_id": "objaverse-1b640e4be73d461abd24eee5e1b61301"
959
+ },
960
+ {
961
+ "repo": "allenai/objaverse",
962
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
963
+ "path": "glbs/000-001/250c1384333d484895778e6b951a0fab.glb",
964
+ "asset_id": "250c1384333d484895778e6b951a0fab",
965
+ "object_id": "objaverse-250c1384333d484895778e6b951a0fab",
966
+ "license": "cc0-1.0",
967
+ "author": "Cleveland Museum of Art",
968
+ "title": "1962.153 Bottle with Fish Design",
969
+ "source_url": "https://sketchfab.com/3d-models/250c1384333d484895778e6b951a0fab",
970
+ "sha256": "e34fd4afda321bb3a5a2c6304d7e1dee3b70d17b2b507778a3047d56d870524a",
971
+ "source_object_id": "objaverse-250c1384333d484895778e6b951a0fab"
972
+ },
973
+ {
974
+ "repo": "allenai/objaverse",
975
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
976
+ "path": "glbs/000-001/d433f7d2bc6b4d6eb95497210b3736dd.glb",
977
+ "asset_id": "d433f7d2bc6b4d6eb95497210b3736dd",
978
+ "object_id": "objaverse-d433f7d2bc6b4d6eb95497210b3736dd",
979
+ "license": "cc0-1.0",
980
+ "author": "Virtual Museums of Ma\u0142opolska",
981
+ "title": "Painted Celtic flask",
982
+ "source_url": "https://sketchfab.com/3d-models/d433f7d2bc6b4d6eb95497210b3736dd",
983
+ "sha256": "369ebdff7bfd051a09f518a6b1855e957f74372874e2670cbb889a29d1f5228e",
984
+ "source_object_id": "objaverse-d433f7d2bc6b4d6eb95497210b3736dd"
985
+ },
986
+ {
987
+ "repo": "allenai/objaverse",
988
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
989
+ "path": "glbs/000-001/d488f678a35c4789a75641d2be1773ef.glb",
990
+ "asset_id": "d488f678a35c4789a75641d2be1773ef",
991
+ "object_id": "objaverse-d488f678a35c4789a75641d2be1773ef",
992
+ "license": "cc0-1.0",
993
+ "author": "Digital Atlas of Ancient Life",
994
+ "title": "Amplexopora filiasa (PRI 76723)",
995
+ "source_url": "https://sketchfab.com/3d-models/d488f678a35c4789a75641d2be1773ef",
996
+ "sha256": "11acf56ca828a407370eca48f1decdca2da10e378dfd76c73d6d25def96a2da0",
997
+ "source_object_id": "objaverse-d488f678a35c4789a75641d2be1773ef"
998
+ },
999
+ {
1000
+ "repo": "allenai/objaverse",
1001
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1002
+ "path": "glbs/000-000/93d6432c6d834ffea49af75e93b4f729.glb",
1003
+ "asset_id": "93d6432c6d834ffea49af75e93b4f729",
1004
+ "object_id": "objaverse-93d6432c6d834ffea49af75e93b4f729",
1005
+ "license": "cc0-1.0",
1006
+ "author": "Digital Atlas of Ancient Life",
1007
+ "title": "PRI Sideratrea Siderea",
1008
+ "source_url": "https://sketchfab.com/3d-models/93d6432c6d834ffea49af75e93b4f729",
1009
+ "sha256": "509e123e5a6e969bb9ffee1e5c781ed2c2bd9347ca67d58264ca4e1ac0950ea5",
1010
+ "source_object_id": "objaverse-93d6432c6d834ffea49af75e93b4f729"
1011
+ },
1012
+ {
1013
+ "repo": "allenai/objaverse",
1014
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1015
+ "path": "glbs/000-000/30256f207c5e4500befb371273ab6878.glb",
1016
+ "asset_id": "30256f207c5e4500befb371273ab6878",
1017
+ "object_id": "objaverse-30256f207c5e4500befb371273ab6878",
1018
+ "license": "cc0-1.0",
1019
+ "author": "cineg",
1020
+ "title": "Candle Holder",
1021
+ "source_url": "https://sketchfab.com/3d-models/30256f207c5e4500befb371273ab6878",
1022
+ "sha256": "888e65cb92495736abdc3c425302afa7ce11131d23b54921725ab18b94115c6d",
1023
+ "source_object_id": "objaverse-30256f207c5e4500befb371273ab6878"
1024
+ },
1025
+ {
1026
+ "repo": "allenai/objaverse",
1027
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1028
+ "path": "glbs/000-000/71db1c656c1c415f9ba0948e0dba8ba6.glb",
1029
+ "asset_id": "71db1c656c1c415f9ba0948e0dba8ba6",
1030
+ "object_id": "objaverse-71db1c656c1c415f9ba0948e0dba8ba6",
1031
+ "license": "cc0-1.0",
1032
+ "author": "galway3d",
1033
+ "title": "Fox",
1034
+ "source_url": "https://sketchfab.com/3d-models/71db1c656c1c415f9ba0948e0dba8ba6",
1035
+ "sha256": "396d35947c52811e43188b60859cd9231d1669f1993211fd4e5921fc67a40f02",
1036
+ "source_object_id": "objaverse-71db1c656c1c415f9ba0948e0dba8ba6"
1037
+ },
1038
+ {
1039
+ "repo": "allenai/objaverse",
1040
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1041
+ "path": "glbs/000-001/57284863a5c74b3ea2da7dbd26876662.glb",
1042
+ "asset_id": "57284863a5c74b3ea2da7dbd26876662",
1043
+ "object_id": "objaverse-57284863a5c74b3ea2da7dbd26876662",
1044
+ "license": "cc0-1.0",
1045
+ "author": "galway3d",
1046
+ "title": "Toorelectra - Sweathouse",
1047
+ "source_url": "https://sketchfab.com/3d-models/57284863a5c74b3ea2da7dbd26876662",
1048
+ "sha256": "177732d31e10229d647e9f87f6dc1bfb9cdf7592a9ade72a1a51518f7564b83a",
1049
+ "source_object_id": "objaverse-57284863a5c74b3ea2da7dbd26876662"
1050
+ },
1051
+ {
1052
+ "repo": "allenai/objaverse",
1053
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1054
+ "path": "glbs/000-001/5a0ea446a4284839aaad41bfb054f376.glb",
1055
+ "asset_id": "5a0ea446a4284839aaad41bfb054f376",
1056
+ "object_id": "objaverse-5a0ea446a4284839aaad41bfb054f376",
1057
+ "license": "cc0-1.0",
1058
+ "author": "Minneapolis Institute of Art",
1059
+ "title": "Yan steamer, 11th century BCE",
1060
+ "source_url": "https://sketchfab.com/3d-models/5a0ea446a4284839aaad41bfb054f376",
1061
+ "sha256": "45d12874d38a7fe1ef1b4612912ccfabb7541cb8eb0dde961dd057e426ab61ea",
1062
+ "source_object_id": "objaverse-5a0ea446a4284839aaad41bfb054f376"
1063
+ },
1064
+ {
1065
+ "repo": "allenai/objaverse",
1066
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1067
+ "path": "glbs/000-000/9525cde4b189451289432e3f98ffc90d.glb",
1068
+ "asset_id": "9525cde4b189451289432e3f98ffc90d",
1069
+ "object_id": "objaverse-9525cde4b189451289432e3f98ffc90d",
1070
+ "license": "cc0-1.0",
1071
+ "author": "Museo Nacional de Historia Natural de Chile",
1072
+ "title": "Pelagornis chilensis. Rama mandibular derecha",
1073
+ "source_url": "https://sketchfab.com/3d-models/9525cde4b189451289432e3f98ffc90d",
1074
+ "sha256": "92424bd9516d529890b8002610b074f115ce6e9b42fdd582602897115bba7f43",
1075
+ "source_object_id": "objaverse-9525cde4b189451289432e3f98ffc90d"
1076
+ },
1077
+ {
1078
+ "repo": "allenai/objaverse",
1079
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1080
+ "path": "glbs/000-001/f8f81494d773464eb4af4c863a212ab9.glb",
1081
+ "asset_id": "f8f81494d773464eb4af4c863a212ab9",
1082
+ "object_id": "objaverse-f8f81494d773464eb4af4c863a212ab9",
1083
+ "license": "cc0-1.0",
1084
+ "author": "Digital Atlas of Ancient Life",
1085
+ "title": "Ursus spelaeus (cave bear) lower jaw (PRI 50009)",
1086
+ "source_url": "https://sketchfab.com/3d-models/f8f81494d773464eb4af4c863a212ab9",
1087
+ "sha256": "6149bc417c4a33a209655629a9e6aa46f7498166c4b9c44e830e45c4d2a08903",
1088
+ "source_object_id": "objaverse-f8f81494d773464eb4af4c863a212ab9"
1089
+ },
1090
+ {
1091
+ "repo": "allenai/objaverse",
1092
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1093
+ "path": "glbs/000-000/0068a53f561d4dccbaef45841107a42d.glb",
1094
+ "asset_id": "0068a53f561d4dccbaef45841107a42d",
1095
+ "object_id": "objaverse-0068a53f561d4dccbaef45841107a42d",
1096
+ "license": "cc0-1.0",
1097
+ "author": "Museo Nacional de Historia Natural de Chile",
1098
+ "title": "Ericusa sowerbyi 1025",
1099
+ "source_url": "https://sketchfab.com/3d-models/0068a53f561d4dccbaef45841107a42d",
1100
+ "sha256": "f51bc1301f8ef27e139c9f994e5c8257eb0ab8f71613ed46f0878c2e477982da",
1101
+ "source_object_id": "objaverse-0068a53f561d4dccbaef45841107a42d"
1102
+ },
1103
+ {
1104
+ "repo": "allenai/objaverse",
1105
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1106
+ "path": "glbs/000-000/559b7a2ae50f426a8993b609d22931ff.glb",
1107
+ "asset_id": "559b7a2ae50f426a8993b609d22931ff",
1108
+ "object_id": "objaverse-559b7a2ae50f426a8993b609d22931ff",
1109
+ "license": "cc0-1.0",
1110
+ "author": "Digital Atlas of Ancient Life",
1111
+ "title": "Angiosperm: Koelreuteria allenii (Cornell Univ.)",
1112
+ "source_url": "https://sketchfab.com/3d-models/559b7a2ae50f426a8993b609d22931ff",
1113
+ "sha256": "36b7be877bd77ebb5c24b4615cb0b059226a27727867b9ee40be5eb94bcc1bb0",
1114
+ "source_object_id": "objaverse-559b7a2ae50f426a8993b609d22931ff"
1115
+ },
1116
+ {
1117
+ "repo": "allenai/objaverse",
1118
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1119
+ "path": "glbs/000-001/4478d3dd074b40ee96fcbcb227e5a732.glb",
1120
+ "asset_id": "4478d3dd074b40ee96fcbcb227e5a732",
1121
+ "object_id": "objaverse-4478d3dd074b40ee96fcbcb227e5a732",
1122
+ "license": "cc0-1.0",
1123
+ "author": "Virtual Museums of Ma\u0142opolska",
1124
+ "title": "COTY powder packaging",
1125
+ "source_url": "https://sketchfab.com/3d-models/4478d3dd074b40ee96fcbcb227e5a732",
1126
+ "sha256": "eb3723c04cb44b69b7298628308e15161f16b584121c479c8910fc8ea642a95d",
1127
+ "source_object_id": "objaverse-4478d3dd074b40ee96fcbcb227e5a732"
1128
+ },
1129
+ {
1130
+ "repo": "allenai/objaverse",
1131
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1132
+ "path": "glbs/000-001/ddc820bb5e3a422b9693912322e23acc.glb",
1133
+ "asset_id": "ddc820bb5e3a422b9693912322e23acc",
1134
+ "object_id": "objaverse-ddc820bb5e3a422b9693912322e23acc",
1135
+ "license": "cc0-1.0",
1136
+ "author": "Digital Atlas of Ancient Life",
1137
+ "title": "Trilobite: Isotelus sp. (PRI 45502)",
1138
+ "source_url": "https://sketchfab.com/3d-models/ddc820bb5e3a422b9693912322e23acc",
1139
+ "sha256": "767ebeec273e4ac6536d1c96371c304927bac5a364517e2cbbd646bd533227a1",
1140
+ "source_object_id": "objaverse-ddc820bb5e3a422b9693912322e23acc"
1141
+ },
1142
+ {
1143
+ "repo": "allenai/objaverse",
1144
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1145
+ "path": "glbs/000-001/dd354a8ba61446c0a8c98685458ee5a9.glb",
1146
+ "asset_id": "dd354a8ba61446c0a8c98685458ee5a9",
1147
+ "object_id": "objaverse-dd354a8ba61446c0a8c98685458ee5a9",
1148
+ "license": "cc0-1.0",
1149
+ "author": "Digital Atlas of Ancient Life",
1150
+ "title": "Brachiopod: Athyris spiriferoides (PRI 44050)",
1151
+ "source_url": "https://sketchfab.com/3d-models/dd354a8ba61446c0a8c98685458ee5a9",
1152
+ "sha256": "189992257282b2d49fd3aca211fbcc65119c5c87aff4aa95e199fd01091fa146",
1153
+ "source_object_id": "objaverse-dd354a8ba61446c0a8c98685458ee5a9"
1154
+ },
1155
+ {
1156
+ "repo": "allenai/objaverse",
1157
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1158
+ "path": "glbs/000-001/0b7c6e8e32144b72806ed31cb49b4145.glb",
1159
+ "asset_id": "0b7c6e8e32144b72806ed31cb49b4145",
1160
+ "object_id": "objaverse-0b7c6e8e32144b72806ed31cb49b4145",
1161
+ "license": "cc0-1.0",
1162
+ "author": "Digital Atlas of Ancient Life",
1163
+ "title": "Pyrite",
1164
+ "source_url": "https://sketchfab.com/3d-models/0b7c6e8e32144b72806ed31cb49b4145",
1165
+ "sha256": "853f762ce4665b29593b3bf341bbfe28211d44d9b853b55ff84deec894d81ad2",
1166
+ "source_object_id": "objaverse-0b7c6e8e32144b72806ed31cb49b4145"
1167
+ },
1168
+ {
1169
+ "repo": "allenai/objaverse",
1170
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1171
+ "path": "glbs/000-000/1034cd8e4df5430cb874f012415a43b0.glb",
1172
+ "asset_id": "1034cd8e4df5430cb874f012415a43b0",
1173
+ "object_id": "objaverse-1034cd8e4df5430cb874f012415a43b0",
1174
+ "license": "cc0-1.0",
1175
+ "author": "Virtual Museums of Ma\u0142opolska",
1176
+ "title": "Ding censer with an openwork cover",
1177
+ "source_url": "https://sketchfab.com/3d-models/1034cd8e4df5430cb874f012415a43b0",
1178
+ "sha256": "4cdf363f7d84fd44406fc6e5237c5baa5166506a7a58241f22d93e9d8bcdb630",
1179
+ "source_object_id": "objaverse-1034cd8e4df5430cb874f012415a43b0"
1180
+ },
1181
+ {
1182
+ "repo": "allenai/objaverse",
1183
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1184
+ "path": "glbs/000-001/3c1bae0687144f51861a8a52be036c2b.glb",
1185
+ "asset_id": "3c1bae0687144f51861a8a52be036c2b",
1186
+ "object_id": "objaverse-3c1bae0687144f51861a8a52be036c2b",
1187
+ "license": "cc0-1.0",
1188
+ "author": "Virtual Museums of Ma\u0142opolska",
1189
+ "title": "A Statue of Saint Stanislaus",
1190
+ "source_url": "https://sketchfab.com/3d-models/3c1bae0687144f51861a8a52be036c2b",
1191
+ "sha256": "7d5415ff3734d5c7ee9cf832575829544b18ca348081a09bfd451cefb0a48bc4",
1192
+ "source_object_id": "objaverse-3c1bae0687144f51861a8a52be036c2b"
1193
+ },
1194
+ {
1195
+ "repo": "allenai/objaverse",
1196
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1197
+ "path": "glbs/000-000/0c16db638e0a45f2b4cbcb87fe455e6a.glb",
1198
+ "asset_id": "0c16db638e0a45f2b4cbcb87fe455e6a",
1199
+ "object_id": "objaverse-0c16db638e0a45f2b4cbcb87fe455e6a",
1200
+ "license": "cc0-1.0",
1201
+ "author": "Virtual Museums of Ma\u0142opolska",
1202
+ "title": "A twin capital with decoration of plant motifs",
1203
+ "source_url": "https://sketchfab.com/3d-models/0c16db638e0a45f2b4cbcb87fe455e6a",
1204
+ "sha256": "e012cf77e231d3d2344a6e02bcebfb496cf1b8d0b8ba3e9da5b936ed2f89d8e7",
1205
+ "source_object_id": "objaverse-0c16db638e0a45f2b4cbcb87fe455e6a"
1206
+ },
1207
+ {
1208
+ "repo": "allenai/objaverse",
1209
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1210
+ "path": "glbs/000-000/dcd2f3f53bab48899cb0aaefefc9d9d5.glb",
1211
+ "asset_id": "dcd2f3f53bab48899cb0aaefefc9d9d5",
1212
+ "object_id": "objaverse-dcd2f3f53bab48899cb0aaefefc9d9d5",
1213
+ "license": "cc0-1.0",
1214
+ "author": "Virtual Museums of Ma\u0142opolska",
1215
+ "title": "Vodka distillation set",
1216
+ "source_url": "https://sketchfab.com/3d-models/dcd2f3f53bab48899cb0aaefefc9d9d5",
1217
+ "sha256": "7e8878f3b4fd65e80dd7e16fa06b27e6800881e487b3bccfc319d416b56b0df1",
1218
+ "source_object_id": "objaverse-dcd2f3f53bab48899cb0aaefefc9d9d5"
1219
+ },
1220
+ {
1221
+ "repo": "allenai/objaverse",
1222
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1223
+ "path": "glbs/000-006/dd64acda343d4e38a8023285b89175c3.glb",
1224
+ "asset_id": "dd64acda343d4e38a8023285b89175c3",
1225
+ "object_id": "objaverse-dd64acda343d4e38a8023285b89175c3",
1226
+ "license": "cc0-1.0",
1227
+ "author": "Minneapolis Institute of Art",
1228
+ "title": "Mina'i 'Bowl Depicting a Seated King,' 12th C CE",
1229
+ "source_url": "https://sketchfab.com/3d-models/dd64acda343d4e38a8023285b89175c3",
1230
+ "sha256": "a65ae2df9165b95cd0f01b5ae0bcfe24176bf0935f355e02cd7d335e8fba04bf",
1231
+ "source_object_id": "objaverse-dd64acda343d4e38a8023285b89175c3"
1232
+ },
1233
+ {
1234
+ "repo": "allenai/objaverse",
1235
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1236
+ "path": "glbs/000-004/2d85ff6291f343e5bf062023f3c33afb.glb",
1237
+ "asset_id": "2d85ff6291f343e5bf062023f3c33afb",
1238
+ "object_id": "objaverse-2d85ff6291f343e5bf062023f3c33afb",
1239
+ "license": "cc0-1.0",
1240
+ "author": "Digital Atlas of Ancient Life",
1241
+ "title": "Bryozoan: Archimedes oweniana (PRI 45535)",
1242
+ "source_url": "https://sketchfab.com/3d-models/2d85ff6291f343e5bf062023f3c33afb",
1243
+ "sha256": "d18ee5e1d0b6343d71bc5e90652b58d7c4650c492121c44aef7a9f8401783d1a",
1244
+ "source_object_id": "objaverse-2d85ff6291f343e5bf062023f3c33afb"
1245
+ },
1246
+ {
1247
+ "repo": "allenai/objaverse",
1248
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1249
+ "path": "glbs/000-005/cd14b616da35470eae6894259697314c.glb",
1250
+ "asset_id": "cd14b616da35470eae6894259697314c",
1251
+ "object_id": "objaverse-cd14b616da35470eae6894259697314c",
1252
+ "license": "cc0-1.0",
1253
+ "author": "Digital Atlas of Ancient Life",
1254
+ "title": "Bivalve: Nodipecten pernodosus (PRI 44328)",
1255
+ "source_url": "https://sketchfab.com/3d-models/cd14b616da35470eae6894259697314c",
1256
+ "sha256": "b27e76c2ec4cbfe038f5cefe1ed2f3c4120eb7b42014a97f086098a392160ce5",
1257
+ "source_object_id": "objaverse-cd14b616da35470eae6894259697314c"
1258
+ },
1259
+ {
1260
+ "repo": "allenai/objaverse",
1261
+ "revision": "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8",
1262
+ "path": "glbs/000-007/0994815e0a994ee69c2e408860d17cee.glb",
1263
+ "asset_id": "0994815e0a994ee69c2e408860d17cee",
1264
+ "object_id": "objaverse-0994815e0a994ee69c2e408860d17cee",
1265
+ "license": "cc0-1.0",
1266
+ "author": "Virtual Museums of Ma\u0142opolska",
1267
+ "title": "Silver salt cellar with a figure of a boy",
1268
+ "source_url": "https://sketchfab.com/3d-models/0994815e0a994ee69c2e408860d17cee",
1269
+ "sha256": "9dec787850e4e5b418aeb031048f818563f76432896c0922fb444dcf6c5ad311",
1270
+ "source_object_id": "objaverse-0994815e0a994ee69c2e408860d17cee"
1271
+ },
1272
+ {
1273
+ "repo": "scenario-labs/3d-collection",
1274
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
1275
+ "path": "assets/scenario_asset_PxAmvCzSumrBKsUwQdALmCVb/output.glb",
1276
+ "sha256": "c264e82d7aff627b33f79e90adcb36acfc73a85b2911aac3b08a9181bfe52001",
1277
+ "asset_id": "scenario:asset_PxAmvCzSumrBKsUwQdALmCVb",
1278
+ "license": "cc-by-4.0",
1279
+ "author": "Scenario",
1280
+ "title": "scenario:asset_PxAmvCzSumrBKsUwQdALmCVb",
1281
+ "source_model": "model_trellis",
1282
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
1283
+ "object_id": "scenario-5002697c4e9509fe4da7",
1284
+ "source_object_id": "scenario-5002697c4e9509fe4da7"
1285
+ },
1286
+ {
1287
+ "repo": "scenario-labs/3d-collection",
1288
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
1289
+ "path": "assets/d3873915ce9e9250/12097a943346f264.glb",
1290
+ "sha256": "39021e31a04464c89faee8d13a9fe996a793f5d57ae177da6c948e040fc55070",
1291
+ "asset_id": "d3873915ce9e9250",
1292
+ "license": "cc-by-4.0",
1293
+ "author": "Scenario",
1294
+ "title": "d3873915ce9e9250",
1295
+ "source_model": "claude-opus-5-5",
1296
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
1297
+ "object_id": "scenario-a76f41b9cbac02843bdd",
1298
+ "source_object_id": "scenario-a76f41b9cbac02843bdd"
1299
+ },
1300
+ {
1301
+ "repo": "scenario-labs/3d-collection",
1302
+ "revision": "55b4c002b4c1529fc48da3dff98516c3069bfa3f",
1303
+ "path": "assets/scenario_asset_Yn4bLidfau88DtfBs3aQZ8GA/output.glb",
1304
+ "sha256": "63fce3dfe0d50d8b9fd807119907d420286e58c56e331ef8989e24498e396982",
1305
+ "asset_id": "scenario:asset_Yn4bLidfau88DtfBs3aQZ8GA",
1306
+ "license": "cc-by-4.0",
1307
+ "author": "Scenario",
1308
+ "title": "scenario:asset_Yn4bLidfau88DtfBs3aQZ8GA",
1309
+ "source_model": "model_tripo-v2-5-multiview-to-3d",
1310
+ "source_url": "https://huggingface.co/datasets/scenario-labs/3d-collection",
1311
+ "object_id": "scenario-b450f77df85a147a528c",
1312
+ "source_object_id": "scenario-b450f77df85a147a528c"
1313
+ }
1314
+ ]
COMMANDS.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Mac commands
2
+
3
+ Run these in macOS Terminal, from the extracted `forma3d` folder. Requires Apple
4
+ Silicon and Python 3.11 (the setup script lets uv manage Python). If `uv` is not
5
+ installed, run `brew install uv` first. Do not paste Hugging Face tokens into chat.
6
+
7
+ ```bash
8
+ bash setup-mac.sh
9
+ source "$HOME/Library/Application Support/Forma3D/venv/bin/activate"
10
+ hf auth login
11
+ hf auth whoami
12
+
13
+ # Pin the original checkpoint so the run is reproducible.
14
+ hf download Lucasgitguy-co/image3d-student \
15
+ examples/synthetic-smoke/synthetic-only.pt \
16
+ --revision 1738cdfaf1bb940bf576a96d11b742ce014b9139 \
17
+ --local-dir base
18
+
19
+ # 96 mesh assets, four canonical rendered views per object.
20
+ # Dataset files and original meshes stay on your machine.
21
+ python scripts/prepare_hf.py \
22
+ --out data/forma3d-v1 --cache data/downloads \
23
+ --scenario 64 --objaverse 32 --objaverse-shards 8 --resume \
24
+ --grid 16 --views 4 --max-file-mb 16 --max-download-mb 2048
25
+
26
+ # The base checkpoint width is 64. All learned weights are loaded.
27
+ # Use a NEW --out directory for every run.
28
+ caffeinate -i image3d train \
29
+ --manifest data/forma3d-v1/manifest.jsonl \
30
+ --init-from base/examples/synthetic-smoke/synthetic-only.pt \
31
+ --out runs/forma3d-v1 --device mps \
32
+ --width 64 --steps 5000 --batch-size 2 --lr 0.0001 \
33
+ --eval-every 100 --validation-fraction 0.2 --seed 42
34
+
35
+ # Independent held-out evaluation, release packaging, then publication.
36
+ python scripts/release.py \
37
+ --run runs/forma3d-v1 --data data/forma3d-v1 \
38
+ --base base/examples/synthetic-smoke/synthetic-only.pt \
39
+ --release release/forma3d-v1 --device mps \
40
+ --repo Lucasgitguy-co/forma3d-tiny --publish
41
+ ```
42
+
43
+ The last command requires a Hugging Face token with permission to create and write
44
+ model repositories. It creates a private repository, uploads the complete evaluated
45
+ release, and makes it public only after a successful upload. It refuses to overwrite
46
+ an existing repository. If an upload fails, a private partial repository can remain;
47
+ inspect it before retrying. No raw source datasets or authentication files are uploaded.
48
+
49
+ For a fresh run, the same sequence is available as one command:
50
+
51
+ ```bash
52
+ caffeinate -i bash train-mac.sh --publish
53
+ ```
54
+
55
+ This reuses the runtime in `~/Library/Application Support/Forma3D/venv`, creating it
56
+ only if missing. It uses that interpreter explicitly and verifies/reuses the local
57
+ base checkpoint. With the dataset already prepared, training needs no Hugging Face
58
+ connection. Publication still requires service availability and your saved HF login.
59
+ Use `bash setup-mac.sh` explicitly when installing updated package source.
60
+ Dataset preparation now verifies and resumes completed objects, including the old
61
+ 64-Scenario/28-Objaverse shortage. It saves progress after each object and searches
62
+ eight Objaverse metadata shards. Completely black rendered objects are replaced;
63
+ exact image/target duplicates remain in the same object group. Excluded existing
64
+ files are preserved but omitted from the manifests. If preparation stops, rerun the same command.
65
+ Training and release directories still must be fresh; after training has started,
66
+ follow the individual commands from the failed stage. The wrapper does not resume
67
+ optimizer state. Downloaded meshes remain cached in `data/downloads`.
68
+
69
+ Publication requires completed optimizer steps, lower validation and independent
70
+ test loss than the starting checkpoint, higher test occupancy IoU, test IoU at least
71
+ 0.05, and nonempty qualitative predictions. These are baseline research checks,
72
+ not proof of production quality. A failed gate writes `runs/forma3d-v1/evaluation.json`
73
+ and does not publish. Inspect the generated PNG comparisons in `runs/forma3d-v1/inspection`.
74
+
75
+ To inspect first without publishing, omit `--publish`. When subsequently publishing,
76
+ use a fresh `--release` directory. The evaluation is repeated against the actual weights.
77
+
78
+ To test inference after training:
79
+
80
+ ```bash
81
+ image3d generate --checkpoint runs/forma3d-v1/best.pt \
82
+ --image your-centered-cutout.png --out results/object.ply --device mps
83
+ image3d preview --ply results/object.ply --out results/preview.png
84
+ ```
85
+
86
+ Replace `your-centered-cutout.png` with a real file. Output is Gaussian PLY, not GLB
87
+ or a triangle mesh. Real photos are outside the tested proxy-render distribution.
88
+
89
+ For a larger experiment, increase object counts, shard count and download budget
90
+ in a fresh dataset directory after checking free disk space. Source metadata is
91
+ pinned, selection is deterministic, and all views/known shared inputs stay grouped.
92
+ The starter run is not a claim that 96 objects or 5,000 steps are enough for strong
93
+ generalization. Training time depends on the Mac and is not yet benchmarked for
94
+ the full recipe. `Ctrl-C` saves `last.pt`; `--init-from runs/forma3d-v1/last.pt`
95
+ starts a fresh optimizer in a new output directory and is not exact resume.
96
+
97
+ If Terminal cannot use Metal, `--device mps` fails explicitly. `--device cpu` is
98
+ available for small tests and Intel Macs but is much slower. Keep the selected
99
+ device consistent in training and evaluation commands.
100
+
101
+ ## Local runtime repair — 2026-11-03
102
+
103
+ The previous `.venv` under Documents contained offloaded (`dataless`) files, causing
104
+ Python read timeouts. The runtime now lives under Library/Application Support and
105
+ uses a regular package installation rather than an editable `.pth` link. The old
106
+ `.venv`, source data, and checkpoints are preserved.
107
+
108
+ A Hugging Face 503 can prevent browsing or publishing without affecting local
109
+ training. Wait and retry the evaluation/publish step when the service is available;
110
+ do not rerun completed training. Use a new `--release` directory when restaging.
DATASETS.md ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Data selection and attribution
2
+
3
+ Reviewed 2026-11-02. User requested commercial-use-compatible data and exclusion
4
+ of noncommercial datasets. This recipe uses only the sources explicitly marked
5
+ included below. Repository-level labels do not replace individual asset terms.
6
+
7
+ | Source | Status | Reason |
8
+ |---|---|---|
9
+ | [scenario-labs/3d-collection](https://huggingface.co/datasets/scenario-labs/3d-collection) | Included, bounded GLB subset | Explicit CC-BY-4.0 row filter; Hunyuan-labeled models excluded; checksums verified against metadata. Attribution: Scenario; modifications: normalization, surface sampling, Gaussian proxy rendering. |
10
+ | [scenario-labs/3d-collection-hunyuan](https://huggingface.co/datasets/scenario-labs/3d-collection-hunyuan) | Excluded | Dataset expressly prohibits using assets to train or improve AI models. |
11
+ | [3dlg-hcvc/MultiScan](https://huggingface.co/datasets/3dlg-hcvc/MultiScan) | Excluded | CC-BY-NC-4.0, gated scene data. |
12
+ | [huanngzh/3D-Front](https://huggingface.co/datasets/huanngzh/3D-Front) | Excluded | CC-BY-NC-4.0, indoor scenes rather than directly aligned object targets. |
13
+ | [facebook/show3d-dataset](https://huggingface.co/datasets/facebook/show3d-dataset) | Excluded | CC-BY-NC-4.0; interaction/video data needs a separate task-specific pipeline. |
14
+ | [Voxel51/gaussian_splatting](https://huggingface.co/datasets/Voxel51/gaussian_splatting) | Deferred; not used | Card labels Apache-2.0 and describes a few scene reconstructions. This object-centered recipe does not establish camera alignment, object crops, or source-scene rights from the card alone. No importer or download is provided. |
15
+ | [allenai/objaverse](https://huggingface.co/datasets/allenai/objaverse) | Added: CC0 assets only | Dataset compilation is ODC-By; assets have separate licenses. Script accepts only individual `cc0` metadata entries, retains author/title/source links, and excludes animated assets. |
16
+ | [allenai/objaverse-xl](https://huggingface.co/datasets/allenai/objaverse-xl) | Future candidate; not used | Heterogeneous per-file licensing; no blanket commercial-use assumption or importer in this kit. |
17
+
18
+ Pinned revisions:
19
+
20
+ - Scenario: `55b4c002b4c1529fc48da3dff98516c3069bfa3f`
21
+ - Objaverse: `556637099bf4fa79ea7b239d0d9c328b8a2e9ac8`
22
+ - Original model: `1738cdfaf1bb940bf576a96d11b742ce014b9139`
23
+
24
+ The actual asset inventory is generated as `sources.json`, with asset IDs, source
25
+ URLs, authors, licenses, revision IDs and SHA-256 hashes. Published releases copy
26
+ this file to `ATTRIBUTIONS.json`. Keep it with the released model. Rejected assets
27
+ are recorded in `skipped.json`. The model card must not list excluded or merely
28
+ considered datasets as training sources.
29
+
30
+ License references: [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/),
31
+ [CC0](https://creativecommons.org/publicdomain/zero/1.0/),
32
+ [ODC-By](https://opendatacommons.org/licenses/by/1-0/).
LICENSE ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
NOTICE ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Forma3D-Tiny v0.2.0, derived from Image3D Student v0.1.0
2
+ Copyright 2026 Lucasgitguy-co.
3
+
4
+ Original project source, documentation and procedural demonstration artifacts are released under Apache License 2.0.
5
+
6
+ The optional Idol integration and Gaussian attribute conventions were developed with reference to
7
+ speridlabs/idol-sdk, revision 4702a7f00850e34b6e83a2170cc123c3e9570744 (Apache-2.0).
8
+ Its architecture is imported as an optional dependency; pretrained teacher weights are not redistributed.
9
+ Adaptations in this project: staged loading, query-chunk attention, explicit real-valued RoPE selection,
10
+ independent student training, coordinate-preserving Gaussian IO, and diagnostic rendering.
11
+ Upstream attribution is retained in licenses/Idol-APACHE-2.0.txt and THIRD_PARTY.md.
README.md ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ pipeline_tag: image-to-3d
4
+ base_model: Lucasgitguy-co/image3d-student
5
+ model_name: Forma3D-Tiny v0.2
6
+ datasets:
7
+ - allenai/objaverse
8
+ - scenario-labs/3d-collection
9
+ tags:
10
+ - pytorch
11
+ - gaussian-splatting
12
+ - research-prototype
13
+ - mesh-proxy-supervision
14
+ ---
15
+ # Forma3D-Tiny v0.2
16
+
17
+ An experimental compact image-to-Gaussian model post-trained from Image3D Student's
18
+ synthetic demonstration checkpoint. This is a coarse research baseline, not a
19
+ general-purpose photo-to-3D model. Its grid is 16 cubed and
20
+ it has 306,321 parameters. Selected checkpoint: step 4800;
21
+ completed run: 5000 steps.
22
+
23
+ ## Actual training data and preprocessing
24
+
25
+ Only the datasets listed above were used, with per-asset provenance in ATTRIBUTIONS.json.
26
+ Scenario assets are CC-BY-4.0; the Objaverse subset is CC0. Original objects were centered
27
+ and uniformly scaled into a 0.9-wide cube, surface sampled, and converted to isotropic
28
+ Gaussian proxy targets. Orthographic images were rendered from these same proxy clouds.
29
+ This is not teacher distillation from Idol, Hunyuan, InstantMesh, or Hi3D, and it did not
30
+ train on natural photographs, MultiScan, 3D-Front, Show3D, or Voxel51 scene splats.
31
+
32
+ Related source inputs and all views stay in the same object group. A separate 15% test
33
+ partition is excluded from training and validation-based checkpoint selection.
34
+
35
+ ## Measured results
36
+
37
+ Independent test objects: 14; test views: 60.
38
+ Base test loss: 0.842823; post-trained test loss:
39
+ 0.584055. Base occupancy IoU:
40
+ 0.272567; post-trained occupancy IoU:
41
+ 0.307005.
42
+ See evaluation.json for the full results and checks. These scores measure coarse proxy
43
+ reconstruction on the rendered data distribution; they do not prove photo realism,
44
+ watertight meshes, production quality, or texture fidelity. Near duplicates can remain
45
+ despite source grouping and exact-byte deduplication.
46
+
47
+ ## Run on a Mac
48
+
49
+ Download this repository, then run `bash setup-mac.sh` and
50
+ `source "$HOME/Library/Application Support/Forma3D/venv/bin/activate"`.
51
+
52
+ ```sh
53
+ image3d generate --checkpoint model.pt --image your-centered-cutout.png \
54
+ --out results/object.ply --device mps
55
+ image3d preview --ply results/object.ply --out results/preview.png
56
+ ```
57
+
58
+ Inputs are centered objects on black, matching the training framing. Natural photos
59
+ are outside the verified distribution. Output is Gaussian PLY, not a triangle mesh.
60
+ CPU works with `--device cpu`; CUDA support is implemented but was not tested on the
61
+ Mac used to prepare these scripts.
62
+
63
+ ## License and attribution
64
+
65
+ Source code and these weights are offered under Apache-2.0. Dataset and individual
66
+ asset licenses remain separate; retain ATTRIBUTIONS.json and consult DATASETS.md.
67
+ This license statement does not grant rights to third-party trademarks or likenesses.
68
+ See COMMANDS.md for reproduction commands.
SHA256SUMS ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ a9ba265d76a139fa5e7d95a3176e6d6053e811cc722afe11ab5ae5dac61cfa14 ATTRIBUTIONS.json
2
+ 9988ea29538b73886bfc1fd404edcf5bb64b7acfc7586fa6b7430ce13d02cb4b COMMANDS.md
3
+ 4c09bfeb821d41b9da58c9a20c28c4000f40956f4359a04274556436a4ed009f DATASETS.md
4
+ cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE
5
+ 05f38086626c05b43280173a453858ff2eb4273d63b554c94492c64f09a20ab3 NOTICE
6
+ b4fbe86b0118756c0f22228868d3815c731dbd02866d0a5a8bbf04e66e832c47 README.md
7
+ ef7c689f184a7921b02887eeb8d859e8cca77da6d2082999bb19bf29beda61f1 THIRD_PARTY.md
8
+ 25d53c6500d9e45aca8a2ce1fe54030e05a0822c554ab24cfcbfeaa631ee9c91 config.json
9
+ b838b35d053ec45f9de150414f98a6b329e4f0be52d9a1c1095320050d8b22bb evaluation.json
10
+ cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 licenses/Idol-APACHE-2.0.txt
11
+ 83c065d2a50cf086928542cf8d40dc4416b379e38b9aa61d842dc9106d4b3306 model.pt
12
+ f2beee0eea3e9e76d921fc2b2587df3e55115b7a0e7f331d684b8a32256ebc7d pyproject.toml
13
+ 53dc8f90461d899ed8c15574c3e96f9bf07da4d3ee783a47ec3a3b077b6ee9ca requirements-tested-macos.txt
14
+ 03325cb525f9e0562865f8df123678a147db38680b024f0845482dc2d5bc1651 scripts/prepare_hf.py
15
+ 96f7df49a214e05b86c2d86023d6500986a4d17b2dfe8b23ab7d213d75375fad scripts/release.py
16
+ 9eaa2118115870e618fe71e130e3671c419a81ac484c80f30ca89b9e2eb677a5 setup-mac.sh
17
+ c09ce8cb78cd68ae32b618ba49f97508b6ce14bc89e88c5b80cc3e2487bd919c src/image3d_student/__init__.py
18
+ b4be53a864458a84009e91277ff64767dffc6139ca3afcc50526747743722c02 src/image3d_student/cli.py
19
+ d34f9fa50d574764e5e2c1c31c1ca477f2bc4a1887e103c5c47b754f1f1d8c72 src/image3d_student/data.py
20
+ e01d1b42929c993d92cad1bde8944b14c6a8e325fc279d8fd3e9c7287523ad69 src/image3d_student/demo.py
21
+ 7335dcc99fcd9cea5c217841376f0ca8c0ca179809b4df34e344bf929d11da51 src/image3d_student/engine.py
22
+ a18005f75a66846446b2574b4f1b085ebde5321e835c4e5b4507e15e812ee5ef src/image3d_student/model.py
23
+ 41961fae62d2819c1e3f455e74539a66b8c4f57bedd9fb9379497b3a5764c692 src/image3d_student/splats.py
24
+ 2e2439bc0a48c52e32a8e273f879ed7328fdb82632a996ed3e239e0391ca3a59 src/image3d_student/teacher_idol.py
25
+ 4487becd424209645b3cc463c3f17a3b3b32abb5fc9c3fd50190cf1122757298 train-mac.sh
26
+ c3478f8a0f1708ff19dccba080e8bb089dcde43a4907dde16d25edff430fe559 training.json
THIRD_PARTY.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Third-party scope
2
+
3
+ This training kit extends Lucasgitguy-co/image3d-student, Apache-2.0. The original
4
+ checkpoint is downloaded separately. No new trained weights are bundled in the kit.
5
+
6
+ Optional Idol SDK integration is inherited from the original project, pinned to
7
+ `4702a7f00850e34b6e83a2170cc123c3e9570744`; its Apache notice is retained in
8
+ `licenses/Idol-APACHE-2.0.txt`. The Mac recipe does not install or run Idol, Hi3D,
9
+ InstantMesh, Hunyuan, or gated encoders. Their weights are not redistributed.
10
+
11
+ Dependencies retain their respective licenses. Third-party dataset terms are
12
+ documented in DATASETS.md; per-asset attribution is generated during preparation
13
+ and copied into any published release. Code licensing does not relicense datasets.
config.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "grid": 16,
3
+ "width": 64
4
+ }
evaluation.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint_sha256": "449e14a96d3507f7ad8e8c270d1fd632a09e0753254d0bfc93b659832d8b8ca8",
3
+ "base_sha256": "dd1a1719541c5603125e7f9379b0ad8ede20b7e9f2816a04e9120244cdbf528e",
4
+ "test_manifest_sha256": "d29a8be0d5e773874a21e59496b934f3647954213c43f972cf68abbb80dc40df",
5
+ "test_objects": 14,
6
+ "test_samples": 60,
7
+ "baseline_test": {
8
+ "occupancy": 0.5195401266217232,
9
+ "position": 0.11201683692634105,
10
+ "colour": 0.06971513153985143,
11
+ "scale": 0.6968644132216771,
12
+ "rotation": 0.006667846724546204,
13
+ "opacity": 0.0014822189676730582,
14
+ "geometry": 0.0,
15
+ "loss": 0.8428226768970489,
16
+ "occupancy_iou": 0.27256669824322066
17
+ },
18
+ "posttrained_test": {
19
+ "occupancy": 0.4215678572654724,
20
+ "position": 0.09369222347935041,
21
+ "colour": 0.03420027456401537,
22
+ "scale": 0.0023372950294287876,
23
+ "rotation": 8.206806187445181e-05,
24
+ "opacity": 0.00015286443649529247,
25
+ "geometry": 0.0,
26
+ "loss": 0.5840554296970367,
27
+ "occupancy_iou": 0.30700542802611985
28
+ },
29
+ "checks": {
30
+ "validation_loss_improved": true,
31
+ "test_loss_improved": true,
32
+ "test_occupancy_iou_improved": true,
33
+ "test_occupancy_iou_at_least_005": true
34
+ },
35
+ "passed": true,
36
+ "scope": "Rendered mesh-proxy evaluation only; does not establish real-photo or mesh reconstruction quality",
37
+ "published_model_sha256": "83c065d2a50cf086928542cf8d40dc4416b379e38b9aa61d842dc9106d4b3306"
38
+ }
licenses/Idol-APACHE-2.0.txt ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:83c065d2a50cf086928542cf8d40dc4416b379e38b9aa61d842dc9106d4b3306
3
+ size 1735755
pyproject.toml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "forma3d-tiny"
7
+ version = "0.2.0"
8
+ license = "Apache-2.0"
9
+ license-files = ["LICENSE", "NOTICE", "THIRD_PARTY.md", "licenses/*.txt"]
10
+ readme = "README.md"
11
+ authors = [{name = "Lucasgitguy-co"}]
12
+ description = "Experimental local image-to-Gaussian student with cached teacher supervision"
13
+ requires-python = ">=3.11,<3.14"
14
+ dependencies = ["torch>=2.5", "numpy>=1.26", "pillow>=10", "plyfile>=1", "trimesh>=4", "scipy>=1.11"]
15
+
16
+ [project.optional-dependencies]
17
+ test = ["pytest>=8"]
18
+ data = ["huggingface_hub>=0.34", "pyarrow>=17"]
19
+ teacher = ["idol @ git+https://github.com/speridlabs/idol-sdk.git@4702a7f00850e34b6e83a2170cc123c3e9570744"]
20
+
21
+ [project.scripts]
22
+ image3d = "image3d_student.cli:main"
23
+
24
+ [tool.setuptools.packages.find]
25
+ where = ["src"]
26
+
27
+ [tool.pytest.ini_options]
28
+ testpaths = ["tests"]
requirements-tested-macos.txt ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ anyio==4.16.0
2
+ click==8.5.0
3
+ filelock==4.2.7
4
+ fsspec==2026.9.0
5
+ h11==0.16.0
6
+ hf-xet==1.8.0
7
+ httpcore2==2.16.0
8
+ httpx2==2.16.0
9
+ huggingface-hub==2.4.0
10
+ idna==3.20
11
+ iniconfig==2.3.1
12
+ jinja2==3.1.6
13
+ markupsafe==3.0.4
14
+ mpmath==1.3.0
15
+ networkx==3.6.1
16
+ numpy==2.4.6
17
+ packaging==26.3
18
+ pillow==13.0.0
19
+ pluggy==1.7.0
20
+ plyfile==1.1.5
21
+ pyarrow==26.0.0
22
+ pygments==2.21.0
23
+ pytest==9.2.0
24
+ pyyaml==6.0.3
25
+ scipy==1.17.1
26
+ setuptools==84.2.1
27
+ sympy==1.14.0
28
+ torch==2.15.0
29
+ tqdm==4.70.1
30
+ trimesh==5.2.0
31
+ truststore==0.10.5
32
+ typing-extensions==4.16.0
scripts/prepare_hf.py ADDED
@@ -0,0 +1,463 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Prepare paired, canonical rendered images and coarse Gaussian targets.
2
+
3
+ These are mesh-derived proxy targets, NOT pretrained-teacher outputs or photos.
4
+ Only public, explicitly allowed assets are downloaded. Source meshes stay local.
5
+ """
6
+ import argparse
7
+ import gzip
8
+ import hashlib
9
+ import json
10
+ import random
11
+ import shutil
12
+ import time
13
+ import urllib.error
14
+ import urllib.request
15
+ from pathlib import Path, PurePosixPath
16
+
17
+ import numpy as np
18
+ import pyarrow.parquet as pq
19
+ import trimesh
20
+ from huggingface_hub import hf_hub_download
21
+
22
+ from image3d_student.data import cache_sample, splat_targets
23
+ from image3d_student.splats import Splats, preview
24
+ from image3d_student.engine import split_rows
25
+
26
+ SCENARIO = ("scenario-labs/3d-collection", "55b4c002b4c1529fc48da3dff98516c3069bfa3f")
27
+ OBJAVERSE = ("allenai/objaverse", "556637099bf4fa79ea7b239d0d9c328b8a2e9ac8")
28
+
29
+
30
+ def digest(path):
31
+ h = hashlib.sha256()
32
+ with Path(path).open("rb") as f:
33
+ for block in iter(lambda: f.read(1024 * 1024), b""):
34
+ h.update(block)
35
+ return h.hexdigest()
36
+
37
+
38
+ class Downloader:
39
+ def __init__(self, root, max_file_mb, max_total_mb, reserve_gb):
40
+ self.root = Path(root)
41
+ self.root.mkdir(parents=True, exist_ok=True)
42
+ self.max_file = int(max_file_mb * 1024**2)
43
+ self.max_total = int(max_total_mb * 1024**2)
44
+ self.reserve = int(reserve_gb * 1024**3)
45
+ self.total = 0
46
+
47
+ def get(self, repo, revision, filename, expected=None):
48
+ parts = PurePosixPath(filename)
49
+ if parts.is_absolute() or ".." in parts.parts or not filename.endswith(".glb"):
50
+ raise ValueError("Only relative GLB paths are allowed")
51
+ out = self.root / repo.replace("/", "--") / revision / filename
52
+ if out.exists():
53
+ if expected and digest(out) != expected:
54
+ raise ValueError("Cached source checksum mismatch")
55
+ if out.stat().st_size > self.max_file:
56
+ raise ValueError("Cached asset exceeds per-file limit")
57
+ return out
58
+ if self.total >= self.max_total:
59
+ raise RuntimeError("Download budget exhausted")
60
+ out.parent.mkdir(parents=True, exist_ok=True)
61
+ url = f"https://huggingface.co/datasets/{repo}/resolve/{revision}/{filename}"
62
+ for attempt in range(4):
63
+ tmp = out.with_suffix(".part")
64
+ try:
65
+ # Public URL only: credentials are never forwarded to asset hosts.
66
+ with urllib.request.urlopen(url, timeout=60) as response, tmp.open("wb") as f:
67
+ length = int(response.headers.get("Content-Length", 0))
68
+ if length > self.max_file:
69
+ raise ValueError("Asset exceeds per-file limit")
70
+ count = 0
71
+ while block := response.read(1024 * 1024):
72
+ count += len(block)
73
+ self.total += len(block)
74
+ if count > self.max_file:
75
+ raise ValueError("Asset exceeds per-file limit")
76
+ if self.total > self.max_total:
77
+ raise RuntimeError("Download budget exhausted")
78
+ if shutil.disk_usage(self.root).free < self.reserve + len(block):
79
+ raise RuntimeError("Free disk space below reserve")
80
+ f.write(block)
81
+ if expected and digest(tmp) != expected:
82
+ raise ValueError("Source checksum mismatch")
83
+ tmp.replace(out)
84
+ return out
85
+ except urllib.error.HTTPError as exc:
86
+ if exc.code not in (429, 500, 502, 503, 504) or attempt == 3:
87
+ raise
88
+ time.sleep(min(2**attempt, 8))
89
+ finally:
90
+ tmp.unlink(missing_ok=True)
91
+ raise RuntimeError("Download retries exhausted")
92
+
93
+
94
+ def scenario_candidates(cache, seed):
95
+ repo, revision = SCENARIO
96
+ path = hf_hub_download(repo, "data/train-00000-of-00001.parquet", repo_type="dataset",
97
+ revision=revision, local_dir=Path(cache) / "metadata/scenario")
98
+ rows = pq.read_table(path, columns=["id", "license", "model", "inputs", "outputs"]).to_pylist()
99
+ # Connected components keep alternate meshes generated from shared inputs together.
100
+ parent = {}
101
+
102
+ def find(x):
103
+ parent.setdefault(x, x)
104
+ if parent[x] != x:
105
+ parent[x] = find(parent[x])
106
+ return parent[x]
107
+
108
+ candidates = []
109
+ for row in rows:
110
+ if row["license"] != "cc-by-4.0" or "hunyuan" in (row["model"] or "").lower():
111
+ continue
112
+ assets = (row.get("inputs") or {}).get("assets") or []
113
+ keys = ["input:" + (a.get("sha256") or a["path"]) for a in assets if a.get("sha256") or a.get("path")]
114
+ keys += ["output:" + o["sha256"] for o in row["outputs"] if o.get("sha256")]
115
+ keys += [row["id"]]
116
+ for key in keys[1:]:
117
+ parent[find(key)] = find(keys[0])
118
+ for output in row["outputs"]:
119
+ if output.get("format") == "glb":
120
+ candidates.append({"repo": repo, "revision": revision, "path": output["path"],
121
+ "sha256": output.get("sha256"), "asset_id": row["id"], "license": "cc-by-4.0",
122
+ "author": "Scenario", "title": row["id"], "source_model": row["model"],
123
+ "source_url": f"https://huggingface.co/datasets/{repo}", "group_key": keys[0]})
124
+ break
125
+ for row in candidates:
126
+ row["object_id"] = "scenario-" + hashlib.sha256(find(row.pop("group_key")).encode()).hexdigest()[:20]
127
+ candidates.sort(key=lambda r: r["asset_id"])
128
+ random.Random(seed).shuffle(candidates)
129
+ return candidates
130
+
131
+
132
+ def objaverse_candidates(cache, seed, shards):
133
+ repo, revision = OBJAVERSE
134
+ candidates = []
135
+ for shard in range(shards):
136
+ part = f"000-{shard:03d}"
137
+ path = hf_hub_download(repo, f"metadata/{part}.json.gz", repo_type="dataset", revision=revision,
138
+ local_dir=Path(cache) / "metadata/objaverse")
139
+ with gzip.open(path) as f:
140
+ records = json.load(f)
141
+ for uid, row in records.items():
142
+ # Start with the more conservative CC0 subset; no NC/SA/unknown assets.
143
+ if row.get("license") != "cc0" or row.get("isAgeRestricted") or row.get("animationCount", 0):
144
+ continue
145
+ candidates.append({"repo": repo, "revision": revision, "path": f"glbs/{part}/{uid}.glb",
146
+ "asset_id": uid, "object_id": "objaverse-" + uid, "license": "cc0-1.0",
147
+ "author": row.get("user", {}).get("displayName", "Unknown"), "title": row.get("name", uid),
148
+ "source_url": row.get("viewerUrl", f"https://sketchfab.com/3d-models/{uid}")})
149
+ candidates.sort(key=lambda r: r["asset_id"])
150
+ random.Random(seed).shuffle(candidates)
151
+ return candidates
152
+
153
+
154
+ def mesh_splats(path, count, grid, seed):
155
+ scene = trimesh.load_scene(path, process=False)
156
+ meshes = []
157
+ for node in scene.graph.nodes_geometry:
158
+ matrix, name = scene.graph[node]
159
+ mesh = scene.geometry[name].copy()
160
+ if not isinstance(mesh, trimesh.Trimesh) or not len(mesh.faces):
161
+ continue
162
+ mesh.apply_transform(matrix)
163
+ meshes.append(mesh)
164
+ if not meshes or sum(len(m.faces) for m in meshes) > 500_000:
165
+ raise ValueError("Missing mesh or more than 500,000 triangles")
166
+ bounds = np.array([m.bounds for m in meshes])
167
+ low, high = bounds[:, 0].min(axis=0), bounds[:, 1].max(axis=0)
168
+ extent = float((high - low).max())
169
+ if not np.isfinite(bounds).all() or extent < 1e-8:
170
+ raise ValueError("Degenerate mesh")
171
+ center = (low + high) / 2
172
+ factor = .9 / extent
173
+ areas = np.array([m.area for m in meshes])
174
+ if not np.isfinite(areas).all() or areas.sum() <= 0:
175
+ raise ValueError("Invalid surface area")
176
+ counts = np.random.default_rng(seed).multinomial(count, areas / areas.sum())
177
+ points, colours = [], []
178
+ for mesh, n in zip(meshes, counts):
179
+ if not n:
180
+ continue
181
+ xyz, faces = trimesh.sample.sample_surface(mesh, int(n), seed=seed)
182
+ bary = trimesh.triangles.points_to_barycentric(mesh.triangles[faces], xyz)
183
+ vis = mesh.visual
184
+ if vis.kind == "texture" and vis.uv is not None:
185
+ uv = (vis.uv[mesh.faces[faces]] * bary[:, :, None]).sum(axis=1)
186
+ sampled = np.asarray(vis.material.to_color(uv))
187
+ if sampled.ndim == 0:
188
+ raise ValueError("Material has no usable texture or base colour")
189
+ # Untextured PBR materials can return one constant RGBA value.
190
+ if sampled.ndim == 1:
191
+ sampled = np.broadcast_to(sampled, (n, len(sampled)))
192
+ colour = sampled[:, :3] / 255.
193
+ elif vis.kind == "vertex":
194
+ colour = (vis.vertex_colors[mesh.faces[faces], :3] * bary[:, :, None]).sum(axis=1) / 255.
195
+ elif vis.kind == "face":
196
+ colour = vis.face_colors[faces, :3] / 255.
197
+ else:
198
+ colour = np.full((n, 3), .65)
199
+ points.append((xyz - center) * factor)
200
+ colours.append(colour)
201
+ xyz = np.concatenate(points).astype(np.float32)
202
+ rgb = np.concatenate(colours).astype(np.float32)
203
+ n = len(xyz)
204
+ splats = Splats(xyz, rgb, np.full((n, 3), .6 / grid),
205
+ np.tile([1, 0, 0, 0], (n, 1)), np.full((n, 1), .9))
206
+ transform = np.eye(4)
207
+ transform[:3, :3] *= factor
208
+ transform[:3, 3] = -center * factor
209
+ return splats, transform.tolist()
210
+
211
+
212
+ def save_progress(out, args, rows, provenance, failures):
213
+ state = {"version": 1, "settings": vars(args), "rows": rows,
214
+ "sources": provenance, "skipped": failures}
215
+ temporary = out / "progress.json.tmp"
216
+ temporary.write_text(json.dumps(state))
217
+ temporary.replace(out / "progress.json")
218
+
219
+
220
+ def check_resume_settings(previous, args):
221
+ for key in ("grid", "views", "surface_points", "seed", "scenario", "objaverse"):
222
+ if previous[key] != getattr(args, key):
223
+ raise ValueError(f"Cannot change {key} while resuming; use a new dataset directory")
224
+
225
+
226
+ def recover_legacy(out, args):
227
+ """Recover the old writer's completed files without rendering or downloading.
228
+
229
+ Old runs saved sources and arrays, but lost manifest rows on insufficient
230
+ candidates. Recreate those rows and verify targets against cached GLBs.
231
+ """
232
+ previous = json.loads((out / "preparation.json").read_text())["settings"]
233
+ check_resume_settings(previous, args)
234
+ provenance = json.loads((out / "sources.json").read_text())
235
+ failures = json.loads((out / "skipped.json").read_text())
236
+ rows = []
237
+ for index, item in enumerate(provenance):
238
+ path = Path(args.cache) / item["repo"].replace("/", "--") / item["revision"] / item["path"]
239
+ if not path.is_file() or digest(path) != item["sha256"]:
240
+ raise ValueError(f"Missing or corrupt cached source for {item['asset_id']}")
241
+ splats, transform = mesh_splats(path, args.surface_points, args.grid,
242
+ int(item["sha256"][:8], 16) ^ args.seed)
243
+ stem = hashlib.sha256((item["repo"] + item["asset_id"]).encode()).hexdigest()[:20]
244
+ for view in range(args.views):
245
+ sample_id = f"{stem}-v{view}"
246
+ image, target = f"images/{sample_id}.png", f"targets/{sample_id}.npz"
247
+ yaw = 2 * np.pi * view / args.views
248
+ c, s = np.cos(yaw), np.sin(yaw)
249
+ rotation = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], np.float32)
250
+ rotated = Splats(splats.xyz @ rotation.T, splats.rgb, splats.scale, splats.quat, splats.opacity)
251
+ expected = splat_targets(rotated, args.grid)
252
+ with np.load(out / target, allow_pickle=False) as cached:
253
+ if set(cached.files) != set(expected):
254
+ raise ValueError(f"Target fields differ for {sample_id}")
255
+ for key, value in expected.items():
256
+ if not np.array_equal(cached[key], value):
257
+ raise ValueError(f"Recovered target differs for {sample_id}: {key}")
258
+ from PIL import Image
259
+ with Image.open(out / image) as check:
260
+ check.verify()
261
+ rows.append({"id": sample_id, "image": image, "target": target,
262
+ "source": "mesh-proxy:" + item["repo"], "grid": args.grid,
263
+ "teachers": {"appearance": "mesh-proxy:" + item["repo"], "coarse": None, "fine": None},
264
+ "teacher_gaussians": len(splats.xyz), "retained_gaussians": int(expected["occ"].sum()),
265
+ "geometry_transforms": {"coarse": None, "fine": None},
266
+ "image_sha256": digest(out / image), "target_sha256": digest(out / target),
267
+ "metadata": {**item, "normalization_matrix": transform, "yaw_radians": float(yaw),
268
+ "render": "orthographic Gaussian proxy, camera +z",
269
+ "target": "isotropic surface-sampled mesh proxy; not a pretrained teacher"}})
270
+ if (index + 1) % 10 == 0 or index + 1 == len(provenance):
271
+ print(json.dumps({"recovered_objects": index + 1, "existing_objects": len(provenance)}), flush=True)
272
+ save_progress(out, args, rows, provenance, failures)
273
+ return rows, provenance, failures
274
+
275
+
276
+ def load_progress(out, args):
277
+ if not (out / "progress.json").exists():
278
+ return recover_legacy(out, args)
279
+ state = json.loads((out / "progress.json").read_text())
280
+ if state.get("version") != 1:
281
+ raise ValueError("Unsupported preparation progress version")
282
+ check_resume_settings(state["settings"], args)
283
+ for row in state["rows"]:
284
+ for key in ("image", "target"):
285
+ path = (out / row[key]).resolve()
286
+ if not path.is_relative_to(out.resolve()) or digest(path) != row[key + "_sha256"]:
287
+ raise ValueError(f"Prepared file checksum mismatch: {row['id']} {key}")
288
+ return state["rows"], state["sources"], state["skipped"]
289
+
290
+
291
+ def prune_invisible(out, rows, provenance, failures):
292
+ from PIL import Image
293
+ bad = set()
294
+ for row in rows:
295
+ with Image.open(out / row["image"]) as image:
296
+ if image.convert("RGB").getbbox() is None:
297
+ bad.add((row["metadata"]["repo"], row["metadata"]["asset_id"]))
298
+ for repo, asset in sorted(bad):
299
+ failures.append({"repo": repo, "asset": asset,
300
+ "error": "Rendered view has no visible pixels", "terminal": True})
301
+ if bad:
302
+ print(json.dumps({"excluded_invisible_objects": len(bad), "existing_files_preserved": True}), flush=True)
303
+ return ([r for r in rows if (r["metadata"]["repo"], r["metadata"]["asset_id"]) not in bad],
304
+ [p for p in provenance if (p["repo"], p["asset_id"]) not in bad])
305
+
306
+
307
+ def group_duplicates(rows, provenance):
308
+ """Link entire objects when any views or target files are byte-identical."""
309
+ parent = {}
310
+ def find(x):
311
+ parent.setdefault(x, x)
312
+ if parent[x] != x:
313
+ parent[x] = find(parent[x])
314
+ return parent[x]
315
+ hashes = {}
316
+ for row in rows:
317
+ meta = row["metadata"]
318
+ original = meta.setdefault("source_object_id", meta["object_id"])
319
+ find(original)
320
+ for field in ("image_sha256", "target_sha256"):
321
+ key = (field, row[field])
322
+ if key in hashes:
323
+ a, b = find(original), find(hashes[key])
324
+ parent[max(a, b)] = min(a, b)
325
+ else:
326
+ hashes[key] = original
327
+ for row in rows:
328
+ row["metadata"]["object_id"] = find(row["metadata"]["source_object_id"])
329
+ for item in provenance:
330
+ original = item.setdefault("source_object_id", item["object_id"])
331
+ item["object_id"] = find(original)
332
+
333
+
334
+ def prepare(args):
335
+ out = Path(args.out)
336
+ occupied = out.exists() and any(out.iterdir())
337
+ if occupied and not getattr(args, "resume", False):
338
+ raise ValueError("Output is not empty. Use --resume to retain completed objects.")
339
+ if args.scenario + args.objaverse < 4:
340
+ raise ValueError("Request at least four objects")
341
+ out.mkdir(parents=True, exist_ok=True)
342
+ if occupied:
343
+ all_rows, provenance, failures = load_progress(out, args)
344
+ else:
345
+ all_rows, provenance, failures = [], [], []
346
+ save_progress(out, args, all_rows, provenance, failures)
347
+ all_rows, provenance = prune_invisible(out, all_rows, provenance, failures)
348
+ save_progress(out, args, all_rows, provenance, failures)
349
+ seen = {item["sha256"] for item in provenance}
350
+ completed = {(item["repo"], item["asset_id"]) for item in provenance}
351
+ rejected = {(f["repo"], f["asset"]) for f in failures if f.get("terminal")}
352
+ counts = {}
353
+ fetch = Downloader(args.cache, args.max_file_mb, args.max_download_mb, args.reserve_gb)
354
+ sources = []
355
+ if args.scenario:
356
+ ready = sum(item["repo"] == SCENARIO[0] for item in provenance)
357
+ candidates = scenario_candidates(args.cache, args.seed) if ready < args.scenario else []
358
+ sources.append((SCENARIO[0], candidates, args.scenario, ready))
359
+ if args.objaverse:
360
+ ready = sum(item["repo"] == OBJAVERSE[0] for item in provenance)
361
+ candidates = objaverse_candidates(args.cache, args.seed, args.objaverse_shards) if ready < args.objaverse else []
362
+ sources.append((OBJAVERSE[0], candidates, args.objaverse, ready))
363
+ for repo, candidates, wanted, accepted in sources:
364
+ for item in candidates:
365
+ if accepted >= wanted:
366
+ break
367
+ if (item["repo"], item["asset_id"]) in completed | rejected:
368
+ continue
369
+ staging = out / "_staging"
370
+ try:
371
+ path = fetch.get(item["repo"], item["revision"], item["path"], item.get("sha256"))
372
+ checksum = digest(path)
373
+ if checksum in seen:
374
+ continue
375
+ item["sha256"] = checksum
376
+ item_seed = int(checksum[:8], 16) ^ args.seed
377
+ splats, transform = mesh_splats(path, args.surface_points, args.grid, item_seed)
378
+ stem = hashlib.sha256((item["repo"] + item["asset_id"]).encode()).hexdigest()[:20]
379
+ staging.mkdir(parents=True, exist_ok=True)
380
+ rows = []
381
+ for view in range(args.views):
382
+ yaw = 2 * np.pi * view / args.views
383
+ c, s = np.cos(yaw), np.sin(yaw)
384
+ rotation = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], np.float32)
385
+ rotated = Splats(splats.xyz @ rotation.T, splats.rgb, splats.scale, splats.quat, splats.opacity)
386
+ image = staging / "input.png"
387
+ rendered = preview(rotated, size=128)
388
+ if rendered.getbbox() is None:
389
+ raise ValueError("Rendered view has no visible pixels")
390
+ rendered.save(image)
391
+ metadata = {**item, "object_id": item["object_id"], "normalization_matrix": transform,
392
+ "yaw_radians": float(yaw), "render": "orthographic Gaussian proxy, camera +z",
393
+ "target": "isotropic surface-sampled mesh proxy; not a pretrained teacher"}
394
+ rows.append(cache_sample(staging, f"{stem}-v{view}", image, rotated, args.grid,
395
+ source="mesh-proxy:" + item["repo"], extra=metadata))
396
+ for folder in ("images", "targets"):
397
+ (out / folder).mkdir(exist_ok=True)
398
+ for file in (staging / folder).iterdir():
399
+ file.replace(out / folder / file.name)
400
+ all_rows.extend(rows)
401
+ seen.add(checksum)
402
+ provenance.append(item)
403
+ completed.add((item["repo"], item["asset_id"]))
404
+ accepted += 1
405
+ save_progress(out, args, all_rows, provenance, failures)
406
+ print(json.dumps({"repo": item["repo"], "accepted": accepted, "requested": wanted,
407
+ "asset": item["asset_id"]}), flush=True)
408
+ except RuntimeError:
409
+ raise # resource limits are a hard stop
410
+ except Exception as exc:
411
+ failures.append({"repo": item["repo"], "asset": item["asset_id"],
412
+ "error": type(exc).__name__ + ": " + str(exc)[:200],
413
+ "terminal": "no visible pixels" in str(exc)})
414
+ print(json.dumps({"skipped": item["asset_id"], "reason": failures[-1]["error"]}), flush=True)
415
+ finally:
416
+ shutil.rmtree(staging, ignore_errors=True)
417
+ counts[repo] = {"requested": wanted, "prepared": accepted}
418
+ group_duplicates(all_rows, provenance)
419
+ save_progress(out, args, all_rows, provenance, failures)
420
+ (out / "sources.json").write_text(json.dumps(provenance, indent=2))
421
+ (out / "skipped.json").write_text(json.dumps(failures, indent=2))
422
+ report = {"counts": counts, "samples": len(all_rows), "objects": len(provenance),
423
+ "distinct_groups": len({r["metadata"]["object_id"] for r in all_rows}),
424
+ "settings": vars(args), "rendered_proxy_data": True,
425
+ "excluded": ["scenario-labs/3d-collection-hunyuan", "3dlg-hcvc/MultiScan",
426
+ "huanngzh/3D-Front", "facebook/show3d-dataset", "Voxel51/gaussian_splatting"]}
427
+ (out / "preparation.json").write_text(json.dumps(report, indent=2))
428
+ if any(v["prepared"] < v["requested"] for v in counts.values()):
429
+ raise ValueError("Not enough eligible assets. Completed objects are saved. Rerun with --resume and a larger --objaverse-shards value.")
430
+ if report["distinct_groups"] < 4:
431
+ raise ValueError("Not enough independent object groups")
432
+ # The test partition never enters training or checkpoint selection.
433
+ development, test = split_rows(all_rows, .15, args.seed + 1)
434
+ for name, rows in [("manifest.jsonl", development), ("test-manifest.jsonl", test)]:
435
+ (out / name).write_text("".join(json.dumps(r) + "\n" for r in rows))
436
+ print(json.dumps(report, indent=2))
437
+
438
+
439
+ def main():
440
+ p = argparse.ArgumentParser(description=__doc__)
441
+ p.add_argument("--out", required=True)
442
+ p.add_argument("--cache", default="data/downloads")
443
+ p.add_argument("--scenario", type=int, default=64)
444
+ p.add_argument("--objaverse", type=int, default=32)
445
+ p.add_argument("--objaverse-shards", type=int, default=8)
446
+ p.add_argument("--resume", action="store_true", help="Reuse and verify completed objects, including older failed runs")
447
+ p.add_argument("--grid", type=int, choices=[8, 16, 32], default=16)
448
+ p.add_argument("--views", type=int, default=4)
449
+ p.add_argument("--surface-points", type=int, default=4096)
450
+ p.add_argument("--seed", type=int, default=42)
451
+ p.add_argument("--max-file-mb", type=int, default=16)
452
+ p.add_argument("--max-download-mb", type=int, default=2048)
453
+ p.add_argument("--reserve-gb", type=float, default=2)
454
+ args = p.parse_args()
455
+ if min(args.scenario, args.objaverse) < 0 or not 1 <= args.objaverse_shards <= 160:
456
+ p.error("Invalid object counts or shard count")
457
+ if min(args.views, args.surface_points, args.max_file_mb, args.max_download_mb, args.reserve_gb) <= 0:
458
+ p.error("Counts and limits must be positive")
459
+ prepare(args)
460
+
461
+
462
+ if __name__ == "__main__":
463
+ main()
scripts/release.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Evaluate a completed run, stage a self-contained release, optionally publish it."""
2
+ import argparse
3
+ import hashlib
4
+ import json
5
+ import shutil
6
+ from pathlib import Path
7
+
8
+ import torch
9
+ from torch.utils.data import DataLoader
10
+
11
+ from image3d_student.data import CachedDataset, load_manifest
12
+ from image3d_student.engine import device_for, evaluate, generate
13
+ from image3d_student.model import Student
14
+
15
+
16
+ def sha(path):
17
+ return hashlib.sha256(Path(path).read_bytes()).hexdigest()
18
+
19
+
20
+ def evaluate_release(args):
21
+ run, dataset = Path(args.run), Path(args.data)
22
+ meta = json.loads((run / "run.json").read_text())
23
+ checkpoint = torch.load(run / "best.pt", map_location="cpu", weights_only=True)
24
+ last = torch.load(run / "last.pt", map_location="cpu", weights_only=True)
25
+ if last["step"] != meta["steps_requested"]:
26
+ raise ValueError("Training did not complete the requested steps")
27
+ if checkpoint.get("step", 0) < 1 or not meta.get("initialization"):
28
+ raise ValueError("Expected completed post-training from a base checkpoint")
29
+ if sha(args.base) != meta["initialization"]["sha256"]:
30
+ raise ValueError("Base checkpoint differs from the training initialization")
31
+ if sha(dataset / "manifest.jsonl") != meta["manifest_sha256"]:
32
+ raise ValueError("Training manifest changed")
33
+ development = load_manifest(dataset / "manifest.jsonl")
34
+ test = load_manifest(dataset / "test-manifest.jsonl")
35
+ selected_ids = set(meta["train_ids"]) | set(meta["val_ids"])
36
+ if selected_ids != {r["id"] for r in development}:
37
+ raise ValueError("Run split does not match development manifest")
38
+ if {r["metadata"]["object_id"] for r in development} & {r["metadata"]["object_id"] for r in test}:
39
+ raise ValueError("Test object leakage")
40
+ for key in ["image_sha256", "target_sha256"]:
41
+ if {r[key] for r in development} & {r[key] for r in test}:
42
+ raise ValueError("Duplicate data across development and test")
43
+ device = device_for(args.device)
44
+ model = Student(**checkpoint["config"]).to(device)
45
+ model.load_state_dict(checkpoint["model"])
46
+ loader = DataLoader(CachedDataset(dataset / "test-manifest.jsonl"), batch_size=1)
47
+ final = evaluate(model, loader, device)
48
+ base = torch.load(args.base, map_location="cpu", weights_only=True)
49
+ initial = Student(**checkpoint["config"]).to(device)
50
+ result = initial.load_state_dict({k: v for k, v in base["model"].items() if k not in ("coords", "centers")}, strict=False)
51
+ if set(result.missing_keys) != {"coords", "centers"} or result.unexpected_keys:
52
+ raise ValueError("Base architecture mismatch")
53
+ baseline = evaluate(initial, loader, device)
54
+ best_validation = min(json.loads(line)["validation"]["loss"] for line in
55
+ (run / "metrics.jsonl").read_text().splitlines())
56
+ checks = {"validation_loss_improved": best_validation < meta["baseline_validation"]["loss"],
57
+ "test_loss_improved": final["loss"] < baseline["loss"],
58
+ "test_occupancy_iou_improved": final["occupancy_iou"] > baseline["occupancy_iou"],
59
+ "test_occupancy_iou_at_least_005": final["occupancy_iou"] >= .05}
60
+ report = {"checkpoint_sha256": sha(run / "best.pt"), "base_sha256": sha(args.base),
61
+ "test_manifest_sha256": sha(dataset / "test-manifest.jsonl"),
62
+ "test_objects": len({r["metadata"]["object_id"] for r in test}),
63
+ "test_samples": len(test), "baseline_test": baseline, "posttrained_test": final,
64
+ "checks": checks, "passed": all(checks.values()),
65
+ "scope": "Rendered mesh-proxy evaluation only; does not establish real-photo or mesh reconstruction quality"}
66
+ (run / "evaluation.json").write_text(json.dumps(report, indent=2))
67
+ print(json.dumps(report, indent=2), flush=True)
68
+ # Keep qualitative inspection files local; all held-out objects, first view.
69
+ example_dir = run / "inspection"
70
+ example_dir.mkdir(exist_ok=True)
71
+ seen = set()
72
+ from image3d_student.splats import preview, read_ply
73
+ from PIL import Image, ImageDraw
74
+ for row in test:
75
+ group = row["metadata"]["object_id"]
76
+ if group in seen:
77
+ continue
78
+ seen.add(group)
79
+ out = example_dir / (row["id"] + ".ply")
80
+ if not out.exists():
81
+ try:
82
+ generate(run / "best.pt", dataset / row["image"], out, args.device)
83
+ except ValueError as exc:
84
+ if "No occupied cells" not in str(exc):
85
+ raise
86
+ report["checks"]["nonempty_examples"] = False
87
+ report["passed"] = False
88
+ continue
89
+ sheet = Image.new("RGB", (512, 152), "black")
90
+ sheet.paste(Image.open(dataset / row["image"]).convert("RGB").resize((128, 128)), (0, 24))
91
+ splats = read_ply(out)
92
+ for i, angle in enumerate([0, 1.5707963, 3.1415927]):
93
+ sheet.paste(preview(splats, size=128, yaw=angle), (128 * (i + 1), 24))
94
+ ImageDraw.Draw(sheet).text((5, 5), "Input proxy | prediction front | side | back", fill="white")
95
+ sheet.save(out.with_suffix(".png"))
96
+ if len(seen) >= 8:
97
+ break
98
+ (run / "evaluation.json").write_text(json.dumps(report, indent=2))
99
+ if not report["passed"]:
100
+ raise ValueError("Evaluation gate failed. Nothing was published. Inspect evaluation.json and improve data/training.")
101
+ return checkpoint, meta, report
102
+
103
+
104
+ def stage(args, checkpoint, meta, report):
105
+ source = Path(__file__).resolve().parents[1]
106
+ release = Path(args.release)
107
+ if release.exists():
108
+ raise ValueError("Release directory already exists; choose a new --release path")
109
+ release.mkdir(parents=True)
110
+ shutil.copytree(source / "src", release / "src", ignore=shutil.ignore_patterns("__pycache__", "*.egg-info"))
111
+ shutil.copytree(source / "scripts", release / "scripts", ignore=shutil.ignore_patterns("__pycache__"))
112
+ shutil.copytree(source / "licenses", release / "licenses")
113
+ for filename in ["pyproject.toml", "LICENSE", "NOTICE", "THIRD_PARTY.md", "DATASETS.md", "COMMANDS.md", "setup-mac.sh", "train-mac.sh", "requirements-tested-macos.txt"]:
114
+ shutil.copyfile(source / filename, release / filename)
115
+ # Publish inference weights only; optimizer and local absolute paths stay local.
116
+ public_meta = {k: v for k, v in meta.items() if k != "dataset"}
117
+ torch.save({"format": 1, "config": checkpoint["config"], "model": checkpoint["model"],
118
+ "step": checkpoint["step"], "metadata": public_meta}, release / "model.pt")
119
+ (release / "config.json").write_text(json.dumps(checkpoint["config"], indent=2))
120
+ (release / "training.json").write_text(json.dumps(public_meta, indent=2))
121
+ (release / "evaluation.json").write_text(json.dumps({**report,
122
+ "published_model_sha256": sha(release / "model.pt")}, indent=2))
123
+ shutil.copyfile(Path(args.data) / "sources.json", release / "ATTRIBUTIONS.json")
124
+ used = sorted({r["repo"] for r in json.loads((release / "ATTRIBUTIONS.json").read_text())})
125
+ datasets_yaml = "\n".join("- " + repo for repo in used)
126
+ text = f'''---
127
+ license: apache-2.0
128
+ pipeline_tag: image-to-3d
129
+ base_model: Lucasgitguy-co/image3d-student
130
+ model_name: Forma3D-Tiny v0.2
131
+ datasets:
132
+ {datasets_yaml}
133
+ tags:
134
+ - pytorch
135
+ - gaussian-splatting
136
+ - research-prototype
137
+ - mesh-proxy-supervision
138
+ ---
139
+ # Forma3D-Tiny v0.2
140
+
141
+ An experimental compact image-to-Gaussian model post-trained from Image3D Student's
142
+ synthetic demonstration checkpoint. This is a coarse research baseline, not a
143
+ general-purpose photo-to-3D model. Its grid is {checkpoint["config"]["grid"]} cubed and
144
+ it has {meta["parameters"]:,} parameters. Selected checkpoint: step {checkpoint["step"]};
145
+ completed run: {meta["steps_requested"]} steps.
146
+
147
+ ## Actual training data and preprocessing
148
+
149
+ Only the datasets listed above were used, with per-asset provenance in ATTRIBUTIONS.json.
150
+ Scenario assets are CC-BY-4.0; the Objaverse subset is CC0. Original objects were centered
151
+ and uniformly scaled into a 0.9-wide cube, surface sampled, and converted to isotropic
152
+ Gaussian proxy targets. Orthographic images were rendered from these same proxy clouds.
153
+ This is not teacher distillation from Idol, Hunyuan, InstantMesh, or Hi3D, and it did not
154
+ train on natural photographs, MultiScan, 3D-Front, Show3D, or Voxel51 scene splats.
155
+
156
+ Related source inputs and all views stay in the same object group. A separate 15% test
157
+ partition is excluded from training and validation-based checkpoint selection.
158
+
159
+ ## Measured results
160
+
161
+ Independent test objects: {report["test_objects"]}; test views: {report["test_samples"]}.
162
+ Base test loss: {report["baseline_test"]["loss"]:.6f}; post-trained test loss:
163
+ {report["posttrained_test"]["loss"]:.6f}. Base occupancy IoU:
164
+ {report["baseline_test"]["occupancy_iou"]:.6f}; post-trained occupancy IoU:
165
+ {report["posttrained_test"]["occupancy_iou"]:.6f}.
166
+ See evaluation.json for the full results and checks. These scores measure coarse proxy
167
+ reconstruction on the rendered data distribution; they do not prove photo realism,
168
+ watertight meshes, production quality, or texture fidelity. Near duplicates can remain
169
+ despite source grouping and exact-byte deduplication.
170
+
171
+ ## Run on a Mac
172
+
173
+ Download this repository, then run `bash setup-mac.sh` and
174
+ `source "$HOME/Library/Application Support/Forma3D/venv/bin/activate"`.
175
+
176
+ ```sh
177
+ image3d generate --checkpoint model.pt --image your-centered-cutout.png \\
178
+ --out results/object.ply --device mps
179
+ image3d preview --ply results/object.ply --out results/preview.png
180
+ ```
181
+
182
+ Inputs are centered objects on black, matching the training framing. Natural photos
183
+ are outside the verified distribution. Output is Gaussian PLY, not a triangle mesh.
184
+ CPU works with `--device cpu`; CUDA support is implemented but was not tested on the
185
+ Mac used to prepare these scripts.
186
+
187
+ ## License and attribution
188
+
189
+ Source code and these weights are offered under Apache-2.0. Dataset and individual
190
+ asset licenses remain separate; retain ATTRIBUTIONS.json and consult DATASETS.md.
191
+ This license statement does not grant rights to third-party trademarks or likenesses.
192
+ See COMMANDS.md for reproduction commands.
193
+ '''
194
+ (release / "README.md").write_text(text)
195
+ sums = [sha(p) + " " + str(p.relative_to(release)) for p in sorted(release.rglob("*")) if p.is_file()]
196
+ (release / "SHA256SUMS").write_text("\n".join(sums) + "\n")
197
+ return release
198
+
199
+
200
+ def main():
201
+ p = argparse.ArgumentParser(description=__doc__)
202
+ p.add_argument("--run", required=True)
203
+ p.add_argument("--data", required=True)
204
+ p.add_argument("--base", required=True)
205
+ p.add_argument("--release", default="release/forma3d-tiny")
206
+ p.add_argument("--repo", default="Lucasgitguy-co/forma3d-tiny")
207
+ p.add_argument("--device", choices=["mps", "cpu", "cuda", "auto"], default="mps")
208
+ p.add_argument("--publish", action="store_true")
209
+ args = p.parse_args()
210
+ checkpoint, meta, report = evaluate_release(args)
211
+ release = stage(args, checkpoint, meta, report)
212
+ if args.publish:
213
+ from huggingface_hub import HfApi
214
+ api = HfApi()
215
+ # Refuse accidental replacement of a previously published model.
216
+ if api.repo_exists(args.repo, repo_type="model"):
217
+ raise ValueError("Repository already exists. Choose a new --repo; no overwrite was performed.")
218
+ api.create_repo(args.repo, repo_type="model", private=True)
219
+ commit = api.upload_folder(repo_id=args.repo, folder_path=release,
220
+ commit_message="Publish evaluated Forma3D-Tiny v0.2")
221
+ api.update_repo_settings(args.repo, private=False)
222
+ print(f"Published https://huggingface.co/{args.repo} at {commit.oid}")
223
+ else:
224
+ print(f"Evaluated release staged at {release}; nothing published.")
225
+
226
+
227
+ if __name__ == "__main__":
228
+ main()
setup-mac.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ cd "$(dirname "$0")"
4
+ if ! command -v uv >/dev/null 2>&1; then
5
+ echo 'Install uv first: brew install uv' >&2
6
+ exit 1
7
+ fi
8
+ # Keep native libraries out of Documents, where macOS can offload their contents.
9
+ FORMA3D_RUNTIME_DIR="${FORMA3D_RUNTIME_DIR:-$HOME/Library/Application Support/Forma3D}"
10
+ export UV_CACHE_DIR="$FORMA3D_RUNTIME_DIR/uv-cache"
11
+ mkdir -p "$FORMA3D_RUNTIME_DIR"
12
+ uv venv --python 3.11 --allow-existing "$FORMA3D_RUNTIME_DIR/venv"
13
+ uv pip install --python "$FORMA3D_RUNTIME_DIR/venv/bin/python" \
14
+ -r requirements-tested-macos.txt "$PWD[data,test]"
15
+ "$FORMA3D_RUNTIME_DIR/venv/bin/python" -m image3d_student.cli doctor
src/image3d_student/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ """Research prototype; no pretrained general-purpose student weights are bundled."""
4
+
5
+ __version__ = "0.2.0"
src/image3d_student/cli.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ import argparse
4
+ import importlib.util
5
+ import json
6
+ import platform
7
+ import shutil
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ import torch
12
+
13
+
14
+ def parser():
15
+ p = argparse.ArgumentParser(description="Local image-to-Gaussian student research prototype")
16
+ sub = p.add_subparsers(dest="command", required=True)
17
+ sub.add_parser("doctor", help="Check dependencies, Metal availability and disk space; no downloads")
18
+ demo = sub.add_parser("demo-data", help="Create synthetic code-test fixtures, NOT teacher data")
19
+ demo.add_argument("--out", required=True)
20
+ demo.add_argument("--count", type=int, default=12)
21
+ demo.add_argument("--grid", type=int, choices=[8,16,32], default=8)
22
+ cache = sub.add_parser("cache", help="Cache Idol PLY with optional aligned geometry teacher meshes")
23
+ cache.add_argument("--image", required=True, help="Exact prepared/framed input used by teacher")
24
+ cache.add_argument("--idol-ply", required=True)
25
+ cache.add_argument("--out", required=True)
26
+ cache.add_argument("--id", required=True)
27
+ cache.add_argument("--object-id", help="Shared ID for all images of the same object, to prevent validation leakage")
28
+ cache.add_argument("--grid", type=int, choices=[8,16,32], default=16)
29
+ cache.add_argument("--coarse-mesh", help="InstantMesh output; this command imports, does not run InstantMesh")
30
+ cache.add_argument("--coarse-transform", help="JSON 4x4 mesh-to-Idol-PLY matrix")
31
+ cache.add_argument("--fine-mesh", help="Hi3D output; this command imports, does not run Hi3D")
32
+ cache.add_argument("--fine-transform", help="JSON 4x4 mesh-to-Idol-PLY matrix")
33
+ train = sub.add_parser("train", help="Train the student on cached targets")
34
+ train.add_argument("--manifest", required=True)
35
+ train.add_argument("--out", required=True)
36
+ train.add_argument("--device", choices=["auto","cuda","mps","cpu"], default="auto")
37
+ train.add_argument("--init-from", help="Post-train checkpoint weights; optimizer starts fresh")
38
+ train.add_argument("--steps", type=int, default=1000)
39
+ train.add_argument("--batch-size", type=int, default=1)
40
+ train.add_argument("--width", type=int, default=128)
41
+ train.add_argument("--lr", type=float, default=3e-4)
42
+ train.add_argument("--seed", type=int, default=42)
43
+ train.add_argument("--eval-every", type=int, default=50)
44
+ train.add_argument("--validation-fraction", type=float, default=.2)
45
+ train.add_argument("--allow-synthetic", action="store_true")
46
+ generate = sub.add_parser("generate", help="Generate standard 3DGS PLY with a trained student")
47
+ generate.add_argument("--checkpoint", required=True)
48
+ generate.add_argument("--image", required=True, help="Centered cutout or teacher-prepared image, black background")
49
+ generate.add_argument("--out", required=True)
50
+ generate.add_argument("--device", choices=["auto","cuda","mps","cpu"], default="auto")
51
+ generate.add_argument("--threshold", type=float, default=.5)
52
+ generate.add_argument("--max-splats", type=int, default=32768)
53
+ render = sub.add_parser("preview", help="CPU diagnostic turntable contact sheet")
54
+ render.add_argument("--ply", required=True)
55
+ render.add_argument("--out", required=True)
56
+ teacher = sub.add_parser("teacher-idol", help="EXPERIMENTAL staged Mac runner; weights not bundled")
57
+ teacher.add_argument("--image", required=True)
58
+ teacher.add_argument("--out", required=True)
59
+ teacher.add_argument("--cache", default=".cache/huggingface")
60
+ teacher.add_argument("--weights", default="speridlabs/idol")
61
+ teacher.add_argument("--device", choices=["mps","cpu"], default="mps")
62
+ teacher.add_argument("--mode", choices=["real","synthetic"], default="synthetic")
63
+ teacher.add_argument("--steps", type=int, default=20)
64
+ teacher.add_argument("--gaussians", type=int, default=32768)
65
+ teacher.add_argument("--query-chunk", type=int, default=128)
66
+ teacher.add_argument("--seed", type=int, default=42)
67
+ teacher.add_argument("--allow-download", action="store_true", help="Explicitly allow downloading model weights and gated encoders")
68
+ return p
69
+
70
+
71
+ def main():
72
+ p = parser()
73
+ args = p.parse_args()
74
+ try:
75
+ if args.command == "doctor":
76
+ report = {"python": platform.python_version(), "platform": platform.platform(), "torch": str(torch.__version__),
77
+ "mps_available": torch.backends.mps.is_available(), "mps_built": torch.backends.mps.is_built(),
78
+ "free_disk_gib": round(shutil.disk_usage(Path.cwd()).free / 1024**3, 2),
79
+ "idol_installed": importlib.util.find_spec("idol") is not None,
80
+ "teacher_status": {"Idol": "experimental adapter, real weights unverified",
81
+ "InstantMesh": "cached mesh import only; no Mac execution adapter",
82
+ "Hi3D": "cached mesh import only; no Mac execution adapter"},
83
+ "weights_bundled": False, "quantization": "FP32 student; no binary kernels or 1-bit claims"}
84
+ print(json.dumps(report, indent=2))
85
+ elif args.command == "demo-data":
86
+ from .demo import create_demo
87
+ print(create_demo(args.out, args.count, args.grid))
88
+ elif args.command == "cache":
89
+ from .data import cache_sample
90
+ from .splats import read_ply
91
+ print(json.dumps(cache_sample(args.out, args.id, args.image, read_ply(args.idol_ply), args.grid,
92
+ coarse=args.coarse_mesh, coarse_transform=args.coarse_transform,
93
+ fine=args.fine_mesh, fine_transform=args.fine_transform,
94
+ extra={"object_id": args.object_id or args.id, "idol_ply": str(Path(args.idol_ply).resolve())}), indent=2))
95
+ elif args.command == "train":
96
+ from .engine import train
97
+ train(args)
98
+ elif args.command == "generate":
99
+ from .engine import generate
100
+ print(json.dumps(generate(args.checkpoint, args.image, args.out, args.device, args.threshold, args.max_splats), indent=2))
101
+ elif args.command == "preview":
102
+ from PIL import Image, ImageDraw
103
+ import numpy as np
104
+ from .splats import preview, read_ply
105
+ splats = read_ply(args.ply)
106
+ sheet = Image.new("RGB", (1024, 280), "#111111")
107
+ draw = ImageDraw.Draw(sheet)
108
+ for i in range(4):
109
+ sheet.paste(preview(splats, yaw=i*np.pi/2), (i*256, 24))
110
+ draw.text((i*256+8, 6), f"{i*90} degrees - diagnostic view", fill="white")
111
+ out = Path(args.out)
112
+ if out.exists():
113
+ raise ValueError("Preview already exists")
114
+ out.parent.mkdir(parents=True, exist_ok=True)
115
+ sheet.save(out)
116
+ elif args.command == "teacher-idol":
117
+ from .teacher_idol import run_idol
118
+ run_idol(args)
119
+ except (ValueError, RuntimeError, FileNotFoundError, ImportError) as exc:
120
+ print(f"Error: {exc}", file=sys.stderr)
121
+ return 2
122
+ return 0
123
+
124
+
125
+ if __name__ == "__main__":
126
+ raise SystemExit(main())
src/image3d_student/data.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ import hashlib
4
+ import json
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+ import torch
9
+ from PIL import Image, ImageOps
10
+ from torch.utils.data import Dataset
11
+
12
+ from .splats import Splats, read_ply
13
+
14
+
15
+ def grid_centers(grid):
16
+ axis = (np.arange(grid, dtype=np.float32) + .5) / grid - .5
17
+ return np.stack(np.meshgrid(axis, axis, axis, indexing="ij"), axis=-1).reshape(-1, 3)
18
+
19
+
20
+ def cell_indices(xyz, grid):
21
+ if not np.isfinite(xyz).all() or (np.abs(xyz) > .50001).any():
22
+ raise ValueError("Targets must be aligned inside [-0.5,0.5]^3. No silent normalization is performed.")
23
+ ijk = np.floor((xyz + .5) * grid).astype(np.int64).clip(0, grid-1)
24
+ return (ijk[:, 0] * grid + ijk[:, 1]) * grid + ijk[:, 2]
25
+
26
+
27
+ def splat_targets(splats, grid):
28
+ """One highest-opacity teacher Gaussian per occupied cell; explicitly lossy."""
29
+ cells = cell_indices(splats.xyz, grid)
30
+ order = np.argsort(-splats.opacity[:, 0], kind="stable")
31
+ _, first = np.unique(cells[order], return_index=True)
32
+ keep = order[first]
33
+ slots = cells[keep]
34
+ result = {"occ": np.zeros((grid**3, 1), np.float32), "xyz": grid_centers(grid),
35
+ "rgb": np.zeros((grid**3, 3), np.float32),
36
+ "scale": np.full((grid**3, 3), 1 / grid / 3, np.float32),
37
+ "quat": np.tile(np.array([1, 0, 0, 0], np.float32), (grid**3, 1)),
38
+ "opacity": np.zeros((grid**3, 1), np.float32),
39
+ "geometry": np.zeros((grid**3, 2), np.float32),
40
+ "geometry_valid": np.zeros(2, np.float32), "grid": np.array(grid, np.int32)}
41
+ result["occ"][slots] = 1
42
+ for key in ("xyz", "rgb", "scale", "quat", "opacity"):
43
+ result[key][slots] = getattr(splats, key)[keep]
44
+ return result
45
+
46
+
47
+ def mesh_occupancy(path, transform_path, grid):
48
+ import trimesh
49
+ if not transform_path:
50
+ raise ValueError("Every geometry teacher needs an explicit --*-transform JSON matrix, even for identity.")
51
+ transform = np.asarray(json.loads(Path(transform_path).read_text()), dtype=float)
52
+ if transform.shape != (4, 4) or not np.isfinite(transform).all() or not np.allclose(transform[3], [0,0,0,1]):
53
+ raise ValueError("Transform must be a finite affine 4x4 matrix")
54
+ mesh = trimesh.load(str(path), force="mesh", process=False)
55
+ if not isinstance(mesh, trimesh.Trimesh) or len(mesh.faces) == 0:
56
+ raise ValueError("Geometry teacher must contain a triangle mesh")
57
+ mesh.apply_transform(transform)
58
+ cell_indices(np.asarray(mesh.vertices), grid) # validates the whole object
59
+ points, _ = trimesh.sample.sample_surface(mesh, min(200_000, grid**3 * 16), seed=42)
60
+ mask = np.zeros(grid**3, np.float32)
61
+ mask[np.unique(cell_indices(points, grid))] = 1
62
+ return mask
63
+
64
+
65
+ def cache_sample(root, sample_id, image_path, splats, grid=16, source="idol",
66
+ coarse=None, coarse_transform=None, fine=None, fine_transform=None, extra=None):
67
+ root = Path(root)
68
+ if not sample_id or any(c not in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" for c in sample_id):
69
+ raise ValueError("Sample ID may contain only letters, digits, - and _")
70
+ if grid not in (8, 16, 32):
71
+ raise ValueError("Grid must be 8, 16 or 32")
72
+ target = splat_targets(splats, grid)
73
+ for channel, mesh, transform in [(0, coarse, coarse_transform), (1, fine, fine_transform)]:
74
+ if mesh:
75
+ target["geometry"][:, channel] = mesh_occupancy(mesh, transform, grid)
76
+ target["geometry_valid"][channel] = 1
77
+ row = {"id": sample_id, "image": f"images/{sample_id}.png", "target": f"targets/{sample_id}.npz",
78
+ "source": source, "grid": grid, "teachers": {"appearance": source,
79
+ "coarse": "InstantMesh" if coarse else None, "fine": "Hi3D" if fine else None},
80
+ "teacher_gaussians": len(splats.xyz), "retained_gaussians": int(target["occ"].sum()),
81
+ "geometry_transforms": {"coarse": json.loads(Path(coarse_transform).read_text()) if coarse else None,
82
+ "fine": json.loads(Path(fine_transform).read_text()) if fine else None},
83
+ "metadata": extra or {}}
84
+ manifest = root / "manifest.jsonl"
85
+ rows = load_manifest(manifest) if manifest.exists() else []
86
+ if any(r["id"] == sample_id for r in rows):
87
+ raise ValueError(f"Sample {sample_id} already exists; choose a new ID")
88
+ if rows and any(r["grid"] != grid for r in rows):
89
+ raise ValueError("Do not mix grid resolutions in one dataset")
90
+ image = Image.open(image_path)
91
+ image.load()
92
+ if root.joinpath(row["image"]).exists() or root.joinpath(row["target"]).exists():
93
+ raise ValueError("Sample files already exist; refusing to overwrite")
94
+ root.joinpath("images").mkdir(parents=True, exist_ok=True)
95
+ root.joinpath("targets").mkdir(parents=True, exist_ok=True)
96
+ image.save(root / row["image"])
97
+ row["image_sha256"] = hashlib.sha256((root / row["image"]).read_bytes()).hexdigest()
98
+ np.savez_compressed(root / row["target"], **target)
99
+ row["target_sha256"] = hashlib.sha256((root / row["target"]).read_bytes()).hexdigest()
100
+ # Single-writer dataset. Atomic manifest replacement avoids partial JSON lines.
101
+ tmp = manifest.with_suffix(".tmp")
102
+ tmp.write_text("".join(json.dumps(r) + "\n" for r in [*rows, row]))
103
+ tmp.replace(manifest)
104
+ return row
105
+
106
+
107
+ def load_manifest(path):
108
+ rows = [json.loads(line) for line in Path(path).read_text().splitlines() if line.strip()]
109
+ if not rows or len({r["id"] for r in rows}) != len(rows):
110
+ raise ValueError("Manifest must contain nonempty, unique sample IDs")
111
+ return rows
112
+
113
+
114
+ def image_tensor(path, size=128):
115
+ """Already-framed RGB or RGBA cutout; black background, square letterbox."""
116
+ with Image.open(path) as original:
117
+ rgba = ImageOps.exif_transpose(original).convert("RGBA")
118
+ bg = Image.new("RGBA", rgba.size, (0, 0, 0, 255))
119
+ bg.alpha_composite(rgba)
120
+ image = ImageOps.pad(bg.convert("RGB"), (size, size), method=Image.Resampling.LANCZOS, color="black")
121
+ return torch.from_numpy(np.array(image, dtype=np.float32).transpose(2, 0, 1) / 255)
122
+
123
+
124
+ class CachedDataset(Dataset):
125
+ def __init__(self, manifest, rows=None):
126
+ self.root = Path(manifest).resolve().parent
127
+ self.rows = load_manifest(manifest) if rows is None else rows
128
+ if not self.rows:
129
+ raise ValueError("Empty dataset")
130
+ self.grid = self.rows[0]["grid"]
131
+ for row in self.rows:
132
+ if row["grid"] != self.grid:
133
+ raise ValueError("Mixed grids")
134
+ for key in ("image", "target"):
135
+ p = (self.root / row[key]).resolve()
136
+ if not p.is_relative_to(self.root) or not p.is_file():
137
+ raise ValueError(f"Invalid dataset {key} path")
138
+ digest = hashlib.sha256(p.read_bytes()).hexdigest()
139
+ if digest != row[f"{key}_sha256"]:
140
+ raise ValueError(f"Dataset {key} hash mismatch for {row['id']}")
141
+
142
+ def __len__(self):
143
+ return len(self.rows)
144
+
145
+ def __getitem__(self, i):
146
+ row = self.rows[i]
147
+ with np.load(self.root / row["target"], allow_pickle=False) as cached:
148
+ target = {k: torch.from_numpy(cached[k].copy()).float() for k in cached.files if k != "grid"}
149
+ return image_tensor(self.root / row["image"]), target
src/image3d_student/demo.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ from pathlib import Path
4
+
5
+ import numpy as np
6
+
7
+ from .data import cache_sample
8
+ from .splats import Splats, preview
9
+
10
+
11
+ def create_demo(root, count=12, grid=8):
12
+ """Procedural ellipsoids only. Never presented as outputs of any real teacher."""
13
+ if count < 4:
14
+ raise ValueError("Use at least four fixtures")
15
+ root = Path(root)
16
+ root.mkdir(parents=True, exist_ok=True)
17
+ rng = np.random.default_rng(17)
18
+ phi, theta = np.meshgrid(np.linspace(.06, np.pi-.06, 14), np.linspace(0, 2*np.pi, 28, endpoint=False))
19
+ unit = np.stack([np.sin(phi)*np.cos(theta), np.cos(phi), np.sin(phi)*np.sin(theta)], axis=-1).reshape(-1, 3)
20
+ for i in range(count):
21
+ radii = rng.uniform(.17, .36, 3)
22
+ xyz = (unit * radii).astype(np.float32)
23
+ colour = rng.uniform(.2, .95, 3)
24
+ rgb = np.clip(colour[None] * (.8 + .2 * unit[:, 1:2]), 0, 1)
25
+ splats = Splats(xyz, rgb, np.full_like(xyz, .035), np.tile([1,0,0,0], (len(xyz),1)), np.full((len(xyz),1), .9))
26
+ image_path = root / f"fixture-{i:03}.png"
27
+ preview(splats, size=128).save(image_path)
28
+ cache_sample(root, f"fixture-{i:03}", image_path, splats, grid, source="synthetic",
29
+ extra={"purpose": "code verification only", "object_id": f"fixture-{i:03}"})
30
+ image_path.unlink()
31
+ return root / "manifest.jsonl"
src/image3d_student/engine.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ import json
4
+ import hashlib
5
+ import random
6
+ import time
7
+ from pathlib import Path
8
+
9
+ import numpy as np
10
+ import torch
11
+ from torch.utils.data import DataLoader
12
+
13
+ from .data import CachedDataset, image_tensor, load_manifest
14
+ from .model import Student, distillation_loss
15
+ from .splats import Splats, write_ply
16
+
17
+
18
+ def device_for(name="auto"):
19
+ if name == "auto":
20
+ name = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
21
+ if name == "mps" and not torch.backends.mps.is_available():
22
+ raise ValueError("Metal GPU unavailable in this process. Run in a normal macOS Terminal, or use --device cpu.")
23
+ if name == "cuda" and not torch.cuda.is_available():
24
+ raise ValueError("CUDA requested but unavailable")
25
+ if name not in ("mps", "cpu", "cuda"):
26
+ raise ValueError("Supported devices: cpu, mps, cuda")
27
+ torch.set_num_threads(min(4, torch.get_num_threads()))
28
+ return torch.device(name)
29
+
30
+
31
+ def split_rows(rows, fraction, seed):
32
+ if not 0 <= fraction < 1:
33
+ raise ValueError("Validation fraction must lie in [0,1)")
34
+ # Keep repeated views/crops of the same object together. Supply object_id in cache metadata.
35
+ groups = {}
36
+ for row in rows:
37
+ group = row.get("metadata", {}).get("object_id", row["id"])
38
+ groups.setdefault(group, []).append(row)
39
+ keys = sorted(groups)
40
+ random.Random(seed).shuffle(keys)
41
+ n = max(1, round(len(keys) * fraction)) if fraction else 0
42
+ if n >= len(keys):
43
+ raise ValueError("Need at least two different objects for validation, or explicitly use --validation-fraction 0 for an overfit test")
44
+ val_keys = set(keys[:n])
45
+ train = [r for k in keys if k not in val_keys for r in groups[k]]
46
+ val = [r for k in keys if k in val_keys for r in groups[k]]
47
+ if {r["image_sha256"] for r in train} & {r["image_sha256"] for r in val}:
48
+ raise ValueError("Identical images occur across training/validation. Assign the same object-id to related samples.")
49
+ return train, val
50
+
51
+
52
+ def on_device(target, device):
53
+ return {k: v.to(device) for k, v in target.items()}
54
+
55
+
56
+ @torch.no_grad()
57
+ def evaluate(model, loader, device):
58
+ model.eval()
59
+ sums = {}
60
+ for image, target in loader:
61
+ target = on_device(target, device)
62
+ pred = model(image.to(device))
63
+ loss, terms = distillation_loss(pred, target, model.grid)
64
+ occupied = pred["occ"].sigmoid() > .5
65
+ truth = target["occ"] > .5
66
+ terms = {**terms, "loss": loss, "occupancy_iou": (occupied & truth).sum() / (occupied | truth).sum().clamp_min(1)}
67
+ for key, value in terms.items():
68
+ sums[key] = sums.get(key, 0.) + float(value)
69
+ return {k: v / len(loader) for k, v in sums.items()}
70
+
71
+
72
+ def save_checkpoint(path, model, optimizer, step, metadata):
73
+ payload = {"format": 1, "config": model.config, "model": {k: v.detach().cpu() for k, v in model.state_dict().items()},
74
+ "optimizer": optimizer.state_dict(), "step": step, "metadata": metadata}
75
+ tmp = Path(path).with_suffix(".tmp")
76
+ torch.save(payload, tmp)
77
+ tmp.replace(path)
78
+
79
+
80
+ def train(args):
81
+ if args.steps < 1 or args.batch_size < 1 or args.lr <= 0 or args.eval_every < 1:
82
+ raise ValueError("Steps, batch size, learning rate, and evaluation interval must be positive")
83
+ device = device_for(args.device)
84
+ random.seed(args.seed)
85
+ np.random.seed(args.seed)
86
+ torch.manual_seed(args.seed)
87
+ rows = load_manifest(args.manifest)
88
+ synthetic = any(r["source"] == "synthetic" for r in rows)
89
+ if synthetic and not args.allow_synthetic:
90
+ raise ValueError("Synthetic fixtures are code tests, not teacher data. Add --allow-synthetic for an explicit smoke test.")
91
+ train_rows, val_rows = split_rows(rows, args.validation_fraction, args.seed)
92
+ train_data = CachedDataset(args.manifest, train_rows)
93
+ generator = torch.Generator().manual_seed(args.seed)
94
+ loader = DataLoader(train_data, batch_size=args.batch_size, shuffle=True, num_workers=0, generator=generator)
95
+ val_loader = DataLoader(CachedDataset(args.manifest, val_rows), batch_size=1) if val_rows else None
96
+ model = Student(train_data.grid, args.width).to(device)
97
+ initialization = None
98
+ if getattr(args, "init_from", None):
99
+ initial_path = Path(args.init_from)
100
+ state = torch.load(initial_path, map_location="cpu", weights_only=True)
101
+ if state.get("format") != 1 or state["config"]["width"] != args.width:
102
+ raise ValueError("Initialization requires format=1 and matching --width")
103
+ # Coordinates are deterministic buffers, not learned weights. Rebuild them
104
+ # for the target grid while preserving every learned encoder/decoder weight.
105
+ learned = {k: v for k, v in state["model"].items() if k not in ("centers", "coords")}
106
+ result = model.load_state_dict(learned, strict=False)
107
+ if set(result.missing_keys) != {"centers", "coords"} or result.unexpected_keys:
108
+ raise ValueError("Checkpoint architecture mismatch")
109
+ initialization = {"sha256": hashlib.sha256(initial_path.read_bytes()).hexdigest(),
110
+ "config": state["config"], "step": state["step"],
111
+ "optimizer": "fresh AdamW; weights-only post-training"}
112
+ optimizer = torch.optim.AdamW(model.parameters(), lr=args.lr, weight_decay=1e-4)
113
+ run = Path(args.out)
114
+ if run.exists() and any(run.iterdir()):
115
+ raise ValueError("Run directory must be empty; choose a new --out directory")
116
+ run.mkdir(parents=True, exist_ok=True)
117
+ meta = {"synthetic_only": all(r["source"] == "synthetic" for r in rows),
118
+ "contains_synthetic": synthetic, "device": str(device), "torch": str(torch.__version__),
119
+ "seed": args.seed, "train_ids": [r["id"] for r in train_rows], "val_ids": [r["id"] for r in val_rows],
120
+ "parameters": sum(p.numel() for p in model.parameters()),
121
+ "teachers": sorted({v for r in rows for v in r["teachers"].values() if v}),
122
+ "validation": "held-out objects" if val_rows else "none; training overfit test only",
123
+ "dataset": str(Path(args.manifest).resolve()),
124
+ "manifest_sha256": hashlib.sha256(Path(args.manifest).read_bytes()).hexdigest(),
125
+ "initialization": initialization, "steps_requested": args.steps,
126
+ "learning_rate": args.lr, "batch_size": args.batch_size,
127
+ "validation_fraction": args.validation_fraction}
128
+ if val_loader:
129
+ meta["baseline_validation"] = evaluate(model, val_loader, device)
130
+ (run / "run.json").write_text(json.dumps(meta, indent=2))
131
+ print(json.dumps(meta), flush=True)
132
+ step, best, started = 0, float("inf"), time.monotonic()
133
+ iterator = iter(loader)
134
+ try:
135
+ while step < args.steps:
136
+ try:
137
+ images, target = next(iterator)
138
+ except StopIteration:
139
+ iterator = iter(loader)
140
+ images, target = next(iterator)
141
+ model.train()
142
+ optimizer.zero_grad(set_to_none=True)
143
+ pred = model(images.to(device))
144
+ loss, terms = distillation_loss(pred, on_device(target, device), model.grid)
145
+ if not torch.isfinite(loss):
146
+ raise RuntimeError("Nonfinite training loss; stopping")
147
+ loss.backward()
148
+ torch.nn.utils.clip_grad_norm_(model.parameters(), 1.)
149
+ optimizer.step()
150
+ step += 1
151
+ if step == 1 or step % args.eval_every == 0 or step == args.steps:
152
+ record = {"step": step, "seconds": round(time.monotonic()-started, 3),
153
+ "train_loss": float(loss.detach()), **{k: float(v.detach()) for k, v in terms.items()}}
154
+ if val_loader:
155
+ record["validation"] = evaluate(model, val_loader, device)
156
+ score = record["validation"]["loss"]
157
+ if score < best:
158
+ best = score
159
+ save_checkpoint(run / "best.pt", model, optimizer, step, meta)
160
+ with (run / "metrics.jsonl").open("a") as handle:
161
+ handle.write(json.dumps(record) + "\n")
162
+ print(json.dumps(record), flush=True)
163
+ save_checkpoint(run / "last.pt", model, optimizer, step, meta)
164
+ except KeyboardInterrupt:
165
+ print("Interrupted; saving completed optimizer steps.", flush=True)
166
+ finally:
167
+ if step:
168
+ save_checkpoint(run / "last.pt", model, optimizer, step, meta)
169
+ return meta
170
+
171
+
172
+ @torch.no_grad()
173
+ def generate(checkpoint, image, out, device="auto", threshold=.5, max_splats=32768):
174
+ if not 0 < threshold < 1 or max_splats < 1:
175
+ raise ValueError("Threshold must be in (0,1) and max-splats positive")
176
+ device = device_for(device)
177
+ state = torch.load(checkpoint, map_location="cpu", weights_only=True)
178
+ if state.get("format") != 1 or state.get("step", 0) < 1:
179
+ raise ValueError("Expected a trained image3d-student checkpoint")
180
+ model = Student(**state["config"])
181
+ model.load_state_dict(state["model"])
182
+ model.to(device).eval()
183
+ if device.type == "mps":
184
+ torch.mps.synchronize()
185
+ started = time.monotonic()
186
+ pred = model(image_tensor(image)[None].to(device))
187
+ score = pred["occ"][0, :, 0].sigmoid()
188
+ valid = torch.nonzero(score >= threshold).flatten()
189
+ if len(valid) == 0:
190
+ raise ValueError("No occupied cells above threshold. Train longer or inspect validation; no fabricated fallback splats were exported.")
191
+ valid = valid[torch.argsort(score[valid], descending=True)[:max_splats]]
192
+ values = {k: pred[k][0, valid].cpu().numpy() for k in ("xyz", "rgb", "scale", "quat", "opacity")}
193
+ elapsed = time.monotonic() - started
194
+ splats = Splats(**values)
195
+ out = Path(out)
196
+ if out.exists() or out.with_suffix(".json").exists():
197
+ raise ValueError("Output already exists; choose a new filename")
198
+ write_ply(out, splats)
199
+ report = {"gaussians": len(valid), "seconds_preprocess_and_forward": elapsed,
200
+ "device": str(device), "checkpoint_step": state["step"], "training": state["metadata"],
201
+ "note": ("Synthetic-trained output is a pipeline demonstration, not a pretrained image-to-3D result."
202
+ if state["metadata"].get("contains_synthetic") else "Experimental cached-target student; inspect unseen-object quality.")}
203
+ out.with_suffix(".json").write_text(json.dumps(report, indent=2))
204
+ return report
src/image3d_student/model.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ import math
4
+
5
+ import torch
6
+ from torch import nn
7
+ from torch.nn import functional as F
8
+
9
+ from .data import grid_centers
10
+
11
+
12
+ class Student(nn.Module):
13
+ """Small image-conditioned coordinate MLP; fixed cells avoid unordered point regression.
14
+
15
+ 15 Gaussian outputs + 2 auxiliary geometry logits. This is a coarse baseline,
16
+ not an architecture expected to reproduce million-splat teacher detail.
17
+ """
18
+ def __init__(self, grid=16, width=128):
19
+ super().__init__()
20
+ if grid not in (8, 16, 32) or width < 16:
21
+ raise ValueError("Unsupported grid or width")
22
+ self.config = {"grid": grid, "width": width}
23
+ self.grid = grid
24
+ blocks, channels = [], 3
25
+ for out in (24, 48, 96, 128):
26
+ blocks.extend([nn.Conv2d(channels, out, 3, stride=2, padding=1), nn.GroupNorm(8, out), nn.SiLU()])
27
+ channels = out
28
+ self.encoder = nn.Sequential(*blocks, nn.AdaptiveAvgPool2d(4), nn.Flatten(),
29
+ nn.Linear(128*4*4, width), nn.SiLU())
30
+ centers = torch.from_numpy(grid_centers(grid))
31
+ freq = 2**torch.arange(4, dtype=torch.float32) * math.pi * 2
32
+ angles = centers[..., None] * freq
33
+ self.register_buffer("centers", centers)
34
+ self.register_buffer("coords", torch.cat([centers, angles.sin().flatten(1), angles.cos().flatten(1)], dim=1))
35
+ self.query = nn.Sequential(nn.Linear(27, width), nn.SiLU())
36
+ self.decoder = nn.Sequential(nn.Linear(width, width), nn.SiLU(), nn.Linear(width, width), nn.SiLU(), nn.Linear(width, 17))
37
+ with torch.no_grad():
38
+ self.decoder[-1].bias.zero_()
39
+ self.decoder[-1].bias[0] = -2
40
+
41
+ def forward(self, images):
42
+ features = self.encoder(images)
43
+ raw = self.decoder(features[:, None, :] + self.query(self.coords)[None])
44
+ quat = raw[..., 10:14] + raw.new_tensor([1, 0, 0, 0])
45
+ return {"occ": raw[..., :1], "xyz": self.centers[None] + raw[..., 1:4].tanh() / (2*self.grid),
46
+ "rgb": raw[..., 4:7].sigmoid(),
47
+ "scale": (raw[..., 7:10].clamp(-8, 5) - math.log(self.grid*3)).exp(),
48
+ "quat": F.normalize(quat, dim=-1, eps=1e-8), "opacity": raw[..., 14:15].sigmoid(),
49
+ "geometry": raw[..., 15:17]}
50
+
51
+
52
+ def balanced_bce(logits, target):
53
+ error = F.binary_cross_entropy_with_logits(logits, target, reduction="none")
54
+ positive = (error * target).sum() / target.sum().clamp_min(1)
55
+ negative = (error * (1-target)).sum() / (1-target).sum().clamp_min(1)
56
+ return (positive + negative) / 2
57
+
58
+
59
+ def distillation_loss(pred, target, grid):
60
+ mask = target["occ"]
61
+ def masked(value):
62
+ return (value * mask).sum() / (mask.sum().clamp_min(1) * value.shape[-1])
63
+ terms = {"occupancy": balanced_bce(pred["occ"], mask),
64
+ "position": masked(((pred["xyz"] - target["xyz"]) * grid).square()),
65
+ "colour": masked((pred["rgb"] - target["rgb"].clamp(0, 1)).square()),
66
+ "scale": masked((pred["scale"].log() - target["scale"].clamp_min(1e-8).log()).square()),
67
+ "rotation": masked(1 - (pred["quat"] * target["quat"]).sum(-1, keepdim=True).square().clamp(0, 1)),
68
+ "opacity": masked((pred["opacity"] - target["opacity"]).square())}
69
+ geometry = pred["geometry"].sum() * 0
70
+ for i in range(2):
71
+ available = target["geometry_valid"][:, i] > 0
72
+ if available.any():
73
+ geometry = geometry + balanced_bce(pred["geometry"][available, :, i:i+1], target["geometry"][available, :, i:i+1])
74
+ terms["geometry"] = geometry
75
+ total = terms["occupancy"] + terms["position"] + 2*terms["colour"] + .1*terms["scale"] + .1*terms["rotation"] + terms["opacity"] + .25*geometry
76
+ return total, terms
src/image3d_student/splats.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ """Activated Gaussian attributes and standard degree-zero 3DGS PLY IO.
4
+
5
+ Coordinates are preserved as supplied. Idol's *exported PLY* uses its y-up frame;
6
+ we do not apply Idol's internal z-up conversion a second time.
7
+ """
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+
11
+ import numpy as np
12
+ from plyfile import PlyData, PlyElement
13
+
14
+ C0 = 0.28209479177387814
15
+
16
+
17
+ @dataclass
18
+ class Splats:
19
+ xyz: np.ndarray
20
+ rgb: np.ndarray
21
+ scale: np.ndarray
22
+ quat: np.ndarray # w,x,y,z
23
+ opacity: np.ndarray
24
+
25
+ def __post_init__(self):
26
+ n = len(self.xyz)
27
+ if n == 0:
28
+ raise ValueError("No Gaussians: refusing to write or train on an empty object.")
29
+ for name, width in [("xyz", 3), ("rgb", 3), ("scale", 3), ("quat", 4), ("opacity", 1)]:
30
+ a = np.asarray(getattr(self, name), dtype=np.float32).reshape(-1, width)
31
+ if a.shape != (n, width) or not np.isfinite(a).all():
32
+ raise ValueError(f"Invalid {name} shape or nonfinite values")
33
+ setattr(self, name, a)
34
+ if (self.scale <= 0).any():
35
+ raise ValueError("Gaussian scales must be positive")
36
+ if (self.opacity < 0).any() or (self.opacity > 1).any():
37
+ raise ValueError("Opacity must lie in [0,1]")
38
+ norm = np.linalg.norm(self.quat, axis=1, keepdims=True)
39
+ if (norm < 1e-8).any():
40
+ raise ValueError("Zero quaternion")
41
+ self.quat = self.quat / norm
42
+
43
+ def take(self, indices):
44
+ return Splats(**{k: getattr(self, k)[indices] for k in self.__dataclass_fields__})
45
+
46
+
47
+ def read_ply(path):
48
+ v = PlyData.read(str(path))["vertex"].data
49
+ required = ["x", "y", "z", "f_dc_0", "f_dc_1", "f_dc_2", "opacity",
50
+ "scale_0", "scale_1", "scale_2", "rot_0", "rot_1", "rot_2", "rot_3"]
51
+ if not set(required).issubset(v.dtype.names):
52
+ raise ValueError("Expected a Gaussian-splat PLY, not a mesh or ordinary point-cloud PLY")
53
+ col = lambda names: np.column_stack([v[k] for k in names]).astype(np.float32)
54
+ return Splats(col(["x", "y", "z"]), 0.5 + C0 * col([f"f_dc_{i}" for i in range(3)]),
55
+ np.exp(np.clip(col([f"scale_{i}" for i in range(3)]), -20, 5)),
56
+ col([f"rot_{i}" for i in range(4)]),
57
+ 1 / (1 + np.exp(-np.clip(col(["opacity"]), -30, 30))))
58
+
59
+
60
+ def write_ply(path, splats):
61
+ path = Path(path)
62
+ path.parent.mkdir(parents=True, exist_ok=True)
63
+ names = ["x", "y", "z", "nx", "ny", "nz", "f_dc_0", "f_dc_1", "f_dc_2", "opacity",
64
+ "scale_0", "scale_1", "scale_2", "rot_0", "rot_1", "rot_2", "rot_3"]
65
+ opacity = np.clip(splats.opacity, 1e-6, 1 - 1e-6)
66
+ values = np.concatenate([splats.xyz, np.zeros_like(splats.xyz), (splats.rgb - 0.5) / C0,
67
+ np.log(opacity / (1 - opacity)), np.log(splats.scale), splats.quat], axis=1)
68
+ table = np.empty(len(values), dtype=[(k, "f4") for k in names])
69
+ for i, name in enumerate(names):
70
+ table[name] = values[:, i]
71
+ PlyData([PlyElement.describe(table, "vertex")], text=False).write(str(path))
72
+
73
+
74
+ def rotation_matrices(q):
75
+ w, x, y, z = q.T
76
+ return np.stack([1-2*(y*y+z*z), 2*(x*y-z*w), 2*(x*z+y*w),
77
+ 2*(x*y+z*w), 1-2*(x*x+z*z), 2*(y*z-x*w),
78
+ 2*(x*z-y*w), 2*(y*z+x*w), 1-2*(x*x+y*y)], axis=-1).reshape(-1, 3, 3)
79
+
80
+
81
+ def preview(splats, size=256, yaw=0.0):
82
+ """CPU orthographic Gaussian preview; debugging only, not an evaluation renderer."""
83
+ from PIL import Image
84
+ c, s = np.cos(yaw), np.sin(yaw)
85
+ view = np.array([[c, 0, s], [0, 1, 0], [-s, 0, c]], dtype=np.float32)
86
+ xyz = splats.xyz @ view.T
87
+ rot = rotation_matrices(splats.quat)
88
+ cov = (rot * (splats.scale ** 2)[:, None, :]) @ rot.transpose(0, 2, 1)
89
+ cov = view[None] @ cov @ view.T[None]
90
+ pixels = size / 1.25
91
+ canvas = np.zeros((size, size, 3), dtype=np.float32)
92
+ # Back to front, camera on +z. Image y points down.
93
+ for i in np.argsort(xyz[:, 2]):
94
+ center = np.array([xyz[i, 0], -xyz[i, 1]]) * pixels + size / 2
95
+ flip = np.diag([1., -1.])
96
+ covariance = flip @ cov[i, :2, :2] @ flip * pixels ** 2 + np.eye(2) * 0.3
97
+ radius = min(size, int(np.ceil(3 * np.sqrt(np.linalg.eigvalsh(covariance).max()))))
98
+ lo = np.maximum(0, np.floor(center - radius).astype(int))
99
+ hi = np.minimum(size, np.ceil(center + radius + 1).astype(int))
100
+ if np.any(hi <= lo):
101
+ continue
102
+ yy, xx = np.mgrid[lo[1]:hi[1], lo[0]:hi[0]]
103
+ delta = np.stack([xx - center[0], yy - center[1]], axis=-1)
104
+ exponent = np.einsum("...i,ij,...j->...", delta, np.linalg.inv(covariance), delta)
105
+ alpha = (splats.opacity[i, 0] * np.exp(-0.5 * exponent)).clip(0, .99)[..., None]
106
+ patch = canvas[lo[1]:hi[1], lo[0]:hi[0]]
107
+ patch[:] = patch * (1-alpha) + np.clip(splats.rgb[i], 0, 1) * alpha
108
+ return Image.fromarray((canvas.clip(0, 1) * 255).astype(np.uint8))
src/image3d_student/teacher_idol.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2026 Lucasgitguy-co
3
+ """Experimental, staged Idol inference for Apple MPS.
4
+
5
+ Upstream revision: 4702a7f00850e34b6e83a2170cc123c3e9570744.
6
+ No weights are bundled. Full-weight inference has NOT been verified by this project.
7
+ """
8
+ import gc
9
+ import json
10
+ import os
11
+ import shutil
12
+ from pathlib import Path
13
+
14
+ import numpy as np
15
+ import torch
16
+ from PIL import Image
17
+
18
+ from .engine import device_for
19
+
20
+
21
+ def patch_attention(layers, query_chunk=128):
22
+ """Bound attention working memory by splitting only the query dimension.
23
+
24
+ Each query still sees ALL keys/values. Does not split or change softmax's key axis.
25
+ Disable CUDA-specific optimized sampling and avoid complex RoPE tensors on MPS.
26
+ """
27
+ if query_chunk < 1:
28
+ raise ValueError("query_chunk must be positive")
29
+ from torch.nn import functional as F
30
+
31
+ def attention(*args):
32
+ q, k, v = args[0].unbind(dim=2) if len(args) == 1 else args
33
+ q, k, v = (t.permute(0, 2, 1, 3) for t in (q, k, v))
34
+ chunks = [F.scaled_dot_product_attention(q[:, :, start:start+query_chunk], k, v)
35
+ for start in range(0, q.shape[2], query_chunk)]
36
+ return torch.cat(chunks, dim=2).permute(0, 2, 1, 3)
37
+
38
+ layers.scaled_dot_product_attention = attention
39
+ layers.RePo3DRotaryEmbedding.real_valued = True
40
+ return attention
41
+
42
+
43
+ def release(device):
44
+ gc.collect()
45
+ if device.type == "mps":
46
+ torch.mps.synchronize()
47
+ torch.mps.empty_cache()
48
+
49
+
50
+ @torch.no_grad()
51
+ def run_idol(args):
52
+ if args.steps < 1 or args.gaussians < 32768 or args.gaussians > 1048576 or args.gaussians % 32:
53
+ raise ValueError("Steps must be positive; Idol requires 32768..1048576 Gaussians, divisible by 32")
54
+ device = device_for(args.device)
55
+ cache = Path(args.cache).resolve()
56
+ cache.mkdir(parents=True, exist_ok=True)
57
+ os.environ["HF_HOME"] = str(cache)
58
+ os.environ["HF_HUB_OFFLINE"] = "0" if args.allow_download else "1"
59
+ os.environ["ATTN_BACKEND"] = "sdpa"
60
+ if args.allow_download and shutil.disk_usage(cache).free < 16 * 1024**3:
61
+ raise ValueError("Less than 16 GiB disk space available. This conservative download guard leaves room for teacher weights, encoders and temporary files. Free space, or use an existing complete cache without --allow-download.")
62
+ try:
63
+ from huggingface_hub import hf_hub_download, snapshot_download
64
+ from safetensors.torch import load_file
65
+ from tensordict import TensorDict
66
+ from idol.conditioning import ImageEncoder, require_encoder_access
67
+ from idol.models import BiRefNet, GaussianFixedlenDecoder, LatentSeqMMFlowModel, OctreeProbabilityFixedlenDecoder, layers
68
+ from idol.preprocess import CROP_MARGIN, preprocess_image, has_real_alpha
69
+ from idol.sampler import sample_flow
70
+ from idol.camera import decode_camera
71
+ except ImportError as exc:
72
+ raise RuntimeError("Install the optional teacher dependencies: python -m pip install '.[teacher]'") from exc
73
+ out = Path(args.out)
74
+ if out.exists():
75
+ raise ValueError("Teacher output directory already exists; choose a new --out")
76
+ # Local-only by default. Hugging Face authentication is never written to project files.
77
+ config_path = hf_hub_download(args.weights, "config.json", local_files_only=not args.allow_download)
78
+ config = json.loads(Path(config_path).read_text())
79
+ encoders = config["image_encoders"]
80
+ require_encoder_access([encoders["dinov3"], encoders["flux2_vae"]])
81
+ weights = Path(snapshot_download(args.weights, allow_patterns=["config.json", "*.safetensors"],
82
+ local_files_only=not args.allow_download))
83
+ patch_attention(layers, args.query_chunk)
84
+ torch.manual_seed(args.seed)
85
+
86
+ def load(model, name):
87
+ state = load_file(str(weights / f"{name}.safetensors"), device="cpu")
88
+ model.load_state_dict(state, strict=True)
89
+ del state
90
+ return model.eval().requires_grad_(False).to(device)
91
+
92
+ print("Experimental Idol MPS adapter: full-weight compatibility and quality remain unverified.", flush=True)
93
+ with Image.open(args.image) as opened:
94
+ image = opened.copy()
95
+ background = None
96
+ if not has_real_alpha(image):
97
+ print("Stage 1: background removal", flush=True)
98
+ background = load(BiRefNet(), "birefnet")
99
+ prepared = preprocess_image(image, background, config["image_size"], CROP_MARGIN[args.mode])
100
+ del background
101
+ release(device)
102
+ pixels = torch.from_numpy(np.array(prepared)).permute(2, 0, 1).float()[None].div(255).to(device)
103
+ print("Stage 2: image conditioning", flush=True)
104
+ encoder = ImageEncoder(encoders["dinov3"], encoders["flux2_vae"], device="cpu")
105
+ # Both encoders initially reside on CPU; only the active encoder is moved to MPS.
106
+ encoder.dinov3.to(device)
107
+ feature1 = encoder._dinov3_tokens(pixels)
108
+ del encoder.dinov3
109
+ release(device)
110
+ encoder.flux2_vae.to(device)
111
+ feature2 = encoder._flux2_tokens(pixels)
112
+ del encoder, pixels
113
+ release(device)
114
+ cond = TensorDict({"feature1": feature1, "feature2": feature2}, batch_size=1, device=device)
115
+ print("Stage 3: latent sampling", flush=True)
116
+ model = load(LatentSeqMMFlowModel(**config["denoiser"]["args"]), "denoiser")
117
+ noise = TensorDict({"latent": torch.randn(1, model.q_token_length, model.in_channels, device=device),
118
+ "camera": torch.randn(1, 1, model.cam_channels, device=device)}, batch_size=1, device=device)
119
+ result = sample_flow(model, noise, cond=cond, neg_cond=cond.apply(torch.zeros_like), steps=args.steps,
120
+ rescale_t=3., cfg_strength=3., verbose=True, batch_cfg=False)
121
+ latent, camera = result["latent"], decode_camera(result["camera"][0, 0])
122
+ del model, noise, cond, feature1, feature2, result
123
+ release(device)
124
+ print("Stage 4: octree decoding", flush=True)
125
+ model = load(OctreeProbabilityFixedlenDecoder(**config["decoder"]["args"]), "decoder")
126
+ per_anchor = config["decoder_gs"]["args"]["representation_config"]["num_gaussians"]
127
+ anchors = OctreeProbabilityFixedlenDecoder.sample(model, latent, num_points=args.gaussians // per_anchor,
128
+ level=config["max_voxel_level"])
129
+ del model
130
+ release(device)
131
+ print("Stage 5: Gaussian decoding", flush=True)
132
+ model = load(GaussianFixedlenDecoder(**config["decoder_gs"]["args"]), "decoder_gs")
133
+ gaussian = model.to_representation(anchors, model(anchors, latent))[0]
134
+ out.mkdir(parents=True)
135
+ gaussian.save_ply(str(out / "teacher.ply"))
136
+ prepared.save(out / "input.png")
137
+ (out / "metadata.json").write_text(json.dumps({"teacher": args.weights, "steps": args.steps,
138
+ "gaussians": args.gaussians, "seed": args.seed, "device": str(device), "camera": camera,
139
+ "sdk_revision": "4702a7f00850e34b6e83a2170cc123c3e9570744", "weights_snapshot": weights.name,
140
+ "coordinate_frame": "Idol exported PLY (y-up)", "adapter": "experimental staged MPS"}, indent=2))
141
+ print(f"Teacher output saved to {out}", flush=True)
train-mac.sh ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ cd "$(dirname "$0")"
4
+ if [[ "${1:-}" != "--publish" && -n "${1:-}" ]]; then
5
+ echo 'Usage: bash train-mac.sh [--publish]' >&2
6
+ exit 2
7
+ fi
8
+ FORMA3D_RUNTIME_DIR="${FORMA3D_RUNTIME_DIR:-$HOME/Library/Application Support/Forma3D}"
9
+ FORMA3D_PYTHON="$FORMA3D_RUNTIME_DIR/venv/bin/python"
10
+ if [[ ! -x "$FORMA3D_PYTHON" ]]; then
11
+ bash setup-mac.sh
12
+ fi
13
+ # Never depend on the caller's PATH, aliases, activation, or editable .pth files.
14
+ "$FORMA3D_PYTHON" -m image3d_student.cli doctor
15
+ if [[ ! -f base/examples/synthetic-smoke/synthetic-only.pt ]]; then
16
+ "$FORMA3D_RUNTIME_DIR/venv/bin/hf" download Lucasgitguy-co/image3d-student \
17
+ examples/synthetic-smoke/synthetic-only.pt \
18
+ --revision 1738cdfaf1bb940bf576a96d11b742ce014b9139 --local-dir base
19
+ fi
20
+ "$FORMA3D_PYTHON" - <<'PY'
21
+ from pathlib import Path
22
+ import hashlib
23
+ path = Path("base/examples/synthetic-smoke/synthetic-only.pt")
24
+ expected = "dd1a1719541c5603125e7f9379b0ad8ede20b7e9f2816a04e9120244cdbf528e"
25
+ if hashlib.sha256(path.read_bytes()).hexdigest() != expected:
26
+ raise SystemExit("Base checkpoint checksum mismatch; restore the pinned original checkpoint.")
27
+ print("Verified local base checkpoint; no Hugging Face connection required for training.")
28
+ PY
29
+ if [[ -s data/forma3d-v1/manifest.jsonl && -s data/forma3d-v1/test-manifest.jsonl ]]; then
30
+ echo 'Using completed dataset. Training will verify the cached sample hashes.'
31
+ else
32
+ "$FORMA3D_PYTHON" scripts/prepare_hf.py --out data/forma3d-v1 --cache data/downloads \
33
+ --scenario 64 --objaverse 32 --objaverse-shards 8 --grid 16 --views 4 --resume \
34
+ --max-file-mb 16 --max-download-mb 2048
35
+ fi
36
+ "$FORMA3D_PYTHON" -m image3d_student.cli train --manifest data/forma3d-v1/manifest.jsonl \
37
+ --init-from base/examples/synthetic-smoke/synthetic-only.pt \
38
+ --out runs/forma3d-v1 --device mps --width 64 --steps 5000 \
39
+ --batch-size 2 --lr 0.0001 --eval-every 100 --validation-fraction 0.2 --seed 42
40
+ if [[ "${1:-}" == "--publish" ]]; then set -- --publish; else set --; fi
41
+ "$FORMA3D_PYTHON" scripts/release.py --run runs/forma3d-v1 --data data/forma3d-v1 \
42
+ --base base/examples/synthetic-smoke/synthetic-only.pt \
43
+ --release release/forma3d-v1 --device mps --repo Lucasgitguy-co/forma3d-tiny \
44
+ "$@"
training.json ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "synthetic_only": false,
3
+ "contains_synthetic": false,
4
+ "device": "mps",
5
+ "torch": "2.15.0",
6
+ "seed": 42,
7
+ "train_ids": [
8
+ "e72c70c3a1e70f61edd5-v0",
9
+ "e72c70c3a1e70f61edd5-v1",
10
+ "e72c70c3a1e70f61edd5-v2",
11
+ "e72c70c3a1e70f61edd5-v3",
12
+ "0d291e312da4267be597-v0",
13
+ "0d291e312da4267be597-v1",
14
+ "0d291e312da4267be597-v2",
15
+ "0d291e312da4267be597-v3",
16
+ "84e4d421b6e5a54babac-v0",
17
+ "84e4d421b6e5a54babac-v1",
18
+ "84e4d421b6e5a54babac-v2",
19
+ "84e4d421b6e5a54babac-v3",
20
+ "f008965c2682f5284b4a-v0",
21
+ "f008965c2682f5284b4a-v1",
22
+ "f008965c2682f5284b4a-v2",
23
+ "f008965c2682f5284b4a-v3",
24
+ "01a7f40607c8cc615f61-v0",
25
+ "01a7f40607c8cc615f61-v1",
26
+ "01a7f40607c8cc615f61-v2",
27
+ "01a7f40607c8cc615f61-v3",
28
+ "f09b694a85d9fb4ae019-v0",
29
+ "f09b694a85d9fb4ae019-v1",
30
+ "f09b694a85d9fb4ae019-v2",
31
+ "f09b694a85d9fb4ae019-v3",
32
+ "e6c0c457e7b31561c451-v0",
33
+ "e6c0c457e7b31561c451-v1",
34
+ "e6c0c457e7b31561c451-v2",
35
+ "e6c0c457e7b31561c451-v3",
36
+ "78896f0abf8077250b90-v0",
37
+ "78896f0abf8077250b90-v1",
38
+ "78896f0abf8077250b90-v2",
39
+ "78896f0abf8077250b90-v3",
40
+ "b46a1c9864cb8b45fbe3-v0",
41
+ "b46a1c9864cb8b45fbe3-v1",
42
+ "b46a1c9864cb8b45fbe3-v2",
43
+ "b46a1c9864cb8b45fbe3-v3",
44
+ "6aaedee39b80ba8b7189-v0",
45
+ "6aaedee39b80ba8b7189-v1",
46
+ "6aaedee39b80ba8b7189-v2",
47
+ "6aaedee39b80ba8b7189-v3",
48
+ "acb330462014e2d1fadf-v0",
49
+ "acb330462014e2d1fadf-v1",
50
+ "acb330462014e2d1fadf-v2",
51
+ "acb330462014e2d1fadf-v3",
52
+ "506f7b7a7c46bcbd7b3d-v0",
53
+ "506f7b7a7c46bcbd7b3d-v1",
54
+ "506f7b7a7c46bcbd7b3d-v2",
55
+ "506f7b7a7c46bcbd7b3d-v3",
56
+ "877b14c0a003ed864972-v0",
57
+ "877b14c0a003ed864972-v1",
58
+ "877b14c0a003ed864972-v2",
59
+ "877b14c0a003ed864972-v3",
60
+ "d98b7eab417645c408d5-v0",
61
+ "d98b7eab417645c408d5-v1",
62
+ "d98b7eab417645c408d5-v2",
63
+ "d98b7eab417645c408d5-v3",
64
+ "767aff69879484e9b54b-v0",
65
+ "767aff69879484e9b54b-v1",
66
+ "767aff69879484e9b54b-v2",
67
+ "767aff69879484e9b54b-v3",
68
+ "3a307f409ee3c0236ccf-v0",
69
+ "3a307f409ee3c0236ccf-v1",
70
+ "3a307f409ee3c0236ccf-v2",
71
+ "3a307f409ee3c0236ccf-v3",
72
+ "e9848ffcaeb4bae99e2f-v0",
73
+ "e9848ffcaeb4bae99e2f-v1",
74
+ "e9848ffcaeb4bae99e2f-v2",
75
+ "e9848ffcaeb4bae99e2f-v3",
76
+ "f54650801d02e5d43e10-v0",
77
+ "f54650801d02e5d43e10-v1",
78
+ "f54650801d02e5d43e10-v2",
79
+ "f54650801d02e5d43e10-v3",
80
+ "892e464cf207e7425400-v0",
81
+ "892e464cf207e7425400-v1",
82
+ "892e464cf207e7425400-v2",
83
+ "892e464cf207e7425400-v3",
84
+ "6b56e16d01faf9b952a4-v0",
85
+ "6b56e16d01faf9b952a4-v1",
86
+ "6b56e16d01faf9b952a4-v2",
87
+ "6b56e16d01faf9b952a4-v3",
88
+ "ff4bcdb48f7a73ce8f21-v0",
89
+ "ff4bcdb48f7a73ce8f21-v1",
90
+ "ff4bcdb48f7a73ce8f21-v2",
91
+ "ff4bcdb48f7a73ce8f21-v3",
92
+ "39a959b3abba0a20445f-v0",
93
+ "39a959b3abba0a20445f-v1",
94
+ "39a959b3abba0a20445f-v2",
95
+ "39a959b3abba0a20445f-v3",
96
+ "487ec3573a2ca1585f1d-v0",
97
+ "487ec3573a2ca1585f1d-v1",
98
+ "487ec3573a2ca1585f1d-v2",
99
+ "487ec3573a2ca1585f1d-v3",
100
+ "4110e3fcc9c9692aebb0-v0",
101
+ "4110e3fcc9c9692aebb0-v1",
102
+ "4110e3fcc9c9692aebb0-v2",
103
+ "4110e3fcc9c9692aebb0-v3",
104
+ "91b9e1671c9f2fa0c94d-v0",
105
+ "91b9e1671c9f2fa0c94d-v1",
106
+ "91b9e1671c9f2fa0c94d-v2",
107
+ "91b9e1671c9f2fa0c94d-v3",
108
+ "ffd52f05142cacd19926-v0",
109
+ "ffd52f05142cacd19926-v1",
110
+ "ffd52f05142cacd19926-v2",
111
+ "ffd52f05142cacd19926-v3",
112
+ "a7b178ca7586f58d4097-v0",
113
+ "a7b178ca7586f58d4097-v1",
114
+ "a7b178ca7586f58d4097-v2",
115
+ "a7b178ca7586f58d4097-v3",
116
+ "e70b599ffd981c2bc6e4-v0",
117
+ "e70b599ffd981c2bc6e4-v1",
118
+ "e70b599ffd981c2bc6e4-v2",
119
+ "e70b599ffd981c2bc6e4-v3",
120
+ "d73e287e1bdffce35b5e-v0",
121
+ "d73e287e1bdffce35b5e-v1",
122
+ "d73e287e1bdffce35b5e-v2",
123
+ "d73e287e1bdffce35b5e-v3",
124
+ "479fa0112556943251d3-v0",
125
+ "479fa0112556943251d3-v1",
126
+ "479fa0112556943251d3-v2",
127
+ "479fa0112556943251d3-v3",
128
+ "d565ef67b0f63a87fbd1-v0",
129
+ "d565ef67b0f63a87fbd1-v1",
130
+ "d565ef67b0f63a87fbd1-v2",
131
+ "d565ef67b0f63a87fbd1-v3",
132
+ "dba4d5ea99b771567e65-v0",
133
+ "dba4d5ea99b771567e65-v1",
134
+ "dba4d5ea99b771567e65-v2",
135
+ "dba4d5ea99b771567e65-v3",
136
+ "1991d8540d749adbd5a2-v0",
137
+ "1991d8540d749adbd5a2-v1",
138
+ "1991d8540d749adbd5a2-v2",
139
+ "1991d8540d749adbd5a2-v3",
140
+ "d3d0a3244bfbbecb7a81-v0",
141
+ "d3d0a3244bfbbecb7a81-v1",
142
+ "d3d0a3244bfbbecb7a81-v2",
143
+ "d3d0a3244bfbbecb7a81-v3",
144
+ "ad38410cc4305837cdb5-v0",
145
+ "ad38410cc4305837cdb5-v1",
146
+ "ad38410cc4305837cdb5-v2",
147
+ "ad38410cc4305837cdb5-v3",
148
+ "ebb51cc1980b817b5293-v0",
149
+ "ebb51cc1980b817b5293-v1",
150
+ "ebb51cc1980b817b5293-v2",
151
+ "ebb51cc1980b817b5293-v3",
152
+ "d0528548ab492ec49c9a-v0",
153
+ "d0528548ab492ec49c9a-v1",
154
+ "d0528548ab492ec49c9a-v2",
155
+ "d0528548ab492ec49c9a-v3",
156
+ "fdca1c9444afdf164314-v0",
157
+ "fdca1c9444afdf164314-v1",
158
+ "fdca1c9444afdf164314-v2",
159
+ "fdca1c9444afdf164314-v3",
160
+ "e507f81099340e7731c1-v0",
161
+ "e507f81099340e7731c1-v1",
162
+ "e507f81099340e7731c1-v2",
163
+ "e507f81099340e7731c1-v3",
164
+ "e359f477410745cb90bd-v0",
165
+ "e359f477410745cb90bd-v1",
166
+ "e359f477410745cb90bd-v2",
167
+ "e359f477410745cb90bd-v3",
168
+ "f6f8dfa58f3a7ee4a6ce-v0",
169
+ "f6f8dfa58f3a7ee4a6ce-v1",
170
+ "f6f8dfa58f3a7ee4a6ce-v2",
171
+ "f6f8dfa58f3a7ee4a6ce-v3",
172
+ "980b32fad9f17c74634e-v0",
173
+ "980b32fad9f17c74634e-v1",
174
+ "980b32fad9f17c74634e-v2",
175
+ "980b32fad9f17c74634e-v3",
176
+ "de616e5af2ae654855de-v0",
177
+ "de616e5af2ae654855de-v1",
178
+ "de616e5af2ae654855de-v2",
179
+ "de616e5af2ae654855de-v3",
180
+ "39ff027ad9a68325c378-v0",
181
+ "39ff027ad9a68325c378-v1",
182
+ "39ff027ad9a68325c378-v2",
183
+ "39ff027ad9a68325c378-v3",
184
+ "40a403b1f00a7731bb0c-v0",
185
+ "40a403b1f00a7731bb0c-v1",
186
+ "40a403b1f00a7731bb0c-v2",
187
+ "40a403b1f00a7731bb0c-v3",
188
+ "79432b2b1f925ac322aa-v0",
189
+ "79432b2b1f925ac322aa-v1",
190
+ "79432b2b1f925ac322aa-v2",
191
+ "79432b2b1f925ac322aa-v3",
192
+ "49aa39b4083329b974a3-v0",
193
+ "49aa39b4083329b974a3-v1",
194
+ "49aa39b4083329b974a3-v2",
195
+ "49aa39b4083329b974a3-v3",
196
+ "2cea1c878a4547ece95e-v0",
197
+ "2cea1c878a4547ece95e-v1",
198
+ "2cea1c878a4547ece95e-v2",
199
+ "2cea1c878a4547ece95e-v3",
200
+ "07290c65376571fc88e3-v0",
201
+ "07290c65376571fc88e3-v1",
202
+ "07290c65376571fc88e3-v2",
203
+ "07290c65376571fc88e3-v3",
204
+ "b33aeb679195ac416fd9-v0",
205
+ "b33aeb679195ac416fd9-v1",
206
+ "b33aeb679195ac416fd9-v2",
207
+ "b33aeb679195ac416fd9-v3",
208
+ "50762ad6529b83e23d3e-v0",
209
+ "50762ad6529b83e23d3e-v1",
210
+ "50762ad6529b83e23d3e-v2",
211
+ "50762ad6529b83e23d3e-v3",
212
+ "1497430051592337cdfc-v0",
213
+ "1497430051592337cdfc-v1",
214
+ "1497430051592337cdfc-v2",
215
+ "1497430051592337cdfc-v3",
216
+ "b12004dfbec10d17137b-v0",
217
+ "b12004dfbec10d17137b-v1",
218
+ "b12004dfbec10d17137b-v2",
219
+ "b12004dfbec10d17137b-v3",
220
+ "7fec3c65a68dbe7758fd-v0",
221
+ "7fec3c65a68dbe7758fd-v1",
222
+ "7fec3c65a68dbe7758fd-v2",
223
+ "7fec3c65a68dbe7758fd-v3",
224
+ "54da5dddde1e0361afec-v0",
225
+ "54da5dddde1e0361afec-v1",
226
+ "54da5dddde1e0361afec-v2",
227
+ "54da5dddde1e0361afec-v3",
228
+ "38cbe4583d4af82bc1cc-v0",
229
+ "38cbe4583d4af82bc1cc-v1",
230
+ "38cbe4583d4af82bc1cc-v2",
231
+ "38cbe4583d4af82bc1cc-v3",
232
+ "07e668758676dbec5048-v0",
233
+ "07e668758676dbec5048-v1",
234
+ "07e668758676dbec5048-v2",
235
+ "07e668758676dbec5048-v3",
236
+ "f7c40d2912c6461a63a2-v0",
237
+ "f7c40d2912c6461a63a2-v1",
238
+ "f7c40d2912c6461a63a2-v2",
239
+ "f7c40d2912c6461a63a2-v3",
240
+ "9c91b0b9762c72ffb714-v0",
241
+ "9c91b0b9762c72ffb714-v1",
242
+ "9c91b0b9762c72ffb714-v2",
243
+ "9c91b0b9762c72ffb714-v3",
244
+ "8c360413890122153c7c-v0",
245
+ "8c360413890122153c7c-v1",
246
+ "8c360413890122153c7c-v2",
247
+ "8c360413890122153c7c-v3",
248
+ "7d76a5fc01ddbc5f5382-v0",
249
+ "7d76a5fc01ddbc5f5382-v1",
250
+ "7d76a5fc01ddbc5f5382-v2",
251
+ "7d76a5fc01ddbc5f5382-v3",
252
+ "95b2b7b5a0e29c6551d5-v0",
253
+ "95b2b7b5a0e29c6551d5-v1",
254
+ "95b2b7b5a0e29c6551d5-v2",
255
+ "95b2b7b5a0e29c6551d5-v3",
256
+ "eea38754ae954df09aec-v0",
257
+ "eea38754ae954df09aec-v1",
258
+ "eea38754ae954df09aec-v2",
259
+ "eea38754ae954df09aec-v3",
260
+ "ae721d3ddbeb66f2a3bb-v0",
261
+ "ae721d3ddbeb66f2a3bb-v1",
262
+ "ae721d3ddbeb66f2a3bb-v2",
263
+ "ae721d3ddbeb66f2a3bb-v3",
264
+ "30ee3daeaecfc3ecc40b-v0",
265
+ "30ee3daeaecfc3ecc40b-v1",
266
+ "30ee3daeaecfc3ecc40b-v2",
267
+ "30ee3daeaecfc3ecc40b-v3"
268
+ ],
269
+ "val_ids": [
270
+ "478e3ebcd3a9761cc58d-v0",
271
+ "478e3ebcd3a9761cc58d-v1",
272
+ "478e3ebcd3a9761cc58d-v2",
273
+ "478e3ebcd3a9761cc58d-v3",
274
+ "3cccc2387af01902fa18-v0",
275
+ "3cccc2387af01902fa18-v1",
276
+ "3cccc2387af01902fa18-v2",
277
+ "3cccc2387af01902fa18-v3",
278
+ "2d390b9a71cd4246f2a6-v0",
279
+ "2d390b9a71cd4246f2a6-v1",
280
+ "2d390b9a71cd4246f2a6-v2",
281
+ "2d390b9a71cd4246f2a6-v3",
282
+ "d35f5efca2a60d63c4b6-v0",
283
+ "d35f5efca2a60d63c4b6-v1",
284
+ "d35f5efca2a60d63c4b6-v2",
285
+ "d35f5efca2a60d63c4b6-v3",
286
+ "c7714db5f938b7d85acb-v0",
287
+ "c7714db5f938b7d85acb-v1",
288
+ "c7714db5f938b7d85acb-v2",
289
+ "c7714db5f938b7d85acb-v3",
290
+ "65e3fde922ac3d23531c-v0",
291
+ "65e3fde922ac3d23531c-v1",
292
+ "65e3fde922ac3d23531c-v2",
293
+ "65e3fde922ac3d23531c-v3",
294
+ "bc4619d7cd2a0a22a0db-v0",
295
+ "bc4619d7cd2a0a22a0db-v1",
296
+ "bc4619d7cd2a0a22a0db-v2",
297
+ "bc4619d7cd2a0a22a0db-v3",
298
+ "57931985b05b3df37cb3-v0",
299
+ "57931985b05b3df37cb3-v1",
300
+ "57931985b05b3df37cb3-v2",
301
+ "57931985b05b3df37cb3-v3",
302
+ "69323a0945566e60c044-v0",
303
+ "69323a0945566e60c044-v1",
304
+ "69323a0945566e60c044-v2",
305
+ "69323a0945566e60c044-v3",
306
+ "a167a77232c4ca4795d2-v0",
307
+ "a167a77232c4ca4795d2-v1",
308
+ "a167a77232c4ca4795d2-v2",
309
+ "a167a77232c4ca4795d2-v3",
310
+ "3eec7426834f92771ac7-v0",
311
+ "3eec7426834f92771ac7-v1",
312
+ "3eec7426834f92771ac7-v2",
313
+ "3eec7426834f92771ac7-v3",
314
+ "0872ba96c873ac55e532-v0",
315
+ "0872ba96c873ac55e532-v1",
316
+ "0872ba96c873ac55e532-v2",
317
+ "0872ba96c873ac55e532-v3",
318
+ "b9dcd7e6a510a0952c17-v0",
319
+ "b9dcd7e6a510a0952c17-v1",
320
+ "b9dcd7e6a510a0952c17-v2",
321
+ "b9dcd7e6a510a0952c17-v3",
322
+ "866805ebff659448f234-v0",
323
+ "866805ebff659448f234-v1",
324
+ "866805ebff659448f234-v2",
325
+ "866805ebff659448f234-v3",
326
+ "f750f07092510231c565-v0",
327
+ "f750f07092510231c565-v1",
328
+ "f750f07092510231c565-v2",
329
+ "f750f07092510231c565-v3",
330
+ "99bbae502355dd6cb0ec-v0",
331
+ "99bbae502355dd6cb0ec-v1",
332
+ "99bbae502355dd6cb0ec-v2",
333
+ "99bbae502355dd6cb0ec-v3"
334
+ ],
335
+ "parameters": 306321,
336
+ "teachers": [
337
+ "mesh-proxy:allenai/objaverse",
338
+ "mesh-proxy:scenario-labs/3d-collection"
339
+ ],
340
+ "validation": "held-out objects",
341
+ "manifest_sha256": "1c446a51de294439cfc2244dd0cee936485ee5b70bbcdef6795c7cb09e742904",
342
+ "initialization": {
343
+ "sha256": "dd1a1719541c5603125e7f9379b0ad8ede20b7e9f2816a04e9120244cdbf528e",
344
+ "config": {
345
+ "grid": 8,
346
+ "width": 64
347
+ },
348
+ "step": 100,
349
+ "optimizer": "fresh AdamW; weights-only post-training"
350
+ },
351
+ "steps_requested": 5000,
352
+ "learning_rate": 0.0001,
353
+ "batch_size": 2,
354
+ "validation_fraction": 0.2,
355
+ "baseline_validation": {
356
+ "occupancy": 0.5287473667412996,
357
+ "position": 0.11035483225714415,
358
+ "colour": 0.07344755931990221,
359
+ "scale": 0.6529320403933525,
360
+ "rotation": 0.007450982979207765,
361
+ "opacity": 0.0016474263943564438,
362
+ "geometry": 0.0,
363
+ "loss": 0.8536830507218838,
364
+ "occupancy_iou": 0.2525805914774537
365
+ }
366
+ }