「 プログラムをコピー 」に続いて「 プレイヤーを起動 」をクリックし、プレイヤー画面に貼り付けると、WEBブラウザ上でそのままプログラムを実行できます。

>> プレイヤーを起動できない場合はこちら

encode Shift_JIS ;


import Graphics ; 
import Graphics3D ; 
import GUI ; 
import Math ; 




void main( string args[] ){


    TITLE = "展開図を折るようにして組み立てる四角反柱の接合体" ;
    int winw = 256*2.75, winh = 256*2.75, winx = 70, n = 255 ;
    int bgcolor[ ] = Color( n, n, n ) ;

    hide();
    Set3DGraphics( winw, winh, winx, bgcolor ) ;
    SetLights() ;
    SetCoordinates() ;
    SetElements() ;
    PrepareStage() ;


/* animation loop  */

    int picture_save_number = 1 * 10000 ;
    int loop_periodic_time = 1000 / FPS ;
    bool loop_termination = false ;

    while ( KEEP_LOOP ){ 

        T += STEP ; // 時刻
        COUNT ++ ; // loop カウント
        if ( COUNT % 100 == 0 ) {
            print( (COUNT/100) + ", " ) ;
        }

        ForwardMotion() ; // アニメーション

        if ( CREATE_GUI ) {
            CreateGuiElements() ; // GUI の設置
            CREATE_GUI = false ;
            TURN_GUI = true ;
        }

        PaintGraphics( loop_periodic_time ) ;

        if ( SAVE_A_PICTURE ) {
            SaveImagePNG( picture_save_number ) ;
        }

        loop_termination = ( PICTURE_NUMBER == PICTURE_END_NUMBER ) ;
        if ( loop_termination ) {
            ExitLoopOverImageLimit() ;
        }
    }


    exit() ;


}




// import


/* NUMERIC */

double o = 0.0, a = 1.0 ;
double Slv = 2*cos( PI/4 ) , ISlv = cos( PI/4 ) ;
double Gld = 2*cos( PI/5 ) , IGld = Gld - 1.0 ;
double Plt = 2*cos( PI/6 ) , IPlt = tan( PI/6 ) ;
int O = newVector( o, o, o ) ; 

double l = 1.0 ; // 長さに用いる単位
int N ;

// symmetry
int S24 = 24, S12 = 12, S8 = 8, S6 = 6, S5 = 5, S4 = 4, S3 = 3, S2 = 2 ; 
int R4 = 4, R8 = 8 ;


/* 3DGRAPHICS */

string TITLE;
int MAIN_GRAPHICS, MAIN_WINDOW, MAIN_DISPLAY_LABEL, RENDERER ;
int WIDTH, HEIGHT, WINDOW_POSITION_X ;
{
    int n = 256 ;
    WIDTH = n * 2.75 ; WIDTH = n * 4 ; 
    HEIGHT = n * 2.75 ; HEIGHT = n * 3 ; 
    WINDOW_POSITION_X = 70 ; WINDOW_POSITION_X = 1910 - WIDTH ;
}

void Set3DGraphics( int w, int h, int x, int bgcolor[ ] ) {

    WIDTH = w ;
    HEIGHT = h ;
    WINDOW_POSITION_X = x ;
    int bgred = bgcolor[0] ;
    int bggreen = bgcolor[1] ;
    int bgblue = bgcolor[2] ;
    int framewidth_x = 14 ;
    int framewidth_y = 39 ;
    int bgalpha = 255 ;

    MAIN_GRAPHICS = newGraphics()
    RENDERER = newGraphics3DRenderer( WIDTH, HEIGHT, MAIN_GRAPHICS ) ;
    MAIN_WINDOW = newWindow( 
        WINDOW_POSITION_X, 0, WIDTH + framewidth_x, HEIGHT + framewidth_y, TITLE 
    ) ;
    MAIN_DISPLAY_LABEL = newGraphicsLabel( 0, 0, WIDTH, HEIGHT, MAIN_GRAPHICS ) ;
    addComponent( MAIN_DISPLAY_LABEL, MAIN_WINDOW );
    setGraphics3DDefaultEventHandler( RENDERER, MAIN_DISPLAY_LABEL );
    setGraphics3DColor( RENDERER, bgred, bggreen, bgblue, bgalpha );
}


/* GUI */

void onWindowClose( int id ) { 
    KEEP_LOOP = false ; 
}

void onKeyDown( int id, string key ){

    if ( key == "SPACE" ) {
        if ( SAVE_A_PICTURE ) {
            SAVE_A_PICTURE = false ;
            alert( PICTURE_NUMBER + " 枚目までで画像の保存を中止しました。" );
        } else {
            alert( ( PICTURE_NUMBER+1 ) + " 枚目以降の画像を保存します。" );
            SAVE_A_PICTURE = true ;
        }
    }
}

void PaintGraphics( int sleeptime ) {
    sleep( sleeptime );
    paintGraphics3D( RENDERER );
    paintComponent( MAIN_DISPLAY_LABEL );
    paintComponent( MAIN_WINDOW );
}

void SavePicture( int picid ) {
    int picnumber = 0 ;
    PICTURE_NUMBER = PICTURE_NUMBER + 1 ; 
    picnumber = picid + PICTURE_NUMBER ; 
    exportGraphics(
        MAIN_GRAPHICS, "./movie/0" + picnumber + ".png", "PNG" 
    ) ;
}

void SaveImagePNG( int picid ) {
    int picnumber = 0 ;
    PICTURE_NUMBER = PICTURE_NUMBER + 1 ; 
    picnumber = picid + PICTURE_NUMBER ; 
    exportGraphics(
        MAIN_GRAPHICS, "./movie/a" + picnumber + ".png", "PNG" 
    ) ;
}

void SaveImageJPEG( int picid ) {
    int picnumber = 0 ;
    PICTURE_NUMBER = PICTURE_NUMBER + 1 ; 
    picnumber = picid + PICTURE_NUMBER ; 
    exportGraphics(
        MAIN_GRAPHICS, "./movie/a" + picnumber + ".jpg", "JPEG" 
    ) ;
}

void ExitLoopOverImageLimit() {
    alert( 
        "画像の保存が上限 ( " 
        + PICTURE_END_NUMBER 
        + " 枚 ) に達したため、CGアニメーションを終了します。"
    );
    KEEP_LOOP = false ;
}


/* FUNCTIONS */

// permuation
int Permuation( int n[ ] ) {

    
}

