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

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

encode Shift_JIS ;

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




void main( string args[] ){


    hide() ;

    TITLE = "多面体影絵(1)" ; 
    int panelh = 60, panelw = 0 ;
    int winw = 256*2.4, winh = 256*2.4, c = 0 ;
    int bgcolor[ ] = Color( c, c, c ) ;
    Set3DGraphics( winw, winh, -1000, -1000, panelw, panelh, bgcolor ) ;

    SetLights() ;
    SetCoordinates() ;
    SetElements() ;
    PrepareStage( panelw, panelh ) ;

    PrepareMovie() ;
    PrintBasicInfo() ;

    WINDOW_POSITION_X = 200 ;
    setComponentLocation( MAIN_WINDOW, WINDOW_POSITION_X, 0 ) ;


    while ( KEEP_LOOP ){ 

        if ( KEEP_MOTION ) {

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

            if ( INCREASE_T ) {
                T += STEP ;
                if ( T > END_T ) {
                    T = END_T ;
                }
            } else {
                T -= STEP ;
                if ( T < START_T ) {
                    T = START_T ;
                }
            }
        }

        if ( CREATE_GUI ) {
            CreateOperationPanel();
            CREATE_GUI = false ;
            GUI_CREATED = true ;
            KEEP_MOTION = false ;
            T = START_T ;
        }

        PaintGraphics( 1000 / FPS );

        if ( SAVE_A_PICTURE ) {
            SaveImage( "PNG" ) ;
            if ( PICTURE_NUMBER > PICTURE_END_NUMBER ) {
                ExitLoopOverImageLimit() ;
            }
        }

        if ( COUNT > COUNT_LIMIT ) {
            ExitLoopOverCountLimit() ;
        }

        COUNT ++ ;

    }


    exit();


}



// import


// LIB000
/* NUMERIC */

double o = 0.0, a = 1.0, d = 10.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 R3 = 3, R4 = 4, R5 = 5, R6 = 6, R8 = 8 ;


// LIB012
/* 3DGRAPHICS */

string TITLE ;
int MAIN_GRAPHICS, MAIN_WINDOW, MAIN_DISPLAY_LABEL, RENDERER ;
int WIDTH = 0, HEIGHT = 0, WINDOW_POSITION_X = 0 ;

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

    WIDTH = w + leftspace ;
    HEIGHT = h + lowspace;
    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( w, h, MAIN_GRAPHICS ) ;
    MAIN_WINDOW = newWindow( 
        WINDOW_POSITION_X, y, WIDTH + framewidth_x, HEIGHT + framewidth_y, TITLE 
    ) ;
    MAIN_DISPLAY_LABEL = newGraphicsLabel( 
        leftspace, 0, w, h, MAIN_GRAPHICS 
    ) ;
    addComponent( MAIN_DISPLAY_LABEL, MAIN_WINDOW );
    setGraphics3DDefaultEventHandler( RENDERER, MAIN_DISPLAY_LABEL );
    setGraphics3DColor( RENDERER, bgred, bggreen, bgblue, bgalpha );
}

void PrepareStage( int leftspace, int lowspace ) {

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

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

    int w = getWorldCoordinate( RENDERER ) ;
    setCoordinateOrigin( w, o, o, o )
    setCoordinateEulerAngle( w, o, o, o );
    setCameraOrigin( w, o, o, CAMERA_ORIGIN_Z );
    setCameraEulerAngle( w, o, o, o );
}


// LIB025_PLAYER_10 ;
/* EVENTHANDLERS */

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

int ACCEL= 1 ; // 倍速再生
void onKeyDown( int id, string key ){

    if ( GUI_CREATED ) {
        if ( key == "SPACE" ) {
        } else     if ( key == "P" ) {
            if ( KEEP_MOTION ) {
                KEEP_MOTION = false ;
                setComponentText( BUTTON[0], BUTTON_TEXT[0][0] ) ;
                setComponentText( TEXT_LABEL[0], (string)( (int)( T - START_T ) ) ) ;
            } else {
                KEEP_MOTION = true ;
                setComponentText( BUTTON[0], BUTTON_TEXT[0][1] ) ;
                if ( INCREASE_T ) {
                    if ( T == END_T ) {
                        T = START_T ;
                    }
                } else {
                    if ( T == START_T ) {
                        T = END_T ;
                    }
                }
            }
        } else if ( key == "R" ) {
            if ( INCREASE_T ) {
                INCREASE_T = false ;
                setComponentColor( TEXT_LABEL[0], 0, 0, 255, 255, 0, 0, 0, 0 ) ;
                setComponentColor( TEXT_LABEL[1], 0, 0, 255, 255, 0, 0, 0, 0 ) ;
            } else {
                INCREASE_T = true ;
                setComponentColor( TEXT_LABEL[0], 255, 0, 255, 255, 0, 0, 0, 0 ) ;
                setComponentColor( TEXT_LABEL[1], 255, 0, 255, 255, 0, 0, 0, 0 ) ;
            }
            RefreshIndicator() ;
        } else if ( key == "S" ) {
            if ( SPIN ) {
                SPIN = false ;
            } else {
                SPIN = true ;
            }
            setComponentState( CHECK_BOX[1], SPIN ) ;
        } else if ( key == "A" ) {
            int formeri = ACCEL + 2 ;
            ACCEL++ ;
            if ( ACCEL > 4 ) {
                ACCEL = 0 ;
            }
            int n = ACCEL + 2 ;
            STEP = TIME_FLOW / FPS * ( 2^( ACCEL - 1 ) ) ;
            int c1[ ] = { 30, 30, 30, 255, 80, 80, 255, 80 } ;
            int c2[ ] = { 200, 10, 10, 255, 120, 120, 255, 80 } ;
            setComponentColor( 
                BUTTON[formeri], 
                c1[0], c1[1], c1[2], c1[3], c1[4], c1[5], c1[6], c1[7]
            ) ;
            setComponentColor( 
                BUTTON[n], 
                c2[0], c2[1], c2[2], c2[3], c2[4], c2[5], c2[6], c2[7]
            ) ;
            RefreshIndicator() ;
        } else if ( key == "C" ) {
            alert( " このキーは使用できません " ) ;
        }
    }
}

// operation panel
int BUTTON[ 2+5 ], N = length( BUTTON ) ;
string BUTTON_TEXT[ N ][ 2 ] ;
int TEXT_LABEL[ 6 ] ;
int INDICATOR[ 1 ] ; // text label 要素数は WIDTH に依存するので、後で確定する
int INDIW ; // inidicator の幅 onMouseLeftDrag で必要なのでワールド変数
int CHECK_BOX[ 2 ] ;

