//req. pen 3d extensions
//redFrik 050703, updated for sc3.3.1 090621

//--
(
	var width= 300, height= 200, cSize= 20, i1, matrix1;
	var w, x, y, z, focalDistance, n, run= true;
	w= Window("3d test1", Rect(128, 64, width, height), false);
	u= UserView(w, Rect(0, 0, width, height));
	u.background= Color.white;
	w.onClose_({run= false});
	w.front;
	i1= 0;
	focalDistance= 130;
	n= 10;
	x= Array.series(n, 0, 0.1).dup(n).flat;
	y= Array.series(n, 0, 0.1).stutter(n);
	z= Array.series(n, 0.5, 0).dup(n).flat;
	u.drawFunc= {
		i1= (i1+0.03)%2pi;
		matrix1= Pen.mRotateY(i1);
		x.size.do{|i|
			var vector, ox, oy, oz;
			vector= [x[i], y[i], z[i]];
			vector= Pen.vectorMatrixMul(vector, matrix1);
			oz= vector[2];
			ox= focalDistance*vector[0]/(oz*cSize+width);
			oy= focalDistance*vector[1]/(oz*cSize+height);
			Pen.strokeRect(Rect(ox*width+150, oy*height+50, cSize*oz, cSize*oz));
		};
	};
	{while{run} {0.01.wait; u.refresh}}.fork(AppClock);
)

//--
(
	var width= 300, height= 300, cSize= 20, i1, i2, i3, matrix1, matrix2, matrix3;
	var w, x, y, z, focalDistance, n, run= true;
	w= Window("3d test2", Rect(128, 64, width, height), false);
	u= UserView(w, Rect(0, 0, width, height));
	u.background= Color.white;
	w.onClose_({run= false});
	w.front;
	i1= i2= i3= 0;
	focalDistance= 100;
	n= 8;
	x= Array.series(10, 0, 0.1).dup(10).flat;
	y= Array.series(10, 0, 0.1).stutter(10);
	z= Array.series(10, 0.5, 0).dup(10).flat;
	u.drawFunc= {
		i1= (i1+0.030)%2pi;
		i2= (i2+0.041)%2pi;
		i3= (i3-0.052)%2pi;
		matrix1= Pen.mRotateX(i1);
		matrix2= Pen.mRotateY(i2);
		matrix3= Pen.mRotateZ(i3);
		x.size.do{|i|
			var vector, ox, oy, oz;
			vector= [x[i], y[i], z[i]];
			vector= Pen.vectorMatrixMul(vector, matrix1);
			vector= Pen.vectorMatrixMul(vector, matrix2);
			vector= Pen.vectorMatrixMul(vector, matrix3);
			oz= vector[2];
			ox= focalDistance*vector[0]/(oz*cSize+width);
			oy= focalDistance*vector[1]/(oz*cSize+height);
			n.do{|i|
				Pen.strokeColor= Color.grey(0, n-i/n);
				Pen.strokeRect(Rect(ox*width+150, oy*height+150, cSize*oz, cSize*oz));
				if(i<(n-1), {
					Pen.rotate(1+(i*0.01), 1);
				});
			};
		};
	};
	{while{run} {0.01.wait; u.refresh}}.fork(AppClock);
)

