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

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

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




void main( string args[] ){


    TITLE = "菱形十二面体と立方八面体" ; 
    int winw = 256*2.75, winh = 256*2.75, winx = 90, n = 0 ;
    int bgcolor[ ] = Color( n, n, n ) ;

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


    int loop_periodic_time = 1000 / FPS ;
    bool loop_termination = false ;

    while ( KEEP_LOOP ){ 

        T += STEP ;
        COUNT ++ ;
        if ( COUNT % 100 == 0 ) {
            print( (COUNT/100) + ", " );
        }

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

        if ( CREATE_GUI ) {
            CreateGuiElements();
            CREATE_GUI = false ;
            GUI_CREATED = true ;
        }

        PaintGraphics( loop_periodic_time );

        if ( SAVE_A_PICTURE ) {
            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( 
                        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
                    ) ;
                    PICTURE_SAVE_ID = nin ;
                }
                SaveImagePNG( PICTURE_SAVE_ID * 10000 ) ;
            }
        }

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


    exit();


}




/* import ここから */

// LIB000

/* NUMERIC */

double o = 0.0, a = 1.0 ;
double d = 0.1 ;
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 ;


// LIB010

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


// LIB020

/* EVENTHANDLERS */

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

void onKeyDown( int id, string key ){

    if ( key == "SPACE" ) {
        if ( SAVE_A_PICTURE ) {
            PICTURE_SAVED = true ;
            PICTURE_ALERT = true ;
        } else {
            PICTURE_SAVED = false ;
            PICTURE_ALERT = true ;
            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 ;
}


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

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 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[ ][ ], int ng, bool cullout, bool cullin ) {

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

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

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

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] ) ;
    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, 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 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 ) ;
    }
}
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] ) ;
        }
    }
}
    