void CreateOperationPanel() {

    int windowframew = 8 ;
    int compareasidespace = 2 ;
    int componentspace = 12 ;
    int indiy = getComponentSize( MAIN_DISPLAY_LABEL )[1] + 2 ;

    // button
    int labelh = 12 ;
    int buttonx = 3*compareasidespace, button0w = 115, buttonh = 32 ;
    int buttony = indiy + labelh + 4 ;
    BUTTON_TEXT[0][0] = "   実 行(P)" ;
    BUTTON_TEXT[0][1] = "   停 止(P)" ;
    BUTTON[0] = newButton( 
        3*compareasidespace,
        buttony,
        button0w, buttonh, BUTTON_TEXT[0][0]
    ) ;
    int button1w = 75 ;
    int labelw = 26, charw = 16, labelx = buttonx + button0w + componentspace;
    BUTTON_TEXT[1][0] = "反転(R)" ;
    BUTTON[1] = newButton(
        labelx + 2*labelw + 3*charw + componentspace,
        buttony + 1*buttonh/8, 
        button1w, 7*buttonh/8, BUTTON_TEXT[1][0]
    ) ;
    setComponentFontBold( BUTTON[1], false ) ;
    BUTTON_TEXT[2][0] = "0.5" ;
    BUTTON_TEXT[3][0] = "1.0" ;
    BUTTON_TEXT[4][0] = "2.0" ;
    BUTTON_TEXT[5][0] = "4.0" ;
    BUTTON_TEXT[6][0] = "8.0" ;
    int button2w = 51 ;
    int c1[ ] = { 200, 10, 10, 255, 120, 120, 255, 80 } ;
    int c2[ ] = { 30, 30, 30, 255, 80, 80, 255, 80 } ;
    for ( int i=2; i<length( BUTTON ); i++ ) {
        BUTTON[i] = newButton(
            labelx + 2*labelw + 4*charw + button1w + componentspace + button2w*( i - 2 ),
            buttony + buttonh/2,
            button2w, 1*buttonh/2, BUTTON_TEXT[i][0]
        ) ;
        setComponentFontBold( BUTTON[i], true ) ;
        if ( i == 3 ) {
            setComponentColor( 
                BUTTON[i], 
                c1[0], c1[1], c1[2], c1[3], c1[4], c1[5], c1[6], c1[7]
            ) ;
        } else {
            setComponentColor( 
                BUTTON[i], 
                c2[0], c2[1], c2[2], c2[3], c2[4], c2[5], c2[6], c2[7]
            ) ;
        }
    }

    // text label TEXT_LABEL[5] はボタンとして使用
    int labely = buttony ;
    label h = buttonh/2 ;
    TEXT_LABEL[0] = newTextLabel(
        labelx,
        labely,
        labelw, labelh, "0  "
    ) ;
    setComponentFontBold( TEXT_LABEL[0], true ) ;
    setComponentColor( TEXT_LABEL[0], 255, 0, 255, 255, 0, 0, 0, 0 ) ;
    TEXT_LABEL[1] = newTextLabel(
        labelx + labelw,
        labely,
        charw, labelh, "秒"
    ) ;
    setComponentFontBold( TEXT_LABEL[1], false ) ;
    setComponentColor( TEXT_LABEL[1], 255, 0, 255, 255, 0, 0, 0, 0 ) ;
    TEXT_LABEL[2] = newTextLabel(
        labelx + labelw + charw,
        labely,
        charw, labelh, "/"
    ) ;
    string totaltimedisplay = (string)( (int)( END_T - START_T ) ) ;
    TEXT_LABEL[3] = newTextLabel(
        labelx + labelw + 2*charw,
        labely,
        labelw, labelh, totaltimedisplay
    ) ;
    setComponentFontBold( TEXT_LABEL[3], false ) ;
    TEXT_LABEL[4] = newTextLabel(
        labelx + 2*labelw + 2*charw,
        labely,
        charw, labelh, "秒"
    ) ;
    setComponentFontBold( TEXT_LABEL[4], false ) ;
    int label5x =  labelx + 2*labelw + 4*charw + button1w + componentspace ;
    int label5w = 2*button2w ;
    TEXT_LABEL[5] = newButton( // ボタンであること注意
        label5x,
        buttony,
        label5w + 1, buttonh/2, "倍速(A)"
    ) ;
    setComponentFontBold( TEXT_LABEL[5], false ) ;
    setComponentColor( 
        TEXT_LABEL[5], 
        0, 0, 0, c1[3], c1[4], c1[5], c1[6], c1[7]
    ) ;

    // check box
    CHECK_BOX[0] = newCheckBox(
        buttonx + button0w + componentspace - 5,
        labely + buttonh/2,
        90, buttonh/2, "" , false ) ;
    ) ;
    setComponentFontBold( CHECK_BOX[0], false ) ;
    CHECK_BOX[1] = newCheckBox(
        label5x + label5w + componentspace - 3,
        buttony - 2,
        180, buttonh/2, "倍速に独立な定速回転(S), SPIN ) ;
    ) ;
    setComponentFontBold( CHECK_BOX[1], false ) ;

    // indicator
    int indiw = 14 ;
    INDIW = indiw ;
    int dummy[ (int)( ( WIDTH - 10 ) / indiw ) ] ;
    INDICATOR = dummy ; // WIDTH と indiw で要素数を決める
    for ( int i=0; i<length( INDICATOR ); i++ ) {
        INDICATOR[i] = newTextLabel(
            2*compareasidespace + indiw * i,
            indiy,
            indiw, labelh, "=="
        ) ;
        setComponentFontBold( INDICATOR[i], true ) ;
        setComponentColor( INDICATOR[i],
            160, 140, 160, 255, 0, 0, 0, 0
        ) ;
    }

    // operation panel
    for ( int i=0; i<length( BUTTON ); i++ ) {
        addComponent( BUTTON[i], MAIN_WINDOW ) ;
    }
    for ( int i=0; i<length( TEXT_LABEL ); i++ ) {
        addComponent( TEXT_LABEL[i], MAIN_WINDOW ) ;
    }
    for ( int i=0; i<length( INDICATOR ); i++ ) {
        addComponent( INDICATOR[i], MAIN_WINDOW ) ;
    }
    for ( int i=0; i<length( CHECK_BOX ); i++ ) {
        addComponent( CHECK_BOX[i], MAIN_WINDOW ) ;
    }
    RefreshIndicator() ;
}

void onButtonClick( int id ){

    if ( GUI_CREATED ) {
        if ( id != TEXT_LABEL[5] ) {
            if ( id == BUTTON[0] ) {
                if ( KEEP_MOTION ) {
                    KEEP_MOTION = false ;
                    setComponentText( BUTTON[0], BUTTON_TEXT[0][0] ) ;
                    setComponentText( TEXT_LABEL[0], (string)( (int)( T - START_T ) ) ) ;
                } else {
                    KEEP_MOTION = true ;
                    setComponentText( BUTTON[0], BUTTON_TEXT[0][1] ) ;
                    if ( INCREASE_T ) {
                        if ( T == END_T ) {
                            T = START_T ;
                        }
                    } else {
                        if ( T == START_T ) {
                            T = END_T ;
                        }
                    }
                }
            } else if ( id == BUTTON[1] ) {
                if ( INCREASE_T ) {
                    INCREASE_T = false ;
                    setComponentColor( 
                        TEXT_LABEL[0], 0, 0, 255, 255, 0, 0, 0, 0 
                    ) ;
                    setComponentColor( 
                        TEXT_LABEL[1], 0, 0, 255, 255, 0, 0, 0, 0 
                    ) ;
                } else {
                    INCREASE_T = true ;
                    setComponentColor( 
                        TEXT_LABEL[0], 255, 0, 255, 255, 0, 0, 0, 0 
                    ) ;
                    setComponentColor( 
                        TEXT_LABEL[1], 255, 0, 255, 255, 0, 0, 0, 0 
                    ) ;
                }
                RefreshIndicator() ;
            } else {
                int formeri = ACCEL + 2, n = 2 ;
                while ( id != BUTTON[n] ) {
                    n++ ;
                }
                ACCEL = n - 2 ;
                STEP = TIME_FLOW / FPS * ( 2^( ACCEL - 1 ) ) ;
            int c1[ ] = { 30, 30, 30, 255, 80, 80, 255, 80 } ;
            int c2[ ] = { 200, 10, 10, 255, 120, 120, 255, 80 } ;
                setComponentColor( 
                    BUTTON[formeri], 
                    c1[0], c1[1], c1[2], c1[3], c1[4], c1[5], c1[6], c1[7]
                ) ;
                setComponentColor( 
                    BUTTON[n], 
                    c2[0], c2[1], c2[2], c2[3], c2[4], c2[5], c2[6], c2[7]
                ) ;
                RefreshIndicator() ;
            }
        } else { // TEXT_LABEL[5]
            int formeri = ACCEL + 2 ;
            ACCEL++ ;
            if ( ACCEL > 4 ) {
                ACCEL = 0 ;
            }
            int n = ACCEL + 2 ;
            STEP = TIME_FLOW / FPS * ( 2^( ACCEL - 1 ) ) ;
            int c1[ ] = { 30, 30, 30, 255, 80, 80, 255, 80 } ;
            int c2[ ] = { 200, 10, 10, 255, 120, 120, 255, 80 } ;
            setComponentColor( 
                BUTTON[formeri], 
                c1[0], c1[1], c1[2], c1[3], c1[4], c1[5], c1[6], c1[7]
            ) ;
            setComponentColor( 
                BUTTON[n], 
                c2[0], c2[1], c2[2], c2[3], c2[4], c2[5], c2[6], c2[7]
            ) ;
            RefreshIndicator() ;
        }
    }
}

