diff --git a/docs/shots/laneE/r39_magpie_ab.png b/docs/shots/laneE/r39_magpie_ab.png new file mode 100644 index 0000000..3730105 Binary files /dev/null and b/docs/shots/laneE/r39_magpie_ab.png differ diff --git a/pipeline/_bird_b.json b/pipeline/_bird_b.json new file mode 100644 index 0000000..bd6ea76 --- /dev/null +++ b/pipeline/_bird_b.json @@ -0,0 +1 @@ +{"source":"web/js/world/magpie.js :: birdGeometry() via createMagpie()","tris":182,"verts":216,"material":{"vertexColors":true,"roughness":0.62,"metalness":0,"side":"DoubleSide","wind":"wing"},"bbox":{"min":[-0.3400000035762787,-0.07649999856948853,-0.25999999046325684],"max":[0.3400000035762787,0.08999999612569809,0.4099999964237213],"size":[0.6800000071525574,0.16649999469518661,0.6699999868869781]},"foldedScaleX":0.42,"index":[0,9,10,1,10,11,2,11,12,3,12,13,4,13,14,5,14,15,6,15,16,7,16,17,10,9,19,9,18,19,11,10,20,10,19,20,12,11,21,11,20,21,13,12,22,12,21,22,14,13,23,13,22,23,15,14,24,14,23,24,16,15,25,15,24,25,17,16,26,16,25,26,19,18,28,18,27,28,20,19,29,19,28,29,21,20,30,20,29,30,22,21,31,21,30,31,23,22,32,22,31,32,24,23,33,23,32,33,25,24,34,24,33,34,26,25,35,25,34,35,28,27,37,27,36,37,29,28,38,28,37,38,30,29,39,29,38,39,31,30,40,30,39,40,32,31,41,31,40,41,33,32,42,32,41,42,34,33,43,33,42,43,35,34,44,34,43,44,37,36,46,36,45,46,38,37,47,37,46,47,39,38,48,38,47,48,40,39,49,39,48,49,41,40,50,40,49,50,42,41,51,41,50,51,43,42,52,42,51,52,44,43,53,43,52,53,46,45,55,47,46,56,48,47,57,49,48,58,50,49,59,51,50,60,52,51,61,53,52,62,63,70,71,64,71,72,65,72,73,66,73,74,67,74,75,68,75,76,71,70,78,70,77,78,72,71,79,71,78,79,73,72,80,72,79,80,74,73,81,73,80,81,75,74,82,74,81,82,76,75,83,75,82,83,78,77,85,77,84,85,79,78,86,78,85,86,80,79,87,79,86,87,81,80,88,80,87,88,82,81,89,81,88,89,83,82,90,82,89,90,85,84,92,84,91,92,86,85,93,85,92,93,87,86,94,86,93,94,88,87,95,87,94,95,89,88,96,88,95,96,90,89,97,89,96,97,92,91,99,93,92,100,94,93,101,95,94,102,96,95,103,97,96,104,111,112,106,112,113,107,113,114,108,114,115,109,115,116,110,123,122,117,124,123,118,125,124,119,126,125,120,127,126,121,128,130,129,130,131,129,132,134,133,134,135,133,136,138,137,138,139,137,140,142,141,142,143,141,144,146,145,146,147,145,148,150,149,150,151,149,152,154,153,154,155,153,156,158,157,158,159,157,160,162,161,162,163,161,164,166,165,166,167,165,168,170,169,170,171,169,172,174,173,174,175,173,176,178,177,178,179,177,180,182,181,182,183,181,184,186,185,186,187,185,188,190,189,190,191,189,192,194,193,194,195,193,196,198,197,198,199,197,200,202,201,202,203,201,204,206,205,206,207,205,208,210,209,210,211,209,212,214,213,214,215,213],"position":[0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,0,0.07649999856948853,0,-0.042500000447034836,0.06625094264745712,0,-0.03005203790962696,0.06625094264745712,0.05259106680750847,-2.602374520384451e-18,0.06625094264745712,0.07437500357627869,0.03005203790962696,0.06625094264745712,0.05259106680750847,0.042500000447034836,0.06625094264745712,9.108310717948002e-18,0.03005203790962696,0.06625094264745712,-0.05259106680750847,7.8071233543582e-18,0.06625094264745712,-0.07437500357627869,-0.03005203790962696,0.06625094264745712,-0.05259106680750847,-0.042500000447034836,0.06625094264745712,-1.8216621435896004e-17,-0.07361216098070145,0.03824999928474426,0,-0.05205165594816208,0.03824999928474426,0.09109039604663849,-4.507444883373438e-18,0.03824999928474426,0.12882128357887268,0.05205165594816208,0.03824999928474426,0.09109039604663849,0.07361216098070145,0.03824999928474426,1.5776056471421573e-17,0.05205165594816208,0.03824999928474426,-0.09109039604663849,1.3522334236530007e-17,0.03824999928474426,-0.12882128357887268,-0.05205165594816208,0.03824999928474426,-0.09109039604663849,-0.07361216098070145,0.03824999928474426,-3.1552112942843146e-17,-0.08500000089406967,4.6842741780510425e-18,0,-0.06010407581925392,4.6842741780510425e-18,0.10518213361501694,-5.204749040768902e-18,4.6842741780510425e-18,0.14875000715255737,0.06010407581925392,4.6842741780510425e-18,0.10518213361501694,0.08500000089406967,4.6842741780510425e-18,1.8216621435896004e-17,0.06010407581925392,4.6842741780510425e-18,-0.10518213361501694,1.56142467087164e-17,4.6842741780510425e-18,-0.14875000715255737,-0.06010407581925392,4.6842741780510425e-18,-0.10518213361501694,-0.08500000089406967,4.6842741780510425e-18,-3.643324287179201e-17,-0.07361216098070145,-0.03824999928474426,0,-0.05205165594816208,-0.03824999928474426,0.09109039604663849,-4.507444883373438e-18,-0.03824999928474426,0.12882128357887268,0.05205165594816208,-0.03824999928474426,0.09109039604663849,0.07361216098070145,-0.03824999928474426,1.5776056471421573e-17,0.05205165594816208,-0.03824999928474426,-0.09109039604663849,1.3522334236530007e-17,-0.03824999928474426,-0.12882128357887268,-0.05205165594816208,-0.03824999928474426,-0.09109039604663849,-0.07361216098070145,-0.03824999928474426,-3.1552112942843146e-17,-0.042500000447034836,-0.06625094264745712,0,-0.03005203790962696,-0.06625094264745712,0.05259106680750847,-2.602374520384451e-18,-0.06625094264745712,0.07437500357627869,0.03005203790962696,-0.06625094264745712,0.05259106680750847,0.042500000447034836,-0.06625094264745712,9.108310717948002e-18,0.03005203790962696,-0.06625094264745712,-0.05259106680750847,7.8071233543582e-18,-0.06625094264745712,-0.07437500357627869,-0.03005203790962696,-0.06625094264745712,-0.05259106680750847,-0.042500000447034836,-0.06625094264745712,-1.8216621435896004e-17,-1.0409498081537804e-17,-0.07649999856948853,0,-7.360626148953102e-18,-0.07649999856948853,1.2881095553872775e-17,-6.373978986557175e-34,-0.07649999856948853,1.8216621435896004e-17,7.360626148953102e-18,-0.07649999856948853,1.2881095553872775e-17,1.0409498081537804e-17,-0.07649999856948853,2.230892668253885e-33,7.360626148953102e-18,-0.07649999856948853,-1.2881095553872775e-17,1.9121937418849005e-33,-0.07649999856948853,-1.8216621435896004e-17,-7.360626148953102e-18,-0.07649999856948853,-1.2881095553872775e-17,-1.0409498081537804e-17,-0.07649999856948853,-4.46178533650777e-33,0,0.08999999612569809,-0.14000000059604645,0,0.08999999612569809,-0.14000000059604645,0,0.08999999612569809,-0.14000000059604645,0,0.08999999612569809,-0.14000000059604645,0,0.08999999612569809,-0.14000000059604645,0,0.08999999612569809,-0.14000000059604645,0,0.08999999612569809,-0.14000000059604645,-0.03232818841934204,0.07949593663215637,-0.14000000059604645,-0.01616409420967102,0.07949593663215637,-0.11200296878814697,0.01616409420967102,0.07949593663215637,-0.11200296878814697,0.03232818841934204,0.07949593663215637,-0.14000000059604645,0.01616409420967102,0.07949593663215637,-0.16799703240394592,-0.01616409420967102,0.07949593663215637,-0.16799703240394592,-0.03232818841934204,0.07949593663215637,-0.14000000059604645,-0.052308108657598495,0.051995933055877686,-0.14000000059604645,-0.026154054328799248,0.051995933055877686,-0.09469984471797943,0.026154054328799248,0.051995933055877686,-0.09469984471797943,0.052308108657598495,0.051995933055877686,-0.14000000059604645,0.026154054328799248,0.051995933055877686,-0.18530015647411346,-0.026154054328799248,0.051995933055877686,-0.18530015647411346,-0.052308108657598495,0.051995933055877686,-0.14000000059604645,-0.052308108657598495,0.01800406537950039,-0.14000000059604645,-0.026154054328799248,0.01800406537950039,-0.09469984471797943,0.026154054328799248,0.01800406537950039,-0.09469984471797943,0.052308108657598495,0.01800406537950039,-0.14000000059604645,0.026154054328799248,0.01800406537950039,-0.18530015647411346,-0.026154054328799248,0.01800406537950039,-0.18530015647411346,-0.052308108657598495,0.01800406537950039,-0.14000000059604645,-0.03232818841934204,-0.009495936334133148,-0.14000000059604645,-0.01616409420967102,-0.009495936334133148,-0.11200296878814697,0.01616409420967102,-0.009495936334133148,-0.11200296878814697,0.03232818841934204,-0.009495936334133148,-0.14000000059604645,0.01616409420967102,-0.009495936334133148,-0.16799703240394592,-0.01616409420967102,-0.009495936334133148,-0.16799703240394592,-0.03232818841934204,-0.009495936334133148,-0.14000000059604645,-6.735557192910056e-18,-0.019999999552965164,-0.14000000059604645,-3.367778596455028e-18,-0.019999999552965164,-0.14000000059604645,3.367778596455028e-18,-0.019999999552965164,-0.14000000059604645,6.735557192910056e-18,-0.019999999552965164,-0.14000000059604645,3.367778596455028e-18,-0.019999999552965164,-0.14000000059604645,-3.367778596455028e-18,-0.019999999552965164,-0.14000000059604645,-6.735557192910056e-18,-0.019999999552965164,-0.14000000059604645,0,0.029999999329447746,-0.25999999046325684,0,0.029999999329447746,-0.25999999046325684,0,0.029999999329447746,-0.25999999046325684,0,0.029999999329447746,-0.25999999046325684,0,0.029999999329447746,-0.25999999046325684,0,0.029999999329447746,-0.25999999046325684,0,0.050999999046325684,-0.18000000715255737,0.019972186535596848,0.03648935630917549,-0.18000000715255737,0.01234349049627781,0.013010642491281033,-0.18000000715255737,-0.01234349049627781,0.013010642491281033,-0.18000000715255737,-0.019972186535596848,0.03648935630917549,-0.18000000715255737,-5.143516582334358e-18,0.050999999046325684,-0.18000000715255737,0,0.029999999329447746,-0.18000000715255737,0,0.029999999329447746,-0.18000000715255737,0,0.029999999329447746,-0.18000000715255737,0,0.029999999329447746,-0.18000000715255737,0,0.029999999329447746,-0.18000000715255737,0,0.050999999046325684,-0.18000000715255737,0.019972186535596848,0.03648935630917549,-0.18000000715255737,0.01234349049627781,0.013010642491281033,-0.18000000715255737,-0.01234349049627781,0.013010642491281033,-0.18000000715255737,-0.019972186535596848,0.03648935630917549,-0.18000000715255737,-5.143516582334358e-18,0.050999999046325684,-0.18000000715255737,0.026000000536441803,0.06700000166893005,-0.07249999791383743,0.026000000536441803,0.06700000166893005,-0.1274999976158142,0.026000000536441803,0.05299999937415123,-0.07249999791383743,0.026000000536441803,0.05299999937415123,-0.1274999976158142,-0.026000000536441803,0.06700000166893005,-0.1274999976158142,-0.026000000536441803,0.06700000166893005,-0.07249999791383743,-0.026000000536441803,0.05299999937415123,-0.1274999976158142,-0.026000000536441803,0.05299999937415123,-0.07249999791383743,-0.026000000536441803,0.06700000166893005,-0.1274999976158142,0.026000000536441803,0.06700000166893005,-0.1274999976158142,-0.026000000536441803,0.06700000166893005,-0.07249999791383743,0.026000000536441803,0.06700000166893005,-0.07249999791383743,-0.026000000536441803,0.05299999937415123,-0.07249999791383743,0.026000000536441803,0.05299999937415123,-0.07249999791383743,-0.026000000536441803,0.05299999937415123,-0.1274999976158142,0.026000000536441803,0.05299999937415123,-0.1274999976158142,-0.026000000536441803,0.06700000166893005,-0.07249999791383743,0.026000000536441803,0.06700000166893005,-0.07249999791383743,-0.026000000536441803,0.05299999937415123,-0.07249999791383743,0.026000000536441803,0.05299999937415123,-0.07249999791383743,0.026000000536441803,0.06700000166893005,-0.1274999976158142,-0.026000000536441803,0.06700000166893005,-0.1274999976158142,0.026000000536441803,0.05299999937415123,-0.1274999976158142,-0.026000000536441803,0.05299999937415123,-0.1274999976158142,0.054999999701976776,0.06499999761581421,0.16499999165534973,0.054999999701976776,0.06499999761581421,0.03500000387430191,0.054999999701976776,0.04500000178813934,0.16499999165534973,0.054999999701976776,0.04500000178813934,0.03500000387430191,-0.054999999701976776,0.06499999761581421,0.03500000387430191,-0.054999999701976776,0.06499999761581421,0.16499999165534973,-0.054999999701976776,0.04500000178813934,0.03500000387430191,-0.054999999701976776,0.04500000178813934,0.16499999165534973,-0.054999999701976776,0.06499999761581421,0.03500000387430191,0.054999999701976776,0.06499999761581421,0.03500000387430191,-0.054999999701976776,0.06499999761581421,0.16499999165534973,0.054999999701976776,0.06499999761581421,0.16499999165534973,-0.054999999701976776,0.04500000178813934,0.16499999165534973,0.054999999701976776,0.04500000178813934,0.16499999165534973,-0.054999999701976776,0.04500000178813934,0.03500000387430191,0.054999999701976776,0.04500000178813934,0.03500000387430191,-0.054999999701976776,0.06499999761581421,0.16499999165534973,0.054999999701976776,0.06499999761581421,0.16499999165534973,-0.054999999701976776,0.04500000178813934,0.16499999165534973,0.054999999701976776,0.04500000178813934,0.16499999165534973,0.054999999701976776,0.06499999761581421,0.03500000387430191,-0.054999999701976776,0.06499999761581421,0.03500000387430191,0.054999999701976776,0.04500000178813934,0.03500000387430191,-0.054999999701976776,0.04500000178813934,0.03500000387430191,0.02500000037252903,0.010999999940395355,0.4099999964237213,0.02500000037252903,0.010999999940395355,0.10999999195337296,0.02500000037252903,-0.010999999940395355,0.4099999964237213,0.02500000037252903,-0.010999999940395355,0.10999999195337296,-0.02500000037252903,0.010999999940395355,0.10999999195337296,-0.02500000037252903,0.010999999940395355,0.4099999964237213,-0.02500000037252903,-0.010999999940395355,0.10999999195337296,-0.02500000037252903,-0.010999999940395355,0.4099999964237213,-0.02500000037252903,0.010999999940395355,0.10999999195337296,0.02500000037252903,0.010999999940395355,0.10999999195337296,-0.02500000037252903,0.010999999940395355,0.4099999964237213,0.02500000037252903,0.010999999940395355,0.4099999964237213,-0.02500000037252903,-0.010999999940395355,0.4099999964237213,0.02500000037252903,-0.010999999940395355,0.4099999964237213,-0.02500000037252903,-0.010999999940395355,0.10999999195337296,0.02500000037252903,-0.010999999940395355,0.10999999195337296,-0.02500000037252903,0.010999999940395355,0.4099999964237213,0.02500000037252903,0.010999999940395355,0.4099999964237213,-0.02500000037252903,-0.010999999940395355,0.4099999964237213,0.02500000037252903,-0.010999999940395355,0.4099999964237213,0.02500000037252903,0.010999999940395355,0.10999999195337296,-0.02500000037252903,0.010999999940395355,0.10999999195337296,0.02500000037252903,-0.010999999940395355,0.10999999195337296,-0.02500000037252903,-0.010999999940395355,0.10999999195337296,-0.3400000035762787,0.04500000178813934,-0.08500000089406967,1.7881393032936899e-9,0.04500000178813934,-0.08500000089406967,-0.3400000035762787,0.04500000178813934,0.0650000050663948,1.7881393032936899e-9,0.04500000178813934,0.0650000050663948,-0.31619998812675476,0.04800000041723251,0.004999999422580004,-0.17339999973773956,0.04800000041723251,0.004999999422580004,-0.31619998812675476,0.04800000041723251,0.054999999701976776,-0.17339999973773956,0.04800000041723251,0.054999999701976776,-1.7881393032936899e-9,0.04500000178813934,-0.08500000089406967,0.3400000035762787,0.04500000178813934,-0.08500000089406967,-1.7881393032936899e-9,0.04500000178813934,0.0650000050663948,0.3400000035762787,0.04500000178813934,0.0650000050663948,0.17339999973773956,0.04800000041723251,0.004999999422580004,0.31619998812675476,0.04800000041723251,0.004999999422580004,0.17339999973773956,0.04800000041723251,0.054999999701976776,0.31619998812675476,0.04800000041723251,0.054999999701976776],"normal":[0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0.4610839784145355,0.8873565196990967,0,-0.3383724093437195,0.9209330677986145,0.19335566461086273,-3.050111710886797e-17,0.9586343169212341,0.2846405804157257,0.3383724093437195,0.9209330677986145,0.19335566461086273,0.4610839784145355,0.8873565196990967,3.226657199896235e-17,0.3383724093437195,0.9209330677986145,-0.19335566461086273,9.150334140043656e-17,0.9586343169212341,-0.2846405804157257,-0.3383724093437195,0.9209330677986145,-0.19335566461086273,-0.4610839784145355,0.8873565196990967,-6.45331439979247e-17,-0.8416975736618042,0.5399492383003235,0,-0.6820616126060486,0.6187788248062134,0.3897494971752167,-7.127496377525239e-17,0.746711790561676,0.6651477217674255,0.6820616126060486,0.6187788248062134,0.3897494971752167,0.8416975736618042,0.5399492383003235,5.890184397145149e-17,0.6820616126060486,0.6187788248062134,-0.3897494971752167,2.1382489132575717e-16,0.746711790561676,-0.6651477217674255,-0.6820616126060486,0.6187788248062134,-0.3897494971752167,-0.8416975736618042,0.5399492383003235,-1.1780368794290299e-16,-1,6.803593625473155e-17,0,-0.8682431578636169,8.354004717360896e-17,0.49613893032073975,-1.0715659629247974e-16,1.190628950632251e-16,1,0.8682431578636169,8.354004717360896e-17,0.49613893032073975,1,6.803593625473155e-17,6.997981731167606e-17,0.8682431578636169,8.354004717360896e-17,-0.49613893032073975,3.214697822599943e-16,1.190628950632251e-16,-1,-0.8682431578636169,8.354004717360896e-17,-0.49613893032073975,-1,6.803593625473155e-17,-1.3995963462335213e-16,-0.8416975736618042,-0.5399492383003235,0,-0.6820616126060486,-0.6187788248062134,0.3897494971752167,-7.127496377525239e-17,-0.746711790561676,0.6651477217674255,0.6820616126060486,-0.6187788248062134,0.3897494971752167,0.8416975736618042,-0.5399492383003235,5.890184397145149e-17,0.6820616126060486,-0.6187788248062134,-0.3897494971752167,2.1382489132575717e-16,-0.746711790561676,-0.6651477217674255,-0.6820616126060486,-0.6187788248062134,-0.3897494971752167,-0.8416975736618042,-0.5399492383003235,-1.1780368794290299e-16,-0.4610839784145355,-0.8873565196990967,0,-0.3383724093437195,-0.9209330677986145,0.19335566461086273,-3.050111710886797e-17,-0.9586343169212341,0.2846405804157257,0.3383724093437195,-0.9209330677986145,0.19335566461086273,0.4610839784145355,-0.8873565196990967,3.226657199896235e-17,0.3383724093437195,-0.9209330677986145,-0.19335566461086273,9.150334140043656e-17,-0.9586343169212341,-0.2846405804157257,-0.3383724093437195,-0.9209330677986145,-0.19335566461086273,-0.4610839784145355,-0.8873565196990967,-6.45331439979247e-17,-1.1021821673266511e-16,-1,0,-7.793604410735001e-17,-1,4.4534884710430327e-17,-6.748918613621786e-33,-1,6.298183624225295e-17,7.793604410735001e-17,-1,4.4534884710430327e-17,1.1021821673266511e-16,-1,7.713050263958595e-33,7.793604410735001e-17,-1,-4.4534884710430327e-17,2.0246757310233297e-32,-1,-6.298183624225295e-17,-7.793604410735001e-17,-1,-4.4534884710430327e-17,-1.1021821673266511e-16,-1,-1.542610052791719e-32,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,-0.5877852439880371,0.80901700258255,0,-0.29389262199401855,0.80901700258255,0.5090369582176208,0.29389262199401855,0.80901700258255,0.5090369582176208,0.5877852439880371,0.80901700258255,7.198293111792428e-17,0.29389262199401855,0.80901700258255,-0.5090369582176208,-0.29389262199401855,0.80901700258255,-0.5090369582176208,-0.5877852439880371,0.80901700258255,-1.4396586223584855e-16,-0.9510565400123596,0.30901700258255005,0,-0.4755282700061798,0.30901700258255005,0.8236390948295593,0.4755282700061798,0.30901700258255005,0.8236390948295593,0.9510565400123596,0.30901700258255005,1.1647082866083914e-16,0.4755282700061798,0.30901700258255005,-0.8236390948295593,-0.4755282700061798,0.30901700258255005,-0.8236390948295593,-0.9510565400123596,0.30901700258255005,-2.329416573216783e-16,-0.9510565400123596,-0.30901700258255005,0,-0.4755282700061798,-0.30901700258255005,0.8236390948295593,0.4755282700061798,-0.30901700258255005,0.8236390948295593,0.9510565400123596,-0.30901700258255005,1.1647082866083914e-16,0.4755282700061798,-0.30901700258255005,-0.8236390948295593,-0.4755282700061798,-0.30901700258255005,-0.8236390948295593,-0.9510565400123596,-0.30901700258255005,-2.329416573216783e-16,-0.5877852439880371,-0.80901700258255,0,-0.29389262199401855,-0.80901700258255,0.5090369582176208,0.29389262199401855,-0.80901700258255,0.5090369582176208,0.5877852439880371,-0.80901700258255,7.198293111792428e-17,0.29389262199401855,-0.80901700258255,-0.5090369582176208,-0.29389262199401855,-0.80901700258255,-0.5090369582176208,-0.5877852439880371,-0.80901700258255,-1.4396586223584855e-16,-1.2246468525851679e-16,-1,0,-6.123234262925839e-17,-1,1.0605752472130298e-16,6.123234262925839e-17,-1,1.0605752472130298e-16,1.2246468525851679e-16,-1,1.4997597572211942e-32,6.123234262925839e-17,-1,-1.0605752472130298e-16,-6.123234262925839e-17,-1,-1.0605752472130298e-16,-1.2246468525851679e-16,-1,-2.9995195144423884e-32,0,0.9672309756278992,-0.25389811396598816,0.9198912978172302,0.2988907992839813,-0.25389811396598816,0.5685241222381592,-0.7825062870979309,-0.25389811396598816,-0.5685241222381592,-0.7825062870979309,-0.25389811396598816,-0.9198912978172302,0.2988907992839813,-0.25389811396598816,-2.3690325688576624e-16,0.9672309756278992,-0.25389811396598816,0,0.9672309756278992,-0.25389811396598816,0.9198912978172302,0.2988907992839813,-0.25389811396598816,0.5685241222381592,-0.7825062870979309,-0.25389811396598816,-0.5685241222381592,-0.7825062870979309,-0.25389811396598816,-0.9198912978172302,0.2988907992839813,-0.25389811396598816,-2.3690325688576624e-16,0.9672309756278992,-0.25389811396598816,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,0,-6.123234262925839e-17,1,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17,0,1,6.123234262925839e-17],"color":[0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.48514994978904724,0.5028864741325378,0.5271151065826416,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.009721217676997185,0.01032982300966978,0.011612244881689548,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369,0.7912979125976562,0.7758222222328186,0.7230551242828369]} \ No newline at end of file diff --git a/pipeline/bird_to_glb.py b/pipeline/bird_to_glb.py new file mode 100644 index 0000000..3c5a861 --- /dev/null +++ b/pipeline/bird_to_glb.py @@ -0,0 +1,96 @@ +"""PROCITY Lane E — bird_to_glb.py (R39, the magpie A/B) + +Turn `pipeline/dump_bird.mjs`'s dump of LANE B'S OWN `birdGeometry()` into a GLB, so the identical +`render_views.py` camera rig that shot E's tinted 894-tri GLB can shoot B's 182-tri procedural bird +from the identical angles under the identical light. Rendering the two through different pipelines +would make the picture arguable; this makes it decisive. + + BL=/Applications/Blender.app/Contents/MacOS/Blender + "$BL" --background --python pipeline/bird_to_glb.py -- IN.json OUT.glb [--fold] + +`--fold` applies magpie.js's perch pose (`place(..., folded=true)` scales the instance X by 0.42), +because B's bird has TWO silhouettes off one geometry and E's GLB has one. + +Vertex colours ride as COLOR_0 and are wired straight into Base Color, matching +`MeshStandardMaterial({ vertexColors: true, roughness: 0.62, metalness: 0, side: DoubleSide })`. +Normals are the ones three.js computed, imported as custom split normals — a Blender-recomputed +normal would shade the sphere differently from the browser. +""" +import bpy, sys, json + +ARGV = sys.argv[sys.argv.index("--") + 1:] +SRC, OUT = ARGV[0], ARGV[1] +FOLD = "--fold" in ARGV +FOLD_X = 0.42 # magpie.js: the perched instance is squashed in X, wings in + +d = json.load(open(SRC)) +pos, nrm, col, idx = d["position"], d["normal"], d["color"], d["index"] +nv = len(pos) // 3 + +# ── FRAME. three: +Y up, nose along −Z. E's published magpie GLB: +Y up, HEAD AT +Z (that is what +# render_views.py's rig assumes — "glTF +Z head -> Blender -Y"). Blender's glTF exporter with +# export_yup writes glTF = (Bx, Bz, −By). So to land B's bird in E's frame we want +# glTF = (−xt, yt, −zt) (a 180° yaw, det = +1 ⇒ winding preserved) +# which means the Blender vertex must be (−xt, zt, yt). Without this the two rows of the sheet +# would be shot from opposite ends of the bird and the comparison would be worthless. +def to_blender(x, y, z): + return (-x, z, y) + +fx = FOLD_X if FOLD else 1.0 +verts = [to_blender(pos[i * 3] * fx, pos[i * 3 + 1], pos[i * 3 + 2]) for i in range(nv)] +faces = [tuple(idx[i:i + 3]) for i in range(0, len(idx), 3)] if idx else \ + [(i, i + 1, i + 2) for i in range(0, nv, 3)] + +for o in list(bpy.data.objects): + bpy.data.objects.remove(o, do_unlink=True) + +me = bpy.data.meshes.new("bird") +me.from_pydata(verts, [], faces) +me.update() +ob = bpy.data.objects.new("bird", me) +bpy.context.collection.objects.link(ob) + +# three's own normals, per corner (folding in X inverts nothing: 0.42 > 0, so only a rescale) +if nrm: + loops = [] + for p in me.polygons: + for vi in p.vertices: + loops.append(to_blender(nrm[vi * 3], nrm[vi * 3 + 1], nrm[vi * 3 + 2])) + try: + me.normals_split_custom_set(loops) + except Exception as e: # never let shading cosmetics kill the export + print("custom normals skipped:", e) + +# COLOR_0 — the whole argument for B's bird is that the white is IN the vertices +if col: + ca = me.color_attributes.new(name="Col", type='FLOAT_COLOR', domain='POINT') + for i in range(nv): + ca.data[i].color = (col[i * 3], col[i * 3 + 1], col[i * 3 + 2], 1.0) + me.color_attributes.active_color = ca + me.attributes.active_color = ca + +mat = bpy.data.materials.new("birdMat") +mat.use_nodes = True +mat.use_backface_culling = False # three: side = DoubleSide +nt = mat.node_tree +bsdf = nt.nodes["Principled BSDF"] +bsdf.inputs["Roughness"].default_value = 0.62 +bsdf.inputs["Metallic"].default_value = 0.0 +if col: + cattr = nt.nodes.new("ShaderNodeVertexColor") + cattr.layer_name = "Col" + nt.links.new(cattr.outputs["Color"], bsdf.inputs["Base Color"]) + # FAIRNESS. E's published magpie carries normalize.py's emissiveFactor 0.28 WITH an + # emissiveTexture, i.e. 0.28 × its own albedo — a self-lit copy of its own markings. Handing B's + # bird the identical treatment (0.28 × its vertex colour) is the only way the two rows of the + # sheet are lit the same; without it the render flatters E by construction and the ruling is + # worthless. `--noemit` drops it, for the ?noassets-honest version of B's material. + if "--noemit" not in ARGV: + nt.links.new(cattr.outputs["Color"], bsdf.inputs["Emission Color"]) + bsdf.inputs["Emission Strength"].default_value = 0.28 +me.materials.append(mat) + +bpy.ops.export_scene.gltf(filepath=OUT, export_format='GLB', + export_apply=True, export_yup=True, + export_normals=True, export_vertex_color='ACTIVE') +print(f"WROTE {OUT} tris={len(faces)} verts={nv} folded={FOLD}") diff --git a/pipeline/dump_bird.mjs b/pipeline/dump_bird.mjs new file mode 100644 index 0000000..4a2f353 --- /dev/null +++ b/pipeline/dump_bird.mjs @@ -0,0 +1,95 @@ +#!/usr/bin/env node +// PROCITY Lane E — dump_bird.mjs (R39, the magpie A/B) +// +// Dump Lane B's PROCEDURAL magpie geometry, by RUNNING LANE B'S OWN MODULE — not by re-implementing +// it. `web/js/world/magpie.js` is imported unmodified; the bare `three` / `three/addons/` specifiers +// its imports use are resolved to the repo's OWN vendored build through a node resolve hook, so the +// vertices dumped here are byte-for-byte the vertices the browser gets. That matters: an A/B render +// against a hand-ported strawman proves nothing, and the whole point of R39 item 1 is that Fable +// rules on the picture. +// +// node pipeline/dump_bird.mjs [OUT.json] +// +// Writes { tris, verts, position[], normal[], color[], index[]|null } in the mesh's own metric frame +// (metres, three's +Y up, nose along −Z). `pipeline/bird_to_glb.py` turns it into a GLB so the same +// `render_views.py` rig that shot E's tinted GLB can shoot B's bird from the same cameras. +import { registerHooks } from 'node:module'; +import { pathToFileURL } from 'node:url'; +import { writeFileSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const HERE = dirname(fileURLToPath(import.meta.url)); +const ROOT = resolve(HERE, '..'); +const VENDOR = pathToFileURL(resolve(ROOT, 'web/vendor/three.module.js')).href; +const ADDONS = pathToFileURL(resolve(ROOT, 'web/vendor/addons')).href + '/'; + +// The repo's importmap, as a node resolver: "three" and "three/addons/*" only. +registerHooks({ + resolve(spec, ctx, next) { + if (spec === 'three') return { url: VENDOR, shortCircuit: true }; + if (spec.startsWith('three/addons/')) { + return { url: ADDONS + spec.slice('three/addons/'.length), shortCircuit: true }; + } + return next(spec, ctx); + }, +}); + +const { generatePlan } = await import(pathToFileURL(resolve(ROOT, 'web/js/citygen/plan.js')).href); +const { createMagpie } = await import(pathToFileURL(resolve(ROOT, 'web/js/world/magpie.js')).href); + +const plan = generatePlan(20261990); +const scene = { add() {}, remove() {} }; +const camera = { position: { x: 0, y: 1.6, z: 0 } }; +const m = createMagpie({ scene, plan, citySeed: 20261990, townKey: null, camera, chunks: null, lighting: null, force: true }); +const mesh = m.group.children.find((c) => c.isInstancedMesh); +const g = mesh.geometry; + +const idx = g.index ? Array.from(g.index.array) : null; +const pos = Array.from(g.attributes.position.array); +const nrm = g.attributes.normal ? Array.from(g.attributes.normal.array) : null; +const col = g.attributes.color ? Array.from(g.attributes.color.array) : null; +const tris = idx ? idx.length / 3 : pos.length / 9; + +const out = { + source: 'web/js/world/magpie.js :: birdGeometry() via createMagpie()', + tris, verts: pos.length / 3, + material: { vertexColors: true, roughness: 0.62, metalness: 0, side: 'DoubleSide', wind: 'wing' }, + bbox: (() => { + g.computeBoundingBox(); + const b = g.boundingBox; + return { min: [b.min.x, b.min.y, b.min.z], max: [b.max.x, b.max.y, b.max.z], + size: [b.max.x - b.min.x, b.max.y - b.min.y, b.max.z - b.min.z] }; + })(), + // the perch pose is the same geometry squashed in X (magpie.js `place(..., folded)`) + foldedScaleX: 0.42, + index: idx, position: pos, normal: nrm, color: col, +}; +const dst = process.argv.find((a) => a.endsWith('.json')) || resolve(HERE, '_bird_b.json'); +writeFileSync(dst, JSON.stringify(out)); +console.log(`bird: ${tris} triangles, ${out.verts} verts, bbox size ${out.bbox.size.map((v) => v.toFixed(3)).join(' × ')} m → ${dst}`); + +// ── --sim: WHICH POSE IS THE PLAYER ACTUALLY LOOKING AT? ──────────────────────────────────────── +// The A/B is usually argued as "the swoop is the whole point", but magpie.js's own clock says the +// swoop is the minority state: COOLDOWN 5.5 s perched against SWOOP_T 1.25 + RETURN_T 1.9 = 3.15 s +// in the air, and the mesh is drawn out to DEFEND_R × 2.2 = 74.8 m where it can only be perched. +// So walk a player down the street past a territory at WALK speed and COUNT the frames. +if (process.argv.includes('--sim')) { + const t = m.territories[0] || { x: 0, z: 0 }; + const DT = 1 / 60, SPEED = 4.6, OFFSET = 4.0; // WALK m/s, and how far off the perch you pass + globalThis.window = { PROCITY: { game: { day: 1 } } }; + const tally = {}; + let frames = 0; + for (let i = 0; i < 60 * 60; i++) { // 60 s of walking + const s = -140 + i * DT * SPEED; // straight past the perch, 140 m either side + camera.position.x = t.x + s; camera.position.z = t.z + OFFSET; + m.update(DT); + tally[m.state.mode] = (tally[m.state.mode] || 0) + 1; + if (m.count > 0) frames++; + } + const drawn = Object.entries(tally).filter(([k]) => k === 'perched' || k === 'swooping' || k === 'returning'); + const total = drawn.reduce((a, [, v]) => a + v, 0); + console.log(`sim: 60 s walk at ${SPEED} m/s, ${OFFSET} m off the perch — modes ${JSON.stringify(tally)}`); + console.log(`sim: bird DRAWN in ${frames} of 3600 frames (${(frames / 36).toFixed(1)}%)`); + for (const [k, v] of drawn) console.log(`sim: ${k.padEnd(10)} ${v} frames = ${(100 * v / total).toFixed(1)}% of the frames it is on screen`); +} diff --git a/pipeline/render_views.py b/pipeline/render_views.py index 686a2d1..569a147 100644 --- a/pipeline/render_views.py +++ b/pipeline/render_views.py @@ -34,9 +34,33 @@ def bounds(o): Vector((max(c.x for c in cs), max(c.y for c in cs), max(c.z for c in cs)))) +def kill_emission(): + """Zero every imported material's emission. + + [R39] Needed for an A/B that is allowed to decide anything. `normalize.py` gives every baked GLB + `emissiveFactor 0.28` WITH an `emissiveTexture`, i.e. 0.28 x its own albedo — blacks stay black, + whites get brighter. A vertex-coloured mesh cannot express that in glTF at all (COLOR_0 + multiplies base colour only), and Blender's exporter silently writes a FLAT 0.28, which lifts the + black bird to grey and renders the comparison meaningless. So the fair move is to strip it from + BOTH sides and light the two candidates identically off sky + sun. Stated on the sheet: a baked + GLB reads slightly BETTER in game than it does here, which is the safe direction to be wrong in. + """ + for m in bpy.data.materials: + if not m.use_nodes: + continue + for n in m.node_tree.nodes: + for sock in ("Emission Strength", "Emission Color"): + if sock in n.inputs: + for lk in list(n.inputs[sock].links): + m.node_tree.links.remove(lk) + n.inputs[sock].default_value = 0.0 if sock == "Emission Strength" else (0, 0, 0, 1) + + def main(): wipe() bpy.ops.import_scene.gltf(filepath=SRC) + if "--noemit" in ARGV: + kill_emission() objs = [o for o in bpy.data.objects if o.type == 'MESH'] ob = objs[0] mn, mx = bounds(ob) diff --git a/pipeline/view_sheet.py b/pipeline/view_sheet.py index 9e034c1..63ad759 100644 --- a/pipeline/view_sheet.py +++ b/pipeline/view_sheet.py @@ -8,8 +8,16 @@ One row of views per input (each composited over sky — bird-against-sky is the matters), then a strip that re-samples the swoop / flank / rear views to 64 / 48 / 32 px and magnifies them NEAREST: a 0.36 m bird at 3-10 m on a 1080-high screen is 50-100 px, so 64 px is the honest test of whether a marking reads and 32 px is the pessimistic one. + +`--ab` (R39, the two magpies) lays the distance strip out as a GRID — one line per candidate, the +same view and the same pixel size stacked vertically — because a single 27-cell line is a list and +what a ruling needs is a column you can look down. It then repeats that grid under linear MOTION +BLUR, since the bird is seen for ~1.2 s crossing peripheral vision and a marking that only reads on +a still is not a marking the player ever sees. """ import sys +import textwrap +import numpy as np from PIL import Image, ImageDraw SKY = (158, 184, 219) @@ -17,12 +25,16 @@ PAD, LBL = 10, 16 STRIP = ("swoop", "flank", "rear34") SIZES = (64, 48, 32) CELL = 112 +GUTTER = 150 def over_sky(p, bg=SKY): im = Image.open(p).convert("RGBA") out = Image.new("RGB", im.size, bg) out.paste(im, (0, 0), im) + a = im.getchannel("A") + bb = a.getbbox() # the SUBJECT's extent — motion blur is scaled to the bird + out.info["subject"] = bb or (0, 0, im.width, im.height) return out @@ -35,11 +47,95 @@ def load(path): return views +def motion_blur(im, frac): + """Linear horizontal smear whose length is `frac` × the SUBJECT's on-screen width. + + A true average of N sub-frame positions, not a gaussian: that is what a shutter integrates and + it is what decides whether a 5 cm white wing bar survives being dragged across its own body. + """ + bb = im.info.get("subject", (0, 0, im.width, im.height)) + span = max(1, int(round(frac * (bb[2] - bb[0])))) + if span < 2: + return im + pad = span // 2 + 2 + a = np.asarray(Image.new("RGB", (im.width + 2 * pad, im.height), SKY), dtype=np.float32).copy() + a[:, pad:pad + im.width] = np.asarray(im, dtype=np.float32) + n = min(96, span) + acc = np.zeros_like(a) + for i in range(n): + off = int(round((i / (n - 1) - 0.5) * span)) + acc += np.roll(a, off, axis=1) + acc /= n + out = Image.fromarray(acc[:, pad:pad + im.width].astype("uint8")) + out.info["subject"] = bb + return out + + +def ab_sheet(out_path, title, rows, notes): + """One line per candidate, stacked, still and then moving. Built for a ruling, not a gallery.""" + w, h = next(iter(rows[0][1].values())).size + ncol = max(len(v) for _, v in rows) + cols = [(n, s) for n in STRIP for s in SIZES] + blocks = [("AT THE SIZE IT IS ACTUALLY SEEN — still (rendered px, magnified NEAREST)", 0.0), + ("MOVING — smear = 25% of the bird's width (the approach: ~0.11 m/frame at 60 fps)", 0.25), + ("MOVING — smear = 100% of the bird's width (the pass: swoop covers 34 m in 1.25 s " + "⇒ 0.45 m/frame, ~1 body length)", 1.0)] + W = max(PAD + ncol * (w + PAD), GUTTER + len(cols) * (CELL + PAD) + PAD) + H = (24 + len(rows) * (h + LBL + PAD) + + len(blocks) * (LBL + 14 + len(rows) * (CELL + LBL + 4)) + PAD + + LBL * (sum(max(1, len(l) // 300 + 1) for l in notes) * 3 + 2)) + sheet = Image.new("RGB", (W, H), (24, 24, 26)) + d = ImageDraw.Draw(sheet) + d.text((PAD, 5), title, fill=(240, 240, 240)) + y = 24 + for label, views in rows: + d.text((PAD, y), label, fill=(250, 210, 120)) + y += LBL + for i, (n, im) in enumerate(views.items()): + x = PAD + i * (w + PAD) + sheet.paste(im, (x, y)) + d.text((x + 4, y + 2), n, fill=(40, 40, 40)) + y += h + PAD + for head, frac in blocks: + d.text((PAD, y), head, fill=(250, 210, 120)) + y += LBL + for i, (n, s) in enumerate(cols): + d.text((GUTTER + i * (CELL + PAD) + 3, y), f"{n} {s}px", fill=(175, 175, 175)) + y += 14 + for label, views in rows: + d.text((PAD, y + CELL // 2 - 6), label[:22], fill=(225, 225, 225)) + for i, (n, s) in enumerate(cols): + if n not in views: + continue + src = motion_blur(views[n], frac) if frac else views[n] + sheet.paste(src.resize((s, s), Image.LANCZOS).resize((CELL, CELL), Image.NEAREST), + (GUTTER + i * (CELL + PAD), y)) + y += CELL + LBL + 4 + y += 4 + for line in notes: + for part in textwrap.wrap(line, width=max(60, (W - 2 * PAD) // 6)) or [""]: + d.text((PAD, y), part, fill=(190, 190, 190)) + y += LBL + sheet = sheet.crop((0, 0, W, min(sheet.height, y + PAD))) # the height estimate over-reserves + sheet.save(out_path) + print(f"ab sheet -> {out_path} {sheet.size}") + + def main(): out_path, title = sys.argv[1], sys.argv[2] rows = [] args = sys.argv[3:] extra = None + notes = [] + if "--note" in args: # --note "line" ["line" ...] : footer, always last + i = args.index("--note") + notes = args[i + 1:] + args = args[:i] + if "--ab" in args: + args.remove("--ab") + for i in range(0, len(args), 2): + rows.append((args[i], load(args[i + 1]))) + return ab_sheet(out_path, title, rows, notes) if "--extra" in args: # --extra IMG.png "caption": pasted under the sheet i = args.index("--extra") extra = (args[i + 1], args[i + 2])