let my={} function init(){let version='0.94' my.drag={n:0,onQ:false,holdX:0,holdY:0} my.mode=getJSQueryVar('mode','pent-pyramid') this.curvyQ=['cone','cylinder','sphere','hemisphere'].indexOf(my.mode)>=0 this.flatyQ=['plane','coplanar'].indexOf(my.mode)>=0 my.pointsQ=false my.wd=450 my.ht=450 let s='' s+='' s+='' if(this.curvyQ||this.flatyQ){}else{s+='' s+='
' s+='Coloring: ' s+=getDropdownHTML(['Multi','Shaded','Two','Glass','PureGlass','Beams'],'clrChg','clrType') s+='
'} if(my.mode=='coplanar'){my.pointsQ=true my.mode='3 points' s+='
' s+='Type: ' s+=getDropdownHTML(['3 points','4 coplanar points','4 points','6 coplanar points','6 points'],'coplanarChg','coplanarType') s+='
'} s+=wrap({cls:'copyrt',pos:'abs',style:'left:5px; bottom:3px'},`© 2022 Rod Pierce v${version}`) s=wrap({cls:'js',style:'width:'+my.wd+'px; height:'+my.ht+'px;'},s) docInsert(s) my.can=new Can('canvasId',my.wd,my.ht,2) this.transMat=[[1,0,0],[0,1,0],[0,0,1],[0,0,0],] this.f=500 this.shapes=[] this.clrs=['#ff0000','#0000ff','#ff9900','#00ff00','#ffff00','#660066','#99ff00','#0099ff','#00ff99','#9900ff','#ff0099','#006666','#666600','#990000','#009999','#999900','#003399','#ff00ff','#993333','#330099'] this.explodeQ=false my.dragModeQ=false my.drag.onQ=false my.drag.holdX=0 my.drag.holdY=0 this.poly=new Poly() xAngle=2 yAngle=4 zAngle=0 let el=my.can.el el.addEventListener('touchstart',ontouchstart,false) el.addEventListener('touchmove',ontouchmove,false) el.addEventListener('mousedown',onmouseDown,false) el.addEventListener('mousemove',onmouseMove,false) el.addEventListener('mouseup',onmouseUp,false) stt()} function ontouchstart(ev){my.drag.onQ=true let touch=ev.targetTouches[0] let[mouseX,mouseY]=my.can.mousePos(ev) my.drag.holdX=mouseX my.drag.holdY=mouseY} function ontouchmove(ev){let touch=ev.targetTouches[0] ev.clientX=touch.clientX ev.clientY=touch.clientY ev.touchQ=true onmouseMove(ev) ev.preventDefault()} function onmouseDown(ev){my.drag.onQ=true let[mouseX,mouseY]=my.can.mousePos(ev) my.drag.holdX=mouseX my.drag.holdY=mouseY} function onmouseUp(ev){my.drag.onQ=false} function onmouseMove(ev){let[mouseX,mouseY]=my.can.mousePos(ev) if(my.dragModeQ){if(my.drag.onQ){settransMat(-(my.drag.holdY-mouseY)*3,(my.drag.holdX-mouseX)*3,0,transMat) my.drag.holdX=mouseX my.drag.holdY=mouseY update()}}else{yAngle=-(mouseX-my.wd/2)/25 xAngle=(mouseY-my.ht/2)/25}} function toggleDrag(){my.dragModeQ=!my.dragModeQ toggleBtn('dragBtn',my.dragModeQ) if(my.dragModeQ){document.getElementById('dragBtn').innerHTML='Drag'}else{document.getElementById('dragBtn').innerHTML='Spin'}} function toggleExplode(){this.explodeQ=!this.explodeQ toggleBtn('explodeBtn',this.explodeQ) restart()} function toggleBtn(btn,onq){if(onq){document.getElementById(btn).classList.add('hi') document.getElementById(btn).classList.remove('lo')}else{document.getElementById(btn).classList.add('lo') document.getElementById(btn).classList.remove('hi')}} function getDropdownHTML(opts,funcName,id){let s='' s+='' return s} function clrChg(){let el=document.getElementById('clrType') if(el.selectedIndex==-1)return null let t=el.options[el.selectedIndex].text setClrs(t) update()} function coplanarChg(){let el=document.getElementById('coplanarType') if(el.selectedIndex==-1)return null let t=el.options[el.selectedIndex].text my.mode=t restart()} function getClrType(){if(this.curvyQ||this.flatyQ){if(my.mode=='plane'){return 'Glass'}else{return 'Shaded'}}else{let div=document.getElementById('clrType') if(div.selectedIndex==-1)return 'Multi' return div.options[div.selectedIndex].text}} function stt(){shapes=[] poly.shapeType=my.mode setShapesFromPoly() settransMat(200,50,0,transMat) my.can.clear() drawShapes() this.frameNo=0 animate()} function restart(){shapes=[] poly.shapeType=my.mode setShapesFromPoly() update()} function animate(){this.frameNo++ if(my.dragModeQ){}else{settransMat(xAngle,yAngle,zAngle,transMat) update()} if(this.frameNo<1e8){requestAnimationFrame(animate)}} function update(){my.can.clear() drawShapes()} function drawShapes(){let prevDepth=0 let sortNeededQ=false for(let i=0,len=shapes.length;i0){if(shape.depth>0)+1 let grn=((dark*255)>>0)+1 angle=this.getNormalAngle(this.pts,1) dark=1-angle/Math.PI let blu=((dark*255)>>0)+1 this.fillClr='rgba('+red+','+grn+','+blu+','+alpha+')'} Shape3D.prototype.getNormalAngle=function(pts,dimN){if(pts.length<3)return 0 let a=[pts[1].x-pts[0].x,pts[1].y-pts[0].y,pts[1].z-pts[0].z] let b=[pts[2].x-pts[1].x,pts[2].y-pts[1].y,pts[2].z-pts[1].z] let cross=[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]] let mag=Math.sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2]) let theta=Math.acos(cross[dimN]/mag) return theta} Shape3D.prototype.calcCentroid=function(){centroid=new Pt3d() for(let i=0;i0){centroid.x/=this.pts.length centroid.y/=this.pts.length centroid.z/=this.pts.length}} Shape3D.prototype.drawsurface=function(aboutEyeQ,viewType){let g=my.can.g g.lineJoin='round' let xsum=0 let ysum=0 let zsum=0 let clips=[] let zMin=Number.MAX_VALUE let zMax=-Number.MAX_VALUE let i=0 let ptRot while(i2){g.beginPath() for(i=0,len=pt2s.length;i{if(cls.length==0)cls='btn' return '