void InitializeIndicator() {

    int n = length( INDICATOR ) - 1 ;
    int dispT = T - START_T ;
    int cinc[ 8 ] = { 255, 0, 255, 255, 0, 0, 0, 0 } ;
    int cdec[ 8 ] = { 0, 0, 255, 255, 0, 0, 0, 0 } ;
    int cind[ 8 ] = { 160, 150, 160, 255, 0, 0, 0, 0 } ;
    if ( INCREASE_T ) {
        setComponentColor( TEXT_LABEL[0], 
            cinc[0], cinc[1], cinc[2], cinc[3], cinc[4], cinc[5], cinc[6], cinc[7] 
        ) ;
        setComponentColor( TEXT_LABEL[1],
            cinc[0], cinc[1], cinc[2], cinc[3], cinc[4], cinc[5], cinc[6], cinc[7] 
        ) ;
        if ( T == START_T ) {
            setComponentColor( INDICATOR[0],
                cinc[0], cinc[1], cinc[2], cinc[3], cinc[4], cinc[5], cinc[6], cinc[7] 
            ) ;
        }
        if ( T == END_T ) {
            setComponentColor( INDICATOR[n],
                cinc[0], cinc[1], cinc[2], cinc[3], cinc[4], cinc[5], cinc[6], cinc[7] 
            ) ;
        }
        setComponentColor( INDICATOR[n],
            cinc[0], cinc[1], cinc[2], cinc[3], cinc[4], cinc[5], cinc[6], cinc[7] 
        ) ;
        setComponentText( TEXT_LABEL[0], (string)( dispT ) ) ;
        setComponentText( BUTTON[0], BUTTON_TEXT[0][0] ) ;
        if ( T == START_T ) {
            setComponentText( INDICATOR[0], ">>" ) ;
        } else if ( T == END_T ) {
            setComponentText( INDICATOR[n], ">>" ) ;
        }
        if ( KEEP_MOTION ) {
            setComponentText( BUTTON[0], BUTTON_TEXT[0][1] ) ;
        }
    } else {
        setComponentColor( TEXT_LABEL[0],
            cdec[0], cdec[1], cdec[2], cdec[3], cdec[4], cdec[5], cdec[6], cdec[7] 
        ) ;
        setComponentColor( TEXT_LABEL[1],
            cdec[0], cdec[1], cdec[2], cdec[3], cdec[4], cdec[5], cdec[6], cdec[7] 
        ) ;
        if ( T == START_T ) {
            setComponentColor( INDICATOR[0],
                cdec[0], cdec[1], cdec[2], cdec[3], cdec[4], cdec[5], cdec[6], cdec[7] 
            ) ;
        }
        if ( T == END_T ) {
            setComponentColor( INDICATOR[n],
                cdec[0], cdec[1], cdec[2], cdec[3], cdec[4], cdec[5], cdec[6], cdec[7] 
            ) ;
        }
        setComponentText( TEXT_LABEL[0], "0  " ) ;
        setComponentText( BUTTON[0], BUTTON_TEXT[0][0] ) ;
        if ( T == START_T ) {
            setComponentText( INDICATOR[0], "<<" ) ;
        } else if ( T == END_T ) {
            setComponentText( INDICATOR[n], "<<" ) ;
        }
        if ( KEEP_MOTION ) {
            setComponentText( BUTTON[0], BUTTON_TEXT[0][1] ) ;
        }
    }
    for ( int i=1; i<n-1; i++ ) {
        setComponentColor( INDICATOR[i],
            cind[0], cind[1], cind[2], cind[3], cind[4], cind[5], cind[6], cind[7] 
        ) ;
        setComponentText( INDICATOR[i], "==" ) ;
    }
}

void RefreshIndicator() {

    double t = ( T - START_T ) / ( END_T - START_T ) ;
    if ( t < o ) {
        t = o ;
    } else if ( t > a ) {
        t = a ;
    }
    int n = length( INDICATOR ) - 1 ;
    int index = n * t ;
    for ( int i=0; i<=n; i++ ) {
        if ( i == index ) {
            if ( INCREASE_T ) {
                setComponentColor( INDICATOR[i],
                    255, 0, 255, 255, 0, 0, 0, 0
                ) ;
                setComponentText( INDICATOR[i], ">>" ) ;
            } else {
                setComponentColor( INDICATOR[i],
                    0, 0, 255, 255, 0, 0, 0, 0
                ) ;
                setComponentText( INDICATOR[i], "<<" ) ;
            }
        } else {
            setComponentColor( INDICATOR[i],
                160, 140, 160, 255, 0, 0, 0, 0
            ) ;
            setComponentText( INDICATOR[i], "==" ) ;
        }
    }
}

void onMouseLeftClick( int id, int x, int y, int count ){

    if ( GUI_CREATED ) {
        int n = length( INDICATOR ) - 1 ;
        for ( int i=0; i<length( INDICATOR ); i++ ) {
            if ( id == INDICATOR[i] ) {
                T = START_T + ( END_T - START_T ) * i / n ;
                setComponentText( 
                    TEXT_LABEL[0], (string)( (int)( T - START_T ) ) 
                ) ;
                if ( !KEEP_MOTION ) {
                    Movie( o, true ) ;
                }
                RefreshIndicator() ;
            }
        }
    }
}

void onMouseLeftDrag( int id, int x, int y, int count ){

    if ( GUI_CREATED ) {
        int n = length( INDICATOR ) - 1, nx ;
        double u ;
        for ( int i=0; i<length( INDICATOR ); i++ ) {
            if ( id == INDICATOR[i] ) {
                nx = INDIW * i + x ; // MAIN_WINDOW 左基準の座標値
                u = a*nx / ( ( n + 1 ) * INDIW ) ; // 規格化
                if ( u < o ) {
                    u = o ;
                } else if ( u > a ) {
                    u = a ;
                }
                T = START_T + ( END_T - START_T ) * u ;
                setComponentText( 
                    TEXT_LABEL[0], (string)( (int)( T - START_T ) ) 
                ) ;
                if ( !KEEP_MOTION ) {
                    Movie( o, true ) ;
                }
                RefreshIndicator() ;
            }
        }
    }
}

void onCheckBoxClick( int id, bool state ) {

    if ( id == CHECK_BOX[0] ) {
        alert( " このチェックボックスは使用できません " ) ;
    } else {
        if ( SPIN ) {
            SPIN = false ;
        } else {
            SPIN = true ;
        }
    }
}

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

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 ;
}

void SaveImage( string type ) {

    if ( type == "PNG" ) {
        if ( PICTURE_SAVED ) {
            if ( PICTURE_ALERT ) {
                PICTURE_ALERT = false ;
                alert( PICTURE_NUMBER 
                    + " 枚目までで画像の保存を中止しました。" 
                ) ;
            }
            SAVE_A_PICTURE = false ;
        } else {
            if ( PICTURE_ALERT ) {
                PICTURE_ALERT = false ;
                alert( 
                    ( PICTURE_NUMBER+1 ) + " 枚目以降の画像を保存します。" 
                    + linefeed() + "保存番号を入力して下さい" 
                ) ;
                string nin = choice( 
                    "1", "2", "3", "4", "5", "6", "7", "8", "9"
                ) ;
                PICTURE_SAVE_ID = nin ;
            }
            SaveImagePNG( PICTURE_SAVE_ID * 10000 ) ;
        }
    }
}

void ExitLoopOverCountLimit() {

    show() ;
    println( linefeed()
        + linefeed() 
        + "****************************************************************"
        + linefeed() 
        + "*********** このプログラムは 10 秒後に自動終了します ***********"
        + linefeed() 
        + "****************************************************************"
     ) ;
    print( "cout down ...  " ) ;
    for ( int i=0; i<10; i++ ) {
        print( ( 10 - i ) + " ,  "  ) ;
        if ( i == 0 ) {
            beep( 1 ) ;
        }
        sleep ( 1000 ) ;
    }
    print( "0" ) ;
    sleep( 1000 ) ;
    KEEP_LOOP = false ;
}

void PrintBasicInfo() {

    print( linefeed()
        + " title                        " + TITLE + linefeed()
        + linefeed()
        + " movie " + linefeed()
        + " start time                =  " + START_T + " sec" + linefeed()
        + " end time                  =  " + END_T + " sec" + linefeed()
        + " running time              =  " + ( END_T - START_T ) + " sec" + linefeed()
        + " added time                =  " + ( ADDED_T ) + " sec" + linefeed()
        + " 2*PI rotation             =  " + ( ROT_N ) + " times" + linefeed()
        + " number of frames          =  " + (int)( ( END_T - START_T ) / STEP ) + linefeed()
        + " frames / 1sec             =  " + FPS + " /sec" + linefeed()
        + " number of indexed states  =  " + length( SX ) + linefeed()
        + linefeed()
        + " limit " + linefeed()
        + " of image                  =  " + PICTURE_END_NUMBER + linefeed()
        + " of counter                =  " + COUNT_LIMIT + linefeed()
    ) ;
}


// LIB030
/* FUNCTIONS */

// 等式評価
bool Equality( double x1, double x2, double infinitesimal ) {

    double dif = x1 - x2 ;
    return abs( dif ) < infinitesimal ;
}

// 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 ;
}

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

    double value;
    if ( x < x0 ) {
        value = 0.0 ;
    } else if ( x < ( x0 + deltax ) ) {
        double y = ( x - x0 ) / deltax ;
        value = ( 1.0 + sin( -PI/2 + PI*y ) ) / 2 ;
    } 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 ( 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 ) ;
}

