moebius gears

getting the turtle into gears... ;-)
derived from "moebius gears" shaderoo.org/?shader=3gqsg3
by (sloppily) sorting polys in z-direction
and then using reinder's occlusion magic from "Cubic space division #2"

Log in to post a comment.

@reinder: thanks! yes, i stripped away the obsoloete 'magic' :-)
Super cool! (but you only need a fraction of the code you copy-pasted for the occlusion 'magic' :))
// created by florian berger (flockaroo) - 2018
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// derived from "moebius gears" https://www.shaderoo.org/?shader=3GQsG3
// by (sloppily) sorting polys in z-direction (center only)
// and then using reinder's occlusion magic from "Cubic space division #2"
Canvas.setpenopacity(1.);
// Global code will be evaluated once.
const turtle = new Turtle();
const polygonList = [];
const quads = [];
const PI2 = Math.PI*2.0;
const GEAR_NUM = 9;
const TOOTH_NUM = 15;
const GEAR_W = .25;
const GEAR_H = .2;
const GEAR_INNER = .65;
const MOEB_R = 2.;
const TSPEED = 1.;
const RSPEED = 1.;
const iTime = 0.011; // hmm, some occlusion errors occur on some angles in iTime=0
function mcos(x) {
return Math.cos(x);
}
function msin(x) {
return Math.sin(x);
}
function cos2(x) {
return [Math.cos(x[0]),Math.cos(x[1])];
}
function sin2(x) {
return [Math.sin(x[0]),Math.sin(x[1])];
}
function SC(x) {
return [Math.sin(x),Math.cos(x)];
}
function add3(a,b) {
return [a[0]+b[0],a[1]+b[1],a[2]+b[2]];
}
function sub3(a,b) {
return [a[0]-b[0],a[1]-b[1],a[2]-b[2]];
}
function dot3(a,b) {
return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
}
function scale3(a,b) {
return [a[0]*b,a[1]*b,a[2]*b];
}
function mymix(a,b,f) {
return a*(1.0-f)+b*f;
}
function length3(a) {
return Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
}
function normalize3(a) {
return scale3(a,1.0/length3(a));
}
function cross(a,b) {
return [
a[1]*b[2]-b[1]*a[2],
a[2]*b[0]-b[2]*a[0],
a[0]*b[1]-b[0]*a[1]
];
}
function inverseQuat(q)
{
//return vec4(-q.xyz,q.w)/length(q);
// if already normalized this is enough
return [-q[0],-q[1],-q[2],q[3]];
}
function multQuat(a,b)
{
//return vec4(cross(a.xyz,b.xyz) + a.xyz*b.w + b.xyz*a.w, a.w*b.w - dot(a.xyz,b.xyz));
var v=add3(add3(cross(a,b), scale3(a,b[3])), scale3(b,a[3]));
var w=a[3]*b[3]-dot3(a,b);
return [v[0],v[1],v[2],w];
}
function transformVecByQuat( v, q )
{
//return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w*v );
return add3(v, scale3(cross( q, add3(cross( q, v ) , scale3(v,q[3]) )) ,2.0));
}
function axAng2Quat(ax, ang)
{
//return vec4(normalize(ax),1)*sin(vec2(ang*.5)+vec2(0,PI2*.25)).xxxy;
var s=sin2([ang*0.5,ang*0.5+PI2*0.25]);
var nax=normalize3(ax);
return [nax[0]*s[0],nax[1]*s[0],nax[2]*s[0],s[1]];
}
const GEAR_SEG_NUM = 60;
const GEAR_TRI_NUM = (GEAR_SEG_NUM*8);
const inuAll=[
[1,0,1],
[1,1,1],
[0,0,1],
[1,1,1],
[0,1,1],
[0,0,1],
[0,0,1],
[0,1,1],
[0,0,0],
[0,1,1],
[0,1,0],
[0,0,0],
[0,0,0],
[0,1,0],
[1,0,0],
[0,1,0],
[1,1,0],
[1,0,0],
[1,0,0],
[1,1,0],
[1,0,1],
[1,1,0],
[1,1,1],
[1,0,1]
];
function gearPos(idx)
{
var idx24=idx%(8*3);
var ang0=PI2/(GEAR_SEG_NUM)*Math.floor(idx/24);
var ang1=PI2/(GEAR_SEG_NUM)*Math.floor(idx/24+1);
var ri = GEAR_INNER;
var rin = GEAR_INNER;
var ro = 1.0+GEAR_H*.5*Math.cos(ang0*(TOOTH_NUM));
var ron = 1.0+GEAR_H*.5*Math.cos(ang1*(TOOTH_NUM));
var w = GEAR_W;
var quadIdx=Math.floor(idx24/6);
var inu=inuAll[idx24];
var r = mymix(mymix(ro,ron,inu[1]),mymix(ri,rin,inu[1]),inu[0]);
var ang = mymix(ang0,ang1,inu[1]);
var z = mymix(-w,w,inu[2]);
return [msin(ang)*r,mcos(ang)*r,z];
}
function gearsTri(idx)
{
var gear=Math.floor(idx/(GEAR_TRI_NUM*3));
var gidx=Math.floor(idx%(GEAR_TRI_NUM*3));
var dang=PI2/(GEAR_NUM-.5);
var R=MOEB_R;
var ang=gear*dang;
if(ang>PI2*2.) ang-=PI2*2.;
if(ang<0.0) ang+=PI2*2.;
var s=(Math.floor(ang/dang+.01)%2)*2.-1.;
var r=R*Math.tan(dang*.5);
// radial offset of gears is different depending if lying or upright
//R*(1+tan(dang*.5)*GEAR_W*.5) in upright case
//R/cos(dang*.5) in lying case
var pos=scale3([Math.cos(ang),Math.cos(ang+PI2*.25),0],
mymix(R*(1.+Math.tan(dang*.5)*GEAR_W*.5),
R/Math.cos(dang*.5),
-Math.cos(ang*.5+iTime*TSPEED)*.5+.5
)*1.02);
var quat=[0,.707107,0,.707107];
quat=multQuat(quat,axAng2Quat([1,0,0],2.*Math.sin(iTime*1.5*RSPEED)*s));
quat=multQuat(quat,axAng2Quat([0,1,0],ang*.25+iTime*.5*TSPEED));
quat=multQuat(quat,axAng2Quat([0,0,1],ang));
if(gear>GEAR_NUM*2) return [0,0,0];
return add3(pos,transformVecByQuat(scale3(gearPos(gidx),r),inverseQuat(quat)));
}
function rotX(ph,v) {
return [ v[0],v[1]*mcos(ph)+v[2]*msin(ph), v[2]*mcos(ph)-v[1]*msin(ph) ];
}
function project(p)
{
p[2]+=180;
return [p[0]/p[2]*180.,p[1]/p[2]*180.,p[2]];
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6561 chars