// unit step function
double Step( double x ) {

    double value;
    if ( x < 0.0 ) {
        value = 0.0 ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

double Slope( double x, double x0, double deltax ) {

    double value;
    if ( x < x0 ) {
        value = 0.0 ;
    } else if ( x < ( x0 + deltax ) ) {
        value = ( x - x0 ) / deltax ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

// eyeteeth ( teeth of saw )
double Eyeteeth( double x, double width ) {
// 0 <= x <=1
    double s = x ;
    if ( ( x < 0.0 ) || ( x > 1.0 ) ) {
        alert( "Error ( out of range, eyeteeth ) " );
    } else {
        while ( s > width ) {
        s = s - width ;
        }
    }
    return s / width ;
}

// pulsar
double Pulsar( double x, double cycle, double upslope, double top, double downslope ) {
// 0 <= x <=1
    double value;
    double s = Eyeteeth( x, cycle ) ;
    double ups = upslope / cycle ;
    double tops = top / cycle ;
    double downs = downslope / cycle ;
    if ( s < ups ) {
        value = Bump( s / ups * 0.5 ) ; 

    } else if ( s < ups + tops ) {
        value = 1.0 ;
    } else if ( s < ups + tops + downs ) {
            value = Bump( 0.5 + ( ( s - ( ups + tops ) ) / downs ) * 0.5 ) ;
    } else {
        value = 0.0 ;
    }
    return value ;
}

// unit bump function
double Bump( double x ) {

    return ( sin( 2*PI * x - PI/2 ) + 1.0 ) / 2 ;
}


double TurnBump( double x ) {

    return 1.0 - Bump( x ) ;
}

int Parity( int i ) {

    int p;
    if ( i % 2 == 0 ) {
        p = 1 ;
    } else {
        p = -1 ;
    }
    return p ;
}

double[ ] SolveQuadraticEquation( double a, double b, double c ) {

    double D = b^2 - 4 * a * c ;
    double solution[2];
    solution[0] = ( -b - D^0.5 ) / ( 2*a ) ;
    solution[1] = ( -b + D^0.5 ) / ( 2*a ) ;
    return solution ;
}


/* ROUTINE */

void PrintVectorln( int v, string s ) {
    println( "Vector " + s + " = "
        + getVectorX( v ) + ", "
        + getVectorY( v ) + ", "
        + getVectorZ( v )
    );
}

void PrintDoubleArray( double a[ ], string s ) {

    int n = length( a ) ;
    for ( int i=0; i<n; i++ ) {
        println( "s ( " + i + " ) = " + a[i] );
    }
}

void SetParallelLight(
    int light, float x, float y, float z, float power, int renderer
) {

    light = newLight( x, y, z, power ) ; 
    addLight( light, renderer );
}

void SetAmbientLight(
    int light, float x, float y, float z, float power, int renderer
) {

    light = newAmbientLight( x, y, z, power ) ; 
    addLight( light, renderer );
}

void SetPointLight(
    int light, float x, float y, float z, float power, int renderer
) {

    light = newPointLight( x, y, z, power ) ; 
    addLight( light, renderer );
}

void SetPolygonSurface( int id, float x[ ] ) {

    setPolygonEmissive( id, x[0] );
    setPolygonDiffractive( id, x[1] );
    setPolygonDiffuse( id, x[2] );
    setPolygonAmbient( id, x[3] );
    setPolygonSpecular( id, x[4], x[5] );
}

void SetModelSurface( int id, float x[ ] ) {

    setModelEmissive( id, x[0] );
    setModelDiffractive( id, x[1] );
    setModelDiffuse( id, x[2] );
    setModelAmbient( id, x[3] );
    setModelSpecular( id, x[4], x[5] );
}

void SetPolygonColor( int id, int c[ ], int opc ) {

    setPolygonColor( id, c[0], c[1], c[2], opc );
}

void SetModelColor( int id, int c[ ], int opc ) {

    setModelColor( id, c[0], c[1], c[2], opc );
}

void SetLightColor( int id, int c[ ], int opc ) {

    setLightColor( id, c[0], c[1], c[2], opc );
}

void PileCoordinate( int cd[ ] , int renderer ) {

    int n = length( cd ) ;
    for ( int i=0; i<n; i++ ) {
        if ( i == 0 ) {
            addCoordinate( cd[n-1-i], renderer );
        } else {
            addCoordinate( cd[n-1-i], renderer, cd[n-i] );
        }
    }
}

// vectorの和を返す
int GetVectorSum( int v1, int v2 ) {

    int v = newVector() ;
    double vx = getVectorX( v1 ) + getVectorX( v2 ) ;
    double vy = getVectorY( v1 ) + getVectorY( v2 ) ;
    double vz = getVectorZ( v1 ) + getVectorZ( v2 ) ;
    setVector( v, vx, vy, vz );
    return v ;
}

// moveVectorの結果を返す
int GetMoveVector( int v, double x, double y, double z ) {

    int u = newVector( v );
    moveVector( u, x, y, z );
    return u ;
}

// vectorの差を求めて代入する
void VectorDifference( int v, int v1, int v2 ) {

    double vx = getVectorX( v1 ) - getVectorX( v2 ) ;
    double vy = getVectorY( v1 ) - getVectorY( v2 ) ;
    double vz = getVectorZ( v1 ) - getVectorZ( v2 ) ;
    setVector( v, vx, vy, vz );
}

// vectorの差を返す
int GetVectorDifference( int v1, int v2 ) {

    double vx = getVectorX( v1 ) - getVectorX( v2 ) ;
    double vy = getVectorY( v1 ) - getVectorY( v2 ) ;
    double vz = getVectorZ( v1 ) - getVectorZ( v2 ) ;
    int v = newVector( vx, vy, vz ) ;
    return v ;
}

// vectorの定数倍する
void ScaleVector( int v, double x ) {

    scaleVector( v, x, x, x ) ;
}

// vectorの定数倍を返す
int GetScaleVector( int v, double x ) {

    int u = newVector( v ) ;
    scaleVector( u, x, x, x ) ;
    return u ;
}

// vectorの回転を求めて返す
int GetRotXVector( int v, double angle ) {

    int u = newVector( v ) ;
    rotXVector( u, angle );
    return u ;
}
int GetRotYVector( int v, double angle ) {

    int u = newVector( v ) ;
    rotYVector( u, angle );
    return u ;
}
int GetRotZVector( int v, double angle ) {

    int u = newVector( v ) ;
    rotZVector( u, angle );
    return u ;
}
int GetRotVector( int v, double angle, int ax, int rc ) {

    int u = newVector( v ) ;
    rotVector( u, angle, ax, rc );
    return u ;
}

// 内分点を求める。P1V ; VP2 = t : 1-t
int GetInternallyDividingVector(
    double x1, double y1, double z1,
    double x2, double y2, double z2,
    double t
) {

    double vx = ( 1.0 - t )*x1 + t*x2 ;
    double vy = ( 1.0 - t )*y1 + t*y2 ;
    double vz = ( 1.0 - t )*z1 + t*z2 ;
    int v = newVector ( vx, vy, vz ) ;
    return v ;
}

int GetInternallyDividingVector( int v1, int v2, double t ) {

    double vx = ( 1.0 - t )*getVectorX( v1 ) + t*getVectorX( v2 ) ;
    double vy = ( 1.0 - t )*getVectorY( v1 ) + t*getVectorY( v2 ) ;
    double vz = ( 1.0 - t )*getVectorZ( v1 ) + t*getVectorZ( v2 ) ;
    int v = newVector ( vx, vy, vz ) ;
    return v ;
}

// vをcdに配置してCDへ変換したものを求める
int GetTransformedVector( int v, int renderer, int cd, int CD ) {

    int u = newVector( v ) ;
    addVector( v, renderer, cd );
    transformVector( v, u, CD );
    removeVector( v, renderer, cd );
    return u ;
}

void TransformVector( int v, int renderer, int cd, int u, int CD ) {

    addVector( v, renderer, cd );
    transformVector( v, u, CD );
    removeVector( v, renderer, cd );
}

void SetCoordinateOrigin( int cd, double x[ ] ) {

    setCoordinateOrigin( cd, x[0], x[1], x[2] );
}

int GetCoordinateOriginVector( int cd ) {

    int v = newVector(
        getCoordinateOriginX( cd ),
        getCoordinateOriginY( cd ),
        getCoordinateOriginZ( cd )
    );
    return v ;
}

// 重心を返す
int GetVectorGravityCenter( int v[ ] ) {

    int g = newVector( v[0] ) ;
    int lenv = length( v ) ;
    for ( int i=1; i<lenv; i++ ) {
        moveVector( g, v[i] );
    }
    double s = 1.0 / lenv ;
    scaleVector( g, s, s, s);
    return g ;
}

double[ ] getCenterOfGravity( int v[ ] ) {

    int g = newVector( v[0] ) ;
    int lenv = length( v ) ;
    for ( int i=1; i<lenv; i++ ) {
        moveVector( g, v[i] );
    }
    double s = 1.0 / lenv ;
    scaleVector( g, s, s, s);
    double x[ 3 ];
    x[0] = getVectorX( g ) ;
    x[1] = getVectorY( g ) ;
    x[2] = getVectorZ( g ) ;
    return x ;
}

// normal vectorを返す
int GetNormalVectorQuadrangle( int v[ ] ) {

    int v1 = GetVectorDifference( v[2], v[0] ) ;
    int v2 = GetVectorDifference( v[3], v[1] ) ;
    int normalv = newVector() ;
    getVectorCrossProduct( v1, v2, normalv );
    double length = getVectorLength( normalv ) ;
    if ( !( length == o ) ) {
        setVectorLength( normalv, 1.0 );
    } else {
        alert( "error( GetNormalVectorQuadrangle )) ;
    }
    return normalv ;
}

// 2枚の面の作る角の余弦を返す
double GetAngleFaceFace ( int v1[ ], int v2[ ] ) {

    int n1 = GetNormalVectorQuadrangle( v1 ) ;
    int n2 = GetNormalVectorQuadrangle( v2 ) ;
    double costh = getVectorInnerProduct( n1, n2 ) ;
    return costh ;
}

void SetVectorsCoordinateLocationAttitude( int vo, int va, int cd ) {

    double x = getCoordinateOriginX( cd ) ;
    double y = getCoordinateOriginY( cd ) ;
    double z = getCoordinateOriginZ( cd ) ;
    double a = getCoordinateEulerAngleAlpha( cd ) ;
    double b = getCoordinateEulerAngleBeta( cd ) ;
    double g = getCoordinateEulerAngleGamma( cd ) ; 

    setVector( vo, x, y, z );
    setVector( va, a, b, g );
}

void SetCoordinateLocationAttitude( int cd, int vo, int va ) {

    double x = getVectorX( vo ) ;
    double y = getVectorY( vo ) ;
    double z = getVectorZ( vo ) ;
    double a = getVectorX( va ) ;
    double b = getVectorY( va ) ;
    double g = getVectorZ( va ) ; 

    setCoordinateOrigin( cd, x, y, z );
    setCoordinateEulerAngle( cd, a, b, g );
}

void SetCoordinateEulerAngle( int cd, double ea[ ] ) {

    setCoordinateEulerAngle( cd, ea[0], ea[1], ea[2] );
}


void SetCoordinateEulerAngleVector( int cd, int v ) {

    setCoordinateEulerAngle( cd, 
        getVectorX( v ), getVectorY( v ), getVectorZ( v ) 
    );
}

double[ ] GetCoordinateEulerAngle( int cd ) {

    double ea[ 3 ];
    ea[0] = getCoordinateEulerAngleAlpha( cd ) ;
    ea[1] = getCoordinateEulerAngleBeta( cd ) ;
    ea[2] = getCoordinateEulerAngleGamma( cd ) ;
    return ea ;
}

int GetCoordinateEulerAngleVector( int cd ) {

    double ea[ 3 ];
    ea[0] = getCoordinateEulerAngleAlpha( cd ) ;
    ea[1] = getCoordinateEulerAngleBeta( cd ) ;
    ea[2] = getCoordinateEulerAngleGamma( cd ) ;
    int v = newVector( ea ) ;
    return v ;
}

// リセットなしの回転
void RotateCoordinate( 
    int cd, int so, int sa, double angle, int ax, int rc, int renderer, int Cd 
) {

    int dummycd = newCoordinate() ;
    addCoordinate( dummycd, renderer, Cd ) ;
    SetCoordinateLocationAttitude( dummycd, so, sa ) ;
    rotCoordinate( dummycd, angle, ax, rc ) ;
    int sovalue = newVector() ;
    int savalue = newVector();
    SetVectorsCoordinateLocationAttitude( sovalue, savalue, dummycd ) ;
    SetCoordinateLocationAttitude( cd, sovalue, savalue ) ;
    removeCoordinate( dummycd, renderer, Cd ) ;
}

// y軸及びz軸が引数ベクトルと平行な姿勢にする
void SetCoordinateAttitudeYZ( int cd, int vy, int vz ) {

    int uy = newVector( vy ) ;
    int uz = newVector( vz ) ;
    setVectorLength( uy, 1.0 );
    setVectorLength( uz, 1.0 );
    int ux = newVector() ;
    getVectorCrossProduct( uy, uz, ux );
    setCoordinateBaseX( cd, ux );
    setCoordinateBaseY( cd, uy );
    setCoordinateBaseZ( cd, uz );
}

// 原点が v2, cylinder 端点が v1, v2 となるように cd を set する
void SetCoordinateCylinder( int cyl, double rad, int v1, int v2, int cd ) {

    double x[ 3 ];
    x[0] = getVectorX( v1 ) - getVectorX( v2 ) ; 
    x[1] = getVectorY( v1 ) - getVectorY( v2 ) ;
    x[2] = getVectorZ( v1 ) - getVectorZ( v2 ) ;
    int v21 = newVector( x ) ;
    double length = getVectorLength( v21 ) ; // シリンダーの長さ

    if ( length != 0.0 ) {
        int xyprojection = newVector( x[0], x[1], 0.0 ) ;
        setVectorLength( xyprojection, 1.0 ) ;
        double cos1 = getVectorY( xyprojection ) ; // xy射影がy軸となす角の余弦
        double th1; // xy射影がy軸となす角度
        if ( x[1] == 0.0 ) {
            if ( x[0] >= 0.0 ) {
                th1 = PI/2 ;
            } else {
                th1 = -PI/2 ;
            }
        } else if( x[0] < 0.0 ) { 
            th1 = -acos( cos1 ) ; 
        } else {
            th1 = acos( cos1 ) ;
        }

        setVectorLength( v21, 1.0 );
        double sin2 = getVectorZ( v21 ); // 射影と元のベクトルのなす角の正弦
        double th2 = asin( sin2 ) ;

        double alpha = -th1 ;
        double beta = th2 - PI/2 ;
        double gamma = 0.0 ; if ( th1 < 0.0 ) { gamma = PI ; }
        setCoordinateOrigin( cd, v2 );
        setCoordinateEulerAngle( cd, alpha, beta, gamma );
         setModelSize( cyl, rad, rad, length );
    }
}

void SetSphereSize( int sp, double rad ) {

    setModelSize( sp, rad, rad, rad );
}


/* MOTION */

double GetLinearTime( int v ) {

    double t0 = getVectorX( v ) ;
    double t1 = getVectorY( v ) ;
    double t;
    if ( T < t0 ) {
        t = 0.0 ;
    } else if ( T < t1 - STEP ) {
        t = ( T - t0 ) / ( t1 - t0 - STEP ) ;
    } else {
        t = 1.0 ;
    }
    return t ;
}

double GetSmoothTime( int v, double p ) {
// p=0でsin, pはだいたい0.7くらいまで
    double t0 = getVectorX( v ) ;
    double t1 = getVectorY( v ) ;
    double t;
    if ( T < t0 ) {
        t = 0.0 ;
    } else if ( T < t1 - STEP ) {
        t = ( T - t0 ) / ( t1 - t0 - STEP ) ;
    } else {
        t = 1.0 ;
    }
    double value ;
    if ( p > 0.0 ) {
        if ( t < 0.5 ) {
            double u = 2 * ( 1.0 - t ) - 1.0 ;
            double s = ( 1.0 + p )/( 2*p ) 
                        * ( 1.0 - sqrt( 1.0 - 4*p/( ( 1.0 + p )^2 ) * u ) ) ;
            value = ( 1.0 - sin( PI/2 * s ) ) / 2 ;
        } else {
            double u = 2 * t - 1.0 ;
            double s = ( 1.0 + p )/( 2*p ) 
                        * ( 1.0 - sqrt( 1.0 - 4*p/( ( 1.0 + p )^2 ) * u ) ) ;
            value = ( 1.0 + sin( PI/2 * s ) ) / 2 ;
        }
    } else if ( p == 0.0 ) {
        if( t < 0.5 ) {
            double u = 2 * ( 1.0 - t ) - 1.0 ;
            value = ( 1.0 - sin( PI/2 * u ) ) / 2 ;
        } else {
            double u = 2 * t - 1.0 ;
            value = ( 1.0 + sin( PI/2 * u ) ) / 2 ;
        }
    }
    return value ;
}

void SetTRange( int v, double dt1, double dt0 ) {

    double t0 = getVectorY( v ) + dt1 ;
    double t1 = t0 + dt0 ;
    setVector( v, t0, t1, dt0 );
}

void SetTRangeAbsolutely( int v, double t0, double t1 ) {

    setVector( v, t0, t1, t1 - t0 );
}

bool Motion( int v ) {

    return ( T >= getVectorX( v ) ) && ( T < getVectorY( v ) ) ;
}

bool Moment( int v ) {

    double t0 = getVectorX( v ) ;
    double t1 = t0 + STEP ;
    return ( T >= t0 ) && ( T < t1 ) ;
}

// blinder
void VisualizePolygon( int polygon, int renderer, int r, int g, int b, int v ) {

    if ( Motion( v ) ) {
        if ( Moment( v ) ) {
            int screen = getScreenCoordinate( renderer ) ;
            addPolygon( polygon, renderer , screen );
            movePolygon( polygon, o, o, -1.0 );
        }
        double t = GetLinearTime( v ) ;
        int opacity = 255 * t ;
        setPolygonColor( polygon, r, g, b, opacity );
    }
}

void RemovePolygonAfterUnvisualize( 
    int polygon, int renderer, int r, int g, int b, int v 
) {

    double endtime = getVectorY( v ) ;
    int screen = getScreenCoordinate( renderer ) ;
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int opacity = 255 * ( 1.0 - t ) ;
        setPolygonColor( polygon, r, g, b, opacity );
        if ( T > endtime - STEP ) {
            removePolygon( polygon, renderer, screen );
        }
    }
}

void UnvisualezePolygon( int polygon, int r, int g, int b, int endopacity, int v ) {

    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int opacity = 255 - ( 255 - endopacity ) * t ;
        setPolygonColor( polygon, r, g, b, opacity );
    }
}

// text
string TEXT_RUSEN = "http://rusen.seesaa.net" ;

int NewTextPolygonLowLeft( string text, double magnification, double z ) {

    int framewidth_x = 14 ;
    int framewidth_y = 39 ;
    double size = -50 * z / magnification ;
    double x = -size * ( WIDTH - framewidth_x ) / 100 ; 
    double y = -size * ( HEIGHT - framewidth_y ) / 100 ;
    int txtpolygon = newTextPolygon( x, y, 1.0 + z, 0.9 * size, text ) ;
    return txtpolygon ;
}

void OpenTextWhite( int v, double t0, double t1 ) {

    SetTRangeAbsolutely( v, t0, t1 );
    VisualizePolygon( BLINDER, RENDERER, 255, 255, 255, v );
    SetTRange( v, o, 3.0 );
    if ( Moment ( v ) ) {
        COUNT = -1 ;
    }
    RemovePolygonAfterUnvisualize( BLINDER, RENDERER, 255, 255, 255, v );
    SetTRange( v, -4.0, 4.0 );
    VisualizePolygon( TEXT, RENDERER, 255, 255, 255, v );
    SetTRange( v, 3.0, 8.0 )
    UnvisualezePolygon( TEXT, 255, 255, 255, 5, v );
    SetTRange( v, -14.0, o );
}

void OpenBlindBlack( int v, double t0, double t1 ) {

    SetTRangeAbsolutely( v, t0, t1 );
    VisualizePolygon( BLINDER, RENDERER, 0, 0, 0, v );
    SetTRange( v, o, 3.0 );
    if ( Moment ( v ) ) {
        COUNT = -1 ;
    }
    RemovePolygonAfterUnvisualize( BLINDER, RENDERER, 0, 0, 0, v );
    SetTRange( v, -3.0, 5.0 );
    VisualizePolygon( TEXT, RENDERER, 255, 255, 255, v );
    SetTRange( v, 8.0, 5.0 )
    UnvisualezePolygon( TEXT, 255, 255, 255, 5, v );
    SetTRange( v, -18.0, o );
}

void CloseTextWhite( int v, double dt1, double dt0 ) {

    SetTRange( v, dt1, dt0 );
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int opacity = 255*t ;
        setPolygonColor( TEXT, 255, 255, 255, opacity );
    }
    SetTRange( v, dt1, 3.0 );
    VisualizePolygon( BLINDER, RENDERER, 255, 255, 255, v );
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int c = 255 * ( a - t ) ;
        setPolygonColor( TEXT, c, c, c, 255 ) ;
    }
    SetTRange( v , o, 2.0 );
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int opacity = 255 * ( a - t ) ;
        setPolygonColor( TEXT, 0, 0, 0, opacity );
    }
}