double MSlope( double x ) {

    double y ;
    if ( x > 1.0 ) {
        y = x - (int)( x ) ;
    } else if ( x >= 0.0 ) {
        y = x ;
    } else {
        y = x + ( 1.0 - (int)( x ) ) ;
    }
    double value ;
    if ( y > 1.0/2 ) {
        y = 1.0 - y ;
    }
    if ( y > 1.0/3 ) {
        value = 0.0 ;
    } else if ( y > 1.0/6 ) {
        value = 2 - 6*y ;
    } else {
        value = 1.0 ;
    }
    return value ;
}

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 ;
}

// LIB040
/* 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] );
}

// polygonの光学性質をもとめて指定
void SetPolygonSurface( int polygon[ ][ ][ ], float option[ ] ) {

    for ( int i=0; i<length( polygon )[2]; i++ ) {
        for ( int j=0; j<length( polygon )[1]; j++ ) {
            for ( int k=0; k< length( polygon )[0]; k++ ) {
                SetPolygonSurface( polygon[i][j][k], option ) ;
            }
        }
    }
}
void SetPolygonSurface( int polygon[ ][ ], int ng, float option[ ] ) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        SetPolygonSurface( polygon[ng][i], option ) ;
    }
}
void SetPolygonSurface( int polygon[ ][ ][ ], int ng, float option[ ] ) {

    for ( int i=0; i<length( polygon )[1]; i++ ) {
        for ( int j=0; j<length( polygon )[0]; j++ ) {
            SetPolygonSurface( polygon[ng][i][j], option ) ;
        }
    }
}

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

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

// polygon色をまとめて指定
void SetPolygonColors( int polygon[ ][ ], int ng, int color[ ], int opacity ) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        SetPolygonColor( polygon[ng][i], color, opacity ) ;
    }
}
void SetPolygonColors( int polygon[ ][ ][ ], int ng, int color[ ], int opacity ) {

    for ( int i=0; i<length( polygon )[1]; i++ ) {
        for ( int j=0; j<length( polygon )[0]; j++ ) {
            SetPolygonColor( polygon[ng][i][j], color, opacity ) ;
        }
    }
}
void SetPolygonColors( 
    int polygon[ ][ ], int ng, int color[ ][ ], int nc, int opacity 
) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        setPolygonColor( 
            polygon[ng][i], color[nc][0], color[nc][1], color[nc][2], opacity 
        ) ;
    }
}

// polygonのcullingをまとめて指定
void SetPolygonCull( int polygon[ ][ ][ ], bool cullout, bool cullin ) {

    for ( int i=0; i<length( polygon )[2]; i++ ) {
        for ( int j=0; j<length( polygon )[1]; j++ ) {
            for ( int k=0; k<length( polygon)[0]; k++) {
                setPolygonCull( polygon[i][j][k], cullout, cullin ) ;
            }
        }
    }
}
void SetPolygonCull( int polygon[ ][ ], int ng, bool cullout, bool cullin ) {

    for ( int i=0; i<length( polygon )[0]; i++ ) {
        setPolygonCull( polygon[ng][i], cullout, cullin ) ;
    }
}
void SetPolygonCull( int polygon[ ][ ][ ], int ng, bool cullout, bool cullin ) {

    for ( int i=0; i<length( polygon )[1]; i++ ) {
        for ( int j=0; j<length( polygon )[0]; j++ ) {
            setPolygonCull( polygon[ng][i][j], cullout, cullin ) ;
        }
    }
}

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 ;
}

int GetMiddlePointVector( int v1, int v2 ) {

    double x = ( getVectorX( v1 ) + getVectorX( v2 ) ) / 2 ;
    double y = ( getVectorY( v1 ) + getVectorY( v2 ) ) / 2 ;
    double z = ( getVectorZ( v1 ) + getVectorZ( v2 ) ) / 2 ;
    int mid = newVector( x, y, z ) ;
    return mid ;
}

// 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 GetVectorCoordinateOrigin( int cd ) {

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

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

    int g = newVector( v[0] ) ;
    for ( int i=1; i<length( v ); i++ ) {
        moveVector( g, v[i] );
    }
    double s = 1.0 / length( v ) ;
    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 SetVectorsCoordinateLocationAttitude( int so[ ], int sa[ ], int cd[ ] ) {

    double x, y, z, a, b, g ;
    for ( int i=0; i<length( cd ); i++ ) {
        x = getCoordinateOriginX( cd[i] ) ;
        y = getCoordinateOriginY( cd[i] ) ;
        z = getCoordinateOriginZ( cd[i] ) ;
        a = getCoordinateEulerAngleAlpha( cd[i] ) ;
        b = getCoordinateEulerAngleBeta( cd[i] ) ;
        g = getCoordinateEulerAngleGamma( cd[i] ) ;
        setVector( so[i], x, y, z ) ;
        setVector( sa[i], 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, int v ) {

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

double[ ] GetArryCoordinateEulerAngle( int cd ) {

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

int GetVectorCoordinateEulerAngle( 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 ) ;
}

// O から dist 離れた地点へresetなしに移す, y-direction
void SetCoordinateLocationYdirection( int cd, double dist ) {

    int dummycd = newCoordinate() ;
    int v = newVector() ;
    CopyCoordinateAttitude( dummycd, cd ) ;
    walkCoordinate( dummycd, o, dist, o ) ;
    v = GetVectorCoordinateOrigin( dummycd ) ;
    setCoordinateOrigin( cd, v ) ;
}

// 座標系の姿勢をコピー(座標系原点はコピーせず O とする)
void CopyCoordinateAttitude( int cd, int originalcd ) {

    int sa = GetVectorCoordinateEulerAngle( originalcd ) ;
    SetCoordinateLocationAttitude( cd, O, sa ) ;
}

// 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 );
}

// n 番目の多面体のすべての面の頂点を vector で指定する
void SetTriangleVector( int p[ ][ ], int n, int v[ ][ ] ) {

    for ( int i=0; i<length( p ); i++ ) {
        setPolygonVector( p[n][i], v[i][0], v[i][1], v[i][2] ) ;
    }
}
void SetTriangleVector( int p[ ][ ][ ], int n, int v[ ][ ][ ] ) {

    for ( int i=0; i<length( p )[1]; i++ ) {
        for ( int j=0; j<length( p )[0]; j++ ) {
            setPolygonVector( p[n][i][j], v[i][j][0], v[i][j][1], v[i][j][2] ) ;
        }
    }
}

// polygon をまとめて配置する
void AddPolygons( int p[ ][ ][ ], int renderer, int cd[ ] ) {

    for ( int i=0; i<length( p )[2]; i++ ) {
        for ( int j=0; j<length( p )[1]; j++ ) {
            for ( int k=0; k<length( p )[0]; k++ ) {
                addPolygon( p[i][j][k], renderer, cd[i] ) ;
            }
        }
    }
}
void AddPolygons( int p[ ][ ][ ], int ng, int renderer, int cd[ ] ) {

    for ( int i=0; i<length( p )[1]; i++ ) {
        for ( int j=0; j<length( p )[0]; j++ ) {
            addPolygon( p[ng][i][j], renderer, cd[ng] ) ;
        }
    }
}
void AddPolygons( int p[ ][ ], int m, int renderer, int cd[ ][ ], int n ) {

    for ( int i=0; i<length( p )[0]; i++ ) {
        addPolygon( p[m][i], renderer, cd[n][i] ) ;
    }
}
void AddPolygons( int p[ ][ ], int ng, int renderer, int cd ) {

    for ( int i=0; i<length( p )[0]; i++ ) {
        addPolygon( p[ng][i], renderer, cd ) ;
    }
}

int[ ] RV2_1( int v[ ][ ], int n ) { // ベクトルの2次元配列からベクトルの1次元配列を作る

    int m = length( v )[0] ;
    int u[ m ] ;
    for ( int i=0; i<m; i++ ) {
        u[i] = newVector( v[n][i] ) ;
    }
    return u ;
}
int[ ] RV2_0( int v[ ][ ], int n ) { // ベクトルの2次元配列からベクトルの1次元配列を作る

    int m = length( v )[1] ;
    int u[ m ] ;
    for ( int i=0; i<m; i++ ) {
        u[i] = newVector( v[i][n] ) ;
    }
    return u ;
}

int[ ] RA2_0( int arry[ ][ ], int n ) { // 整数型2次元配列から整数型1次元配列を作る

    int m = length( arry )[0] ;
    int rarry[ m ] ;
    for ( int i=0; i<m; i++ ) {
        rarry[i] = arry[n][i] ;
    }
    return rarry ;
}


// LIB052
/* MOTION */

