xxxxxxxxxx
388
// Elout de Kok
// wip - last changed January 11 2023
// the matrix functions seems complixated
// but it's 'common'tech and math that is used for years now
// for you to play with!
// ok let's go!
//-------------------------------------------------------------
//
// very basic soft3D engine - no z-sorting yet!
// my image width and height
let im_w=1024; // image width - you can change the image size
let im_h=1024; // image height
// draw your image in (smaller) steps - better for fps and performance
let my_anim = 0;
let my_counter=0;
let do_once=0; // for the fxpreview
// start my sketch here - init
function setup()
{
// fxrand() and fxpreview(); are declared in my index.html !!!!
// sableRaph fxhash fix for non-determinism creeping into your sketch.
// some other p5 functions besides math.random
// also can use a kind random/noise
// https://twitter.com/sableRaph/status/1543551191283630081
Math.random=fxrand;
randomSeed(fxrand()*999999);
noiseSeed(fxrand()*999999);
// putting the density on 1
// colors between 0 and 255 now?
pixelDensity(1);
createCanvas(im_w, im_h); // now create my canvas
}
// start animation
function draw() //--------------------------------start anim
{
//------------------------
// start my drawing/anim here
if(my_anim==0)
{
//--- clear the screen with a lighter grey color ---
let my_grey= 150 + my_random_int(100);
background(my_grey); // grey // or like red, green, blue
my_anim=1; // now go next in the anim loop
}
//------------------------
//draw a 3D square
else if(my_anim==1)
{
// not sure/// better do it in vanilla javascript first? -___- ^____^
// 0 1
//
//
// 3 2
// not optimised, but this is for the example!
var my_x = [-1, 1, 1, -1 ];
var my_y = [-1,-1, 1, 1 ];
var my_z = [ 0, 0, 0, 0 ];
// my 3D model
// I don't change this base model; keep it as base-reference!
var x1 = my_x[0]; var y1 = my_y[0]; var z1 = my_z[0];
var x2 = my_x[1]; var y2 = my_y[1]; var z2 = my_z[1];
var x3 = my_x[2]; var y3 = my_y[2]; var z3 = my_z[2];
var x4 = my_x[3]; var y4 = my_y[3]; var z4 = my_z[3];
// I'm going to translate / rotate / scale the 3D model data next!
// first making it a vector
var my_v1= vector4(x1, y1, z1, 1);
var my_v2= vector4(x2, y2, z2, 1);
var my_v3= vector4(x3, y3, z3, 1);
var my_v4= vector4(x4, y4, z4, 1);
//console.log(my_v1)
// now translate, rotate and scale it!
// random translation on x,y,z
var tz=my_random_int(11)+2; // translate. tz is the depth; further from cam
var tx=my_random_float_minplus(tz/2); // translate further when z is bigger!
var ty=my_random_float_minplus(tz/2); //
var sx= 1; // scale x
var sy= sx/4; // scale y
var sz= 0; // scale z - not used now!
var rx= degree_to_radian( my_random_int(11) * 90 ) ; // rotate on x
var ry= degree_to_radian( my_random_int(11) * 45 ) ; // rotate on y
var rz= degree_to_radian( my_random_int(11) * 90 ) ; // rotate on z
// xxx amsterdam chillout
// make a new matrix for the translation / rotation / scale
var movemat = go_do_matrix(tx,ty,tz,rx,ry,rz,sx,sy,sz);
// and use the matrix on the points next
var my_newv1 = mat_multi_v4(movemat,my_v1); // do matrix; rotation etc.
var my_newv2 = mat_multi_v4(movemat,my_v2);
var my_newv3 = mat_multi_v4(movemat,my_v3);
var my_newv4 = mat_multi_v4(movemat,my_v4);
x1=my_newv1.x;
y1=my_newv1.y;
z1=my_newv1.z;
x2=my_newv2.x;
y2=my_newv2.y;
z2=my_newv2.z;
x3=my_newv3.x;
y3=my_newv3.y;
z3=my_newv3.z;
x4=my_newv4.x;
y4=my_newv4.y;
z4=my_newv4.z;
//console.log(movemat)
// -------------------'simple' 3D to 2D calculation-------
var siz=im_w; // image width - asuming a square ration now
var halfsizw=im_w/2;
var halfsizh=im_h/2;
var xx1= Math.round( halfsizw + ( x1 * ( 1 /(2.5 + z1) )* siz ) );
var yy1= Math.round( halfsizh + ( y1 * ( 1 /(2.5 + z1) )* siz ) );
var xx2= Math.round( halfsizw + ( x2 * ( 1 /(2.5 + z2) )* siz ) );
var yy2= Math.round( halfsizh + ( y2 * ( 1 /(2.5 + z2) )* siz ) );
var xx3= Math.round( halfsizw + ( x3 * ( 1 /(2.5 + z3) )* siz ) );
var yy3= Math.round( halfsizh + ( y3 * ( 1 /(2.5 + z3) )* siz ) );
var xx4= Math.round( halfsizw + ( x4 * ( 1 /(2.5 + z4) )* siz ) );
var yy4= Math.round( halfsizh + ( y4 * ( 1 /(2.5 + z4) )* siz ) );
// old formula I got from irc-java channel around 1999? changed it as well
strokeWeight( 1 ); // outer line thickness
stroke(0); // color black
// line(xx1,yy1, xx2,yy2);
// line(xx2,yy2, xx3,yy3);
// line(xx3,yy3,xx4,yy4);
// line(xx4,yy4,xx1,yy1);
quad(xx1,yy1, xx2,yy2,xx3,yy3,xx4,yy4);
//console.log(xx1,xx2,xx3,xx4)
my_counter++ // do it in steps to preserve fps
if(my_counter==50) // draw 5 times
{
my_counter=0;
my_anim=4; // now go next
}
}
//------------------------
//------------------------
//wait a bit then do the fxpreview
else if(my_anim==4)
{
my_counter++ // do it in steps to preserve fps on bigger images
if(my_counter==530) // wait for like 0.5 seconds
{
if(do_once==0) // and do the fxpreview just once!
{
fxpreview(); // say to fxhash; take a snapshot now
do_once=1; // and set do once to 1
//- so fxpreview won't get triggered again
}
my_counter=0; // reset my counter as well
my_anim=5; // go next in my anim loop
}
}
//------------------------
else if(my_anim==5)
{
// wait - loop forever
// or start again at 0 - redraw - nice for variation checking
my_anim=0; // restart drawing
}
//------------------------
}
// end of draw() my animation---------------------------
//------------------------------------------------------------------
//-----------------keys saving---------------------------------------
// We use the key pressed function here s = save the large image
// change the name if you want
function keyPressed()
{
// If you hit the s key, it saves an image
// the sketch must be open - activated! before it saves
if (key == 's')
{
save("fxhash_simple3dpixelengine_template.png"); // you want png: bigger but better for printing
}// end s key
}
//-------my own functions using fxhash - random -------------------------------
// my own random functions; that I adjusted for fxhash
// it give back a random number based on 'num' that i send to it
function my_random_int(num)
{
return ((fxrand()*num) << 0); // << 0 converts float to int - fast hack - almost the same as using round()
}
function my_random_float(num) // 0.023123 gives back floating point numbers
{
return ( (fxrand()*num) ); //
}
function my_random_int_minplus(num) //return int between -num +num
{
return ( ( (fxrand() * (num*2)) - num) << 0 );
}
function my_random_float_minplus(num) //return float between -num +num
{
return ( (fxrand() * (num*2)) - num) ;
}
//-------------------------------------------------------------------------
// used (and changed) some matrix and vector math from:
// softwareRasterizer by Simon Yeung (2012)
// javascript: 3D engine & perspective correct texture mapping:
// http://simonstechblog.blogspot.com/2012/04/software-rasterizer-part-2.html
// vector 4
function vector4(x, y, z, w)
{
return {
x : x,
y : y,
z : z,
w : w
};
}
function mat_multi_v4(mat, vec)
{
return vector4( mat[0]*vec.x + mat[4]*vec.y + mat[8]*vec.z + mat[12]*vec.w,
mat[1]*vec.x + mat[5]*vec.y + mat[9]*vec.z + mat[13]*vec.w,
mat[2]*vec.x + mat[6]*vec.y + mat[10]*vec.z + mat[14]*vec.w,
mat[3]*vec.x + mat[7]*vec.y + mat[11]*vec.z + mat[15]*vec.w );
}
// matrix // translate rotate scale 0 fixed by elout..
function go_do_matrix(tx,ty,tz,rx,ry,rz,sx,sy,sz)
{
var mro_x = get_rotx_mat(rx); // do rotation
var mro_y = get_roty_mat(ry);
var mro_z = get_rotz_mat(rz);
var mro_xy = mat_multi(mro_x, mro_y);
var mro_xyz = mat_multi(mro_xy, mro_z);
var mytrans_mat = get_trans_mat(tx,ty,tz);
var myscale_mat = get_scale_mat(sx,sy,sz); // do scale
var myrotsca_mat=mat_multi(mytrans_mat,mro_xyz); //
var myrotscatran_mat=mat_multi(myrotsca_mat,myscale_mat); // final matrix
//if you add the matrixes different, you can get total different results! ^____^
return new Float32Array(myrotscatran_mat);
}
function get_rotx_mat(rad) // rotate
{
var mcos= Math.cos(rad);
var msin= Math.sin(rad);
return new Float32Array([ 1.0, 0.0, 0.0, 0.0,
0.0, mcos, -msin, 0.0,
0.0, msin, mcos, 0.0,
0.0, 0.0, 0.0, 1.0 ]);
}
function get_roty_mat(rad)
{
var mcos= Math.cos(rad);
var msin= Math.sin(rad);
return new Float32Array([ mcos, 0.0, msin, 0.0,
0.0, 1.0, 0.0, 0.0,
-msin, 0.0, mcos, 0.0,
0.0, 0.0, 0.0, 1.0 ]);
}
function get_rotz_mat(rad)
{
var mcos= Math.cos(rad);
var msin= Math.sin(rad);
return new Float32Array([ mcos, -msin, 0.0, 0.0,
msin, mcos, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 ]);
}
function get_scale_mat(x, y, z) // scale
{
return new Float32Array([ x , 0.0, 0.0, 0.0,
0.0, y, 0.0, 0.0,
0.0, 0.0, z, 0.0,
0.0, 0.0, 0.0, 1.0 ]);
}
function get_trans_mat(x, y, z) // translate
{
return new Float32Array([1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
x, y, z, 1.0 ]);
}
function mat_multi(m1, m2)
{
return new Float32Array([
m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3],
m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3],
m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3],
m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3],
m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7],
m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7],
m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7],
m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7],
m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11],
m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11],
m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11],
m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11],
m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15],
m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15],
m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15],
m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15] ]);
}
function degree_to_radian(degree)
{
return degree * Math.PI / 180.0;
}