void CloseBlindBlack( int v, double dt1, double dt0 ) {

    SetTRange( v, dt1, dt0 );
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int opacity = 255*t ;
        setPolygonColor( TEXT, 255, 255, 255, opacity );
    }
    SetTRange( v , 5.0, 5.0 );
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        int opacity = 255 * ( a - t ) ;
        setPolygonColor( TEXT, 255, 255, 255, opacity );
    }
}


/* COLORS */

int[ ] Color( int i, int j, int k ) {

    int c[ 3 ];
    if ( ( i < 0 ) || ( j < 0 ) || ( k < 0 ) 
            || ( i > 255 ) || ( j > 255 ) || ( k > 255 ) ) {
        c = 0 ;
        alert( "Error ( color ) " );
    } else {
        c[0] = i ;
        c[1] = j ;
        c[2] = k ;
    }
    return c ;
}


/* GEOMETRY */

double GetHeightAntiprismByConnectionName( 
    int nside, double rad, string polyhedronname 
) {

    double delta = rad * ( 1 - cos( PI/nside ) ) ;
    double antiprismdhangle ; // 底面と側面の normal vector の作る角
    if ( polyhedronname == "cube" ) {
        antiprismdhangle = 3*PI/4 ;
    } else {
        alert( "error( GetHeightAntiprismByName )) ;
    }
    double antiprismheight = delta * tan( PI - antiprismdhangle ) ;
    return antiprismheight ;
}

int[ ] Get3Vectors4sideAntiprismCubeConnection( double baserad ) {

    int v[ 3 ] ;
    v[0] = newVector( o, o, baserad ) ;
    v[1] = GetRotYVector( v[0], PI/2 ) ;
    double h = GetHeightAntiprismByConnectionName( 4, baserad, "cube" ) ;
    v[2] = newVector( o, h, o ) ;
    return v ;
}


// import end




/* set lights */


int AMBIENT_LIGHT = newAmbientLight( o, o, o, o ) ;
int LIGHT0 = newPointLight( -l, -l, -l, o ) ;
int LIGHT1 = newLight( 0.1, 0.12, 0.2, o ) ;
int LIGHT2 = newLight( -0.2, -0.55, 0.41, o ) ; 

void SetLights() {
    double power = 0.8 ;
    SetAmbientLight ( AMBIENT_LIGHT, o, o, o, power, RENDERER ) ;
}




/* create elements (polygnのみ) */


void SetElements() {

    SetElementOptions() ;
    AddElements() ;
}


int NG = S6 ; // group の数
int TB0[ NG ][ R8+R4 ] ; // 底面0, octagn=R8, 頂点付近=R4
int TB1[ NG ][ R8+R4 ] ; // 底面1, octagn=R8, 頂点付近=R4
int TL0[ NG ][ 3*R4 ] ; // 側面0, 1枚を3分割する
int TL1[ NG ][ 3*R4 ] ; // 側面1, 1枚を3分割する
for ( int i=0; i<NG; i++ ) {
    for ( int j=0; j<R8+R4; j++ ) {
        TB0[i][j] = newTrianglePolygon( O, O, O ) ;
        TB1[i][j] = newTrianglePolygon( O, O, O ) ;
    }
    for ( int j=0; j<3*R4; j++ ) {
        TL0[i][j] = newTrianglePolygon( O, O, O ) ;
        TL1[i][j] = newTrianglePolygon( O, O, O ) ;
    }
}


void SetPolygons4sideAntiprismCubeConnection( 
    int base0[ ][ ], int base1[ ][ ], int latt0[ ][ ], int latt1[ ][ ],
    int ng, double baserad ) {

    int v[ ] = Get3Vectors4sideAntiprismCubeConnection( baserad ) ; // v[0]はz軸上、v[0], v[1]は底面の2頂点、v[2]は高さ
    // edge分点
    int mid1 = GetInternallyDividingVector( v[0], v[1], 1 - ISlv ) ;
    int mid2 = GetRotYVector( mid1, 2*PI/R8 ) ;
    int mid3 = GetRotYVector( mid1, -2*PI/R8 ) ;
    // 底面
    for ( int i=0; i<R8+R4; i++ ) {
        if ( i < R8 ) {
            setPolygonVector( base0[ng][i], O, mid2, mid1 ) ;
            setPolygonVector( base1[ng][i], O, mid1, mid2 ) ;
            rotYPolygon( base0[ng][i], 2*PI/R8 * i ) ;
            rotYPolygon( base1[ng][i], 2*PI/R8 * i ) ;
        } else {
            int n = i - R8 ;
            setPolygonVector( base0[ng][i], v[0], mid3, mid1 ) ;
            setPolygonVector( base1[ng][i], v[0], mid1, mid3 ) ;
            rotYPolygon( base0[ng][i], -PI/2 * n ) ;
            rotYPolygon( base1[ng][i], PI/2 * n ) ;
        }
        movePolygon( base1[ng][i], v[2] ) ;
        rotYPolygon( base1[ng][i], 2*PI/R8 ) ;
    }
    // 側面
    int u = GetRotYVector( v[0], 2*PI/R8 ) ;
    moveVector( u, v[2] ) ;
    for ( int i=0; i<3*R4; i++ ) {
        if ( i%3 == 0 ) {
            setPolygonVector( latt0[ng][i], v[0], mid1, u ) ;
            setPolygonVector( latt1[ng][i], v[0], mid1, u ) ;
        } else if ( i%3 == 1 ) {
            setPolygonVector( latt0[ng][i], mid1, mid2, u ) ;
            setPolygonVector( latt1[ng][i], mid1, mid2, u ) ;
        } else {
            setPolygonVector( latt0[ng][i], mid2, v[1], u ) ;
             setPolygonVector( latt1[ng][i], mid2, v[1], u ) ;
        }
        rotPolygon( latt1[ng][i], PI, mid2 ) ;
        movePolygon( latt1[ng][i], v[2] ) ;
        rotYPolygon( latt0[ng][i], 2*PI/R4 * ( i / 3 ) ) ;
        rotYPolygon( latt1[ng][i], 2*PI/R4 * ( i / 3 ) ) ;
    }
 }


int OPACITY[ ] = { 255, 100 } ;
float OPTION0[ 6 ], OPTION1[ 6 ] ;
{
    float emissive = o ; 
    float diffractive = 0.4 ; 
    float diffuse = 0.6 ; 
    float ambient = 0.1 ;
    float specularintensity = 0.9, specularangle = PI/7; 

    OPTION0[0] = emissive ;
    OPTION0[1] = diffractive ;
    OPTION0[2] = diffuse ;
    OPTION0[3] = ambient ;
    OPTION0[4] = specularintensity ; OPTION0[5] = specularangle ;
    OPTION1 = OPTION0 ;
    OPTION1[4] = 1.0 ; OPTION1[5] = 1.5 ;
}

void SetElementOptions() {

    for ( int i=0; i<NG; i++ ) {
        for ( int j=0; j<R8+R4; j++ ) {
            setPolygonColor( TB0[i][j], 100, 30, 255, OPACITY[0] ) ;
            setPolygonColor( TB1[i][j], 255, 30, 100, OPACITY[0] ) ;
        }
        for ( int j=0; j<3*R4; j++ ) {
            setPolygonColor( TL0[i][j], 180, 255, 30, OPACITY[0] ) ;
            setPolygonColor( TL1[i][j], 255, 250, 30, OPACITY[0] ) ;
        }
        for ( int j=0; j<12; j++ ) {
            SetPolygonSurface( TB0[i][j], OPTION0 ) ;
            SetPolygonSurface( TB1[i][j], OPTION0 ) ;
            SetPolygonSurface( TL0[i][j], OPTION0 ) ;
            SetPolygonSurface( TL1[i][j], OPTION0 ) ;
        }
    }
}


void AddElements() {

    int n = length( COORD ) ;
    addLight( LIGHT1, RENDERER, COORD[n-1] ) ;
    addLight( LIGHT2, RENDERER, COORD[n-1] ) ;
    setLightBrightness( LIGHT1, 0.7 ) ;
    setLightBrightness( LIGHT2, 0.4 ) ;
    for ( int i=0; i<NG; i++ ) {
        SetPolygons4sideAntiprismCubeConnection( TB0, TB1, TL0, TL1, i, o ) ;
        for ( int j=0; j<12; j++ ) {
            addPolygon( TB0[i][j], RENDERER, CD[i] ) ;
            addPolygon( TB1[i][j], RENDERER, CD[i] ) ;
            addPolygon( TL0[i][j], RENDERER, CD[i] ) ;
            addPolygon( TL1[i][j], RENDERER, CD[i] ) ;
        }
    }
}




/* set coordinates */


int COORD[ 7 ] ;
int CD[ NG ] ;
for ( int i=0; i<length( COORD ); i++ ) {
    COORD[i] = newCoordinate() ;
}
for ( int i=0; i<NG; i++ ) {
    CD[i] = newCoordinate() ;
}

void SetCoordinates() {

    PileCoordinate( COORD, RENDERER ) ;
    int len[ ] = length( CD ) ;
    for ( int i=0; i<NG; i++ ) {
        addCoordinate( CD[i], RENDERER, COORD[0] ) ;
    }
}




/* set axes */


int AXIS[ 13 ] ;
{
    int n = length( AXIS ) ; 
    float x, y, z ;
    for ( int i=0; i<n; i++ ) {
        x = ( 5*l - 0.5*l*i ) * l ; y = x ; z = x ;
        AXIS[i] = newAxisModel( x, y, z ) ;
    }
}

void SetAxes() {

    addModel( AXIS[0], RENDERER, COORD[0] ) ;
    for ( int i=0; i<NG; i++ ) {
        addModel( AXIS[2+i], RENDERER, CD[i] ) ;
    }
}




/* prepare stage */


double CAM_X0 = o;
double CAM_Y0 = o;
double CAM_Z0 = 13*l ;
float GRAPHIC_MAGNIFICATION = 1000.0 ;
double GRAPHIC_DISTANCE = 10.0 ;
int WORLD;

void PrepareStage() {

    setGraphics3DCenter( RENDERER, WIDTH / 2, HEIGHT / 2 ) ;
    setGraphics3DDistance( RENDERER, GRAPHIC_DISTANCE ) ;
    setGraphics3DMagnification( RENDERER, GRAPHIC_MAGNIFICATION ) ;

    setGraphics3DClipFront( RENDERER, o ) ;
    setGraphics3DClipBack( RENDERER, -10000.0 ) ;

    WORLD = getWorldCoordinate( RENDERER ) ;
    setCoordinateOrigin( WORLD, o, o, o ) ; 
    setCoordinateEulerAngle( WORLD, o, o, o ) ;
    setCameraOrigin( WORLD, CAM_X0, CAM_Y0, CAM_Z0 ) ;
    setCameraEulerAngle( WORLD, o, o, o ) ;
}




/* animation Loop except
ただし、ForwardMotion() と CreateGuiElements() 以外 */


bool KEEP_LOOP = true ;
bool SAVE_A_PICTURE = false ;

int COUNT = 0 ;
int FPS = 25 ; // frames / 1sec
int PICTURE_NUMBER = 0 ; 
int PICTURE_END_NUMBER = 5000 ;

double T = o ;
double T0 = -100.0 ;
double STEP, TIME_FLOW ;
{
    TIME_FLOW = 1.0 ;
    STEP = TIME_FLOW / FPS ;
}




/* create GUI elements */


int SETTING_WINDOW ; 

int LABEL_SLIDER[ 5 ] ;
N = length( LABEL_SLIDER ) ; int SLIDER[ N ] ; string SLIDER_TEXT[ N ] ; 
double P[ N ] = o, P0[ N ] ;

int CHECK_BOX[ 1 ] ;
N = length( CHECK_BOX ) ; string CHECK_TEXT[ N ] ;
bool SYNCHRO_SLIDER = true ;

int LABEL_SELECT[ 1 ] ;
N = length( LABEL_SELECT ) ; int SELECT[ N ] ; string SELECT_TITLE[ N ] ;
string SELECT_TEXT[ N ][ 3 ] ;
bool GET_TIME = false ;
bool TURN_GET_TIME = false ;
// 展開パターン
int UNFOLD_INDEX = 0 ;
int FORMER_UNFOLD_INDEX = 0 ; 
SELECT_TITLE[0] = "展開のパターン" ;
SELECT_TEXT[0][0] = "リセット(展開のパターンは下から選択)" ;
SELECT_TEXT[0][1] = "頂点でつながった展開のパターン" ;
SELECT_TEXT[0][2] = "稜線でつながった展開のパターン" ;
CHECK_TEXT[0] = "反角柱間の角度をすべてそろえる" ;
SLIDER_TEXT[0] = "1番目と2番目の反角柱間の角度" ; 
SLIDER_TEXT[1] = "2番目と3番目の反角柱間の角度" ; 
SLIDER_TEXT[2] = "3番目と4番目の反角柱間の角度" ; 
SLIDER_TEXT[3] = "4番目と5番目の反角柱間の角度" ; 
SLIDER_TEXT[4] = "5番目と6番目の反角柱間の角度" ; 


void CreateGuiElements() {

    // setting window
    int sidewidth = 6 ;
    int nsell = length( SELECT ) ; int nsel = nsell ;
    int nsldl = length( SLIDER ) ; int nsld = nsldl ;
    int lx = 15 , lw = 250 ; 
    int lh = 15 ; int lyspace = 20 ;
    int sliderx = lx , sliderw = lw, sliderh = lh , slideryspace = 5 ;
    int sliderlabely[ nsldl ] ; int slidery[ nsld ] ;
    int selectx = lx , selectw = lw - sidewidth , selecth = 20 , selectyspace = 5 ;
    int selectlabely[ nsell ] ; int selecty[ nsel ] ;
    int checkx = lx, checkw = lw, checkh = lh, checkyspace = 5 ;
    int checky ;

    {
        int initial_ly = 10;
        for ( int i=0; i<nsel; i++ ) {
            selectlabely[i] = initial_ly 
                + ( lyspace + lh + selectyspace + selecth ) * i ;
            selecty[i] = selectlabely[i] + lh + selectyspace ;
        }
        checky = selecty[nsel-1] + selecth + lyspace ;
        for ( int i=0; i<nsld; i++ ) {
            sliderlabely[i] = checky + checkh + lyspace
                + ( lyspace + lh + slideryspace + sliderh ) * i ;
            slidery[i] = sliderlabely[i] + lh + slideryspace ;
        }
    }

    int wx = WINDOW_POSITION_X + WIDTH + 1 * sidewidth ;
    int wy = 0 ;
    int framewidth_y = 30 ;
    int ww = lw + 2*lx + 2*sidewidth ;
    int wh = slidery[nsld-1] + 70 ;

    {
        string wtext = "Setting Window" ;
        SETTING_WINDOW = newWindow( wx, wy, ww, wh, wtext ) ;

        // select field
        int lentex[ ] = length( SELECT_TEXT ) ; int lentex0 = lentex[0] ;
        for ( int i=0; i<nsel; i++ ) {
            LABEL_SELECT[i] = newTextLabel( 
                                    lx, selectlabely[i], lw, lh, SELECT_TITLE[i]
                                ) ;
            addComponent( LABEL_SELECT[i], SETTING_WINDOW ) ;
            setComponentFontSize( LABEL_SELECT[i], 14 ) ; // default 12
            string text[ lentex0 ] ;
                for ( int j=0; j<lentex0; j++ ) {
                    text[j] = SELECT_TEXT[i][j] ;
                }
            SELECT[i] = newSelectField( selectx, selecty[i], selectw, selecth, text ) ; 
            addComponent( SELECT[i], SETTING_WINDOW ) ;
        }

        // check box (select field と slider の間)
        CHECK_BOX[0] = newCheckBox ( 
                            lx, checky, lw, checkh, CHECK_TEXT[0], true
                        ) ;
        addComponent( CHECK_BOX[0], SETTING_WINDOW ) ;

        // slider
        for ( int i=0; i<nsld; i++ ) {
            LABEL_SLIDER[i] = newTextLabel( 
                                    lx, sliderlabely[i], lw, lh, SLIDER_TEXT[i] 
                                ) ;
            addComponent( LABEL_SLIDER[i], SETTING_WINDOW ) ;
            SLIDER[i] = newHorizontalSlider( sliderx, slidery[i], sliderw, sliderh, o ) ;
            addComponent( SLIDER[i], SETTING_WINDOW ) ;
            if ( SYNCHRO_SLIDER ) {
                if ( i >= 1 ) {
                    hideComponent( SLIDER[i] ) ;
                }
            }
        }
    }

    paintComponent( SETTING_WINDOW ) ;
}




/* event handlers */

void onSliderMove( int id, double value ) {

    if ( ! TURN_GET_TIME ) {

        double p ; int deg[ SLIDER ] ;
        if ( SYNCHRO_SLIDER ) {
            if ( UNFOLD_INDEX == 1 ) {
                for ( int i=0; i<length( SLIDER ); i++ ) {
                    if ( id == SLIDER[i] ) {
                        p = value ;
                    }
                }
                P = p ;
                deg = p * 90 ;
                FoldArroundVertex( P ) ;
            } else if ( UNFOLD_INDEX == 2 ) {
                double anglerange = 2*GetAngleLateralLateral() ;
                float degrange = anglerange/PI * 180 ;
                for ( int i=0; i<length( SLIDER ); i++ ) {
                    if ( id == SLIDER[i] ) {
                        p = value ;
                    }
                }
                P = p ;
                deg = ( p - a/2 ) * degrange ;
                FoldArroundEdge( P ) ;
            }
            for ( int i=0; i<length( SLIDER ); i++ ) {
                int nth = i + 1 , next = nth + 1 ;
                SLIDER_TEXT[i] = 
                    nth + " 番目と" + next + " 番目の反角柱間の角度 " 
                    + deg[i] + " 度" ;
                setComponentText( LABEL_SLIDER[i], SLIDER_TEXT[i] ) ;
                paintComponent( LABEL_SLIDER[i] ) ;
            }
        } else {
            if ( UNFOLD_INDEX == 1 ) {
                for ( int i=0; i<length( SLIDER ); i++ ) {
                    P[i] = getComponentValue( SLIDER[i] ) ;
                    deg[i] = P[i] * 90 ;
                }
                FoldArroundVertex( P ) ;
            } else if ( UNFOLD_INDEX == 2 ) {
                double anglerange = 2*GetAngleLateralLateral() ;
                float degrange = anglerange/PI * 180 ;
                for ( int i=0; i<length( SLIDER ); i++ ) {
                    P[i] = getComponentValue( SLIDER[i] ) ;
                    deg[i] = ( P[i] -a/2 ) * degrange ;
                }
                FoldArroundEdge( P ) ;
            }
            for ( int i=0; i<length( SLIDER ); i++ ) {
                int nth = i, next = nth + 1 ;
                SLIDER_TEXT[i] = 
                nth + " 番目と" + next + " 番目の反角柱間の角度 " 
                + deg[i] + " 度" ;
                setComponentText( LABEL_SLIDER[i], SLIDER_TEXT[i] ) ;
                paintComponent( LABEL_SLIDER[i] ) ;
            }
        }
    }
    if ( FORMER_UNFOLD_INDEX == 0 && UNFOLD_INDEX == 0 ) {
        SLIDER_TEXT[0] = "展開のパターンを選択して下さい" ;
        setComponentFontSize( LABEL_SLIDER[0], 14 ) ;
        setComponentText( LABEL_SLIDER[0], SLIDER_TEXT[0] ) ;
        paintComponent( LABEL_SLIDER[0] ) ;
        paintComponent( SLIDER[0] ) ;
    }
}


void onSelectFieldClick( int id, string text ){

    if ( TURN_GET_TIME ) {
    } else {

        if ( id == SELECT[0] ) {
            int n[ ] = length( SELECT_TEXT ) ;
            for ( int i=0; i<n[0]; i++ ) {
                if ( text == SELECT_TEXT[0][i] ) {
                    if ( ( i == FORMER_UNFOLD_INDEX ) && ( i != 0 ) ) {
                    } else {
                        if ( FORMER_UNFOLD_INDEX == 0 && UNFOLD_INDEX == 0 ) {
                            SLIDER_TEXT[0] = "1 番目と2 番目の反角柱間の角度 " 
                                                + 0 + " 度" ;
                            setComponentFontSize( LABEL_SLIDER[0], 12 ) ;
                            setComponentText( LABEL_SLIDER[0], SLIDER_TEXT[0] ) ;
                            paintComponent( LABEL_SLIDER[0] ) ;
                            paintComponent( SLIDER[0] ) ;
                        }
                        UNFOLD_INDEX = i ;
                        GET_TIME = true ;
                        TURN_GET_TIME = true ;
                    }
                }
            }
        }
    }
}


void onCheckBoxClick( int id , bool state ) {

    if ( !TURN_GET_TIME ) {

        if ( id == CHECK_BOX[0] ) {
            SYNCHRO_SLIDER = state ;
            if ( SYNCHRO_SLIDER ) {
                for ( int i=1; i<length( SLIDER ); i++ ) {
                    hideComponent( SLIDER[i] ) ;
                }
                GET_TIME = true ;
                TURN_GET_TIME = true ;
            } else {
                P[0] = getComponentValue( SLIDER[0] ) ;
                for ( int i=1; i<length( SLIDER ); i++ ) {
                    P[i] = P[0] ;
                    showComponent( SLIDER[i] ) ;
                    setComponentValue( SLIDER[i], P[i] ) ;
                }
            }
        }
    }
}




/* forward motion */


bool CREATE_GUI = false ;
bool TURN_GUI = false ;
double STOP_TIME ;
double GUI_UPTIME ;

void ForwardMotion() {

    int t = newVector( o, o, o ) ; // x,y成分がそれぞれmotion開始、終了時刻
    double toprotrate = 2/180.0 * PI ;

    if ( (!TURN_GUI) || TURN_GET_TIME ) {
        DesignMotion( t, toprotrate ) ; // アニメーション
        STOP_TIME = getVectorY( t ) ; // motion終了時刻
        GUI_UPTIME = STOP_TIME + 1.0 ;
        CREATE_GUI = ( T >= GUI_UPTIME ) && ( T < GUI_UPTIME + STEP ) ;
    }

    if ( T < GUI_UPTIME + 100.0 ) {
        rotYCoordinate( COORD[2], toprotrate ) ;
    }
}

{
    int len[ ] = length( CD ) ;
    N = len[0] ;
}
int SO[ N ] ; // system origin point
int SA[ N ] ; // system Euler Angle
int RC[ N ] ; // rotation center vector
int AX[ N ] ; // rotation axis vector
for ( int i=0; i<N; i++ ) {
    SO[i] = newVector() ;
    SA[i] = newVector() ;
    RC[i] = newVector() ;
    AX[i] = newVector() ;
}

int G = newVector() ; // center of gravity

int BLINDER = newQuadranglePolygon( 2*l,2*l,o, -2*l,2*l,o, -2*l,-2*l,o, 2*l,-2*l,) ;
setPolygonEmissive( BLINDER, 1.0 ) ;
setPolygonSpecular( BLINDER, o, 0.01 ) ;
int TEXT = NewTextPolygonLowLeft( TEXT_RUSEN, GRAPHIC_MAGNIFICATION, -0.5 ) ;


void DesignMotion( int v, double yrotation ) {

    double start_t = 1.0 ;
    double d = 1.0 / 3.0 ; // 時間の単位

    SetTRangeAbsolutely( v, start_t, start_t ) ;

    SetTRange( v, o, STEP ) ;
    if ( Motion( v ) ) {
        double h ;
        for ( int i=0; i<NG; i++ ) {
            h = 2*GetHeightAntiprismByConnectionName( 4, l, "cube" ) * ( i - NG / 2 ) ;
            setCoordinateOrigin( CD[i], o, h, o ) ;
        }
        setCoordinateOrigin( COORD[0], o,10*l, o ) ;
        setCoordinateEulerAngle( COORD[1], o, PI/2, o ) ;
    }

    SetTRange( v, o, 10*d ) ;
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        double rad = l * t ;
        for ( int i=0; i<NG; i++ ) {
            SetPolygons4sideAntiprismCubeConnection( TB0, TB1, TL0, TL1, i, rad ) ;
            double s = Slope( t, 0.25/NG * i, 1 - 0.25/NG * ( NG - 1 ) ) ;
            double rt = 4*l * sin( 2*PI*s ) ;
            double h = 3*GetHeightAntiprismByConnectionName( 4, l, "cube" ) 
                        * ( i - NG / 2 ) ;
            int vt = newVector(    rt * sin( 4*PI*s ), h, rt * cos( 4*PI*s ) ) ;
            setCoordinateOrigin( CD[i], vt ) ;
        }
        setCoordinateOrigin( COORD[0], o, 4*l * ( 1 - t ), o ) ;
        setCoordinateEulerAngle( COORD[1], o, PI/2 * ( 1 - 0.1*t ), o ) ;
    }

    int stop = newVector( v ) ;

    if ( GET_TIME ) {
        T0 = T ;
        GET_TIME = false ;
    }

    if ( FORMER_UNFOLD_INDEX != 0 ) {
        SetTRangeAbsolutely( v, T0, T0 + 3*d - 3*STEP ) ;
        if ( Motion( v ) ) {
            if ( Moment ( v ) ) {
                for ( int i=0; i<length( SLIDER ); i++ ) {
                    P0[i] = getComponentValue( SLIDER[i] ) ;
                }
            }
            double t = GetLinearTime( v ) ;
            int deg ;
            for ( int i=0; i<length( SLIDER ); i++ ) {
                if ( FORMER_UNFOLD_INDEX != UNFOLD_INDEX ) {
                    if ( SYNCHRO_SLIDER ) {
                        P[i] = P0[0] * ( 1 - t ) ;
                    } else {
                        P[i] = P0[i] * ( 1 - t ) ;
                    }
                } else if ( FORMER_UNFOLD_INDEX == UNFOLD_INDEX ) {
                    P[i] = P0[i] * ( 1 - t ) + P0[0] * t ;
                }
            }
            if ( FORMER_UNFOLD_INDEX == 1 ) {
                for( int i=0; i<length( SLIDER ); i++ ) {
                    deg = P[i] * 90 ;
                    setComponentValue( SLIDER[i], P[i] ) ;
                    SLIDER_TEXT[i] = 
                        "反角柱間の角度 " + deg + " 度" + " ...please wait... ";
                    setComponentText( LABEL_SLIDER[i], SLIDER_TEXT[i] ) ;
                    paintComponent( LABEL_SLIDER[i] ) ;
                }
                FoldArroundVertex( P ) ;
            } else ( FORMER_UNFOLD_INDEX == 2 ) {
                double anglerange = 2*GetAngleLateralLateral() ;
                float degrange = anglerange/PI * 180 ;
                for( int i=0; i<length( SLIDER ); i++ ) {
                    deg = ( P[i] - a/2 ) * degrange ;
                    setComponentValue( SLIDER[i], P[i] ) ;
                    SLIDER_TEXT[i] = 
                        "反角柱間の角度 " + deg + " 度" + " ...please wait... ";
                    setComponentText( LABEL_SLIDER[i], SLIDER_TEXT[i] ) ;
                    paintComponent( LABEL_SLIDER[i] ) ;
                    if ( UNFOLD_INDEX == 1 || UNFOLD_INDEX == 0 ) {
                        P[i] = P[i] + 0.5 * t ;
                    }
                }
                FoldArroundEdge( P ) ;
            }
            if ( t == a ) {
                if ( FORMER_UNFOLD_INDEX != UNFOLD_INDEX ) {
                    for ( int i=0; i<length( SLIDER ); i++ ) {
                        int nth = i + 1, next = nth + 1 ;
                        SLIDER_TEXT[i] = 
                            nth + " 番目と" + next + " 番目の反角柱間の角度 " 
                        + 0 + " 度" ;
                        setComponentText( LABEL_SLIDER[i], SLIDER_TEXT[i] ) ;
                        paintComponent( LABEL_SLIDER[i] ) ;
                    }
                } else if ( FORMER_UNFOLD_INDEX == UNFOLD_INDEX ) {
                    for ( int i=0; i<length( SLIDER ); i++ ) {
                        if ( FORMER_UNFOLD_INDEX == 1 ) {
                            deg = P[i] * 90 ;
                        } else if ( FORMER_UNFOLD_INDEX == 2 ) {
                            double anglerange = 2*GetAngleLateralLateral() ;
                            float degrange = anglerange/PI * 180 ;
                            deg = ( P[i] - a/2 ) * degrange ;
                        }
                        int nth = i + 1, next = nth + 1 ;
                        SLIDER_TEXT[i] = 
                            nth + " 番目と" + next + " 番目の反角柱間の角度 " 
                        + deg + " 度" ;
                        setComponentText( LABEL_SLIDER[i], SLIDER_TEXT[i] ) ;
                        paintComponent( LABEL_SLIDER[i] ) ;
                        setComponentValue( SLIDER[i], P[i] ) ;
                    }
                }
                if ( ( FORMER_UNFOLD_INDEX == UNFOLD_INDEX ) && ( UNFOLD_INDEX != 0 ) ) {
                    TURN_GET_TIME = false ;
                }
            }
        }
    }

    double t0 = T0 ;
    if ( FORMER_UNFOLD_INDEX != 0 ) { t0 = T0 + 3*d ; }

    SetTRangeAbsolutely( v, t0, t0 + 3*d );
    if ( Motion( v ) ) {
        if ( Moment ( v ) ) {
            setVector( AX[0], o, a, o ) ;
            for ( int i=0; i<NG; i++ ) {
                SetVectorsCoordinateLocationAttitude( SO[i], SA[i], CD[i] ) ;
                if ( i <= 4 ) {
                    hideComponent( SLIDER[i] ) ;
                }
            }
        }
        double t = GetLinearTime( v ) ;
        double angle = o ;
        if ( FORMER_UNFOLD_INDEX == 0 ) {
            double s1 = Slope( t, o, 0.5*a ) ;
            double s2 = Slope( t, 0.5*a, 0.5*a ) ;
            if ( UNFOLD_INDEX == 0 ) {
                for ( int i=0; i<NG; i++ ) {
                    double s = Slope( t, 0.06*i, a - 0.06*i ) ;
                    double h = 3*GetHeightAntiprismByConnectionName( 4, l, "cube" ) 
                                * ( i - NG / 2 ) ;
                    setCoordinateOrigin( CD[i], o, h, o ) ;
                    setCoordinateEulerAngle( CD[i], PI/2, 2*PI * s, -PI/2 ) ;
                }
            } else {
                for ( int i=0; i<NG; i++ ) {
                    double x = -3*l + 2*l * ( ( i + 1 ) / 2 ) ;
                    double y = getVectorY( SO[i] ) ;
                    double z = 2*l - 2*l * ( i / 2 ) ;
                    int v1 = newVector( x, y, z ) ;
                    int vt1 = GetInternallyDividingVector( SO[i], v1, s1 ) ;
                    int vt2 = newVector( o, -y * s2, o ) ;
                    SetCoordinateLocationAttitude( CD[i], vt1, SA[i] ) ;
                    moveCoordinate( CD[i], vt2 ) ;
                }
            }
            if( UNFOLD_INDEX == 2 ) {
                for ( int i=0; i<=4; i++ ) {
                    angle = PI/4 * s2 * Parity( i ) ;
                    int j = 1 ; if ( i%2 == 1 ) { j = 2 ; }
                    int rc = GetVertexVector( CD[i], j ) ; // i番目の回りの回転 center
                    for ( int j=1+i; j<=5; j++ ) {
                        rotCoordinate( CD[j], angle, AX[0], rc ) ;
                    }
                }
                int origin[ 2 ] ;
                origin[0] = GetCoordinateOriginVector( CD[0] ) ;
                origin[1] = GetCoordinateOriginVector( CD[5] ) ;
                G = GetVectorGravityCenter( origin ) ;
                scaleVector( G, -a, -a, -a ) ;
                setCoordinateOrigin( COORD[0], G ) ;
            }
        } else if ( FORMER_UNFOLD_INDEX == 1 ) {
            double s1 = Slope( t, o, a/2 ) ;
            double s2 = Slope( t, a/2, a/2 ) ;
            if( UNFOLD_INDEX == 0 ) {
                for ( int i=0; i<NG; i++ ) {
                    double x = getVectorX( SO[i] ) ;
                    double y = 3*GetHeightAntiprismByConnectionName( 4, l, "cube" ) 
                                * ( i - NG / 2 ) ;
                    double z = getVectorZ( SO[i] ) ;
                    int v1 = newVector( x, y, z ) ;
                    int vt1 = GetInternallyDividingVector( SO[i], v1, s1 ) ;
                    int vt2 = newVector( -x*s2, o, -z*s2 ) ;
                    setCoordinateOrigin( CD[i], vt1 ) ;
                    moveCoordinate( CD[i], vt2 ) ;
                }
            } else if( UNFOLD_INDEX == 2 ) {
                for ( int i=0; i<NG; i++ ) {
                    SetCoordinateLocationAttitude( CD[i], SO[i], SA[i] ) ;
                }
                for ( int i=0; i<=4; i++ ) {
                    angle = PI/4 * t * Parity( i ) ;
                    int j = 1 ; if ( i%2 == 1 ) { j = 2 ; }
                    int rc = GetVertexVector( CD[i], j ) ; // i番目の回りの回転 center
                    for ( int j=1+i; j<=5; j++ ) {
                        rotCoordinate( CD[j], angle, AX[0], rc ) ;
                    }
                }
                int origin[ 2 ] ;
                origin[0] = GetCoordinateOriginVector( CD[0] ) ;
                origin[1] = GetCoordinateOriginVector( CD[5] ) ;
                G = GetVectorGravityCenter( origin ) ;
                scaleVector( G, -a, -a, -a ) ;
                setCoordinateOrigin( COORD[0], G ) ;
            }
        } else if ( FORMER_UNFOLD_INDEX == 2 ) {
            double s1 = Slope( t, o, a/2 ) ;
            double s2 = Slope( t, a/4, a/2 ) ;
            double s3 = Slope( t, a/2, a/2 ) ;
            if( UNFOLD_INDEX == 0 ) {
                int so[ NG ] ;
                for ( int i=0; i<NG; i++ ) {
                    SetCoordinateLocationAttitude( CD[i], SO[i], SA[i] ) ;
                    so[i] = newVector( SO[i] ) ;
                }
                for ( int i=0; i<=4; i++ ) {
                    angle = -PI/4 * s1 * Parity( i ) ;
                    int j = 1 ; if ( i%2 == 1 ) { j = 2 ; }
                    int rc = GetVertexVector( CD[i], j ) ; // i番目の回りの回転 center
                    for ( int j=1+i; j<=5; j++ ) {
                        rotCoordinate( CD[j], angle, AX[0], rc ) ;
                        so[j] = GetCoordinateOriginVector( CD[j] ) ;
                    }
                }
                for ( int i=0; i<NG; i++ ) {
                    double x = getVectorX( so[i] ) ;
                    double y = 3*GetHeightAntiprismByConnectionName( 4, l, "cube" ) 
                                * ( i - NG / 2 ) ;
                    double z = getVectorZ( so[i] ) ;
                    int v1 = newVector( x, y, z ) ;
                    int vt1 = GetInternallyDividingVector( so[i], v1, s2 ) ;
                    int vt2 = newVector( -x*s3, o, -z*s3 ) ;
                    setCoordinateOrigin( CD[i], vt1 ) ;
                    moveCoordinate( CD[i], vt2 ) ;
                }
            } else if( UNFOLD_INDEX == 1 ) {
                for ( int i=0; i<NG; i++ ) {
                    SetCoordinateLocationAttitude( CD[i], SO[i], SA[i] ) ;
                }
                for ( int i=0; i<=4; i++ ) {
                    angle = -PI/4 * t * Parity( i ) ;
                    int j = 1 ; if ( i%2 == 1 ) { j = 2 ; }
                    int rc = GetVertexVector( CD[i], j ) ; // i番目の回りの回転 center
                    for ( int j=1+i; j<=5; j++ ) {
                        rotCoordinate( CD[j], angle, AX[0], rc ) ;
                    }
                }
            }
            int origin[ 2 ] ;
            origin[0] = GetCoordinateOriginVector( CD[0] ) ;
            origin[1] = GetCoordinateOriginVector( CD[5] ) ;
            G = GetVectorGravityCenter( origin ) ;
            scaleVector( G, -a, -a, -a ) ;
            setCoordinateOrigin( COORD[0], G ) ;
        }
        if ( t == a ) {
            for ( int i=0; i<length( SLIDER ); i++ ) {
                if ( UNFOLD_INDEX == 2 ) {
                    P[i] = a/2 ;
                    setComponentValue( SLIDER[i], P[i] ) ; // slieder原点を瞬間的に移すため、onSliderMove内の処理と干渉しないこと
                } else {
                    P[i] = o ;
                    setComponentValue( SLIDER[i], P[i] ) ;
                }
                if ( SYNCHRO_SLIDER ) {
                    if ( i == 0 ) {
                        showComponent( SLIDER[i] ) ;
                    }
                } else {
                    if ( i <= 4 ) {
                        showComponent( SLIDER[i] ) ;
                    }
                }
            }
            FORMER_UNFOLD_INDEX = UNFOLD_INDEX ;
            TURN_GET_TIME = false ;
        }
    }

    setVector( v, stop ) ;
}