void PrepareMovie() {

    bool loop = true ;
    T = o ;
    int rpm = 10 ;
    double anglepf = 2*PI * rpm / 60 / FPS ;
    while ( loop ) {
        Movie( anglepf, false ) ;
        if ( T >= END_T ) {
            loop = false ;
        }
        if ( T == o ) {
            NewStateVectors( LENGTH, NG ) ;
        }
        T += STEP ;
    }
    T = START_T ;
    Movie( anglepf, false ) ;
    T = o ;
}

void NewStateVectors( int length1, int length2 ) {

    int dummy1[ length1 ], dummy2[ length1 ][ length2 ] ;
    SX = dummy1 ;
    SA = dummy1 ;
    X = dummy2 ;
    A = dummy2 ;
    for ( int i=0; i<length1; i++ ) {
        for ( int j=0; j<length2; j++ ) {
            X[i][j] = newVector() ;
            A[i][j] = newVector() ;
            if ( j == 0 ) {
                SX[i] = newVector() ;
                SA[i] = newVector() ;
            }
        }
    }
}

double Linear( int v, bool tstate ) {

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

double Sin( int v, bool tstate ) {

    double t = Linear( v, tstate ) ;
    double s = ( 1.0 + sin( PI*t - PI/2 ) ) / 2 ;
    return s ;
}

void SetTRangeRight( int u, int v ) {

    setVector( 
        u, getVectorX( u ), getVectorY( v ), getVectorY( v ) - getVectorX( u ) 
    ) ;
}

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 ) ;
}

bool Border( int v ) {

    double t00 = getVectorX( v ) ;
    double t01 = t00 + STEP ;
    double t10 = getVectorY( v ) ;
    double t11 = t00 - STEP ;
    return ( ( T >= t00 ) && ( T < t01 ) ) || ( ( T > t11 ) && ( T <= t10 ) ) ;
}
bool Border0( int v ) {

    double t00 = getVectorX( v ) ;
    double t01 = t00 + STEP ;
    return ( T >= t00 ) && ( T < t01 ) ;
}
bool Border1( int v ) {

    double t10 = getVectorY( v ) ;
    double t11 = t10 - STEP ;
    return ( T > t11 ) && ( T <= t10 ) ;
}

// 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 = Linear( v, true ) ;
        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 = Linear( v, true ) ;
        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 = Linear( v, true ) ;
        int opacity = 255 - ( 255 - endopacity ) * t ;
        setPolygonColor( polygon, r, g, b, opacity );
    }
}

// text
string TEXT_RUSEN = "http://rusen.seesaa.net/" ;
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 ) ;

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 = Linear( v, true ) ;
        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 = Linear( v, true ) ;
        int c = 255 * ( a - t ) ;
        setPolygonColor( TEXT, c, c, c, 255 ) ;
    }
    SetTRange( v , o, 2.0 );
    if ( Motion( v ) ) {
        double t = Linear( v, true ) ;
        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 = Linear( v, true ) ;
        int opacity = 255*t ;
        setPolygonColor( TEXT, 255, 255, 255, opacity );
    }
    SetTRange( v , 5.0, 5.0 );
    if ( Motion( v ) ) {
        double t = Linear( v, true ) ;
        int opacity = 255 * ( a - t ) ;
        setPolygonColor( TEXT, 255, 255, 255, opacity );
    }
}


// LIB060
/* 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 ;
}

int[ ] Color( float r, float g, float b ) {

    int c[ 3 ] ;
    if ( ( r < 0.0 ) || ( g < 0.0 ) || ( b < 0.0 ) 
            || ( r > 1.0 ) || ( g > 1.0 ) || ( b > 1.0 ) ) {
        c = 0 ;
        alert( "Error ( Color ) " );
    } else {
        c[0] = 255 * r ;
        c[1] = 255 * g ;
        c[2] = 255 * b ;
    }
    return c ;
}

int[ ] Color( float x ) {

    int c[ 3 ] ;
    if ( ( x < 0.0 ) || ( x > 1.0 ) ) {
        c = 0 ;
        alert( "Error ( Color ) " );
    } else {
        c = 255 * x ;
    }
    return c ;
}

int[ ] BiColor( float x ) {

    int c[ 3 ] ;
    c[0] = 255 * MSlope( x ) ;
    c[1] = 255 * MSlope( x - 1.0/3 ) ;
    c[2] = 255 * MSlope( x + 1.0/3 ) ;
    return c ;
}

int[ ] MixedColor( 
    float r1, float g1, float b1, 
    float r2, float g2, float b2, 
    double p 
) {

    int color[ 3 ] ;
    float c1[ ] = { r1, g1, b1 } ;
    float c2[ ] = { r2, g2, b2 } ;
    for ( int i=0; i<length( color ); i++ ) {
        color[i] = 255 * ( c1[i] * ( 1 - p ) + c2[i] * p ) ;
    }
    return color ;
}

int[ ] MixedColor( int color1[ ], int color2[ ], double p ){

    int color[ 3 ] ;
    for ( int i=0; i<length( color ); i++ ) {
        color[i] = color1[i] * ( 1 - p ) + color2[i] * p ;
    }
    return color ;
}


// LIB070
/* 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 if ( polyhedronname == "octahedron" ) {
        antiprismdhangle = PI/2 + acos( Slv*IPlt ) ;
    } 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 ;
}

// dodecahedron の inradiusを返す
double GetInradiusDodecahedron( double prad ) {

    return prad * ( Gld + 1 ) / 2 ;
}

// 原点中心、zx平面内、regular n-gonのz軸上の点(z>0)とその反時計回り隣の点

int[ ] Get3VectorsNGon( int n, double rad ) {

    int u[ 3 ] ;
    u[0] = newVector( o, o, o ) ;
    u[1] = newVector( o, o, rad ) ;
    u[2] = GetRotYVector( u[1], 2*PI/n ) ;
    return u ;
}

// square cupola の頂点ベクトルを返す
int[ ] Get12VectorsSquareCupola( double baserad ) {

    int v[ 12 ] ;
    // 7 - 0 底面頂点
    v[0] = newVector( baserad*sin(PI/8), o, baserad*cos(PI/8) ) ; // 底面の edge は z軸に直交する
    for ( int i=1; i<=7; i++ ) {
        v[i] = GetRotYVector( v[0], PI/4 * i ) ;
    }
    // 11 - 8 天井
    double edge = 2 * baserad * sin( PI/8 ) ;
    double h = edge * ISlv ;
    v[8] = newVector( edge/2, h, edge/2 ) ;
    for( int i=9; i<=11; i++ ) {
        v[i] = GetRotYVector( v[8], PI/2 * i ) ;
    }
    return v ;
}
int[ ] Get2VectorsSquareCupola( double baserad ) {

    int v[ 2 ] ;
    v[0] = newVector( baserad*sin(PI/8), o, baserad*cos(PI/8) ) ; // 底面の edge は z軸に直交する
    double edge = 2 * baserad * sin( PI/8 ) ;
    double h = edge * ISlv ;
    v[1] = newVector( edge/2, h, edge/2 ) ; // 天井の edge はx軸に平行
    return v ;
}

// diamond space filler の頂点ベクトルを返す
int[ ][ ][ ] GetVectorsDiamondSpaceFiller( double x ) { // vertex ( x, 0, 0 )

    int v[ S4 ][ R3*2 ][ R3 ] ;
    v[0][0][0] = newVector( o, x, o ) ;
    v[0][0][1] = newVector( -x/2, x/2, x/2 ) ;
    v[0][0][2] = newVector( x/4, x/4, x/4 ) ;
    v[0][1][0] = newVector( v[0][0][1] ) ;
    v[0][1][1] = newVector( o, o, x ) ;
    v[0][1][2] = newVector( v[0][0][2] ) ;
    int ax0 = newVector( a, a, a ) ;
    int ax1 = newVector( a, o, a ) ;
    for ( int i=1; i<R3; i++ ) {
        for ( int j=0; j<R3; j++ ) {
            v[0][2*i][j] = GetRotVector( v[0][0][j], 2*PI/3 * i, ax0, O ) ;
            v[0][2*i+1][j] = GetRotVector( v[0][1][j], 2*PI/3 * i, ax0, O ) ;
        }
    }
    for ( int i=1; i<S4; i++ ) {
        for ( int j=0; j<R3*2; j++ ) {
            for ( int k=0; k<R3; k++ ) {
                v[i][j][k] = GetRotYVector( v[0][j][k], PI/2 * i ) ;
                if ( i%2 == 1 ) {
                    rotVector( v[i][j][k], PI, ax1 ) ;
                }
            }
        }
    }
    return v ;
}
void SetFacesDiamondSpaceFiller( int p[ ][ ][ ], int ng, double x ) {

    int u[ ][ ][ ] = GetVectorsDiamondSpaceFiller( x ) ;
    SetTriangleVector( p, ng, u ) ;
}

// octahedron の頂点ベクトルを返す
int[ ][ ] GetVectorsOctahedron( double x ) { // vertex ( x, 0, 0 )

    int v[ S8 ][ R3 ] ;
    v[0][0] = newVector( x, o, o ) ;
    v[0][1] = newVector( o, x, o ) ;
    v[0][2] = newVector( o, o, x ) ;
    for ( int i=1; i<S8; i++ ) {
        for ( int j=0; j<R3; j++ ) {
            if ( i <= 3 ) {
                v[i][j] = GetRotYVector( v[0][j], PI/2 * ( i%4 ) ) ;
            } else {
                v[i][j] = GetRotZVector( v[0][j], PI ) ;
                rotYVector( v[i][j], PI/2 * ( ( i - 3 ) % 4 ) ) ;
            }
        }
    }
    return v ;
}

int[ ] GetVectors4FacesSymmetry( double x ) { // ( x, x, x )

    int v[ 4 ] ;
    v[0] = newVector( x, x, x ) ;
    v[1] = GetRotYVector( v[0], PI ) ;
    v[2] = GetRotXVector( v[0], PI ) ;
    v[3] = GetRotZVector( v[0], PI ) ;
    return v ;
}

int[ ] GetVectors6FacesSymmetry( double x ) { // ( o, x, o )

    int v[ 6 ] ;
    v[0] = newVector( o, x, o ) ;
    v[1] = GetRotZVector( v[0], PI/2 ) ;
    for ( int i=2; i<=4; i++ ) {
        v[i] = GetRotYVector( v[1], PI/2 * ( i - 1 ) ) ;
    }
    v[5] = GetRotZVector( v[0], PI ) ;
    return v ;
}

int[ ] GetVectors8FacesSymmetry( double x ) { // ( x, x, x )

    int v[ 8 ] ;
    v[0] = newVector( x, x, x ) ;
    v[4] = newVector( x, -x, x ) ;
    for ( int i=1; i<4; i++ ) {
        v[i] = GetRotYVector( v[0], PI/2 * i ) ;
        v[4+i] = GetRotYVector( v[4], PI/2 * i ) ;
    }
    return v ;
}

int[ ] GetEulerAngleVectors8FacesSymmetry() { // y軸が normal vector

    int sa[8] ;
    int cd = newCoordinate() ;
    int ax = newVector( a, o, -a ) ;
    rotXCoordinate( cd, -atan( Slv ) ) ;
    rotYCoordinate( cd, -3*PI/4 ) ;
    sa[0] = GetVectorCoordinateEulerAngle( cd ) ;
    for ( int i=1; i<4; i++ ) {
        rotYCoordinate( cd, PI/2 ) ;
        sa[i] = GetVectorCoordinateEulerAngle( cd ) ;
    }
    setCoordinateEulerAngle( cd, o, o, o ) ;
    rotXCoordinate( cd, PI/2 + atan( ISlv ) ) ;
    rotYCoordinate( cd, PI/4 ) ;
    sa[4] = GetVectorCoordinateEulerAngle( cd ) ;
    for ( int i=5; i<8; i++ ) {
        rotYCoordinate( cd, PI/2 ) ;
        sa[i] = GetVectorCoordinateEulerAngle( cd ) ;
    }
    return sa ;
}

int[ ][ ] GetTransformedVectors6FacesSymmetry( 
    int v[ ], double y, double spiny 
) {

    int n = length( v ) ;
    int u[ 6 ][ n ] ;
    int dely = newVector( o, y, o ) ;
    for ( int i=0; i<=5; i++ ) {
        for ( int j=0; j<n; j++ ) {
            if ( i == 0 ) {
                u[i][j] = newVector( v[j] ) ;
                moveVector( u[i][j], dely ) ;
                rotYVector( u[i][j], spiny ) ;
            } else if ( i == 1 ) {
                u[i][j] = GetRotZVector( u[0][j], -PI/2 ) ;
            } else if ( i <= 4 ) {
                u[i][j] = GetRotYVector( u[1][j], PI/2 * ( i - 1 ) ) ;
            } else {
                u[i][j] = GetRotZVector( u[0][j], PI ) ;
            }
        }
    }
    return u ;
}




/* set lights */


