"""Export only the original GalaxyGlow mesh, named parameters and BC1 noise."""
from pathlib import Path
import gzip,hashlib,json,struct
root=Path('artifacts/galaxy-query-research/power-outer-sources')
models=json.loads((root/'authored-models/original-authored-models.json').read_text())
model=next(m for m in models['models'] if m['name']=='milkywaycore_')
scope={};exec(Path('research/Extract-GalaxyRenderMaterials.py').read_text().split('for group,entry in enumerate(buffers):')[0],scope)
materials=json.loads((root/'material/original-materials.json').read_text())
texture=next(t for t in materials['textures'] if t['name']=='milkywaycoremat.pnoisekernaltexture')
if (texture['sourceFormat'],texture['width'],texture['height'],texture['mips'],texture['gpuBytes'])!=(95,16,16,5,3072):raise ValueError('Original noise texture changed')
params={p['name']:p['floatValues'] if 'floatValues'in p else p['integerValue'] for p in model['material']['parameters']}
# This order is independently constrained by the original PS vector operations:
# centre+innerRadius, outerRadius+innerShape and colour/scale combinations.
constant_names=[['pCoreGlowColourInner'],['pCoreGlowColourOuter'],['pCoreGlowColourScalePowerInner','pCoreGlowColourScalePowerOuter'],
['pCoreGlowGalaxyCentre','pCoreGlowRadiusInner'],['pCoreGlowRadiusOuter','pCoreGlowShapeInner'],['pCoreGlowShapeOuter'],
['pDithering','pGlowInternalCoreAmount'],['pGlowMinMaxDistPercentage']]
constants=[]
for names in constant_names:
values=[v for n in names for v in params[n]]
if len(values)>4:raise ValueError('Original shader material vector overflow')
constants.append(values+[0.]*(4-len(values)))
assert constants[3]==[50000.,40955.,50000.,20000.]
assert constants[4][0]==80000.
data=scope['b'][texture['gpuOffset']:texture['gpuOffset']+texture['gpuBytes']]
mesh=b''.join(struct.pack('<3f',*p) for p in model['positions'])+struct.pack('<'+'H'*model['indexCount'],*model['indices'])
output=Path('XFEEDToolBox.Core/Rendering')
for suffix,payload in [('noise.bc1',data),('mesh.bin',mesh)]:
(output/('original-galaxy-core-'+suffix+'.gz')).write_bytes(gzip.compress(payload,mtime=0))
result=dict(gameImageSha256=models['gameImageSha256'],resource=models['resource'],archiveSha256=models['archiveSha256'],
frozenSha256=models['frozenSha256'],gameProcessAccess=False,gameCalls=0,
mesh=dict(vertexCount=model['vertexCount'],indexCount=model['indexCount'],vertexBytes=model['vertexCount']*12,
payloadBytes=len(mesh),payloadSha256=hashlib.sha256(mesh).hexdigest(),sourcePackedGpuSha256=model['gpuSha256'],
sourceVertexFormat=8,sourceStride=40,originalTransform=model['originalTransform']),
texture=dict(width=16,height=16,mips=texture['mipLayout'],sourceFormat=95,dxgiFormat=71,
formatSource='pinned PE51D4E0 indexes4E2E500; table95=71 (BC1_UNorm)',payloadBytes=len(data),payloadSha256=hashlib.sha256(data).hexdigest()),
shaderClass='GalaxyGlow',parameters=params,shaderMaterialConstantVectors=constants,
shaderMaterialVectorNames=constant_names,fullRestored=False,
sharedHdrFields={'CB1[90].y':'HDR write (constructor 1/256)','CB1[90].z':'HDR read (constructor 256)'},
recoveredOutput='R16 HDR scene, original SourceColor/One blend, default U2 pass5 tone mapping',
unclosed=['runtime material/quality overrides','live HDR factors and post-process options',
'complete original sorted frame and same-state live-client comparison'])
path=output/'original-galaxy-core.json';path.write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(json.dumps(dict(path=str(path),meshBytes=len(mesh),textureBytes=len(data),vertices=model['vertexCount'],indices=model['indexCount'])))
"""Export only the original GalaxyGlow mesh, named parameters and BC1 noise."""
from pathlib import Path
import gzip,hashlib,json,struct
root=Path('artifacts/galaxy-query-research/power-outer-sources')
models=json.loads((root/'authored-models/original-authored-models.json').read_text())
model=next(m for m in models['models'] if m['name']=='milkywaycore_')
scope={};exec(Path('research/Extract-GalaxyRenderMaterials.py').read_text().split('for group,entry in enumerate(buffers):')[0],scope)
materials=json.loads((root/'material/original-materials.json').read_text())
texture=next(t for t in materials['textures'] if t['name']=='milkywaycoremat.pnoisekernaltexture')
if (texture['sourceFormat'],texture['width'],texture['height'],texture['mips'],texture['gpuBytes'])!=(95,16,16,5,3072):raise ValueError('Original noise texture changed')
params={p['name']:p['floatValues'] if 'floatValues'in p else p['integerValue'] for p in model['material']['parameters']}
# This order is independently constrained by the original PS vector operations:
# centre+innerRadius, outerRadius+innerShape and colour/scale combinations.
constant_names=[['pCoreGlowColourInner'],['pCoreGlowColourOuter'],['pCoreGlowColourScalePowerInner','pCoreGlowColourScalePowerOuter'],
['pCoreGlowGalaxyCentre','pCoreGlowRadiusInner'],['pCoreGlowRadiusOuter','pCoreGlowShapeInner'],['pCoreGlowShapeOuter'],
['pDithering','pGlowInternalCoreAmount'],['pGlowMinMaxDistPercentage']]
constants=[]
for names in constant_names:
values=[v for n in names for v in params[n]]
if len(values)>4:raise ValueError('Original shader material vector overflow')
constants.append(values+[0.]*(4-len(values)))
assert constants[3]==[50000.,40955.,50000.,20000.]
assert constants[4][0]==80000.
data=scope['b'][texture['gpuOffset']:texture['gpuOffset']+texture['gpuBytes']]
mesh=b''.join(struct.pack('<3f',*p) for p in model['positions'])+struct.pack('<'+'H'*model['indexCount'],*model['indices'])
output=Path('XFEEDToolBox.Core/Rendering')
for suffix,payload in [('noise.bc1',data),('mesh.bin',mesh)]:
(output/('original-galaxy-core-'+suffix+'.gz')).write_bytes(gzip.compress(payload,mtime=0))
result=dict(gameImageSha256=models['gameImageSha256'],resource=models['resource'],archiveSha256=models['archiveSha256'],
frozenSha256=models['frozenSha256'],gameProcessAccess=False,gameCalls=0,
mesh=dict(vertexCount=model['vertexCount'],indexCount=model['indexCount'],vertexBytes=model['vertexCount']*12,
payloadBytes=len(mesh),payloadSha256=hashlib.sha256(mesh).hexdigest(),sourcePackedGpuSha256=model['gpuSha256'],
sourceVertexFormat=8,sourceStride=40,originalTransform=model['originalTransform']),
texture=dict(width=16,height=16,mips=texture['mipLayout'],sourceFormat=95,dxgiFormat=71,
formatSource='pinned PE51D4E0 indexes4E2E500; table95=71 (BC1_UNorm)',payloadBytes=len(data),payloadSha256=hashlib.sha256(data).hexdigest()),
shaderClass='GalaxyGlow',parameters=params,shaderMaterialConstantVectors=constants,
shaderMaterialVectorNames=constant_names,fullRestored=False,
sharedHdrFields={'CB1[90].y':'HDR write (constructor 1/256)','CB1[90].z':'HDR read (constructor 256)'},
recoveredOutput='R16 HDR scene, original SourceColor/One blend, default U2 pass5 tone mapping',
unclosed=['runtime material/quality overrides','live HDR factors and post-process options',
'complete original sorted frame and same-state live-client comparison'])
path=output/'original-galaxy-core.json';path.write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(json.dumps(dict(path=str(path),meshBytes=len(mesh),textureBytes=len(data),vertices=model['vertexCount'],indices=model['indexCount'])))