// n番目の頂点ベクトルを返す
int GetVertexVector( int cd, int n ) {

    int v[ ] = Get3Vectors4sideAntiprismCubeConnection( l ) ;
    int u = newVector( v[0] ) ;
    if ( n <= 3 ) {
        rotYVector( u, PI/2 * n ) ;
    } else {
        rotYVector( u, PI/2 * ( n - 4 ) + PI/4 ) ;
        moveVector( u, v[2] ) ;
    }
    int w = GetTransformedVector( u, RENDERER, cd, COORD[0] ) ;
    return w ;
}

// 頂点の回りに折る
void FoldArroundVertex( double anp[ ] ) {

    double angle[ ] = anp * PI/2;
    double rot[ NG ] ;
    int so[ NG ], sa[NG], rc[ NG ] ;
    int ax[ NG ];
    int dummycd[ NG ] ;
    for( int i=0; i<NG; i++ ) {
        dummycd[i] = newCoordinate() ;
        addCoordinate( dummycd[i], RENDERER, COORD[0] ) ;
        sa[i] = newVector() ;
    }
    for ( int i=0; i<NG; i++ ) {
        so[i] = newVector( -3*l + 2*l * ( ( i + 1 ) / 2 ), o, 2*l - 2*l * ( i / 2 ) ) ;
        SetCoordinateLocationAttitude( dummycd[i], so[i], O ) ;
        int n ;
        if ( ( i == 0 ) || ( i == 2 ) ) {
            n = 1 ;
        } else if ( ( i == 1 ) ) {
            n = 2 ;
        } else if ( ( i == 3 ) || ( i == 5 ) ) {
            n = 3 ;
        } else {
            n = 0 ;
        }
        rc[i] = GetVertexVector( dummycd[i], n ) ;
        if ( ( i == 0 ) || ( i == 2 ) || ( i == 3 ) || ( i == 5 ) ) {
            ax[i] = newVector( o, o, a ) ;
        } else {
            ax[i] = newVector( a, o, o ) ;
        }
        if ( ( i == 0 ) || ( i == 1 ) ) {
            rot[i] = -angle[i] ;
        } else if ( i == 2 ) {
            rot[i] = -angle[i]/2 ;
        } else if ( i == 3 ) {
            rot[i] = angle[i-1]/2 ;
        } else {
            rot[i] = angle[i-1] ;
        }
    }
    for ( int i=0; i<=2; i++ ) {
        for ( int j=0; j<=i; j++ ) {
            rotCoordinate( dummycd[j], rot[i], ax[i], rc[i] ) ;
            rotCoordinate( dummycd[5-j], rot[5-i], ax[5-i], rc[5-i] ) ;
        }
    }
    double offset ;
    for ( int i=0; i<NG; i++ ) {
        SetVectorsCoordinateLocationAttitude( so[i], sa[i], dummycd[i] ) ;
        SetCoordinateLocationAttitude( CD[i], so[i], sa[i] ) ;
        for ( int j=0; j<12; j++ ) {
            offset = ( angle[0] + angle[1] + angle[2] + angle[3] + angle[4] ) / 20 ;
            setPolygonSortOffset( TL1[i][j], -offset ) ;
        }
    }
}

