coding Shift_JIS; import Math; import Graphics; import Graphics3D; import graphics3d.Graphics3DFramework; // グリッドのX/Y分割数 const int X_N = 140; const int Y_N = 100; // 座標値配列で、X/Y/Z座標を表すインデックス const int X = 0; const int Y = 1; const int Z = 2; // シミュレーション終了時刻(単位はフレーム数) const int END_TIME_COUNT = 500; // 頂点座標を格納する配列(最右次元は0=X,1=Y,2=Z) float vertex[ Y_N ][ X_N ][ 3 ]; // 頂点のZ方向速度 float vertexVZ[ Y_N ][ X_N ] = 0.0; // 頂点のZ方向の力 float vertexFZ[ Y_N ][ X_N ] = 0.0; // 頂点の質量 float mass[ Y_N ][ X_N ]; // 面密度分布の画像ファイルのパス const string DENSITY_FILE_PATH = "density.png"; // 面密度のスケール値 const float DENSITY_SCALE = 10.0; // 領域の辺の長さ const float X_LENGTH = 5.0; const float Y_LENGTH = X_LENGTH / 1.4; // 張力(単位幅のリボン形状を引っ張った際の張力) const float TENSION = 3.0; // 減衰力係数 const float FRICTION = 0.0; // パルス波の幅 const float PULSE_WIDTH = 0.1; // パルス波の高さ const float PULSE_HEIGHT = 1.0; // サイン波の角速度 const float SIN_SPEED = 20.0; // サイン波の高さ const float SIN_HEIGHT = 0.2; // 自由端かどうか const bool FREE_END = true; /** * 1フレームあたり、力学計算(時間発展)を行う回数です。 * * 波を速くしたい場合、DTを荒くしたり、張力を上げると、 * 精度限界を超えて運動が発散してしまう場合があります。 * その回避策で、1フレーム内に細かいDTで繰り返し計算します。 */ const int UPDATE_PER_FRAME = 1; // シミュレーションの時間刻み const float DT = 0.01; // 格子点間距離(ポリゴンの辺の長さ) const float DX = X_LENGTH / (X_N-1); const float DY = Y_LENGTH / (Y_N-1); // 波モデルを配置する座標系 int waveCoordinate; // モデルのIDを格納する int waveModel; // 波のタイプ(実行時に選択) const int WAVE_TYPE_SIN = 1; // 正弦波 const int WAVE_TYPE_PULSE = 2; // パルス波(孤立波) int waveType = WAVE_TYPE_SIN; /* ---------------------------------------------------------------------------------------------------- * ここから、初期化処理に関する部分 * (モデルの生成や初期形状設定など) * ---------------------------------------------------------------------------------------------------- */ /** * ここはフレームワークから、 * プログラム起動後に1度だけコールされます。 */ void onStart(int renderer){ // 負荷の警告を表示 bool go = confirm( "このプログラムは、古いコンピューターには高負荷です。" + lf() + "性能が十分でない場合、動作が重くなる場合があります。" + lf() + "実行しますか?" ); if(!go){ exit(); } // 波のタイプを選択 selectWaveType(); // 波座標系を生成 initializeCoordinate(); // 波座標系を配置 mountCoordinate(waveCoordinate, renderer); // 波座標系に座標軸モデルを生成して配置 mountModel( newAxisModel(3.0,3.0,3.0), renderer, waveCoordinate ); // 波モデルを生成して配置 initializeModel(); // 波モデルを波座標系に配置 mountModel(waveModel, renderer, waveCoordinate); // 波モデルの初期形状を設定 if(waveType == WAVE_TYPE_PULSE){ setGaussianWave(PULSE_WIDTH, PULSE_HEIGHT); }else{ setFlatWave(); } // 面密度分布ファイルを読み込む loadDensityFile(DENSITY_FILE_PATH); } /** * 波のタイプを選択するダイアログを提示します。 */ void selectWaveType(){ alert("波のタイプを選択して下さい:"); string sin = "Sin Wave - 正弦波(サイン波)"; string pulse = "Pulse Wave - 孤立波(パルス波)"; string options[] = {pulse, sin}; string selected = select(options); if(selected == sin){ waveType = WAVE_TYPE_SIN; }else if(selected == pulse){ waveType = WAVE_TYPE_PULSE; }else{ error("波のタイプが不正です:" + selected); exit(); } } /** * 台座となる座標系を生成します。 */ void initializeCoordinate(){ // 波モデルを配置する座標系を生成 waveCoordinate = newCoordinate(); // 原点を 領域長/2 だけ平行移動 moveCoordinate( waveCoordinate, -X_LENGTH/2.0, -Y_LENGTH/2.0, 0.0 ); } /** * モデルを生成します。 */ void initializeModel(){ // 四角形グリッド形式で波のモデルを生成 waveModel = newModel(vertex, QUADRANGLE_GRID); // 波モデルの色設定(赤、緑、青、α値) setModelColor(waveModel, 0, 0, 255, 255); // 裏面のカリング(描画省略)を無効化 setModelCull(waveModel, false, false); } /** * 頂点配列をガウス波束の形状に設定します(パルス波の場合用)。 */ void setGaussianWave(float width, float height){ for(int i=0; i END_TIME_COUNT){ // 終了時刻以降は何しない。 return; } // X / Y方向の線張力(※TENSIONは単位幅あたりの張力) float tensionX = TENSION * Y_LENGTH / Y_N; float tensionY = TENSION * X_LENGTH / X_N; // 波のタイプがサイン波の場合は、境界をsin関数で振動させる if(waveType == WAVE_TYPE_SIN){ for(int i=0; i