int[ ] ReduceDimension_2( int v[ ][ ], int n ) {

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


// LIB050

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


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


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

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


/* import ここまで */




/* set lights */


int AMBIENT_LIGHT = newAmbientLight( o, o, o, o ) ;
int LIGHT0 = newPointLight( -0.2*l, -1.1*l, 1.5*l, o ) ;
int LIGHT1 = newLight( 4.0, 10.0, 10.0, o ) ;
int LIGHT2 = newLight( -8.0, -12.0, 6.0, o ) ; 

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




/* create elements */


void SetElements() {

    SetElementOptions();
    AddElements();
}


int NG = 1 ; // group の数

int R[ NG ][ S12 ]; // rhombus
int S[ NG ][ S6 ]; // square
int D[ NG ][ S8 ]; // triangle
int L[ NG ][ S24 ]; // lectangle
for ( int ng=0; ng<NG; ng++ ) {
    for ( int i=0; i<S12; i++ ) {
        R[ng][i] = newQuadranglePolygon( O, O, O, O ) ;
    }
    for ( int i=0; i<S6; i++ ) {
        S[ng][i] = newQuadranglePolygon( O, O, O, O ) ;
    }
    for ( int i=0; i<S8; i++ ) {
        D[ng][i] = newTrianglePolygon( O, O, O ) ;
    }
    for ( int i=0; i<S24; i++ ) {
        L[ng][i] = newQuadranglePolygon( O, O, O, O ) ;
    }
}


// 稜長xの立方体に外接する菱形十二面体菱形に対して相似比rの菱形
void SetSimilarRhombus( double x , double r ) {

    int v[ ] = GetVectorRhombus( x ) ;
    int g = GetVectorGravityCenter( v ) ;
    for ( int i=0; i<length( v ); i++ ) {
        v[i] = GetVectorDifference( v[i], g ) ;
        scaleVector( v[i], r, r, r );
        v[i] = GetVectorSum( g, v[i] ) ;
    }
    for ( int ng=0; ng<NG; ng++ ) {
        for ( int i=0; i<S12; i++ ) {
            setPolygonVector( R[ng][i], v[0], v[1], v[2], v[3] );
        }
    }
}


// 稜長xの立方体に外接する菱形十二面体の菱形頂点ベクトル。外接させた状態で長軸がxy面内第一象限
int[ ] GetVectorRhombus( double x ) {

    int v[ 4 ];
    v[0] = newVector( x, o, o ) ;
    v[1] = newVector( x/2, x/2, -x/2 ) ;
    v[2] = newVector( o, x, o ) ;
    v[3] = newVector( x/2, x/2, x/2 ) ;
    return v ;
}


// 切稜多面体の全ポリゴンをセット
void DeformRhombic12hedron( 
    int rhombus[ ][ ], int square[ ][ ], int triangle[ ][ ], int lectangle[ ][ ],
    double x , double r, int cd[ ][ ], int parentcd[ ], int ng, int renderer 
) {

    int v[ ] = GetVectorRhombus( x ) ;
    int g = GetVectorGravityCenter( v ) ;
    for ( int i=0; i<length( v ); i++ ) {
        v[i] = GetVectorDifference( v[i], g ) ;
        scaleVector( v[i], r, r, r );
        v[i] = GetVectorSum( g, v[i] ) ;
    }
    for ( int i=0; i<S12; i++ ) {
        setPolygonVector( rhombus[ng][i], v[0], v[1], v[2], v[3] );
    }
    SetSquare( square, v, cd, parentcd, ng, renderer );
    SetTriangle( triangle, v, cd, parentcd, ng, renderer );
    SetLectangle( lectangle, v, cd, parentcd, ng, renderer );
}


void SetSquare( 
    int square[ ][ ], int v[ ], int cd[ ][ ], int parentcd[ ], int ng, int renderer 
) {

    int u[ S4 ];
    u[0] = GetTransformedVector( v[0], renderer, cd[ng][0], parentcd[ng] ) ;
    for ( int i=1; i<S4; i++ ) {
        u[i] = GetRotXVector( u[0], PI/2 * i ) ;
    }
    for ( int i=0; i<S6; i++ ) {
        setPolygonVector( square[ng][i], u[0], u[1], u[2], u[3] );
        if ( ( i >= 1 ) && ( i <= 3 ) ) {
            rotYPolygon( square[ng][i], PI/2 * i );
        } else if ( i >= 4 ) {
            rotZPolygon( square[ng][i], PI/2 * Parity( i ) );
        }
    }
}


void SetTriangle( 
    int triangle[ ][ ], int v[ ], int cd[ ][ ], int parentcd[ ], int ng, int renderer 
) {

    int u[ S3 ];
    u[0] = GetTransformedVector( v[3], renderer, cd[ng][0], parentcd[ng] ) ;
    int ax = newVector( a, a, a ) ;
    for ( int i=1; i<S3; i++ ) {
        u[i] = GetRotVector( u[0], 2*PI/3 * i, ax, O ) ;
    }
    for ( int i=0; i<S8; i++ ) {
        setPolygonVector( triangle[ng][i], u[0], u[1], u[2] );
        rotYPolygon( triangle[ng][i], PI/2 * ( i % 4 ) );
        rotZPolygon( triangle[ng][i], PI * ( i / 4 ) );
    }
}


void SetLectangle( 
    int lectangle[ ][ ], int v[ ], int cd[ ][ ], int parentcd[ ], int ng, int renderer 
) {

    int u[ S4 ];
    u[0] = GetTransformedVector( v[0], renderer, cd[ng][0], parentcd[ng] ) ;
    u[1] = GetTransformedVector( v[3], renderer, cd[ng][0], parentcd[ng] ) ;
    u[2] = GetTransformedVector( v[1], renderer, cd[ng][4], parentcd[ng] ) ;
    u[3] = GetTransformedVector( v[0], renderer, cd[ng][4], parentcd[ng] ) ;
    for ( int i=0; i<S24; i++ ) {
        setPolygonVector( lectangle[ng][i], u[0], u[1], u[2], u[3] );
        rotXPolygon( lectangle[ng][i], PI/2 * ( i % 4 ) );
        if ( ( i >= 4 ) && ( i <= 15 ) ) {
            rotYPolygon( lectangle[ng][i], PI/2 * ( i / 4 ) );
        } else if ( i >= 16 ) {
            rotZPolygon( lectangle[ng][i], PI/2 * Parity( i / 4 ) );
        }
    }
}



int COLOR[ 4 ][ 3 ], OPACITY[ ] = { 255, 175 } ;
{
    float r, g, b ;
    for ( int i=0; i<4; i++ ) {
        if ( i == 0 ) {
            r = 3*a/4 ;    g = o ;        b = a ;
        } else if ( i == 1 ) {
            r = a ;        g = o ;        b = a/4 ;
        } else if ( i == 2 ) {
            r = o ;        g = o ;        b = a ;
        } else if ( i == 3 ) {
            r = a/1.5 ;    g = a ;        b = a/5 ;
        }
        for ( int j=0; j<3; j++ ) {
            COLOR[i][j] = Color( r, g, b )[j] ;
        }
    }
}


float OPTION0[ 6 ], OPTION1[ 6 ];
{
    float emissive = o ; 
    float diffractive = 0.4 ; 
    float diffuse = 0.8 ; 
    float ambient = o ;
    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() {

    for ( int ng=0; ng<NG; ng++ ) {
        SetPolygonCull( R, ng, false, false ) ;
        SetPolygonSurface( R, ng, OPTION0 ) ;
        SetPolygonCull( S, ng, false, false ) ;
        SetPolygonSurface( S, ng, OPTION0 ) ;
        SetPolygonCull( D, ng, false, false ) ;
        SetPolygonSurface( D, ng, OPTION0 ) ;
        SetPolygonCull( L, ng, false, false ) ;
        SetPolygonSurface( L, ng, OPTION0 ) ;
    }
}


void AddElements() {

    int n = length( COORD );
    addLight( LIGHT1, RENDERER, COORD[n-1] ) ;
    addLight( LIGHT0, RENDERER, COORD[n-1] ) ;
    for ( int ng=0; ng<NG; ng++ ) {
        AddPolygons( R, ng, RENDERER, C, ng ) ;
        AddPolygons( S, ng, RENDERER, CD[ng] );
        AddPolygons( D, ng, RENDERER, CD[ng] );
        AddPolygons( L, ng, RENDERER, CD[ng] );
    }
}




/* set coordinates */


int COORD[ 4 ];
int CD[ NG ];
int C[ NG ][ S12 ];
for ( int i=0; i<length( COORD ); i++ ) {
    COORD[i] = newCoordinate() ;
}
for ( int ng=0; ng<NG; ng++ ) {
    CD[ng] = newCoordinate() ;
    for ( int i=0; i<S12; i++ ) {
        C[ng][i] = newCoordinate() ;
    }
}

void SetCoordinates() {

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


void SetCoordinateSymmetry12( int cd[ ][ ], int ng, double x ) {

    for ( int i=0; i<S12; i++ ) {
        SetCoordinateLocationAttitude( cd[ng][i], O, O );
        rotXCoordinate( cd[ng][i], PI/2 * ( i / 4 ) );
        rotYCoordinate( cd[ng][i], PI/2 * ( i % 4 ) );
        walkCoordinate( cd[ng][i], x - l, x - l, o );
    }
}



/* 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, COORD[0] );
    addModel( AXIS[4], RENDERER, CD[0] );
}




/* prepare stage */


double CAMERA_ORIGIN_Z = 3.5 * l ;
float GRAPHIC_MAGNIFICATION = 1000.0 ;
double GRAPHIC_DISTANCE = 10.0 ;

void PrepareStage() {

    setGraphics3DCenter( RENDERER, WIDTH / 2, HEIGHT / 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 );
}




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


bool KEEP_LOOP = true ;
bool SAVE_A_PICTURE = false ;
bool PICTURE_ALERT = true ;
bool PICTURE_SAVED = false ;

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

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




/* create GUI elements */


int SETTING_WINDOW ; 

int LABEL_SLIDER[ 1 ] ;
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 SPIN = true, LIMIT = false ;

int LABEL_SELECT[ 1 ] ;
N = length( LABEL_SELECT ) ; int SELECT[ N ] ; string SELECT_TITLE[ N ] ;
string SELECT_TEXT[ N ][ 3 ] ;
bool MOTION_START = false ;
bool MOTION_END = true ;
int OPACITY_INDEX = 0 ;
int FORMER_OPACITY_INDEX = 0 ; 

SELECT_TITLE[0] = "多面体の透明度" ;
SELECT_TEXT[0][0] = "不透明" ;
SELECT_TEXT[0][1] = "やや透明" ;
SELECT_TEXT[0][2] = "半透明" ;
CHECK_TEXT[0] = "多面体の回転" ;
SLIDER_TEXT[0] = "切稜" ; 

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 = 180 ; 
    int lh = 15 ; int lyspace = 25 ;
    int sliderx = lx , sliderw = lw, sliderh = 20 , slideryspace = 10 ;
    int sliderlabely[ nsldl ] ; int slidery[ nsld ] ;
    int selectx = lx , selectw = lw - sidewidth , selecth = 20 , selectyspace = 10 ;
    int selectlabely[ nsell ] ; int selecty[ nsel ] ;
    int check0x = lx, check0w = lw, check0h = lh, check0yspace = 40;
    int check0y ;

    {
        int initial_ly = 25;
        check0y = initial_ly  ;
        for ( int i=0; i<nsel; i++ ) {
            selectlabely[i] = check0y + check0h + lyspace
                + ( lyspace + lh + selectyspace + selecth ) * i ;
            selecty[i] = selectlabely[i] + lh + selectyspace ;
        }
        for ( int i=0; i<nsld; i++ ) {
            sliderlabely[i] = selecty[nsel-1] + lh + 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] + 85 ;

    {
        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[0] = newCheckBox ( 
                            lx, check0y, lw, check0h, CHECK_TEXT[0], true
                        ) ;
        setComponentFontSize( CHECK_BOX[0], 14 ) ; // default 12
        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] 
                                ) ;
            setComponentFontSize( LABEL_SLIDER[i], 14 ) ; // default 12
            addComponent( LABEL_SLIDER[i], SETTING_WINDOW ) ;
            double inivalue = o ;
            SLIDER[i] = newHorizontalSlider( 
                            sliderx, slidery[i], sliderw, sliderh, inivalue 
                        ) ;
            addComponent( SLIDER[i], SETTING_WINDOW ) ;
        }
    }

    paintComponent( SETTING_WINDOW ) ;
}




