Research: Dexter Quiet reference cage (operator's hand cage, evaluated limit mesh, fidelity to the scan)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ebe8d97840
commit
d426f865ad
5 changed files with 6405 additions and 0 deletions
21
docs/research/dexter-quiet-cage/README.md
Normal file
21
docs/research/dexter-quiet-cage/README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Dexter Quiet: the operator's reference cage (2026-10-12)
|
||||
|
||||
The reference brush-tree target r2 is measured against (ruling brush-tree:ruling:pursue-sdf-composition-remeshing:
|
||||
the operator rebuilds Dexter Quiet by hand as the reference cage).
|
||||
|
||||
Source: `Asset Sources/Ships.blend` in Aetheria, object `Dexter Quiet Cage` (collection Quiet), saved 2026-10-12 17:31.
|
||||
Exported from a copy by `export.py` (Blender, background mode). Files:
|
||||
|
||||
- `cage_raw.obj`: the cage as authored, half a hull: 29 vertices, 25 faces, 9 edges creased at 1.0 (`cage_info.txt`).
|
||||
- `cage_eval.obj`: the evaluated stack: Mirror (merge on) -> Subsurf level 3 (render 2, limit surface on) ->
|
||||
Bevel (0.001, 1 segment, weight-limited) -> Weighted Normal. 3,154 vertices, 3,152 faces.
|
||||
- The scanned original `Dexter Quiet` (4,832 vertices, 5,600 faces) is not copied here; it stays in Ships.blend.
|
||||
|
||||
Fidelity of the hand cage to the scan (vertex-to-nearest-vertex, an upper bound on surface distance; hull diagonal 1.492):
|
||||
cage->scan mean 0.88% p95 2.04% max 3.11% of the diagonal; scan->cage mean 1.29% p95 4.12% max 6.03%.
|
||||
That spread is the artistic liberty a human cage takes, and is the fidelity band an automated remesh is measured against.
|
||||
|
||||
Operator, 2026-10-12: "I'm afraid I had to take a bit of artistic liberty to get the cage to behave, mostly because
|
||||
of how creases work in Blender (generates horrible geometry if the crease path isn't closed)". Body fact for the
|
||||
remesher: crease chains in the cage are closed loops; an open crease path ending inside a face region produces
|
||||
bad subdivision geometry in Blender's Catmull-Clark (OpenSubdiv) evaluation, so a generated cage must close its creases.
|
||||
6306
docs/research/dexter-quiet-cage/cage_eval.obj
Normal file
6306
docs/research/dexter-quiet-cage/cage_eval.obj
Normal file
File diff suppressed because it is too large
Load diff
4
docs/research/dexter-quiet-cage/cage_info.txt
Normal file
4
docs/research/dexter-quiet-cage/cage_info.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[('cage_raw', (29, 25)), ('cage_limit_eval', (3154, 3152)), ('dexter_ref', (4832, 5600))]
|
||||
creases=[(1, 3, 1.0), (5, 1, 1.0), (17, 11, 1.0), (3, 17, 1.0), (13, 16, 1.0), (24, 22, 1.0), (25, 16, 1.0), (13, 11, 1.0), (24, 25, 1.0)]
|
||||
mods=[('MIRROR', {'use_clip': False, 'use_mirror_merge': True}), ('SUBSURF', {'levels': 3, 'render_levels': 2, 'use_limit_surface': True}), ('BEVEL', {'width': 0.0010000001639127731, 'segments': 1, 'limit_method': 'WEIGHT'}), ('WEIGHTED_NORMAL', {})]
|
||||
cage_dims=(0.9702155590057373, 1.0190552473068237, 0.3775596618652344) ref_dims=(0.9811705946922302, 1.0477101802825928, 0.407174676656723)
|
||||
54
docs/research/dexter-quiet-cage/cage_raw.obj
Normal file
54
docs/research/dexter-quiet-cage/cage_raw.obj
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
v -0.050183 -0.515158 0.120381
|
||||
v -0.050183 -0.502594 0.165733
|
||||
v -0.066373 -0.290093 0.034410
|
||||
v -0.066373 -0.279099 0.154038
|
||||
v -0.000000 -0.521785 0.077995
|
||||
v -0.000000 -0.495967 0.196439
|
||||
v 0.000000 -0.257172 0.011836
|
||||
v 0.000000 -0.079878 0.194280
|
||||
v -0.085456 0.296420 0.036890
|
||||
v 0.000000 0.264006 -0.120438
|
||||
v -0.000000 0.324338 0.095861
|
||||
v -0.532850 -0.332750 0.201392
|
||||
v -0.000000 0.083429 0.170193
|
||||
v -0.445757 -0.036017 0.098265
|
||||
v -0.069995 0.072662 0.125021
|
||||
v -0.305911 -0.163824 0.119325
|
||||
v -0.219219 0.256351 -0.032856
|
||||
v -0.271429 -0.083411 0.118972
|
||||
v -0.071629 0.154301 -0.071808
|
||||
v 0.000000 0.096312 -0.125795
|
||||
v -0.230102 0.060001 0.075233
|
||||
v -0.231539 0.092497 -0.020192
|
||||
v 0.002669 0.513952 -0.201831
|
||||
v 0.002669 0.519207 -0.172940
|
||||
v -0.010721 0.515629 -0.180240
|
||||
v -0.106624 0.345361 -0.096021
|
||||
v -0.041564 0.406965 -0.070340
|
||||
v 0.001707 0.450794 -0.082077
|
||||
v 0.001374 0.391670 -0.173090
|
||||
f 1 2 4 3
|
||||
f 15 13 11 9
|
||||
f 5 6 2 1
|
||||
f 3 7 5 1
|
||||
f 8 4 2 6
|
||||
f 22 16 12 14
|
||||
f 20 19 10
|
||||
f 10 19 22 17
|
||||
f 16 18 12
|
||||
f 21 17 14
|
||||
f 15 9 17 21
|
||||
f 3 4 18 16
|
||||
f 19 3 16 22
|
||||
f 4 15 21 18
|
||||
f 18 21 14 12
|
||||
f 7 3 19 20
|
||||
f 17 22 14
|
||||
f 4 8 13 15
|
||||
f 24 23 25
|
||||
f 26 27 25
|
||||
f 9 11 28 27
|
||||
f 29 26 25 23
|
||||
f 10 17 26 29
|
||||
f 17 9 27 26
|
||||
f 27 28 24 25
|
||||
20
docs/research/dexter-quiet-cage/export.py
Normal file
20
docs/research/dexter-quiet-cage/export.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import bpy, sys, bmesh
|
||||
d=sys.argv[-1]
|
||||
dg=bpy.context.evaluated_depsgraph_get()
|
||||
cage=bpy.data.objects['Dexter Quiet Cage']; ref=bpy.data.objects['Dexter Quiet']
|
||||
def dump(o, ev, path):
|
||||
src=o.evaluated_get(dg) if ev else o
|
||||
me=src.to_mesh()
|
||||
with open(path,'w') as f:
|
||||
for v in me.vertices:
|
||||
p=o.matrix_world @ v.co; f.write(f"v {p.x:.6f} {p.y:.6f} {p.z:.6f}\n")
|
||||
for poly in me.polygons: f.write("f "+" ".join(str(i+1) for i in poly.vertices)+"\n")
|
||||
n=(len(me.vertices),len(me.polygons)); src.to_mesh_clear(); return n
|
||||
info=[]
|
||||
info.append(("cage_raw",dump(cage,False,d+"/cage_raw.obj")))
|
||||
info.append(("cage_limit_eval",dump(cage,True,d+"/cage_eval.obj")))
|
||||
info.append(("dexter_ref",dump(ref,False,d+"/dexter_ref.obj")))
|
||||
me=cage.data; a=me.attributes.get('crease_edge')
|
||||
cr=[(e.vertices[0],e.vertices[1],round(a.data[e.index].value,3)) for e in me.edges if a and a.data[e.index].value>0]
|
||||
mods=[(m.type,{k:getattr(m,k) for k in ('levels','render_levels','use_limit_surface','width','segments','limit_method','use_clip','use_mirror_merge') if hasattr(m,k)}) for m in cage.modifiers]
|
||||
open(d+"/cage_info.txt","w").write(f"{info}\ncreases={cr}\nmods={mods}\ncage_dims={tuple(cage.dimensions)} ref_dims={tuple(ref.dimensions)}\n")
|
||||
Loading…
Reference in a new issue