// 稜線の回りに折る
void FoldArroundEdge( double anp[ ] ) { 

    double anglerange = 2*GetAngleLateralLateral() ;
    double angle[ ] = ( anp - a/2 ) * anglerange ;
    double rot[ NG ] ;
    int so[ NG ], sa[NG], rc[ NG ] ;
    int ax[ NG ];
    int dummycd[ NG ] ;
    for( int i=0; i<NG; i++ ) {
        dummycd[i] = newCoordinate() ;
        addCoordinate( dummycd[i], RENDERER, COORD[0] ) ;
        sa[i] = newVector() ;
    }
    for ( int i=0; i<NG; i++ ) {
        so[i] = newVector( -3*l + 2*l * ( ( i + 1 ) / 2 ), o, 2*l - 2*l * ( i / 2 ) ) ;
        SetCoordinateLocationAttitude( dummycd[i], so[i], O ) ;
    }
    for ( int i=0; i<=4; i++ ) {
        double th = PI/4 * Parity( i ) ;
        int j = 1 ; if ( i%2 == 1 ) { j = 2 ; }
        int ax = newVector( o, a, o ) ;
        int rc = GetVertexVector( dummycd[i], j ) ;
        for ( int j=1+i; j<=5; j++ ) {
            rotCoordinate( dummycd[j], th, ax, rc ) ;
        }
    }
    for ( int i=0; i<NG; i++ ) {
        int n , m ;
        if ( ( i == 0 ) || ( i == 2 ) ) {
            n = 1 ; m = 5 ;
        } else if ( ( i == 1 ) ) {
            n = 2 ; m = 5 ;
        } else if ( ( i == 3 ) || ( i == 5 ) ) {
            n = 3 ; m = 6 ;
        } else {
            n = 0 ; m = 4 ;
        }
        rc[i] = GetVertexVector( dummycd[i], n ) ;
        int ax0 = GetVertexVector( dummycd[i], m ) ;
        ax [i] = GetVectorDifference( ax0, rc[i] ) ;
        if ( ( i == 0 ) || ( i == 1 ) || ( i == 4 ) || ( i == 5 ) ) {
            int j = i ; if ( i >= 4 ) { j = i - 1 ; }
            rot[i] = angle[j] * Parity( i ) ;
        } else if ( i == 2 ) {
            rot[i] = angle[i]/2 * Parity( i ) ;
        } else if ( i == 3 ) {
            rot[i] = angle[i-1]/2 * Parity( i ) ;
        }
    }
    for ( int i=0; i<=2; i++ ) {
        for ( int j=0; j<=i; j++ ) {
            rotCoordinate( dummycd[j], rot[i], ax[i], rc[i] ) ;
            rotCoordinate( dummycd[5-j], rot[5-i], ax[5-i], rc[5-i] ) ;
        }
    }
    double offset ;
    for ( int i=0; i<NG; i++ ) {
        SetVectorsCoordinateLocationAttitude( so[i], sa[i], dummycd[i] ) ;
        SetCoordinateLocationAttitude( CD[i], so[i], sa[i] ) ;
        for ( int j=0; j<12; j++ ) {
            offset = ( angle[0] + angle[1] + angle[2] + angle[3] + angle[4] ) / 50 ;
            setPolygonSortOffset( TB0[i][j], offset ) ;
            setPolygonSortOffset( TB1[i][j], -offset ) ;
            setPolygonSortOffset( TL0[i][j], offset ) ;
            setPolygonSortOffset( TL1[i][j], -offset ) ;
        }
    }
}

// 側面二面角
double GetAngleLateralLateral() {

    int v [ ] = Get3Vectors4sideAntiprismCubeConnection( l ) ;
    int u1[ 4 ], u2[ 4 ] ;
    u1[0] = newVector( v[0] ) ;
    u1[1] = newVector( v[1] ) ;
    int m = GetRotYVector( v[0], PI/4 ) ;
    moveVector( m, v[2] ) ;
    u1[2] = newVector( m ) ;
    u1[3] = newVector( v[0] ) ;
    for ( int i=0; i<length( u2 ); i++ ) {
        u2[i] = newVector( u1[i] ) ;
        rotZVector( u2[i], PI ) ;
        rotYVector( u2[i], PI/4 ) ;
    }
    double    costh = GetAngleFaceFace( u1, u2 ) ;
    return acos( costh ) ;
}

inserted by FC2 system