#############################################################################
#
# Warping polygons/teapot out of the teapot's spout, using FFD trivariates.
#
#						Gershon Elber, Sep 2002.
#

save_mat2 = view_mat;
save_res = resolution;
view_mat = rotx( 0 );

#
# Get a model of a teapot.
#

EchoSrc2 = iritState( "EchoSource", false );
interact = procedure( none ):
    viewclear();

include("teapot");
TeapotOrig = load( "teapot" );
free( Body );
free( Spout );
free( Handle );
free( Cap );

interact = procedure( none ):
    viewdclear():
    viewobj(none):
    pause();
EchoSrc2 = iritState( "EchoSource", EchoSrc2 );
free( EchoSrc2 );

#
# Define our warping function.
#

WarpSrf = function( OrigSrf, Tv ): Srf: i: USize: VSize: Pt: x: y: z: u: v:
    Srf = -sreparam( sreparam( OrigSrf, row, 0, 1 ), col, 0, 1 ):
    Srf = srefine( srefine( Srf, col, false, list( 0.111, 0.222, 0.333,
						   0.444, 0.555, 0.666,
						   0.777, 0.888 ) ),
		   row, false, list( 0.111, 0.222, 0.333, 0.444, 0.555, 0.666,
				     0.777, 0.888 ) ):
    USize = nth( ffmsize( Srf ), 1 ):
    VSize = nth( ffmsize( Srf ), 2 ):
    for ( i = 0, 1, USize * VSize - 1,
	Pt = coord( Srf, i ):
	x = coord( Pt, 1 ):
	y = coord( Pt, 2 ):
	z = coord( Pt, 3 ):
	Pt = teval( Tv, x, y, z ):
	v = floor( i / USize ):
	u = i - v * USize:
	Srf = sEditPt( Srf, Pt, u, v ) ):
    return = Srf:
    cpattr( return, OrigSrf );

WarpPoly = function( Pl, Tv ): i: j: P: VList: Pt: V:
    return = 0:
    for ( i = 0, 1, sizeof( Pl ) - 1,
	P = coord( Pl, i ):
	VList = nil():
	for ( j = 0, 1, sizeof( P ) - 1,
	    V = coord( P, j ):
	    snoc( coerce( teval( Tv, coord( V, 0 ),
				     coord( V, 1 ),
				     coord( V, 2 ) ),
			  point_type ),
		  VList ) ):
	if ( thisobj("return") == numeric_type,
	    return = poly( VList, false ),
	    return = mergePoly( list( poly( VList, false ), return ) ) ) ):
    cpattr( return, Pl );

WarpObj = function( Obj, Tv ): return = nil();
WarpObj = function( Obj, Tv ): i:
    if ( thisobj("Obj") == list_type,
	return = nil():
	for ( i = 1, 1, sizeof( Obj ),
	    snoc( WarpObj( nth( Obj, i ), Tv ), return ) ),
	if ( thisobj("Obj") == surface_type,
	    return = WarpSrf( Obj, Tv ),
	    if ( thisobj("Obj") == poly_type,
		return = WarpPoly( Obj, Tv ),
		return = Obj * tx( 0 ) ) ) );

#
# Define the FFD trivariate
#
Teapot = TeapotOrig * sc( 0.2 ) * sx( -1 ) * rx( 90 ) * rz( 180 );

s = planeSrf( -1, -1, 1, 1 ) * sc( 2.4 );
Discs = list( s * sc( 0.02 ) * sx( 2 ) * tx( 0.56 ) * tz( 0.42 ),
	      s * sc( 0.02 ) * sx( 2 ) * trans( vector( 0.66, 0, 0.5 ) ),
	      s * sc( 0.04 ) * sx( 1.5 ) * trans( vector( 0.66, 0, 0.7 ) ),
	      s * sc( 0.15 ) * sx( 1.5 ) * trans( vector( 0.1, -0.1, 1 ) ),
	      s * sc( 0.21 ) * sx( 1.5 ) * trans( vector( 0.25, -0.1, 1.2 ) ),
	      s * sc( 0.2 ) * sx( 1.5 ) * trans( vector( 0.2, 0.1, 1.4) ),
	      s * sc( 0.18 ) * tx( 0.1 ) * tz( 1.5 ) );
Tv = tFromSrfs( Discs, 3 );
attrib( Tv, "transp", 0.5 );
# view( list( axes, Tv, Teapot ), 1 );

#############################################################################
#
# Let the Teapot and Spheres come out of the teapot...
#

resolution = 10;

s1 = sphere( vector( 0.2, 0.2, 0.8 ), 0.18 );
color( s1, yellow );
s2 = sphere( vector( 0.75, 0.25, 0.16667 ), 0.12 ) * sz( 3 );
color( s2, magenta );
c1 = MaxEdgeLen( triangl( cylin( vector( 0.15, 0.85, 0.01 ),
				 vector( 0, 0, 0.98 ), 0.1, 3 ), 1 ), 0.2 );
color( c1, cyan );
c2 = MaxEdgeLen( triangl( cylin( vector( 0.85, 0.85, 0.01 ),
				 vector( 0, 0, 0.98 ), 0.1, 3 ), 1 ), 0.2 );
color( c2, cyan );

Genie = list( TeapotOrig * sc( 0.15 ) * ry( -90 )
			 * trans( vector( 0.5, 0.4, 0.47 ) ),
	      s1, s2, c1, c2 );

b = box( vector( 0, 0, 0 ), 1, 1, 1 );
attrib( b, "transp", 0.5 );

interact( list( axes, b, Genie ) );

WGenie = WarpObj( Genie, Tv );
interact( list( Teapot, WGenie, Tv ) );

save( "GeniTpot", list( Teapot, WGenie, Tv ) );

#############################################################################

view_mat = save_mat2;
resolution = save_res;

free( TeapotOrig );
free( Teapot );
free( s );
free( Tv );
free( Genie );
free( WGenie );
free( Discs );
free( s1 );
free( s2 );
free( c1 );
free( c2 );
free( b );
