coding Shift_JIS; // 文字コードの明示(文字化け予防) import Math; // 数学関数の使用に必要なライブラリの読み込み import Graphics3D; // 3D描画関数を提供するライブラリの読み込み import graphics3d.Graphics3DFramework; // 面倒な処理を代行してくれる3Dプログラム用レームワーク // 以下、波のパラメータを格納する変数 double periodA = 1.0; // 波Aの周期(T) double periodB = 1.0; // 波Bの周期 double wavelengthA = 1.0; // 波Aの波長(λ) double wavelengthB = 1.0; // 波Bの波長 double amplitudeA = 0.12; // 波Aの振幅(A) double amplitudeB = 0.12; // 波Bの振幅 double xA = -1.0; // 波源AのX座標 double xB = 1.0; // 波源BのX座標 double yA = 0.0; // 波源AのY座標 double yB = 0.0; // 波源BのY座標 // 範囲や点数、時間刻みなどの設定変数 const int N = 100; // メッシュの1方向あたり刻み数(大きいほど綺麗な反面、処理が重くなる) const double X_MIN = -4.0; // グラフのX軸の最小値 const double X_MAX = 4.0; // グラフのX軸の最大値 const double Y_MIN = -4.0; // グラフのY軸の最小値 const double Y_MAX = 4.0; // グラフのY軸の最大値 const double Z_MIN = -2.0; // グラフのZ軸の最小値 const double Z_MAX = 2.0; // グラフのZ軸の最大値 const double DX = (X_MAX - X_MIN) / (N-1); // メッシュのX軸方向の刻み幅 const double DY = (Y_MAX - Y_MIN) / (N-1); // メッシュのY軸方向の刻み幅 const double DT = 0.1; // 1ループごとの時間進行量(speed=1.0の時の値) // 波のデータ関連の変数 double waveVertex[ N ][ N ][ 3 ]; // 頂点座標値を格納する配列(最右次元は0=X,1=Y,2=Z) const int X = 0; // 座標値配列で X 座標を表すインデックス const int Y = 1; // 座標値配列で Y 座標を表すインデックス const int Z = 2; // 座標値配列で Z 座標を表すインデックス // 3DCG関連の変数 int waveModel; // モデルのIDを格納する int waveCoordinate; // 波モデルを配置する座標系 int sourceCoordinateA; // 波源Aの球を配置する座標系 int sourceCoordinateB; // 波源Bの球を配置する座標系 // GUI関連の変数 int periodSliderA; // 波Aの周期設定スライダーのIDを格納する int periodSliderB; // 波Bの周期設定スライダーのIDを格納する int wavelengthSliderA; // 波Aの波長設定スライダーのIDを格納する int wavelengthSliderB; // 波Bの波長設定スライダーのIDを格納する int amplitudeSliderA; // 波Aの振幅設定スライダーのIDを格納する int amplitudeSliderB; // 波Bの振幅設定スライダーのIDを格納する int speedSlider; // アニメーション速度スライダーのIDを格納する int infoLabelA; // 波Aの設定値を表示するラベルのIDを格納する int infoLabelB; // 波Bの設定値を表示するラベルのIDを格納する int timeLabel; // 時刻表示ラベルのIDを格納する int resetButton; // 時刻リセットボタンのIDを格納する // その他の制御関連の変数 double speed = 0.7; // アニメーション速度 double t = 0.0; // 時刻変数 // ================================================== // この関数は、フレームワークから、 // プログラム起動後に1度だけコールされます。 // ================================================== void onStart(int renderer){ // 波のパラメータの初期値を数値で入力するか尋ね、必要なら入力して設定 inputParameters(); // 画面サイズを設定 setWindowSize(820, 800); // 色を鮮やかにするために環境光を明るめに設定 setAmbientLightBrightness(1.0); // カメラ距離とカメラ倍率を設定 setGraphics3DMagnification(getRenderer(), 1400.0); setGraphics3DDistance(getRenderer(), 20.0); // 波座標系を生成 initializeCoordinate(); // 波モデルを生成して配置 initializeModel(); // 画面上のGUI部品を生成して配置 initializeGUI(); } // ================================================== // この関数は、フレームワークから、1秒間に数十回 //(フレームレート設定依存)繰り返しコールされます。 // ================================================== void onUpdate(int renderer){ // 波モデルの頂点座標の更新 updateModelVertex(); // 波モデルの色の更新 updateModelColor(); // 波源の位置の更新 updateSourceLocations(); // 時刻を加算(アニメーション速度をかけて変化のスピードを調整) t += DT * speed; } // ================================================== // 起動時に波のパラメータの初期値を訪ねて入力する処理 // ================================================== void inputParameters() { if ( confirm("波のパラメータを数値で入力しますか?") ) { amplitudeA = input("波Aの振幅=", amplitudeA); amplitudeB = input("波Bの振幅=", amplitudeB); wavelengthA = input("波Aの波長=", wavelengthA); wavelengthB = input("波Bの波長=", wavelengthB); periodA = input("波Aの周期=", periodA); periodB = input("波Aの周期=", periodB); } } // ================================================== // 台座となる座標系を生成する処理 // ================================================== void initializeCoordinate(){ // レンダラーのIDを取得(配置の際の引数に必要) int renderer = getRenderer(); // 波モデルを配置する座標系(波座標系)を生成して配置 waveCoordinate = newCoordinate(); mountCoordinate(waveCoordinate, renderer); // 波モデルの中心がワールド座標系の中心に来るよう移動 moveCoordinate(waveCoordinate, -(X_MAX+X_MIN)/2, -(Y_MAX+Y_MIN)/2, 0.0); // 波源Aの座標系を生成し、波座標系上の波源の位置に配置 sourceCoordinateA = newCoordinate(); setCoordinateOrigin(sourceCoordinateA, xA, yA, 0.0); mountCoordinate(sourceCoordinateA, renderer, waveCoordinate); // 波源Bの座標系を生成し、波座標系上の波源の位置に配置 sourceCoordinateB = newCoordinate(); setCoordinateOrigin(sourceCoordinateB, xB, yB, 0.0); mountCoordinate(sourceCoordinateB, renderer, waveCoordinate); } // ================================================== // モデルを生成する処理 // ================================================== void initializeModel(){ // レンダラーのIDを取得(配置の際の引数に必要) int renderer = getRenderer(); // 四角形グリッド形式で波のモデル(波モデル)を生成して配置 waveModel = newModel(waveVertex, QUADRANGLE_GRID); // 生成 setModelColor(waveModel, 0, 0, 255, 255); // 色設定 setModelCull(waveModel, false, false); // 裏面カリング(描画省略)を無効化 mountModel(waveModel, renderer, waveCoordinate); // 配置 // 波源Aを表す球モデル(赤色)を、波源Aの座標系原点に配置 int sourceModelA = newSphereModel(0.2, 0.2, 0.2, 10, 8); // 生成 setModelColor(sourceModelA, 255, 0, 0, 255); // 色設定 mountModel(sourceModelA, renderer, sourceCoordinateA); // 配置 // 波源Bを表す球モデル(緑色)を、波源Bの座標系原点に配置 int sourceModelB = newSphereModel(0.2, 0.2, 0.2, 10, 8); // 生成 setModelColor(sourceModelB, 0, 255, 0, 255); // 色設定 mountModel(sourceModelB, renderer, sourceCoordinateB); // 配置 } // ================================================== // GUI部品の配置など、画面構築処理を行う処理 // ================================================== void initializeGUI() { // Graphics3DFramework で確保されているウィンドウのIDを取得(この上に部品を配置する) int window = getWindow(); // ウィンドウ上部に余白を設定(GUI部品を配置するため) setMarginTop(180); // 時刻表示ラベルを生成して配置 timeLabel = newTextLabel( 10, 10, 200, 20, "" ); mountComponent( timeLabel, window ); // スライダーの左に振幅、周期、波長のラベルを生成して配置 int amplitudeLabel = newTextLabel( 45, 40, 100, 15, "A 振幅 (0〜1)" ); mountComponent( amplitudeLabel, window ); int omegaLabel = newTextLabel( 45, 60, 100, 15, "T 周期 (0.2〜5)" ); mountComponent( omegaLabel, window ); int lambdaLabel = newTextLabel( 45, 80, 100, 15, "λ 波長 (0.7〜4)" ); mountComponent( lambdaLabel, window ); // 振幅スライダー(範囲0.0〜1.0)を生成して配置 amplitudeSliderA = newHorizontalSlider( 150, 40, 300, 20, amplitudeA, 0.0, 1.0 ); amplitudeSliderB = newHorizontalSlider( 450, 40, 300, 20, amplitudeB, 0.0, 1.0 ); mountComponent( amplitudeSliderA, window ); mountComponent( amplitudeSliderB, window ); // 周期スライダー(範囲0.2〜5.0)を生成して配置 periodSliderA = newHorizontalSlider( 150, 60, 300, 20, periodA, 0.2, 5.0 ); periodSliderB = newHorizontalSlider( 450, 60, 300, 20, periodB, 0.2, 5.0 ); mountComponent( periodSliderA, window ); mountComponent( periodSliderB, window ); // 波長スライダー(範囲0.7〜4.0)を生成して配置 wavelengthSliderA = newHorizontalSlider( 150, 80, 300, 20, wavelengthA, 0.7, 4.0 ); wavelengthSliderB = newHorizontalSlider( 450, 80, 300, 20, wavelengthB, 0.7, 4.0 ); mountComponent( wavelengthSliderA, window ); mountComponent( wavelengthSliderB, window ); // スライダー値を表示するラベルを生成して配置 infoLabelA = newTextLabel( 155, 100, 300, 20, "" ); infoLabelB = newTextLabel( 455, 100, 300, 20, "" ); mountComponent( infoLabelA, window ); mountComponent( infoLabelB, window ); updateInfoLabel(); // 波Aと波Bの列を表すラベルを生成して配置 int columnLabelA = newTextLabel(280, 15, 200, 20, "波A(波源:赤)"); int columnLabelB = newTextLabel(580, 15, 200, 20, "波B(波源:緑)"); mountComponent( columnLabelA, window ); mountComponent( columnLabelB, window ); // アニメーション速度のラベルと調整スライダーを生成して配置 int speedLabel = newTextLabel( 10, 140, 140, 15, "アニメーション速度" ); mountComponent( speedLabel, window ); speedSlider = newHorizontalSlider( 150, 140, 400, 20, speed, 0.0, 1.0 ); mountComponent( speedSlider, window ); // 時刻リセットボタンを生成して配置 resetButton = newButton(600, 125, 150, 40, "時刻をリセット"); mountComponent( resetButton, window ); // 配置後にウィンドウを描画して表示内容を更新 paintComponent( window ); } // ================================================== // 波モデルの頂点座標を更新する処理 // ================================================== void updateModelVertex() { for( int yi=0; yi