/* event handlers */


void onSliderMove( int id, double value ) {

    P[0] = 1 - value ;
    DeformRhombic12hedron( R, S, D, L, l, P[0], C, CD, 0, RENDERER );

}


void onCheckBoxClick( int id, bool state ){

    if ( MOTION_END ) {
        if ( id == CHECK_BOX[0] ) {
            SPIN = state ;
        } else {
        }
    }
}


void onSelectFieldClick( int id, string text ){

    if ( MOTION_END ) {
        for ( int i=0; i<length( SELECT_TEXT )[0]; i++ ) {
            if ( text == SELECT_TEXT[0][i] ) {
                if ( i != FORMER_OPACITY_INDEX ) {
                    OPACITY_INDEX = i ;
                    MOTION_START = true ;
                    MOTION_END = false ;
                }
            }
        }
    }
}




/* forward motion */


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

void ForwardMotion() {

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

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

    if ( T < GUI_UPTIME + 1000.0 ) {
        rotYCoordinate( COORD[2], toprotrate ) ;
    } else {
        KEEP_LOOP = false ;
    }
}


int SO[ NG ]; // system origin point
int SA[ NG ]; // system Euler Angle
int RC[ NG ]; // rotation center vector
int AX[ NG ]; // rotation axis vector
for ( int ng=0; ng<NG; ng++ ) {
    SO[ng] = newVector() ;
    SA[ng] = newVector() ;
    RC[ng] = newVector() ;
    AX[ng] = 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 unit = 1.0 / 1 ; // 時間の単位

    SetTRangeAbsolutely( v, start_t, start_t + STEP ) ;
    if ( Motion( v ) ) {
        SetPolygonColors( R, 0, COLOR, 0, OPACITY[0] ) ;
        SetPolygonColors( S, 0, COLOR, 1, OPACITY[0] ) ;
        SetPolygonColors( D, 0, COLOR, 2, OPACITY[0] ) ;
        SetPolygonColors( L, 0, COLOR, 3, OPACITY[0] ) ;
        SetCoordinateSymmetry12( C, 0, l );
        DeformRhombic12hedron( R, S, D, L, l, a, C, CD, 0, RENDERER );
    }

    SetTRange( v, o, 2*unit ) ;
    if ( Motion( v ) ) {
        double t = GetLinearTime( v ) ;
        double s = Slope( t, o, 3 * a/4 ) ;
        setLightBrightness( LIGHT0, 0.8 * s ) ;
        s = Slope( t, a/2, a/2 ) ;
        setLightBrightness( LIGHT1, 0.2 * s ) ;
    }


    int stop = newVector( v ) ;

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

    SetTRangeAbsolutely( v, T0, T0 + unit ) ;

    if ( FORMER_OPACITY_INDEX != OPACITY_INDEX ) {
        if ( Motion( v ) ) {
            double t = GetLinearTime( v ) ;
            float r0 = ( 4 - FORMER_OPACITY_INDEX^2 ) / 4 ;
            float r1 = ( 4 - OPACITY_INDEX^2 ) / 4 ;
            int opacity0 = OPACITY[0] * r0 + OPACITY[1] * ( 1 - r0 ) ;
            int opacity1 = OPACITY[0] * r1 + OPACITY[1] * ( 1 - r1 ) ;
            int opacity = opacity0 * ( 1 - t ) + opacity1 * t ;
            float emissive0 = OPTION0[0] * r0 + OPTION1[0] * ( 1 - r0 ) ;
            float emissive1 = OPTION0[0] * r1 + OPTION1[0] * ( 1 - r1 ) ;
            float emissive = emissive0 * ( 1 - t ) + emissive1 * t ;
            float ambient0 = OPTION0[3] * r0 + OPTION1[3] * ( 1 - r0 ) ;
            float ambient1 = OPTION0[3] * r1 + OPTION1[3] * ( 1 - r1 ) ;
            float ambient = ambient0 * ( 1 - t ) + ambient1 * t ;
            float sref0 = OPTION0[4] * r0 + OPTION1[4] * ( 1 - r0 ) ;
            float sref1 = OPTION0[4] * r1 + OPTION1[4] * ( 1 - r1 ) ;
            float sref = sref0 * ( 1 - t ) + sref1 * t ;
            float sangle0 = OPTION0[5] * r0 + OPTION1[5] * ( 1 - r0 ) ;
            float sangle1 = OPTION0[5] * r1 + OPTION1[5] * ( 1 - r1 ) ;
            float sangle = sangle0 * ( 1 - t ) + sangle1 * t ;
            float option[ ] = {
                emissive, OPTION0[1], OPTION0[2], ambient, sref, sangle
            } ;
            SetPolygonColors( R, 0, COLOR, 0, opacity ) ;
            SetPolygonSurface( R, 0, option ) ;
            SetPolygonColors( S, 0, COLOR, 1, opacity ) ;
            SetPolygonSurface( S, 0, option ) ;
            SetPolygonColors( D, 0, COLOR, 2, opacity ) ;
            SetPolygonSurface( D, 0, option ) ;
            SetPolygonColors( L, 0, COLOR, 3, opacity ) ;
            SetPolygonSurface( L, 0, option ) ;
            if ( t == a ) {
                FORMER_OPACITY_INDEX = OPACITY_INDEX ;
                MOTION_END = true ;
            }
        }
    }

    setVector( v, stop ) ;

}
inserted by FC2 system