//--
(
	var width= 300, height= 300, cSize= 20, i1, i2, i3, matrix1, matrix2, matrix3,
		fifo, del, draw, col;
	var w, x, y, z, focalDistance, n, run= true;
	w= Window("3d test3", Rect(128, 64, width, height), false);
	u= UserView(w, Rect(0, 0, width, height));
	u.background= Color.white;
	w.onClose_({run= false});
	w.front;
	i1= i2= i3= 0;
	focalDistance= 100;
	col= Color.black;
	n= 32;	//num of delays
	del= 1;	//delaytime
	x= [0, 1, 0, 1,   0,   1,   0,   1, 0.5];
	y= [0, 0, 1, 1,   0,   0,   1,   1, 0.5];
	z= [1, 1, 1, 1, 0.1, 0.1, 0.1, 0.1, 0.5];
	fifo= Array.fill(n*del, {Array.fill(x.size, {#[0, 0, 0]})});
	draw= Array.fill(x.size, {#[0, 0, 0]});
	u.drawFunc= {
		cSize= cSize+0.1;
		if(cSize>200, {cSize= 20});
		i1= (i1+0.030)%2pi;
		i2= (i2+0.041)%2pi;
		i3= (i3-0.052)%2pi;
		matrix1= Pen.mRotateX(i1);
		matrix2= Pen.mRotateY(i2);
		matrix3= Pen.mRotateZ(i3);
		x.size.do{|i|				//for all objects
			var vector, ox, oy, oz;
			vector= [x[i], y[i], z[i]];
			vector= Pen.vectorMatrixMul(vector, matrix1);
			vector= Pen.vectorMatrixMul(vector, matrix2);
			vector= Pen.vectorMatrixMul(vector, matrix3);
			oz= vector[2];
			ox= focalDistance*vector[0]/(oz*cSize+width);
			oy= focalDistance*vector[1]/(oz*cSize+height);
			fifo[fifo.size-1][i]= [ox, oy, oz];
		};
		fifo= fifo.rotate(1);
		Pen.strokeColor= col.alpha_(1);
		n.do{|i|							//for all delays
			x.size.do{|j|					//for all objects
				var size, thisDraw;
				thisDraw= fifo[i*del][j];
				size= thisDraw[2]*cSize;
				Pen.strokeRect(Rect(thisDraw[0]*width+150, thisDraw[1]*height+150, size, size));
			};
			if(i<(n-1), {
				Pen.scale(i*0.001+1, 1);
				Pen.strokeColor= col.alpha_((n-i/n).linexp(0, 1, 0.05, 0.5));
			});
		};
	};
	{while{run} {0.01.wait; u.refresh}}.fork(AppClock);
)

//--
(
	var width= 400, height= 400, i1, i2, i3, matrix1, matrix2, matrix3,
		fifo, del, draw, col;
	var w, x, y, z, focalDistance, n, run= true;
	w= Window("3d test4", Rect(128, 64, width, height), false);
	u= UserView(w, Rect(0, 0, width, height));
	u.background= Color.white;
	w.onClose_({run= false});
	w.front;
	i1= i2= i3= 0;
	focalDistance= 100;
	col= Color.black;
	n= 36;	//num of delays
	del= 6;	//delaytime
	x= #[0.5, 1, 0, 1,   0,   1,   0,   1, 0.5];
	y= #[0.5, 0, 1, 1,   0,   0,   1,   1, 0.5];
	z= #[  1, 1, 1, 1, 0.1, 0.1, 0.1, 0.1, 0.5];
	fifo= Array.fill(n*del, {Array.fill(x.size, {#[0, 0, 0]})});
	draw= Array.fill(x.size, {#[0, 0, 0]});
	u.drawFunc= {
		i1= (i1+0.030)%2pi;
		i2= (i2+0.041)%2pi;
		i3= (i3-0.052)%2pi;
		matrix1= Pen.mRotateX(i1);
		matrix2= Pen.mRotateY(i2);
		matrix3= Pen.mRotateZ(i3);
		x.size.do{|i|				//for all objects
			var vector, ox, oy, oz;
			vector= [x[i], y[i], z[i]];
			vector= Pen.vectorMatrixMul(vector, matrix1);
			vector= Pen.vectorMatrixMul(vector, matrix2);
			vector= Pen.vectorMatrixMul(vector, matrix3);
			oz= vector[2];
			ox= focalDistance*vector[0]/(oz+width);
			oy= focalDistance*vector[1]/(oz+height);
			fifo[fifo.size-1][i]= [ox, oy, oz];
		};
		fifo= fifo.rotate(1);
		Pen.strokeColor= col.alpha_(1);
		n.do{|i|							//for all delays
			Pen.moveTo(Point(width/2, height/2));
			x.size.do{|j|					//for all objects
				var size, thisDraw;
				thisDraw= fifo[i*del][j];
				size= thisDraw[2];
				Pen.lineTo(Point(thisDraw[0]*width+(width/2), thisDraw[1]*height+(height/2)));
			};
			Pen.stroke;
			if(i<(n-1), {
				Pen.rotate(i*0.0001+0.015, i*0.00011+0.011);
				Pen.scale(i*0.0001+1.012, i*(-0.00009)+1.001);
				Pen.strokeColor= col.alpha_((n-i/n).linexp(0, 1, 0.05, 0.6));
			});
		};
	};
	{while{run} {0.01.wait; u.refresh}}.fork(AppClock);
)