public AttachBuffer ( |
||
buffer | 割り当てるバッファー | |
attributions | ||
return | void |
/// <summary> /// コントロールを作成する /// </summary> public Viewport3D() { // カメラを作成 this.Camera = new Camera(); // コントロール上でマウスホイールされたら this.glControl.MouseWheel += (sender, e) => { // 距離を変更 this.Camera.R *= Math.Pow(1.5, Math.Sign(e.Delta)); }; // 以前のマウス位置 Vector2?oldMouseLocation = null; // マウスが動いたら this.glControl.MouseMove += (sender, e) => { // 左ボタンか中央ボタンが押されていたら if ((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Middle)) { // マウス位置を取得 var thisMouseLocation = new Vector2(e.X, e.Y); // 一番最初でなければ if (oldMouseLocation != null) { // 移動量を計算 var delta = thisMouseLocation - oldMouseLocation.Value; // 左ドラッグなら if (e.Button == MouseButtons.Left) { // 角度を変更 this.Camera.Theta += -2 * Math.PI * delta.X / this.glControl.Width; this.Camera.Phi += Math.PI * delta.Y / this.glControl.Height; } // 中央ボタンなら else if (e.Button == MouseButtons.Middle) { // ずれ量を調整 delta.X /= (float)this.Camera.R; delta.Y /= (float)this.Camera.R; // カメラの方向余弦取得 double cTheta = System.Math.Cos(this.Camera.Theta); double sTheta = System.Math.Sin(this.Camera.Theta); double cPhi = System.Math.Cos(this.Camera.Phi); double sPhi = System.Math.Sin(this.Camera.Phi); // 水平方向に移動 this.Camera.LookAtX += +delta.X * sTheta - delta.Y * cTheta * sPhi; this.Camera.LookAtY += -delta.X * cTheta - delta.Y * sTheta * sPhi; this.Camera.LookAtZ += +delta.Y * cPhi; } } // 前の位置を覚えておく oldMouseLocation = thisMouseLocation; } // それ以外の場合 else { // マウス位置を初期化 oldMouseLocation = null; } }; // カメラが動いたら this.Camera.Changed += (sender, e) => { // 再描画 base.OnInvalidated(); }; // 注視点に表示するプログラムを作成 var programLookAt = new Program(this, ObjectiveTK.Properties.Resources.lookat_vertex, ObjectiveTK.Properties.Resources.lookat_geometry, ObjectiveTK.Properties.Resources.lookat_fragment); // プログラムを追加 base.Programs.Add(programLookAt); // 注視点の座標をプログラムに設定 programLookAt.AttachBuffer(Buffer.CreateDynamic <Vector3>(this, BeginMode.Points, 1, new[] { 0u }), new VertexAttribution[0]); // 再描画時に this.Invalidated += (sender, e) => { // 注視点の各値も設定しなおし programLookAt.SetUniform("view", this.View); programLookAt.SetUniform("projection", this.Projection); programLookAt.SetUniform("lookat", this.Camera.LookAt); programLookAt.SetUniform("size", 1.0f); }; }
/// <summary> /// 最上位ウインドウを作成 /// </summary> public MainWindow(DemComputerCpu computer) { // コンポーネント初期化 InitializeComponent(); // ポイントスプライトプログラムを作成 this.programPoint = new Program( this.Viewport, Properties.Resources.point_vertex, Properties.Resources.point_geometry, Properties.Resources.point_fragment); // ビューポートにプログラムを追加 this.Viewport.Programs.Add(this.programPoint); // 点の大きさを変更可能に設定 this.programPoint.Enable(EnableCap.ProgramPointSize); // ポイントスプライト用 this.programPoint.Enable(EnableCap.PointSprite); // パラメーター再設定 Action setParameters = () => { // 視野変換および投影変換行列を設定 this.programPoint.SetUniform("view", this.Viewport.View); this.programPoint.SetUniform("projection", this.Viewport.Projection); // 表示する大きさ(拡大率)を設定 this.programPoint.SetUniform("size", (float)this.Viewport.Camera.R); // カメラの位置を設定 this.programPoint.SetUniform("cameraPosition", this.Viewport.Camera.Position); }; // ウインドウが読みこまれたら this.Loaded += (sender, e) => { // 真上からの平行光線を設定 this.programPoint.SetUniform("sunLight", new Vector3(0, 0, -0.6f)); // 環境光強度を割り当て this.programPoint.SetUniform("ambient", 0.1f); // カメラからの光源の強度を割り当て this.programPoint.SetUniform("cameraLight", 0.3f); }; // 再描画時に this.Viewport.Invalidated += (sender, e) => { // パラメーター再設定 setParameters(); }; // カメラが動いたら this.Viewport.Camera.Changed += (sender, e) => { // パラメーター再設定 setParameters(); }; // 終了時に this.Closed += (sender, e) => { // プログラムを削除 this.programPoint.Dispose(); }; // 描画中かどうか bool isRendering = false; // 出力用粒子配列を初期化 var outputParticles = new OutputParticle[0]; // 描画処理 Timer renderer = new Timer((TimerCallback)((state) => { // 描画中でなければ if(!isRendering) { // 描画開始 isRendering = true; // 計算空間画面に this.Viewport.Dispatcher.BeginInvoke((Action)(() => { // 現在の粒子を取得 var thisParticles = computer.GetParticles(); // 出力用と粒子数が違えば if(outputParticles.Length != thisParticles.Length) { // 出力用粒子群を再生成 outputParticles = new OutputParticle[thisParticles.Length]; // 動的バッファーを作成 particlesBuffer = Buffer.CreateDynamic<OutputParticle>( this.Viewport, BeginMode.Points, outputParticles.Length, MainWindow.CreatePointsIndices(outputParticles.Length)); // ポイントスプライトプログラムにバッファーを割り当て programPoint.AttachBuffer(particlesBuffer, new[] { new VertexAttribution("particleX", VertexAttribPointerType.Float, 3, 0), new VertexAttribution("particleD", VertexAttribPointerType.Float, 1, Vector3.SizeInBytes), new VertexAttribution("particleColor", VertexAttribPointerType.Float, 4, Vector3.SizeInBytes + sizeof(float)), }); } // すべての粒子を int i = 0; foreach(var particle in thisParticles) { // 出力用粒子に変換 outputParticles[i++] = new OutputParticle((OpenTK.Vector3)particle.X, (float)particle.D, particle.Material.Color); } // 出力粒子を書き込み particlesBuffer.WriteData(outputParticles); // 再描画 this.Viewport.Invalidate(); // 処理完了 isRendering = false; })); } // 時刻表示パネルに this.TimePanel.Dispatcher.BeginInvoke((Action)(() => { // 時刻・タイムステップ数・時間刻みを表示 this.TBox.Text = computer.T.ToString("G5"); this.StepsBox.Text = computer.TimeStep.ToString(); this.DtBox.Text = computer.Dt.ToString("e"); // 粒子数を表示 this.ParticleCountBox.Text = computer.ParticleCount.ToString(); })); })); // 描画を開始 renderer.Change(0, fps); // 前の時刻と時間ステップ double oldT = 0; double oldTimeStep = 0; var oldRealT = DateTime.Now; var initialT = DateTime.Now; // 速度計測 Timer speedMeasure = new Timer((TimerCallback)((state) => { // 速度表示パネルに this.TimePanel.Dispatcher.BeginInvoke((Action)(() => { // 時間ステップを取得 var thisTimeStep = computer.TimeStep; var thisRealT = DateTime.Now; // 時間ステップが進んでいれば if(thisTimeStep != oldTimeStep) { // 時刻を取得 var thisT = computer.T; // 経過時間を秒で計算 double interval = (double)(thisRealT - oldRealT).TotalSeconds; // 各データを表示 this.StepPerRealBox.Text = (interval / (thisTimeStep - oldTimeStep)).ToString("G5"); this.StepPerRealPerParticleBox.Text = (interval / (thisTimeStep - oldTimeStep) / computer.ParticleCount).ToString("G5"); this.ComputationalPerRealBox.Text = (interval / (thisT - oldT)).ToString("G5"); // 前の時刻と時間ステップを設定 oldT = thisT; oldTimeStep = thisTimeStep; oldRealT = thisRealT; } // 現在時刻を表示 this.RealTimeBox.Text = (thisRealT - initialT).ToString(@"d\.hh\:mm\:ss"); })); })); // 1秒感覚で速度計測を開始 speedMeasure.Change(0, 1000); }
/// <summary> /// コントロールを作成する /// </summary> public Viewport3D() { // カメラを作成 this.Camera = new Camera(); // コントロール上でマウスホイールされたら this.glControl.MouseWheel += (sender, e) => { // 距離を変更 this.Camera.R *= Math.Pow(1.5, Math.Sign(e.Delta)); }; // 以前のマウス位置 Vector2? oldMouseLocation = null; // マウスが動いたら this.glControl.MouseMove += (sender, e) => { // 左ボタンか中央ボタンが押されていたら if((e.Button == MouseButtons.Left) || (e.Button == MouseButtons.Middle)) { // マウス位置を取得 var thisMouseLocation = new Vector2(e.X, e.Y); // 一番最初でなければ if(oldMouseLocation != null) { // 移動量を計算 var delta = thisMouseLocation - oldMouseLocation.Value; // 左ドラッグなら if(e.Button == MouseButtons.Left) { // 角度を変更 this.Camera.Theta += -2 * Math.PI * delta.X / this.glControl.Width; this.Camera.Phi += Math.PI * delta.Y / this.glControl.Height; } // 中央ボタンなら else if(e.Button == MouseButtons.Middle) { // ずれ量を調整 delta.X /= (float)this.Camera.R; delta.Y /= (float)this.Camera.R; // カメラの方向余弦取得 double cTheta = System.Math.Cos(this.Camera.Theta); double sTheta = System.Math.Sin(this.Camera.Theta); double cPhi = System.Math.Cos(this.Camera.Phi); double sPhi = System.Math.Sin(this.Camera.Phi); // 水平方向に移動 this.Camera.LookAtX += +delta.X * sTheta - delta.Y * cTheta * sPhi; this.Camera.LookAtY += -delta.X * cTheta - delta.Y * sTheta * sPhi; this.Camera.LookAtZ += + delta.Y * cPhi; } } // 前の位置を覚えておく oldMouseLocation = thisMouseLocation; } // それ以外の場合 else { // マウス位置を初期化 oldMouseLocation = null; } }; // カメラが動いたら this.Camera.Changed += (sender, e) => { // 再描画 base.OnInvalidated(); }; // 注視点に表示するプログラムを作成 var programLookAt = new Program(this, ObjectiveTK.Properties.Resources.lookat_vertex, ObjectiveTK.Properties.Resources.lookat_geometry, ObjectiveTK.Properties.Resources.lookat_fragment); // プログラムを追加 base.Programs.Add(programLookAt); // 注視点の座標をプログラムに設定 programLookAt.AttachBuffer(Buffer.CreateDynamic<Vector3>(this, BeginMode.Points, 1, new[] { 0u }), new VertexAttribution[0]); // 再描画時に this.Invalidated += (sender, e) => { // 注視点の各値も設定しなおし programLookAt.SetUniform("view", this.View); programLookAt.SetUniform("projection", this.Projection); programLookAt.SetUniform("lookat", this.Camera.LookAt); programLookAt.SetUniform("size", 1.0f); }; }