int AMBIENT_LIGHT = newAmbientLight( o, o, o, 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 = o ;
    SetAmbientLight ( AMBIENT_LIGHT, o, o, o, power, RENDERER );
}




/* create elements */


void SetElements() {

    SetElementOptions();
    AddElements();
}


int NG = 10 ; // group の数
int TR00[ NG ][ S4 ][ R3*2 ] ;
for ( int i=0; i<length( TR00 )[2]; i++ ) {
    for ( int j=0; j<length( TR00 )[1]; j++ ) {
        for ( int k=0; k<length( TR00 )[0]; k++ ) {
            TR00[i][j][k] = newTrianglePolygon( O, O, O ) ;
        }
    }
}

int OPACITY[ ] = { 255, 175 } ;
float OPTION0[ 6 ], OPTION1[ 6 ];
{
    float emissive = o ; 
    float diffractive = 0.8 ; 
    float diffuse = 0.8 ; 
    float ambient = 0.5 ;
    float specularintensity = 0.8, specularangle = PI/3.7; 

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

void SetElementOptions() {

    SetPolygonCull( TR00, false, false ) ;
    SetPolygonSurface( TR00, OPTION0 ) ;
}


void AddElements() {

    int n = length( COORD );
    addLight( LIGHT1, RENDERER, COORD[n-1] ) ;
    addLight( LIGHT2, RENDERER, COORD[n-1] ) ;
    AddPolygons( TR00, RENDERER, CD ) ;
}




/* 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 );
    for ( int i=0; i<NG; i++ ) {
        addCoordinate( CD[i], RENDERER, COORD[0] );
    }
}




/* set axes */


int AXIS[ 10 ];
{
    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, CD[0] ) ;
}




/* prepare stage */


int ICHNOGRAPH = 90 ;
double CAMERA_ORIGIN_Z = 10.5 * l * ICHNOGRAPH ;
float GRAPHIC_MAGNIFICATION = 1000.0 * ICHNOGRAPH ;
double GRAPHIC_DISTANCE = 10.0 ;




/* animation Loop */


bool KEEP_LOOP = true ;
bool SAVE_A_PICTURE = false ;
bool PICTURE_ALERT = true ;
bool PICTURE_SAVED = false ;
bool KEEP_MOTION = true ;
bool INCREASE_T = true ;
bool SPIN = false ;
bool CREATE_GUI = false ;
bool GUI_CREATED = false ;

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

double T = o, START_T = -1.0, END_T = 1000.0, ADDED_T = o ;
double TIME_FLOW = 1.0, STEP = TIME_FLOW / FPS ;
int ROT_N ; // アニメーションでの回転回数

int LENGTH = 1 ; // length( vector )
int SX[ 1 ], X[ 1 ][ NG ] ; // location
int SA[ 1 ], A[ 1 ][ NG ] ; // angle


