Choose Language Hide Translation Bar
Tile JSL part 3 Using the kites and darts from part 2, make a 3D surface. Some of the Scene3D code was borrowed from some of the examples that ship with JMP. This JSL was written to make the video clip. Buried in it are some scaling and animation controlling values, tweaked to make the video just right. There is also a path to a directory on the desktop that will be filled with numbered bitmaps. Part 4 will explain how to use other tools outside of JMP to assemble the bitmaps into a video.

This code expects the variables from part 2 to still be in JMP's memory.

scale = 50;//50;
sbscale = .5;//2;//.4;//1;
///////////////// 3D ///////////////////
fn = Function( {x, y},
x /= scale;
y /= scale;
(((1 + Cos( -Pi() + fraction * 2 * Pi() )) / 2) ^ .95) * scale * Sin( 100 * fraction * Pi() + Sqrt( x * x + y * y ) );
); // the function to plot.  the sheet color assumes the result is between -1 and +1.
addvertex = Function( {a, b, c},
If(
af < 100, b += Random Normal( 0, If( af <= 0, .1, 1 / Sqrt( 100 * af ) ) ),
af > nframes, b += Random Normal( 0, .01 * Sqrt( af - nframes ) ),
0
);
// calculate the normal; this is the vector cross product of the two lines leaving b to a or c
qx = a - b;
qy = a - b;
qz = a - b;
px = c - b;
py = c - b;
pz = c - b;
nx = py * qz - pz * qy;
ny = pz * qx - px * qz;
nz = px * qy - py * qx;
// normalize the normal vector (sheet<<enable(NORMALIZE) could be used, but normalizes every frame)
len = Sqrt( nx * nx + ny * ny + nz * nz );
nx /= len;
ny /= len;
nz /= len;
sheet << Normal( nx, ny, nz ); // the normal at each vertex could be averaged to make the surface more smooth
sheet << Vertex( b, b, b );
);
addpoly = Function( {verts}, //show(verts);stop();
verts = verts |/ (// add a row of z-values to the row of x and row of y
fn( verts[1, 1], verts[2, 1] ) || fn( verts[1, 2], verts[2, 2] ) || fn( verts[1, 3], verts[2, 3] ) || fn( verts[1, 4], verts[2, 4] ));
addvertex( verts[0, 1] / scale, verts[0, 2] / scale, verts[0, 3] / scale );
addvertex( verts[0, 2] / scale, verts[0, 3] / scale, verts[0, 4] / scale );
addvertex( verts[0, 3] / scale, verts[0, 4] / scale, verts[0, 1] / scale );
addvertex( verts[0, 4] / scale, verts[0, 1] / scale, verts[0, 2] / scale );
);
nFrames = 90 * 25;//2250 frames for 90 seconds
xangle = 0;
yangle = 0;
zangle = 0;
changeangle = Function( {frame},
frame = 2 * Pi() * frame / nFrames;
xangle = 400 * ((1 + Cos( Pi() + frame )) / 2);
yangle = 20 * ((1 + Cos( Pi() + frame )) / 2);
zangle = 900 * ((1 + Cos( frame )) / 2);
);
justbluepos = Function( {x, y, fraction}, 10000 ); // out of site
dropinpos = Function( {x, y, fraction}, (1 - fraction) * Random Normal( 10 ) );
scene = Scene Box( 1920 * sbscale, 1080 * sbscale );
scene << background color( RGB Color( 0, 0, .5 ) );
New Window( "Sheet", scene );
picno = 0;
picdir = "\$desktop/picdir/x";
For( af = -130, af <= nFrames + 200, af = af + 1, // a loop to rotate the display list; a gets scaled below, so its not really in degrees
fraction = (af - 1) / nFrames;
sheet = Scene Display List(); // creates a display list, which will hold a list of commands
sheet << Material( Front_and_Back, Specular, 1, 1, 1, 1 );
sheet << Material( Front_and_Back, Shininess, 127 );
sheet << Material( Front_and_Back, Ambient_and_Diffuse, 1, 1, 1, 1 );
sheet << Enable( Color_Material ); // allows the color commands to update the material property
sheet << Begin( QUADS ); // not a quad strip
sheet << Color( HLS Color( .05, .6, .7 ) );
For( i = 1, i <= nkite, i++,
);
sheet << Color( HLS Color( .55, .4, .95 ) );
For( i = 1, i <= ndart, i++,
);
sheet << End();  // ends the quads
sheet << Disable( Color_Material );
scene << Clear;
scene << Light( Light0, Position, -200, -200, 100, 1 );
scene << Light( Light0, DIFFUSE, .8, .8, .8, 1 );
scene << Light( Light0, SPECULAR, .5, .5, .5, 1 );
scene << Enable( Lighting ); // any surfaces rendered after this will respond to the light
scene << Enable( Light0 ); // turn on one of the eight available lights (0...7)
scene << LightModel( LIGHT_MODEL_TWO_SIDE, 1 );
scene << LightModel( LIGHT_MODEL_AMBIENT, .6, .6, .6, 1 );
//scene << FrontFace( CW ); // whoops!  I must have defined the polygons backwards in the normal calculation.  this reverses the definition.
scene << ShadeModel( SMOOTH );
scene << Perspective( 45, 1, 100 );
scene << Translate( 0.0, 0.0, If( af >= nframes, ((nframes - af) / 10) - 15, af <= 0, (af / 10) - 15, -15 ) );
scene << enable( FOG );
scene << fog( FOG_END, 25 ); // fog ends 3 units away, 1 beyond origin
scene << fog( FOG_START, 20 ); // fog begins
scene << fog( FOG_MODE, LINEAR );
changeangle( af );//show(zangle);
scene << Rotate( xangle, 1.0, 0.0, 0.0 ); // spin around the X axis
scene << Rotate( yangle, 0.0, 1.0, 0.0 ); // and the Y axis
scene << Rotate( zangle, 0.0, 0.0, 1.0 ); // and the Z axis
scene << arcball( sheet, 8 );
scene << Update;
Wait( 0 );
// scene << savepicture( picdir || Right( Char( picno++ ), 6, "0" ) || ".png" );
);