PageSourceSearch

https://starwarsdatabase.com/gallery/src/robots/robot-01.js?v=0.67.1&greeting=3

js starwarsdatabase.com collected 2026-10-07 19:30:11 UTC 7,360 bytes, 88 lines download raw bytes

1import * as THREE from '../../assets/vendor/three.module.js';
2
3export const ROBOT_01 = Object.freeze({id:'robot-01',name:'Robot 01',height:1.05,radius:.4,reservation:1.2,maxTriangles:2500,maxDrawCalls:12,maxMaterials:4});
4const C={ivory:0xded6c5,blue:0x4f6478,bronze:0x827354,dark:0x303a34};
5const rad=THREE.MathUtils.degToRad;
6const finite=(n,fallback=0)=>Number.isFinite(n)?n:fallback;
7const clamp=(n,lo,hi)=>THREE.MathUtils.clamp(finite(n),lo,hi);
8
9// Four bevel rings, flat normals, no texture or external model dependency.
10function shell(w,h,d,bevel=.01,taper=1){
11 const positions=[],rings=[];
12 for(const [z,inset] of [[-d/2,bevel],[-d/2+bevel,0],[d/2-bevel,0],[d/2,bevel]]){
13  const x=w/2-inset,y=h/2-inset,c=Math.min(bevel*1.5,x*.3,y*.3);
14  rings.push([[-x+c,-y], [x-c,-y], [x,-y+c], [x,y-c], [x-c,y],[-x+c,y],[-x,y-c],[-x,-y+c]].map(([px,py])=>[px*(taper+(1-taper)*(py+h/2)/h),py,z]));
15 }
16 const tri=(a,b,c)=>positions.push(...a,...b,...c);
17 for(let j=0;j<3;j++)for(let i=0;i<8;i++){const n=(i+1)%8;tri(rings[j][i],rings[j][n],rings[j+1][n]);tri(rings[j][i],rings[j+1][n],rings[j+1][i]);}
18 for(let i=0;i<8;i++){const n=(i+1)%8;tri([0,0,-d/2],rings[0][n],rings[0][i]);tri([0,0,d/2],rings[3][i],rings[3][n]);}
19 const g=new THREE.BufferGeometry();g.setAttribute('position',new THREE.Float32BufferAttribute(positions,3));g.computeVertexNormals();return g;
20}
21function cylinder(r,len,axis='y'){const g=new THREE.CylinderGeometry(r,r,len,12,1,false);if(axis==='x')g.rotateZ(Math.PI/2);if(axis==='z')g.rotateX(Math.PI/2);return g;}
22function piece(g,color,x=0,y=0,z=0,rotation=null){if(rotation){g.rotateX(rotation[0]||0);g.rotateY(rotation[1]||0);g.rotateZ(rotation[2]||0);}g.translate(x,y,z);return {g,color};}
23function bar(a,b,width,depth,color){const va=new THREE.Vector3(...a),vb=new THREE.Vector3(...b),g=shell(width,va.distanceTo(vb),depth,.006);g.applyQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0,1,0),vb.clone().sub(va).normalize()));g.translate(...va.add(vb).multiplyScalar(.5).toArray());return {g,color};}
24function merged(parts,material,name){
25 const pos=[],norm=[],colors=[];
26 for(const {g,color} of parts){const flat=g.index?g.toNonIndexed():g,c=new THREE.Color(color),p=flat.attributes.position,n=flat.attributes.normal;pos.push(...p.array);norm.push(...n.array);for(let i=0;i<p.count;i++)colors.push(c.r,c.g,c.b);if(flat!==g)flat.dispose();g.dispose();}
27 const g=new THREE.BufferGeometry();g.setAttribute('position',new THREE.Float32BufferAttribute(pos,3));g.setAttribute('normal',new THREE.Float32BufferAttribute(norm,3));g.setAttribute('color',new THREE.Float32BufferAttribute(colors,3));g.computeBoundingSphere();const m=new THREE.Mesh(g,material);m.name=name;m.castShadow=false;m.receiveShadow=true;return m;
28}
29
30// Each instance owns its resources; disposing one never invalidates another.
31// Joint contract is intentionally narrower than the maximum shared contract.
32export function createRobot01(){
33 const root=new THREE.Group();root.name=ROBOT_01.name;root.userData.robotId=ROBOT_01.id;
34 const painted=new THREE.MeshStandardMaterial({vertexColors:true,metalness:.12,roughness:.43});
35 const metal=new THREE.MeshStandardMaterial({vertexColors:true,metalness:.8,roughness:.32});
36 const eyesMaterial=new THREE.MeshStandardMaterial({vertexColors:true,metalness:0,roughness:.55});
37 const put=(parent,parts,material,name)=>{const mesh=merged(parts,material,name);parent.add(mesh);return mesh;};
38 const base=[],baseMetal=[];
39 for(const side of [-1,1]){
40  base.push(piece(shell(.145,.09,.23,.012,.92),C.blue,side*.099,.045,.035));
41  base.push(piece(shell(.085,.22,.095,.009,.82),C.ivory,side*.099,.185,-.012));
42  baseMetal.push(piece(cylinder(.039,.034,'x'),C.bronze,side*.106,.298,0));
43 }
44 baseMetal.push(piece(shell(.21,.1,.13,.009,.72),C.bronze,0,.335,0));
45 put(root,base,painted,'Fixed feet and legs');put(root,baseMetal,metal,'Hip joints');
46 const torso=new THREE.Group();torso.name='Torso pivot';torso.position.y=.385;root.add(torso);
47 put(torso,[piece(shell(.30,.405,.19,.012,.70),C.ivory,0,.2075,0),piece(shell(.235,.325,.012,.005,.70),C.blue,0,.222,.102)],painted,'Ivory torso and slate chest');
48 const chest=[];for(let i=0;i<3;i++)chest.push(piece(shell(.098-i*.008,.014,.011,.002),C.bronze,0,.278-i*.037,.116));
49 put(torso,chest,metal,'Three bronze chest vents');
50 const head=new THREE.Group();head.name='Head pivot';head.position.y=.445;torso.add(head);
51 put(head,[piece(cylinder(.036,.07),C.bronze,0,.017,0)],metal,'Swivel neck');
52 put(head,[piece(shell(.36,.20,.17,.016),C.ivory,0,.120,0),piece(shell(.307,.141,.009,.008),C.dark,0,.12,.088)],painted,'Chamfered head and dark face');
53 const eyes=new THREE.Group();eyes.name='Following eyes';head.add(eyes);
54 put(eyes,[-1,1].map(s=>piece(shell(.036,.038,.006,.003),C.ivory,s*.077,.125,.096)),eyesMaterial,'Square ivory optics');
55 const arms=[];
56 for(const side of [-1,1]){
57  const arm=new THREE.Group();arm.name=side===-1?'Greeting arm':'Resting arm';arm.position.set(side*.179,.343,0);torso.add(arm);arms.push(arm);
58  const elbow=[side*.014,-.122,.004],wrist=side===-1?[side*.003,-.071,.125]:[side*.014,-.244,.025];
59  const parts=[bar([side*.016,-.013,0],elbow,.065,.063,C.blue),bar(elbow,wrist,.073,.066,C.ivory)];
60  const hand=new THREE.Vector3(...wrist),direction=new THREE.Vector3(...wrist).sub(new THREE.Vector3(...elbow)).normalize(),end=hand.clone().addScaledVector(direction,.064);
61  for(const dx of [-.023,.023]){const a=hand.clone().add(new THREE.Vector3(dx,0,0)),b=end.clone().add(new THREE.Vector3(dx,0,0));parts.push(bar(a.toArray(),b.toArray(),.018,.026,C.ivory));}
62  put(arm,parts,painted,side===-1?'Bent greeting arm and gripper':'Resting arm and gripper');
63  put(arm,[piece(cylinder(.040,.050,'x'),C.bronze,side*.009,0,0),piece(cylinder(.025,.075,'x'),C.bronze,...elbow)],metal,'Shoulder and elbow 
63joints');
64 }
65 let disposed=false,time=0,greeting=-1;
66 function pose({headYaw=0,headPitch=0,torsoYaw=0,armLift=0,eyeYaw=0,eyePitch=0,tilt=-3}={}){
67  if(disposed)return;
68  torso.rotation.y=rad(clamp(torsoYaw,-15,15));head.rotation.set(rad(clamp(headPitch,-15,15)),rad(clamp(headYaw,-50,50)),rad(clamp(tilt,-3,3)),'YXZ');
69  arms[0].rotation.x=-rad(clamp(armLift,0,25));arms[1].rotation.x=0;
70  eyes.position.set(clamp(eyeYaw,-1,1)*.008,clamp(eyePitch,-1,1)*.006,0);
71  root.updateMatrixWorld(true);
72 }
73 function update(dt,{active=true,reducedMotion=false,target=null}={}){
74  if(disposed)return false;
75  if(reducedMotion){greeting=-1;pose();return false;}
76  if(!active)return false;
77  time+=clamp(dt,0,.05);
78  let wave=0,nod=0;
79  if(greeting>=0){greeting+=clamp(dt,0,.05);if(greeting>=1.8*3)greeting=-1;else{const phase=greeting%1.8;wave=Math.sin(Math.PI*phase/1.8);nod=Math.sin(Math.PI*2*phase/1.8)*4;}}
80  const yaw=target?clamp(target.yaw,-50,50):Math.sin(time*.32)*5;
81  const pitch=target?clamp(target.pitch,-11,11):0;
82  pose({headYaw:yaw,headPitch:pitch+nod,armLift:wave*21,eyeYaw:yaw/50,eyePitch:-pitch/15,tilt:-3+Math.sin(time*.24)*.6});return true;
83 }
84 function greet(){if(disposed)return false;greeting=0;return true;}
85 function reset(){time=0;greeting=-1;pose();}
86 function dispose(){if(disposed)return;disposed=true;root.removeFromParent();root.traverse(o=>{if(o.isMesh)o.geometry.dispose();});for(const m of [painted,metal,eyesMaterial])m.dispose();root.clear();}
87 reset();return {root,pose,update,greet,reset,dispose,spec:ROBOT_01};
88}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.