polats commited on
Commit
f3c3d61
·
verified ·
1 Parent(s): dccc98e

Deploy Karate Wiener (kimodo kata maker)

Browse files
Files changed (3) hide show
  1. .gitattributes +1 -0
  2. app.py +36 -1
  3. assets/citizen_skin_color.png +3 -0
.gitattributes CHANGED
@@ -97,3 +97,4 @@ kata_sequence_taikyoku.png filter=lfs diff=lfs merge=lfs -text
97
  kick_stances_verify.png filter=lfs diff=lfs merge=lfs -text
98
  stance_library_verify.png filter=lfs diff=lfs merge=lfs -text
99
  assets/default_scene.webp filter=lfs diff=lfs merge=lfs -text
 
 
97
  kick_stances_verify.png filter=lfs diff=lfs merge=lfs -text
98
  stance_library_verify.png filter=lfs diff=lfs merge=lfs -text
99
  assets/default_scene.webp filter=lfs diff=lfs merge=lfs -text
100
+ assets/citizen_skin_color.png filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -1013,7 +1013,17 @@ def _render_preview_html(
1013
  payload_json = json.dumps(payload, separators=(",", ":")).replace("</", "<\\/")
1014
  # Display-character catalog (GLB + mapping) is injected per-render, never
1015
  # stored in preview records. Only offer characters whose GLB actually loaded.
1016
- catalog = [c for c in _CHARACTER_CATALOG if c.get("id") == "skeleton" or c.get("glb_b64")]
 
 
 
 
 
 
 
 
 
 
1017
  char_json = json.dumps(catalog, separators=(",", ":")).replace("</", "<\\/")
1018
  cfg = {
1019
  "clothing": CLOTHING_CATALOG,
@@ -1985,6 +1995,30 @@ def _render_preview_html(
1985
  let character = null; // {{ root, anim }}
1986
  let mode = 'skeleton';
1987
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1988
  async function buildCharacter(entry) {{
1989
  const loader = new GLTFLoader();
1990
  const gltf = await loader.parseAsync(decodeBytes(entry.glb_b64).buffer, '');
@@ -1993,6 +2027,7 @@ def _render_preview_html(
1993
  let skinned = null;
1994
  root.traverse(o => {{ if (o.isSkinnedMesh) {{ if (!skinned) skinned = o; o.frustumCulled = false; }} }});
1995
  if (!skinned) throw new Error('GLB has no skinned mesh');
 
1996
  root.visible = false;
1997
  scene.add(root);
1998
  root.updateMatrixWorld(true);
 
1013
  payload_json = json.dumps(payload, separators=(",", ":")).replace("</", "<\\/")
1014
  # Display-character catalog (GLB + mapping) is injected per-render, never
1015
  # stored in preview records. Only offer characters whose GLB actually loaded.
1016
+ catalog = []
1017
+ for c in _CHARACTER_CATALOG:
1018
+ if not (c.get("id") == "skeleton" or c.get("glb_b64")):
1019
+ continue
1020
+ c = dict(c)
1021
+ # The s&box citizen GLB ships untextured (its UV atlas path doesn't resolve);
1022
+ # supply the decompiled skin atlas (served from the dataset like clothing) so
1023
+ # the viewer can map it onto the body. UVs are preserved through UniRig.
1024
+ if c.get("id") == "citizen":
1025
+ c["texture"] = f"{_VIEWER_ASSET_BASE}/textures/citizen_skin_color.png"
1026
+ catalog.append(c)
1027
  char_json = json.dumps(catalog, separators=(",", ":")).replace("</", "<\\/")
1028
  cfg = {
1029
  "clothing": CLOTHING_CATALOG,
 
1995
  let character = null; // {{ root, anim }}
1996
  let mode = 'skeleton';
1997
 
1998
+ // Map a skin atlas (e.g. the decompiled s&box citizen skin) onto a character's
1999
+ // body materials. One shared UV atlas covers the whole body; skip eye/mouth
2000
+ // sub-materials (their own UVs). flipY=false = glTF UV convention.
2001
+ const _charTexLoader = new THREE.TextureLoader();
2002
+ _charTexLoader.setCrossOrigin('anonymous');
2003
+ function applyCharSkin(root, url) {{
2004
+ const tex = _charTexLoader.load(url);
2005
+ tex.colorSpace = THREE.SRGBColorSpace;
2006
+ tex.flipY = false;
2007
+ tex.anisotropy = renderer.capabilities.getMaxAnisotropy();
2008
+ root.traverse(o => {{
2009
+ if (!o.isMesh && !o.isSkinnedMesh) return;
2010
+ const mats = Array.isArray(o.material) ? o.material : [o.material];
2011
+ for (const m of mats) {{
2012
+ if (!m) continue;
2013
+ const name = (m.name || o.name || '').toLowerCase();
2014
+ if (/eye|mouth|teeth|tongue|brow|lash|cornea/.test(name)) continue;
2015
+ m.map = tex;
2016
+ if (m.color) m.color.setScalar(1); // don't tint the atlas with a leftover base color
2017
+ m.needsUpdate = true;
2018
+ }}
2019
+ }});
2020
+ }}
2021
+
2022
  async function buildCharacter(entry) {{
2023
  const loader = new GLTFLoader();
2024
  const gltf = await loader.parseAsync(decodeBytes(entry.glb_b64).buffer, '');
 
2027
  let skinned = null;
2028
  root.traverse(o => {{ if (o.isSkinnedMesh) {{ if (!skinned) skinned = o; o.frustumCulled = false; }} }});
2029
  if (!skinned) throw new Error('GLB has no skinned mesh');
2030
+ if (entry.texture) applyCharSkin(root, entry.texture); // map the s&box skin atlas onto the body
2031
  root.visible = false;
2032
  scene.add(root);
2033
  root.updateMatrixWorld(true);
assets/citizen_skin_color.png ADDED

Git LFS Details

  • SHA256: 7f004bf05d4b61bb3bc7eadffd823676f7f47ce1c813bea9f5c981cce4f69042
  • Pointer size: 131 Bytes
  • Size of remote file: 125 kB