/// <summary> /// コンストラクタ /// </summary> public EffectObject() { Children = new EffectCollection(this); Scenario = new Scenario(); LocalTransform = new Matrix44d(); BaseScale = new Point3d(1.0, 1.0, 1.0); Scale = new Point3d(1.0, 1.0, 1.0); Opacity = 1.0; //Transform = new Matrix44d(); InheritedOpacity = 1.0; // 値をForeverにすると、子要素があってもなくてもオブジェクトが // 終了しなくなります。 // また0にすると最初のフレームでオブジェクトが破棄されてしまうため、 // 初期化の仕方によってはDurationの設定に失敗することがあります。 // そのため、ここでは非常に小さいけれど0より大きい値を設定しています。 Duration = TimeSpan.FromSeconds(0.001); this.AddPropertyChangedHandler("Parent", (_, __) => { OnDataContextChanged(true); UpdateInheritedOpacity(); }); this.AddPropertyChangedHandler("BasePath", (_, __) => OnBasePathChanged(BasePath)); this.AddPropertyChangedHandler("DataContext", (_, __) => OnDataContextChanged(false)); this.AddPropertyChangedHandler("Opacity", (_, __) => UpdateInheritedOpacity()); lock (instanceList) { instanceList.Add(new WeakReference(this)); } }
/// <summary> /// RectangleF型を同じ変換を行う行列に直します。 /// </summary> /// <param name="transform"> /// 事前に積算する基準となる行列です。 /// </param> private static Matrix44d ToMatrix(RectangleF bounds, Matrix44d transform) { var m = (transform != null ? transform.Clone() : new Matrix44d()); m.Translate( bounds.Left + bounds.Width / 2, bounds.Top + bounds.Height / 2, 0.0); m.Scale(bounds.Width, bounds.Height, 1.0); return m; }
/// <summary> /// 行列を加算します。 /// </summary> public void Add(Matrix44d mat) { for (var i = 0; i < Rows; i++) { for (var j = 0; j < Columns; j++) { this[i, j] += mat[i, j]; } } }
/// <summary> /// 行列を減算します。 /// </summary> public void Subtract(Matrix44d mat) { for (var i = 0; i < Rows; i++) { for (var j = 0; j < Columns; j++) { this[i, j] -= mat[i, j]; } } }
/// <summary> /// 行列を拡大縮小します。 /// </summary> public void Scale(double scaleX, double scaleY, double scaleZ) { var m = new Matrix44d(); m[0, 0] = scaleX; m[1, 1] = scaleY; m[2, 2] = scaleZ; // 最後に行列を積算します。 Multiply(m); }
/// <summary> /// 行列を平行移動します。 /// </summary> public void Translate(double offsetX, double offsetY, double offsetZ) { var m = new Matrix44d(); m[0, 3] = offsetX; m[1, 3] = offsetY; m[2, 3] = offsetZ; // 最後に行列を積算します。 Multiply(m); }
/// <summary> /// 列優先の配列から行列を作成します。 /// </summary> public static Matrix44d FromColumnMajorArray(double[] columnMajorArray) { var matrix = new Matrix44d(); int index = 0; for (int j = 0; j < Columns; j++) { for (int i = 0; i < Rows; i++) { matrix[i, j] = columnMajorArray[index++]; } } return(matrix); }
/// <summary> /// 前に行列を積算します。 /// </summary> public void Prepend(Matrix44d mat) { var clone = Clone(); for (int i = 0; i < Rows; i++) { for (int j = 0; j < Columns; j++) { var value = 0.0; for (int k = 0; k < Rows; k++) { value += mat[i, k] * clone[k, j]; } this[i, j] = value; } } }
/// <summary> /// 行列の比較を行います。 /// </summary> public bool Equals(Matrix44d other) { if ((object)other == null) { return(false); } for (int i = 0; i < Rows; i++) { for (int j = 0; j < Columns; j++) { if (MathEx.Compare(this[i, j], other[i, j]) != 0) { return(false); } } } return(true); }
/// <summary> /// 行列を拡大縮小します。 /// </summary> /// <remarks> /// http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/tech07.html /// </remarks> public void Rotate(double angle, double axisX, double axisY, double axisZ) { var m = new Matrix44d(); var c = Math.Cos(angle); var s = Math.Sin(angle); var t = 1.0 - c; var axis = new Point3d(axisX, axisY, axisZ); //axis.Normalize(); // intermediate values var tx = t * axis.X; var ty = t * axis.Y; var tz = t * axis.Z; var sx = s * axis.X; var sy = s * axis.Y; var sz = s * axis.Z; var txy = tx * axis.Y; var tyz = ty * axis.Z; var tzx = tz * axis.X; // set matrix m[0, 0] = tx * axis.X + c; m[0, 1] = txy - sz; m[0, 2] = tzx + sy; m[0, 3] = 0.0; m[1, 0] = txy + sz; m[1, 1] = ty * axis.Y + c; m[1, 2] = tyz - sx; m[1, 3] = 0.0; m[2, 0] = tzx - sy; m[2, 1] = tyz + sx; m[2, 2] = tz * axis.Z + c; m[2, 3] = 0.0; m[3, 0] = 0.0; m[3, 1] = 0.0; m[3, 2] = 0.0; m[3, 3] = 1.0; // 最後に行列を積算します。 Multiply(m); }
/// <summary> /// 掃き出し法による逆行列の計算を行います。 /// </summary> /// <remarks> /// http://www.asahi-net.or.jp/~uc3k-ymd/Lesson/Section03/invmat.html /// </remarks> public Matrix44d Invert() { if (!HasInverse) { throw new MatrixException( "逆行列の計算ができません。"); } var inv = new Matrix44d(); var clone = Clone(); for (var i = 0; i < Rows; ++i) { var tmp = 1.0 / clone[i, i]; for (var j = 0; j < Rows; ++j) { clone[i, j] *= tmp; inv[i, j] *= tmp; } for (var j = 0; j < Rows; ++j) { if (i != j) { var tmp2 = clone[j, i]; for (var k = 0; k < Columns; ++k) { clone[j, k] -= clone[i, k] * tmp2; inv[j, k] -= inv[i, k] * tmp2; } } } } return(inv); }
/// <summary> /// 描画オブジェクトを追加します。 /// </summary> public void AddRender(BlendType blend, Color color, RectangleF bounds, Matrix44d transform, double zorder, double opacity = 1.0) { var alphaByte = (byte)Math.Min(color.A * opacity, 255); var color2 = Color.FromArgb(alphaByte, color); var transform2 = ToMatrix(bounds, transform); AddRender(blend, color2, transform2, zorder); }
/// <summary> /// 描画オブジェクトを追加します。 /// </summary> public void AddRender(BlendType blend, RectangleF bounds, Matrix44d transform, Color color, double zorder) { var transform2 = ToMatrix(bounds, transform); AddRender(blend, color, transform2, zorder); }
/// <summary> /// 描画オブジェクトを追加します。 /// </summary> public void AddRender(GLUtil.Texture texture, BlendType blend, RectangleF bounds, Matrix44d transform, Mesh mesh, double zorder, double opacity = 1.0) { if (texture == null || texture.TextureName == 0) { return; } var alphaByte = (byte)Math.Min(256 * opacity, 255); var color = Color.FromArgb(alphaByte, Color.White); var transform2 = ToMatrix(bounds, transform); AddRender(texture, blend, color, mesh, transform2, zorder); }
/// <summary> /// 列優先の配列から行列を作成します。 /// </summary> public static Matrix44d FromColumnMajorArray(double[] columnMajorArray) { var matrix = new Matrix44d(); int index = 0; for (int j = 0; j < Columns; j++) { for (int i = 0; i < Rows; i++) { matrix[i, j] = columnMajorArray[index++]; } } return matrix; }
/// <summary> /// 行列の比較を行います。 /// </summary> public bool Equals(Matrix44d other) { if ((object)other == null) { return false; } for (int i = 0; i < Rows; i++) { for (int j = 0; j < Columns; j++) { if (MathEx.Compare(this[i, j], other[i, j]) != 0) { return false; } } } return true; }
private void UpdateTransform() { // 行列変換は以下の操作が逆順で行われます。 // 親の変換行列を基準に変換を行います。 // (ワールド座標系から親座標系への変換行列) var m = (Parent != null ? Parent.Transform : new Matrix44d()); // 親座標系からローカル座標系への変換 m.Multiply(LocalTransform); // ローカル座標系での各種変換 m.Translate(Coord.X, Coord.Y, Coord.Z); m.Rotate(RotateZ, 0.0, 0.0, 1.0); m.Scale(Scale.X, Scale.Y, Scale.Z); m.Scale(BaseScale.X, BaseScale.Y, BaseScale.Z); m.Translate(CenterPoint.X, CenterPoint.Y, CenterPoint.Z); Transform = m; Util.SafeCall(() => OnTransformUpdated()); }
/// <summary> /// 描画オブジェクトを追加します。 /// </summary> public void AddRender(BlendType blend, Color color, Matrix44d transform, double zorder) { AddRenderInternal(new RenderData { Mesh = DefaultMesh, Blend = blend, Color = color, Transform = transform, ZOrder = zorder, }); }
/// <summary> /// 掃き出し法による逆行列の計算を行います。 /// </summary> /// <remarks> /// http://www.asahi-net.or.jp/~uc3k-ymd/Lesson/Section03/invmat.html /// </remarks> public Matrix44d Invert() { if (!HasInverse) { throw new MatrixException( "逆行列の計算ができません。"); } var inv = new Matrix44d(); var clone = Clone(); for (var i = 0; i < Rows; ++i) { var tmp = 1.0 / clone[i, i]; for (var j = 0; j < Rows; ++j) { clone[i, j] *= tmp; inv[i, j] *= tmp; } for (var j = 0; j < Rows; ++j) { if (i != j) { var tmp2 = clone[j, i]; for (var k = 0; k < Columns; ++k) { clone[j, k] -= clone[i, k] * tmp2; inv[j, k] -= inv[i, k] * tmp2; } } } } return inv; }
/// <summary> /// 描画オブジェクトを追加します。 /// </summary> public void AddRender(BlendType blend, Color color, Mesh mesh, Matrix44d transform, double zorder) { if (mesh == null) { throw new ArgumentNullException("mesh"); } AddRenderInternal(new RenderData { Blend = blend, Color = color, Mesh = mesh, Transform = transform, ZOrder = zorder, }); }