void ForwardMotion() {

    int rpm = 10 ; // rotation, r/min
    double anglepf = 2*PI * rpm / 60 / FPS ; // angle/frame
    if ( !SPIN ) {
        anglepf = o ;
    }
    if ( !INCREASE_T ) {
        anglepf = -anglepf ;
    }

    // animation
    if ( !GUI_CREATED || KEEP_MOTION ) {
        Movie( anglepf, true ) ;
        if ( !GUI_CREATED ) {
            CREATE_GUI = ( T >= START_T - STEP ) && ( T < START_T ) ;
        }
    }

    // 時刻表示更新と animation 終了処理
    if ( ( T >= START_T ) && ( T <= END_T ) ) {
        if ( GUI_CREATED ) {
            double t = T - START_T ;
            int dispT = t ;
            bool dispstate ;
            if ( INCREASE_T ) {
                dispstate = ( (int)t != (int)( t - STEP ) ) ;
                if ( T == END_T ) {
                    KEEP_MOTION = false ;
                }
            } else { 
                dispstate = ( (int)t != (int)( t + STEP ) ) ;
                if ( T == START_T ) {
                    KEEP_MOTION = false ;
                }
            }
            if ( T == START_T ) {
                dispT = 0 ;
            }
            if ( T == END_T ) {
                dispT = (int)( END_T-START_T ) ;
            }
            RefreshIndicator() ;
            if ( dispstate || T == START_T || T == END_T ) {
                setComponentText( TEXT_LABEL[0], (string)( dispT ) ) ;
                if ( T == START_T || T == END_T ) {
                    InitializeIndicator() ;
                }
            }
        }
    }

// Spin
    if ( T > START_T && SPIN ) {
            int n = length( COORD ) ;
        if ( T < END_T ) {
            rotYCoordinate( COORD[n-4], anglepf ) ;
        } else if ( T >= END_T ) {
            double q = PI/4 ;
            double alp = getCoordinateEulerAngleAlpha( COORD[n-4] ) / q ;
            double bet = getCoordinateEulerAngleBeta( COORD[n-4] ) / q ;
            double gam = getCoordinateEulerAngleGamma( COORD[n-4] ) / q ;
            int inta = alp, intb = bet, intg = gam ;
            double step = 0.8 ;
            if ( alp - inta > step ) {
                inta = inta + 1 ;
            }
            if ( bet - intb > step ) {
                intb = intb + 1 ;
            }
            if ( gam - intg > step ) {
                intg = intg + 1 ;
            }
            setCoordinateEulerAngle( COORD[n-4], q*inta, q*intb, q*intg ) ;
        }
    }
}


void Movie( double anglepf, bool movie ) {

    int g = -1 ;
    bool tstate = INCREASE_T, preliminary = !movie ;
    double unit = 1.0/3.0 ; // 時間の単位

    int open = newVector( o, 0.5, o ) ;

    if ( Motion( open ) ) {
        setGraphics3DColor( RENDERER, 0, 0, 0, 255 ) ;
    }

    SetTRange( open, o, 0.5 ) ;
    if ( Motion( open ) ) {
        double t = Linear( open, tstate ) ;
        int c = 255*t ;
        setGraphics3DColor( RENDERER, c, c, c, 255 ) ;
    }

    if ( T == o && preliminary ) {
        START_T = getVectorY( open ) ;
    }

    int time = newVector( START_T, START_T, o ) ;

// animation ここから

    SetTRange( time, o, 3 * unit ) ;
    if ( Motion( time ) ) {
        if ( Border0( time ) ) {
            setGraphics3DColor( RENDERER, 255, 255, 255, 255 ) ;
            setLightBrightness( AMBIENT_LIGHT, o ) ;
            setLightBrightness( LIGHT1, o ) ;
            setLightBrightness( LIGHT2, o ) ;
            for ( int i=0; i<length( COORD ); i++ ) {
                SetCoordinateEulerAngle( COORD[i], O ) ;
            }
            for ( int i=0; i<10; i++ ) {
                SetFacesDiamondSpaceFiller( TR00, i, o ) ;
                SetPolygonColors( TR00, i, Color( a, a, a ), OPACITY[0] ) ;
            }
        }
        int a0 = newVector( PI/4, o, o ), ax = newVector( o, o, a ) ;
        int x0, v = newVector( l, o, o ) ;
        double t = Linear( time, tstate ) ;
        double angle = -PI/4 ;
        for ( int i=0; i<10; i++ ) {
            if ( i < 4 ) {
                x0 = GetRotZVector( v, PI/2 * i ) ;
                ScaleVector( x0, t ) ;
                RotateCoordinate(
                    CD[i], x0, a0, angle, ax, x0, RENDERER, COORD[0]
                ) ;
                SetFacesDiamondSpaceFiller( TR00, i, l*t ) ;
            } else {
                SetCoordinateLocationAttitude( CD[i], O, O ) ;
                SetFacesDiamondSpaceFiller( TR00, i, o ) ;
            }
        }
    }

    SetTRange( time, 1 * unit, 2 * unit ) ;
    g ++ ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        if ( Border0( time ) && preliminary ) {
            int v[ ] = GetVectors4FacesSymmetry( Slv*l ) ;
            for ( int i=0; i<4; i++ ) {
                SetVectorsCoordinateLocationAttitude( X[g][i], A[g][i], CD[i] ) ;
                setVector( X[g+1][i], v[i] ) ;
            }
        }
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g][i], X[g+1][i], t ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }

    SetTRange( time, o, 1 * unit ) ;
    g ++ ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        if ( Border0( time ) && preliminary ) {
        int v[ ] = GetVectors4FacesSymmetry( l/2 ) ;
            for ( int i=0; i<4; i++ ) {
                setVector( X[g+1][i], v[i] ) ;
                A[g][i] = GetVectorCoordinateEulerAngle( CD[i] ) ;
            }
        }
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g][i], X[g+1][i], t/2 ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }

    SetTRange( time, 1*unit, 1 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g+1][i], X[g][i], a/2 + t/2 ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }

    SetTRange( time, o, 2 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        setCoordinateEulerAngle( COORD[0], PI/2, PI/4 * t, -PI/2 ) ;
        rotXCoordinate( COORD[0], -atan( ISlv ) * t ) ;
    }

    SetTRange( time, o, 1 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g][i], X[g+1][i], t/2 ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }

    SetTRange( time, 1 * unit, 1 * unit ) ;
    int rot00 = newVector( time ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g+1][i], X[g][i], a/2 + t/2 ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }

    SetTRange( time, o, 2 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g][i], X[g+1][i], t ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }
    SetTRangeRight( rot00, time ) ;

    SetTRange( time, 2 * unit, 12 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        double s = Slope( t, o, a/5 ) ;
        double angle = 8*PI * t ;
        int xt,  ax = newVector( a, a, -a ) ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g+1][i], X[g][i], s ) ;
            RotateCoordinate(
                CD[i], xt, A[g][i], angle, ax, xt, RENDERER, COORD[0]
            ) ;
        }
        s = Slope( t, a/4, a-a/4 ) ;
        double s1 = Slope( t, 6*a/7, a/7 ) ;
        angle = 6*PI * s ;
        setVector( ax, a, -a, o ) ;
        int v[ ] = GetVectors6FacesSymmetry( 2*l ), sa ;
        for ( int i=4; i<10; i++ ) {
            if ( Border0( time ) && preliminary ) {
                rotZCoordinate( CD[i], -3*PI/4 ) ;
                A[g][i] = GetVectorCoordinateEulerAngle( CD[i] ) ;
            }
            sa = GetScaleVector( A[g][i], ( 1 - s1 ) ) ;
            RotateCoordinate(
                CD[i], v[i-4], sa, angle, ax, v[i-4], RENDERER, COORD[0]
            ) ;
            SetFacesDiamondSpaceFiller( TR00, i, l*s ) ;
        }
    }

    SetTRange( time, 3 * unit, o ) ;
    int rot10 = newVector( time ) ;

    SetTRange( time, 3 * unit, 12 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        setLightBrightness( AMBIENT_LIGHT, 0.5 * t ) ;
        setLightBrightness( LIGHT1, 0.2 * t ) ;
        setLightBrightness( LIGHT2, 0.5 * t ) ;
    }

    SetTRange( time, 2 * unit, 4 * unit ) ;
    if ( Motion( time ) ) {
        setLightBrightness( AMBIENT_LIGHT, 0.5 ) ;
        setLightBrightness( LIGHT1, 0.2 ) ;
        setLightBrightness( LIGHT2, 0.5 ) ;
        double t = Linear( time, tstate ) ;
        int c0[ ] = Color( a, a, a ), c1[ ] = Color( o, o, a ) ;
        int c[ ] = MixedColor( c0, c1, t ) ;
        for ( int i=0; i<4; i++ ) {
            SetPolygonColors( TR00, i, c, OPACITY[0] ) ;
            SetFacesDiamondSpaceFiller( TR00, i, a - d^-6 ) ;
        }
    }

    SetTRange( time, o, 4 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<4; i++ ) {
            xt = GetInternallyDividingVector( X[g][i], X[g+1][i], t ) ;
            SetCoordinateLocationAttitude( CD[i], xt, A[g][i] ) ;
        }
    }

    SetTRange( time, 4 * unit, 12 * unit ) ;
    SetTRangeRight( rot10, time ) ;

    SetTRange( time, 0 * unit, 12 * unit ) ;
    int rot01 = newVector( getVectorX( time ) + 4*unit, o, o ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int c0[ ] = Color( a, a, a ), c1[ ] = Color( a, o, a ) ;
        int c[ ] = MixedColor( c0, c1, t ) ;
        for ( int i=4; i<10; i++ ) {
            SetPolygonColors( TR00, i, c, OPACITY[0] ) ;
            SetFacesDiamondSpaceFiller( TR00, i, a - d^-6 ) ;
        }
    }
    SetTRangeRight( rot01, time ) ;

    SetTRange( time, o, 5 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        double angle = PI/2 * t ;
        int ax = newVector() ;
        for ( int i=4; i<10; i++ ) {
            if ( Border0( time ) && preliminary ) {
                X[g][i] = GetVectorCoordinateOrigin( CD[i] ) ;
            }
            if ( ( i == 4 ) || ( i == 10 ) ){
                setVector( ax, o, a, o ) ;
            } else if ( ( i == 5 ) || ( i == 7 ) ) {
                setVector( ax, a, o, o ) ;
            } else {
                setVector( ax, o, o, a ) ;
            }
            RotateCoordinate(
                CD[i], X[g][i], O, angle, ax, X[g][i], RENDERER, COORD[0]
            ) ;
        }
    }

    SetTRange( time, o, 5 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=4; i<10; i++ ) {
            if ( Border0( time ) && preliminary ) {
                A[g][i] = GetVectorCoordinateEulerAngle( CD[i] ) ;
            }
            xt = GetScaleVector( X[g][i], a - t/2 ) ;
            setCoordinateOrigin( CD[i], xt ) ;
            if ( Border1( time ) && preliminary ) {
                X[g+1][i] = GetVectorCoordinateOrigin( CD[i] ) ;
            }
        }
    }

    SetTRange( time, 4 * unit, 4 * unit ) ;
    int rot02 = newVector( time ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int c[ ] = Color( o, o, a ) ;
        int opacity = OPACITY[0] * ( 1 - 0.7*t ) ;
        for ( int i=0; i<4; i++ ) {
            SetPolygonColors( TR00, i, c, opacity ) ;
        }
    }

    SetTRange( time, 4 * unit, 4 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int c[ 3 ], opacity ;
        for ( int i=0; i<10; i++ ) {
            if ( i < 4 ) {
                c = Color( o, o, a ) ;
                opacity = OPACITY[0] * ( 0.3 + 0.7*t ) ;
            } else {
                c = Color( a, o, a ) ;
                opacity = OPACITY[0] * ( 1 - 0.7*t ) ;
            }
            SetPolygonColors( TR00, i, c, opacity ) ;
            SetCoordinateLocationAttitude( CD[i], X[g+1][i], A[g][i] ) ;
        }
    }

    SetTRange( time, 4 * unit, 4 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int c[ ] = Color( a, o, a ) ;
        int opacity = OPACITY[0] * ( 0.3 + 0.7*t ) ;
        for ( int i=4; i<10; i++ ) {
            SetPolygonColors( TR00, i, c, opacity ) ;
        }
    }

    SetTRange( time, 4 * unit, 4 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<10; i++ ) {
            xt = GetInternallyDividingVector( X[g+1][i], X[g][i], t ) ;
            setCoordinateOrigin( CD[i], xt ) ;
        }
    }
    SetTRange( time, 4 * unit, 4 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        int xt ;
        for ( int i=0; i<10; i++ ) {
            xt = GetInternallyDividingVector( X[g][i], X[g+1][i], t ) ;
            setCoordinateOrigin( CD[i], xt ) ;
        }
    }

    SetTRange( time, 2 * unit, 4 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        setLightBrightness( AMBIENT_LIGHT, 0.5 * ( 1 - t ) ) ;
        setLightBrightness( LIGHT1, 0.2 * ( 1 - t ) ) ;
        setLightBrightness( LIGHT2, 0.5 * ( 1 - t ) ) ;
        for ( int i=0; i<10; i++ ) {
            SetCoordinateLocationAttitude( CD[i], X[g+1][i], A[g][i] ) ;
        }
    }
    SetTRangeRight( rot02, time ) ;

    SetTRange( time, 1 * unit, 12 * unit ) ;
    int rot11 = newVector( time ) ;
    if ( Motion( time ) ) {
        setLightBrightness( AMBIENT_LIGHT, o ) ;
        setLightBrightness( LIGHT1, o ) ;
        setLightBrightness( LIGHT2, o ) ;
        for ( int i=0; i<10; i++ ) {
            SetCoordinateLocationAttitude( CD[i], X[g+1][i], A[g][i] ) ;
        }
    }

    SetTRange( time, 3 * unit, 3 * unit ) ;
    if ( Motion( time ) ) {
        double t = Linear( time, tstate ) ;
        setLightBrightness( AMBIENT_LIGHT, 0.5 * t ) ;
        setLightBrightness( LIGHT1, 0.2 * t ) ;
        setLightBrightness( LIGHT2, 0.5 * t ) ;
        for ( int i=0; i<10; i++ ) {
            SetFacesDiamondSpaceFiller( TR00, i, a - d^-6 ) ;
            SetCoordinateLocationAttitude( CD[i], X[g+1][i], A[g][i] ) ;
            if ( i < 4 ) {
                SetPolygonColors( TR00, i, Color( o, o, a ), OPACITY[0] ) ;
            } else {
                SetPolygonColors( TR00, i, Color( a, o, a ), OPACITY[0] ) ;
            }
        }
    }

