axonis22 commited on
Commit
2ca5229
·
verified ·
1 Parent(s): 0841fbb

Muse Engine 32 WebGL2 release candidate

Browse files
game/muse-authored/phase30/raw/PHASE30-NOTES.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ Phase 30 scene loading approach: import file -> MuseSceneUnits.decide to get scale/rotation -> apply matrix to vertices -> build MuseMeshCollider from non-indexed triangles.
2
+ Limits: uniform XZ grid, no dynamic updates, sphere approximation for cylinder, 2D DDA stepping for raycast, 4-iteration push out.
3
+ Per frame usage: feetY = groundAtDisc(x,z,0.35, maxY). Step up allowed if newGround - feetY <=0.55 and >0.01. Mantle check up to 1.15.
4
+ Wall test: wallHit(x,z,0.35, feetY+0.3, feetY+1.8) blocks movement.
5
+ Push out: pushOut returns horizontal correction for penetration into walls.
6
+ Headroom: raycast up 1.9m from feet+0.1 to prevent spawn inside ceiling.
7
+ Spawn: findSpawn uses spiral search with groundAtDisc agreement and headroom.
8
+ No physics simulation, only static mesh queries. Keep triangles precomputed.
game/muse-authored/phase30/raw/mesh-collider.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ (function(){
2
+ function barycentricXZ(px,pz,ax,az,bx,bz,cx,cz){var v0x=bx-ax,v0z=bz-az,v1x=cx-ax,v1z=cz-az,v2x=px-ax,v2z=pz-az;var d00=v0x*v0x+v0z*v0z;var d01=v0x*v1x+v0z*v1z;var d11=v1x*v1x+v1z*v1z;var d20=v2x*v0x+v2z*v0z;var d21=v2x*v1x+v2z*v1z;var denom=d00*d11-d01*d01;if(Math.abs(denom)<1e-12)return null;var inv=1/denom;var u=(d11*d20-d01*d21)*inv;var v=(d00*d21-d01*d20)*inv;if(u>= -1e-7 && v>= -1e-7 && u+v<=1+1e-7)return [u,v];return null;}
3
+ function closestPointTri(px,py,pz,ax,ay,az,bx,by,bz,cx,cy,cz){var abx=bx-ax,aby=by-ay,abz=bz-az;var acx=cx-ax,acy=cy-ay,acz=cz-az;var apx=px-ax,apy=py-ay,apz=pz-az;var d1=abx*apx+aby*apy+abz*apz;var d2=acx*apx+acy*apy+acz*apz;if(d1<=0 && d2<=0)return [ax,ay,az];var bcx=cx-bx,bcy=cy-by,bcz=cz-bz;var bpx=px-bx,bpy=py-by,bpz=pz-bz;var d3=bcx*bpx+bcy*bpy+bcz*bpz;if(d3>=0 && d2<=d3)return [bx,by,bz];var ccx=ax-cx,ccy=ay-cy,ccz=az-cz;var cpx=px-cx,cpy=py-cy,cpz=pz-cz;var d4=ccx*cpx+ccy*cpy+ccz*cpz;if(d4>=0 && d1<=d4)return [cx,cy,cz];var vc=acx*abx+acy*aby+acz*abz;var d00=abx*abx+aby*aby+abz*abz;var d11=acx*acx+acy*acy+acz*acz;var d20=d1;var d21=d2;var denom=d00*d11-vc*vc;if(Math.abs(denom)<1e-12)denom=1e-12;var v=d11*d20-vc*d21;var w=vc*d20-d00*d21;if(v>0 && w>0 && v+w<=d00*d11){var inv=1/denom;v*=inv;w*=inv;return [ax+abx*v+acx*w, ay+aby*v+acy*w, az+abz*v+acz*w];}var v=d1/d00;if(v>=0 && v<=1){var px1=ax+abx*v,py1=ay+aby*v,pz1=az+abz*v;return [px1,py1,pz1];}var w=-d4/(ccx*ccx+ccy*ccy+ccz*ccz);if(w>=0 && w<=1){var px1=cx+ccx*w,py1=cy+ccy*w,pz1=cz+ccz*w;return [px1,py1,pz1];}var w=-d3/(bcx*bcx+bcy*bcy+bcz*bcz);if(w>=0 && w<=1){var px1=bx+bcx*w,py1=by+bcy*w,pz1=bz+bcz*w;return [px1,py1,pz1];}return [ax,ay,az];}
4
+ window.MuseMeshCollider={build:function(positions,opts){opts=opts||{};var cell=opts.cell||2.0;var walkableNy=opts.walkableNy!==undefined?opts.walkableNy:0.7;var n=positions.length/9|0;var triN=new Float32Array(n*3),triMinY=new Float32Array(n),triMaxY=new Float32Array(n),triMinX=new Float32Array(n),triMaxX=new Float32Array(n),triMinZ=new Float32Array(n),triMaxZ=new Float32Array(n),walkable=new Uint8Array(n);var min=[Infinity,Infinity,Infinity],max=[-Infinity,-Infinity,-Infinity];for(var i=0;i<n;i++){var b=i*9;var x0=positions[b],y0=positions[b+1],z0=positions[b+2];var x1=positions[b+3],y1=positions[b+4],z1=positions[b+5];var x2=positions[b+6],y2=positions[b+7],z2=positions[b+8];if(x0===x1||y0===y1||z0===z1){triN[i*3+1]=-2;continue;}var e1x=x1-x0,e1y=y1-y0,e1z=z1-z0;var e2x=x2-x0,e2y=y2-y0,e2z=z2-z0;var nx=e1y*e2z-e1z*e2y,ny=e1z*e2x-e1x*e2z,nz=e1x*e2y-e1y*e2x;var len=Math.hypot(nx,ny,nz);if(len<1e-10){triN[i*3+1]=-2;continue;}nx/=len;ny/=len;nz/=len;triN[i*3]=nx;triN[i*3+1]=ny;triN[i*3+2]=nz;var mnx=Math.min(x0,x1,x2),mxx=Math.max(x0,x1,x2);var mnz=Math.min(z0,z1,z2),mxz=Math.max(z0,z1,z2);var mny=Math.min(y0,y1,y2),mxy=Math.max(y0,y1,y2);triMinX[i]=mnx;triMaxX[i]=mxx;triMinZ[i]=mnz;triMaxZ[i]=mxz;triMinY[i]=mny;triMaxY[i]=mxy;walkable[i]=ny>=walkableNy?1:0;min[0]=Math.min(min[0],mnx);min[1]=Math.min(min[1],mny);min[2]=Math.min(min[2],mnz);max[0]=Math.max(max[0],mxx);max[1]=Math.max(max[1],mxy);max[2]=Math.max(max[2],mxz);}var grid={};for(var i=0;i<n;i++){if(triN[i*3+1]===-2)continue;var ix0=Math.floor(triMinX[i]/cell),ix1=Math.floor(triMaxX[i]/cell);var iz0=Math.floor(triMinZ[i]/cell),iz1=Math.floor(triMaxZ[i]/cell);for(var ix=ix0;ix<=ix1;ix++){for(var iz=iz0;iz<=iz1;iz++){var k=ix+','+iz;var arr=grid[k];if(!arr){arr=[];grid[k]=arr;}arr.push(i);}}}var cells=0;for(var k in grid)cells++;var collider={stats:{tris:n,walkable:0,walls:0,cells:cells,min:min,max:max},_positions:positions,_triN:triN,_triMinY:triMinY,_triMaxY:triMaxY,_triMinX:triMinX,_triMaxX:triMaxX,_triMinZ:triMinZ,_triMaxZ:triMaxZ,_walkable:walkable,_grid:grid,_cell:cell,_walkableNy:walkableNy};for(var i=0;i<n;i++)if(walkable[i])collider.stats.walkable++;else collider.stats.walls++;collider.groundAt=function(x,z,maxY){var ix=Math.floor(x/cell),iz=Math.floor(z/cell);var k=ix+','+iz;var arr=grid[k];if(!arr)return null;var best=null;for(var j=0;j<arr.length;j++){var i=arr[j];var b=i*9;var x0=positions[b],y0=positions[b+1],z0=positions[b+2];var x1=positions[b+3],y1=positions[b+4],z1=positions[b+5];var x2=positions[b+6],y2=positions[b+7],z2=positions[b+8];var bc=barycentricXZ(x,z,x0,z0,x1,z1,x2,z2);if(!bc)continue;var u=bc[0],v=bc[1];var w=1-u-v;var y=y0*w+y1*u+y2*v;if(y>maxY)continue;if(best===null||y>best)best=y;}return best;};collider.groundAtDisc=function(x,z,r,maxY){var off=r*0.7;var ys=[];var g=collider.groundAt(x,z,maxY);if(g!==null)ys.push(g);var pts=[[x+off,z],[x-off,z],[x,z+off],[x,z-off]];for(var p=0;p<pts.length;p++){var gx=pts[p][0],gz=pts[p][1];var gg=collider.groundAt(gx,gz,maxY);if(gg!==null)ys.push(gg);}if(ys.length===0)return null;var m=ys[0];for(var k=1;k<ys.length;k++)if(ys[k]>m)m=ys[k];return m;};collider.wallHit=function(x,z,r,yMin,yMax){var step=Math.max(0.01,r*0.9);var y=yMin+r;var end=yMax-r;if(y>end)return false;while(y<=end){var ix0=Math.floor((x-r)/cell),ix1=Math.floor((x+r)/cell);var iz0=Math.floor((z-r)/cell),iz1=Math.floor((z+r)/cell);for(var ix=ix0;ix<=ix1;ix++){for(var iz=iz0;iz<=iz1;iz++){var k=ix+','+iz;var arr=grid[k];if(!arr)continue;for(var j=0;j<arr.length;j++){var i=arr[j];if(walkable[i])continue;if(triMaxY[i]<y-r||triMinY[i]>y+r)continue;var b=i*9;var ax=positions[b],ay=positions[b+1],az=positions[b+2];var bx=positions[b+3],by=positions[b+4],bz=positions[b+5];var cx=positions[b+6],cy=positions[b+7],cz=positions[b+8];var cp=closestPointTri(x,y,z,ax,ay,az,bx,by,bz,cx,cy,cz);var dx=x-cp[0],dy=y-cp[1],dz=z-cp[2];if(dx*dx+dy*dy+dz*dz < (r-1e-7)*(r-1e-7))return true;}}}y+=step;}return false;};collider.pushOut=function(x,z,r,yMin,yMax){var dx=0,dz=0;var step=Math.max(0.01,r*0.9);var y=yMin+r;var end=yMax-r;var iter=0;while(y<=end && iter<4){var ix0=Math.floor((x-r)/cell),ix1=Math.floor((x+r)/cell);var iz0=Math.floor((z-r)/cell),iz1=Math.floor((z+r)/cell);var accX=0,accZ=0;for(var ix=ix0;ix<=ix1;ix++){for(var iz=iz0;iz<=iz1;iz++){var k=ix+','+iz;var arr=grid[k];if(!arr)continue;for(var j=0;j<arr.length;j++){var i=arr[j];if(walkable[i])continue;if(triMaxY[i]<y-r||triMinY[i]>y+r)continue;var b=i*9;var ax=positions[b],ay=positions[b+1],az=positions[b+2];var bx=positions[b+3],by=positions[b+4],bz=positions[b+5];var cx=positions[b+6],cy=positions[b+7],cz=positions[b+8];var cp=closestPointTri(x,y,z,ax,ay,az,bx,by,bz,cx,cy,cz);var ddx=x-cp[0],ddz=z-cp[2];var dist=Math.hypot(ddx,ddz);if(dist<r-1e-7){var pen=r-dist;var nx=ddx/(dist||1),nz=ddz/(dist||1);accX+=nx*pen;accZ+=nz*pen;}}}}var len=Math.hypot(accX,accZ);if(len>1e-7){dx+=accX/len*0.5;dz+=accZ/len*0.5;x+=dx;z+=dz;}else break;y+=step;iter++;}return [dx,dz];};collider.raycast=function(ox,oy,oz,dx,dy,dz,maxT){var len=Math.hypot(dx,dy,dz);if(len<1e-12)return null;dx/=len;dy/=len;dz/=len;var step=Math.max(0.01,cell/2);var t=0;var best=null;var stamp=new Int32Array(n);var stampId=1;var tested=0;while(t<=maxT){var px=ox+dx*t,py=oy+dy*t,pz=oz+dz*t;var ix=Math.floor(px/cell),iz=Math.floor(pz/cell);var k=ix+','+iz;var arr=grid[k];if(arr){for(var j=0;j<arr.length;j++){var i=arr[j];if(stamp[i]===stampId)continue;stamp[i]=stampId;var b=i*9;var x0=positions[b],y0=positions[b+1],z0=positions[b+2];var x1=positions[b+3],y1=positions[b+4],z1=positions[b+5];var x2=positions[b+6],y2=positions[b+7],z2=positions[b+8];var e1x=x1-x0,e1y=y1-y0,e1z=z1-z0;var e2x=x2-x0,e2y=y2-y0,e2z=z2-z0;var pxv=ox-x0,pyv=oy-y0,pzv=oz-z0;var tvec=[0,0,0];var pvec=[dx,dy,dz];var qvec=[e1x,e1y,e1z];var det=qvec[0]*pvec[1]*e2z - qvec[0]*pvec[2]*e2y - qvec[1]*pvec[0]*e2z + qvec[1]*pvec[2]*e2x + qvec[2]*pvec[0]*e2y - qvec[2]*pvec[1]*e2x;if(Math.abs(det)<1e-7)continue;var inv=1/det;var u=(pxv*e2y - pyv*e2x)*pvec[2] - (pxv*e2z - pzv*e2x)*pvec[1];u*=inv;if(u<0||u>1)continue;var v=(qvec[0]*(pyv*e2z - pzv*e2y) - qvec[1]*(pxv*e2z - pzv*e2x) + qvec[2]*(pxv*e2y - pyv*e2x))*inv;if(v<0||u+v>1)continue;var tt=(qvec[0]*(e1y*pzv - e1z*pyv) + qvec[1]*(e1z*pxv - e1x*pzv) + qvec[2]*(e1x*pyv - e1y*pxv))*inv;if(tt<1e-7||tt>maxT)continue;if(!best||tt<best.t){var hx=ox+dx*tt,hy=oy+dy*tt,hz=oz+dz*tt;var nx=e1y*e2z-e1z*e2y,ny=e1z*e2x-e1x*e2z,nz=e1x*e2y-e1y*e2x;var nlen=Math.hypot(nx,ny,nz)||1;nx/=nlen;ny/=nlen;nz/=nlen;best={t:tt,x:hx,y:hy,z:hz,nx:nx,ny:ny,nz:nz,tri:i};}}}t+=step;stampId++;if(stampId===2147483647)for(var s=0;s<n;s++)stamp[s]=0,stampId=1;}return best;};collider.findSpawn=function(hintX,hintZ,opts){opts=opts||{};var maxY=collider.stats.max[1]+1;var best=null,bestD=Infinity;var step=0.5;var maxR= Math.max(Math.abs(collider.stats.max[0]-collider.stats.min[0]),Math.abs(collider.stats.max[2]-collider.stats.min[2]));var rings=Math.ceil(maxR/step);for(var r=0;r<=rings;r++){var rad=r*step;for(var a=0;a<4;a++){var ang=a*Math.PI/2;var x=hintX+Math.cos(ang)*rad;var z=hintZ+Math.sin(ang)*rad;if(x<collider.stats.min[0]||x>collider.stats.max[0]||z<collider.stats.min[2]||z>collider.stats.max[2])continue;var ground=collider.groundAt(x,z,maxY);if(ground===null)continue;var disc=collider.groundAtDisc(x,z,0.35,maxY);if(disc===null||Math.abs(disc-ground)>0.25)continue;if(collider.wallHit(x,z,0.35,ground+0.3,ground+1.8))continue;var head=collider.raycast(x,ground+0.1,z,0,1,0,1.9);if(head)continue;var d=Math.hypot(x-hintX,z-hintZ);if(d<bestD){bestD=d;best=[x,ground,z];}}}return best;};return collider;};})();
game/muse-authored/phase30/raw/scene-units.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ (function(){
2
+ function guessScale(size){var m=Math.max(size[0],size[1],size[2]);if(m>4000)return 0.001;if(m>400)return 0.01;return 1;}
3
+ function guessUnits(s){if(s===0.001)return 'mm';if(s===0.01)return 'cm';return 'm';}
4
+ window.MuseSceneUnits={decide:function(meta,size){var format=(meta&&meta.format)||'glb';var forcedUnits=(meta&&meta.forcedUnits)||'auto';var forcedUp=(meta&&meta.forcedUp)||'auto';var scale=1, zUp=false, upSign=1, units='m', reason='';if(forcedUnits!=='auto'){var map={'m':1,'cm':0.01,'mm':0.001,'in':0.0254,'ft':0.3048};scale=map[forcedUnits]||1;units=forcedUnits;reason='Forced units '+forcedUnits; }else if(format==='glb'||format==='gltf'){scale=1;units='m';reason='glTF/GLB is metres +Y up by spec';}else if(format==='fbx'){var usf=meta&&meta.unitScaleFactor;if(typeof usf==='number'&&usf>0){scale=usf/100;units=usf===1?'cm':usf===100?'m':usf===2.54?'in':'m';reason='FBX UnitScaleFactor '+usf+' -> x'+scale.toFixed(5)+'; UpAxis '+(meta.upAxis!==undefined?meta.upAxis:'?')+' -> rotate';}else{scale=guessScale(size);units=guessUnits(scale);reason='FBX units unknown, guessed from size '+Math.max(size[0],size[1],size[2]).toFixed(1)+' -> '+units;}var upAxis=meta&&meta.upAxis;if(upAxis===2||upAxis===undefined && format==='fbx'){zUp=true;reason+='; UpAxis Z -> rotate -90 X';}upSign=(meta&&meta.upAxisSign)||1;}else{scale=guessScale(size);units=guessUnits(scale);reason='Unknown format, guessed '+units;}if(forcedUp!=='auto'){zUp=forcedUp==='z';reason='Forced up '+forcedUp+(reason?'; '+reason:'');}return {scale:scale,zUp:zUp,upSign:upSign,units:units,reason:reason};},matrix:function(dec){var s=dec.scale||1;var m=new Float32Array(16);m[0]=1*s;m[5]=0;m[6]=0;m[9]=0;m[10]=0;m[11]=0;m[12]=0;m[13]=0;m[14]=0;m[15]=1;if(dec.zUp){var c=0,si=-1;var r=new Float32Array(16);r[0]=1;r[5]=c;r[6]=si;r[9]=si;r[10]=c;r[15]=1;var out=new Float32Array(16);for(var i=0;i<4;i++)for(var j=0;j<4;j++){var sum=0;for(var k=0;k<4;k++)sum+=r[i*4+k]*m[k*4+j];out[i*4+j]=sum;}m=out;}else{m[5]=1*s;m[10]=1*s;}if(dec.upSign===-1){m[5]*=-1;m[6]*=-1;m[7]*=-1;}return m;}};
5
+ })();