3D transformāciju matricas 2
Turpinot tēmu, uzrakstīju programmu, kas implementē vienkāršu scenegraph un zīmē 3D punktus.
Bet rotācija ap Y un Z asīm strādā nepareizi.Bubu, lūdzu, lūdzu, izpalīdzi! Kur man ir kļūda?
public class Vector
{
public double x, y, z;
public Vector(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public static Vector operator *(Vector u, Matrix v)
{
Vector w = new Vector();
w.x = u.x * v.a + u.y * v.d * u.z * v.g + 1 * v.l;
w.y = u.x * v.b + u.y * v.e + u.z * v.i + 1 * v.m;
w.z = u.x * v.c + u.y * v.f + u.z * v.j + 1 * v.n;
double h = u.x * v.p + u.y * v.q + u.z * v.r + 1 * v.s;
w.x /= h;
w.y /= h;
w.z /= h;
return w;
}
}
public class Matrix
{
public double a, b, c, p, d, e, f, q, g, i, j, r, l, m, n, s;
public Matrix()
{
a = 1;
e = 1;
j = 1;
s = 1;
}
public static Matrix operator *(Matrix u, Matrix v)
{
Matrix w = new Matrix();
w.a = u.a * v.a + u.b * v.d + u.c * v.g + u.p * v.l;
w.b = u.a * v.b + u.b * v.e + u.c * v.i + u.p * v.m;
w.c = u.a * v.c + u.b * v.f + u.c * v.j + u.p * v.n;
w.p = u.a * v.p + u.b * v.q + u.c * v.r + u.p * v.s;
w.d = u.d * v.a + u.e * v.d + u.f * v.g + u.q * v.l;
w.e = u.d * v.b + u.e * v.e + u.f * v.i + u.q * v.m;
w.f = u.d * v.c + u.e * v.f + u.f * v.j + u.q * v.n;
w.q = u.d * v.p + u.e * v.q + u.f * v.r + u.q * v.s;
w.g = u.g * v.a + u.i * v.d + u.j * v.g + u.r * v.l;
w.i = u.g * v.b + u.i * v.e + u.j * v.i + u.r * v.m;
w.j = u.g * v.c + u.i * v.f + u.j * v.j + u.r * v.n;
w.r = u.g * v.p + u.i * v.q + u.j * v.r + u.r * v.s;
w.l = u.l * v.a + u.m * v.d + u.n * v.g + u.s * v.l;
w.m = u.l * v.b + u.m * v.e + u.n * v.i + u.s * v.m;
w.n = u.l * v.c + u.m * v.f + u.n * v.j + u.s * v.n;
w.s = u.l * v.p + u.m * v.q + u.n * v.r + u.s * v.s;
return w;
}
public static Matrix RotateX(double angle)
{
Matrix w = new Matrix();
w.e = Math.Cos(angle);
w.f = Math.Sin(angle);
w.i = -Math.Sin(angle);
w.j = Math.Cos(angle);
return w;
}
public static Matrix RotateY(double angle)
{
Matrix w = new Matrix();
w.a = Math.Cos(angle);
w.c = -Math.Sin(angle);
w.g = Math.Sin(angle);
w.j = Math.Cos(angle);
return w;
}
public static Matrix RotateZ(double angle)
{
Matrix w = new Matrix();
w.a = Math.Cos(angle);
w.b = Math.Sin(angle);
w.d = -Math.Sin(angle);
w.e = Math.Cos(angle);
return w;
}
public static Matrix Translate(double x, double y, double z)
{
Matrix w = new Matrix();
w.l = x;
w.m = y;
w.n = z;
return w;
}
public static Matrix Scale(double x, double y, double z)
{
Matrix w = new Matrix();
w.a = x;
w.e = y;
w.j = z;
return w;
}
}
public class Node
{
Matrix transform;
Node parent;
List children;
public Node()
{
transform = new Matrix();
children = new List();
}
public Node(Node parent) : this()
{
Parent = parent;
}
public virtual void Render(Graphics graphics, Matrix transform)
{
foreach (Node i in children)
{
i.Render(graphics, i.transform * transform);
}
}
public List Children
{
get { return children; }
}
public Node Parent
{
get { return parent; }
set
{
if (parent != null)
{
parent.children.Remove(this);
}
if (value != null)
{
value.children.Add(this);
}
parent = value;
}
}
public Matrix Transform
{
get { return transform; }
set { transform = value; }
}
}
public class Mesh : Node
{
List vertices;
Brush brush;
public Mesh() : this(null)
{
}
public Mesh(Node parent) : base(parent)
{
vertices = new List();
brush = Brushes.White;
}
public override void Render(Graphics graphics, Matrix transform)
{
base.Render(graphics, transform);
foreach (Vector i in vertices)
{
Vector j = i * transform;
if (j.z > 0.1)
{
float size = (float)(0.05 / j.z);
graphics.FillRectangle(brush, (float)(j.x / j.z) - size / 2, (float)(j.y / j.z) - size / 2, size, size);
}
}
}
public Brush Brush
{
get { return brush; }
set { brush = value; }
}
public List Vertices
{
get { return vertices; }
}
}
public class Camera : Node
{
public Camera()
{
}
public Camera(Node parent) : base(parent)
{
}
public void Render(Graphics graphics)
{
float w = graphics.VisibleClipBounds.Width / 2;
float h = graphics.VisibleClipBounds.Height / 2;
graphics.Transform = new System.Drawing.Drawing2D.Matrix(h, 0, 0, -h, w, h);
Matrix transform = new Matrix();
Node i;
for (i = this; i.Parent != null; i = i.Parent)
{
transform = i.Transform * transform;
}
i.Render(graphics, transform);
}
}
public partial class Window : Form
{
Node root;
Camera camera;
Mesh cube;
Mesh cube2;
Mesh cube3;
Mesh ground;
public Window()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
root = new Node();
camera = new Camera(root);
camera.Transform = Matrix.Translate(0, -2, 0);
ground = new Mesh(root);
ground.Brush = Brushes.Green;
for (double i = -10; i <= 10; i += 1)
{
for (double j = -10; j <= 10; j += 0.05)
{
ground.Vertices.Add(new Vector(i, 0, j));
ground.Vertices.Add(new Vector(j, 0, i));
}
}
cube = new Mesh(root);
cube.Transform = Matrix.Scale(0.5, 0.5, 0.5) * Matrix.Translate(2, 0.5, 3.5);
for (double i = -1; i <= 1; i += 0.1)
{
cube.Vertices.Add(new Vector(i, -1, -1));
cube.Vertices.Add(new Vector(-1, i, -1));
cube.Vertices.Add(new Vector(-1, -1, i));
cube.Vertices.Add(new Vector(i, 1, -1));
cube.Vertices.Add(new Vector(1, i, -1));
cube.Vertices.Add(new Vector(-1, 1, i));
cube.Vertices.Add(new Vector(1, 1, i));
cube.Vertices.Add(new Vector(1, -1, i));
cube.Vertices.Add(new Vector(-1, i, 1));
cube.Vertices.Add(new Vector(i, -1, 1));
cube.Vertices.Add(new Vector(i, 1, 1));
cube.Vertices.Add(new Vector(1, i, 1));
}
cube2 = new Mesh(root);
cube2.Vertices = cube.Vertices;
cube2.Transform = Matrix.Scale(0.5, 0.5, 0.5) * Matrix.Translate(0, 0.5, 3.5);
cube3 = new Mesh(root);
cube3.Vertices = cube.Vertices;
cube3.Transform = Matrix.Scale(0.5, 0.5, 0.5) * Matrix.Translate(-2, 0.5, 3.5);
}
void Window_Paint(object sender, PaintEventArgs e)
{
camera.Render(e.Graphics);
}
void timer1_Tick(object sender, EventArgs e)
{
cube.Transform = Matrix.RotateZ(0.05) * cube.Transform;
cube2.Transform = Matrix.RotateY(0.05) * cube2.Transform;
cube3.Transform = Matrix.RotateX(0.05) * cube3.Transform;
Invalidate();
}
}