// COORDの回転など
    if ( Motion( rot00 ) ) {
        double t = Linear( rot00, tstate ) ;
        setCoordinateEulerAngle( COORD[0], PI/2, PI/4, -PI/2 ) ;
        rotXCoordinate( COORD[0], -atan( ISlv ) + PI * t ) ;
    } else if ( Motion( rot01 ) ){
        double t = Linear( rot01, tstate ) ;
        setCoordinateEulerAngle( COORD[0], PI/2, PI/4 * ( 1 - t ), -PI/2 ) ;
        rotXCoordinate( COORD[0], ( -atan( ISlv) + PI ) * ( 1 - t ) );
    } else if ( Motion( rot02 ) ) {
        double t = Sin( rot02, tstate ) ;
        setCoordinateEulerAngle( COORD[0], o, -10*PI*t, o ) ;
    }
    if ( Motion( rot10 ) ) {
        double t = Linear( rot10, tstate ) ;
        double s1 = VelvetySlope( t, o, 2*a/5 ) ;
        double s2 = VelvetySlope( t, 3*a/5, 2*a/5 ) ;
        double anglet = -PI*s1 - PI*s2 ;
        setCoordinateEulerAngle( COORD[1], PI/2, anglet, -PI/2 ) ;
    } else if ( Motion( rot11 ) ) {
        double t = Linear( rot11, tstate ) ;
        double s = Slope( t, 3*a/4, a/4 ) ;
        setCoordinateEulerAngle( COORD[1], PI/2, -17*PI/4 * t, -PI/2 ) ;
        rotXCoordinate( COORD[1], ( atan( ISlv) ) * s ) ;
    }

// 終状態
    if ( T >= END_T ) {
        setCoordinateEulerAngle( COORD[1], PI/2, -PI/4, -PI/2 ) ;
        rotXCoordinate( COORD[1], ( atan( ISlv) ) ) ;
        setLightBrightness( AMBIENT_LIGHT, 0.5 ) ;
        setLightBrightness( LIGHT1, 0.2 ) ;
        setLightBrightness( LIGHT2, 0.5 ) ;
        for ( int i=0; i<10; i++ ) {
            SetFacesDiamondSpaceFiller( TR00, i, a - d^-6 ) ;
            SetCoordinateLocationAttitude( CD[i], X[g+1][i], A[g][i] ) ;
            if ( i < 4 ) {
                SetPolygonColors( TR00, i, Color( o, o, a ), OPACITY[0] ) ;
            } else {
                SetPolygonColors( TR00, i, Color( a, o, a ), OPACITY[0] ) ;
            }
        }
    }

// animation ここまで

// 終了時刻の調整
    if ( T == o && preliminary ) {
        double dend = getVectorY( time ) ;
        double cycle = 1 / ( anglepf/( 2*PI ) * FPS ) ;
        if ( cycle - (int)( cycle ) < d^-8 ) {
            cycle = (int)( cycle ) ;
        } else {
            cycle = (int)( cycle ) + 1 ;
        }
        double rotn = ( dend - START_T ) / cycle ;
        ROT_N = rotn ;
        if ( ROT_N < rotn ) {
            ROT_N = ROT_N + 1 ;
        }
        END_T = START_T + (int)( cycle ) * ROT_N ;
        ADDED_T = END_T - dend ;
    }

// 座標系位置、姿勢のセット数の確定
    if ( T == o && preliminary ) {
        LENGTH = g + 2 ;
    }

}

inserted by FC2 system