Обратите внимание, что это учебное упражнение для меня, поэтому я не использую сторонние библиотеки или матричные преобразования, представленные в .net. Пример, включенный ниже, отображает куб в форме и позволяет вращать, используя мышь. Это работает нормально, и теперь я пытаюсь реализовать масштаб на основе прокрутки колеса мыши. Если вы присмотритесь при прокрутке колеса мыши, это немного меняется. < /P>
float CubeSize = 200; // Fixed.
float CameraDistance = 400; // Changes with mouse wheel.
// In the FormCube_MouseWheel event:
this.CameraDistance -= e.Delta * 0.1f; // Zoom sensitivity.
this.CameraDistance = Math.Max(100, Math.Min(1000, this.CameraDistance)); // Clamp
// In the OnPaint event:
var scale = this.CameraDistance / (this.CameraDistance + z2);
Я знаю, что мне еще предстоит понять прогнозы, матрицы и т. Д. На данный момент я просто хочу поэкспериментировать с основными формулами и построить оттуда. возможно): < /p>
using System;
using System.Drawing;
using System.Windows.Forms;
namespace GeometricVisualizer
{
internal static class Program
{
[STAThread]
private static void Main() => Application.Run(new FormCube());
}
public struct Point3D
{
public float X, Y, Z;
public Point3D(float x, float y, float z) { this.X = x; this.Y = y; this.Z = z; }
}
public partial class FormCube: Form
{
private Point MousePositionLast;
private bool MouseStateIsDragging;
private float
CameraAngleX = 0,
CameraAngleY = 0,
CubeSize = 200,
CameraDistance = 400;
private int EdgesDimensionLength0 = 12;
private int [,] Edges = new int [,]
{
{0, 1}, {1, 2}, {2, 3}, {3, 0},
{4, 5}, {5, 6}, {6, 7}, {7, 4},
{0, 4}, {1, 5}, {2, 6}, {3, 7},
};
private Point3D [] Cube = new Point3D []
{
new(x: -1, y: -1, z: -1),
new(x: 1, y: -1, z: -1),
new(x: 1, y: 1, z: -1),
new(x: -1, y: 1, z: -1),
new(x: -1, y: -1, z: 1),
new(x: 1, y: -1, z: 1),
new(x: 1, y: 1, z: 1),
new(x: -1, y: 1, z: 1),
};
private PointF [] CubeProjected = new PointF [8];
public FormCube ()
{
this.EdgesDimensionLength0 = this.Edges.GetLength(0);
this.KeyPreview = true;
this.DoubleBuffered = true;
this.Text = "3D Cube with Mouse Rotation";
this.WindowState = FormWindowState.Maximized;
this.KeyDown += this.FormCube_KeyDown;
this.MouseUp += this.FormCube_MouseUp;
this.MouseDown += this.FormCube_MouseDown;
this.MouseMove += this.FormCube_MouseMove;
this.MouseWheel += this.FormCube_MouseWheel;
this.Resize += this.FormCube_Resize;
this.ResizeEnd += this.FormCube_Resize;
this.ResizeBegin += this.FormCube_Resize;
}
private void FormCube_Resize (object? sender, EventArgs e)
=> this.Invalidate();
private void FormCube_KeyDown (object? sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up: { this.CameraAngleX -= 0.1f; break; }
case Keys.Down: { this.CameraAngleX += 0.1f; break; }
case Keys.Left: { this.CameraAngleY -= 0.1f; break; }
case Keys.Right: { this.CameraAngleY += 0.1f; break; }
case Keys.Add:
case Keys.Oemplus: { this.CameraDistance = Math.Max(100, this.CameraDistance - 20); break; }
case Keys.Subtract:
case Keys.OemMinus: { this.CameraDistance = Math.Min(1000, this.CameraDistance + 20); break; }
case Keys.R: { this.CameraAngleX = 0; this.CameraAngleY = 0; this.CameraDistance = 400; break; }
}
this.Invalidate();
}
private void FormCube_MouseDown (object? sender, MouseEventArgs e)
{
this.MouseStateIsDragging = true;
this.MousePositionLast = e.Location;
}
private void FormCube_MouseMove (object? sender, MouseEventArgs e)
{
if (this.MouseStateIsDragging)
{
var dx = e.X - this.MousePositionLast.X;
var dy = e.Y - this.MousePositionLast.Y;
this.CameraAngleY += dx * 0.01f;
this.CameraAngleX += dy * 0.01f;
this.MousePositionLast = e.Location;
this.Invalidate();
}
}
private void FormCube_MouseUp (object? sender, MouseEventArgs e)
=> this.MouseStateIsDragging = false;
private void FormCube_MouseWheel (object? sender, MouseEventArgs e)
{
this.CameraDistance -= e.Delta * 0.1f; // Zoom mouse sensitivity.
this.CameraDistance = Math.Max(100, Math.Min(1000, this.CameraDistance)); // Clamp zoom.
this.Invalidate();
}
protected override void OnPaint (PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
for (var i = 0; i < this.Cube.Length; i++)
{
var p = this.Cube ;
// Rotate around X axis.
var y1 = (p.Y * (float) Math.Cos(this.CameraAngleX)) - (p.Z * (float) Math.Sin(this.CameraAngleX));
var z1 = (p.Y * (float) Math.Sin(this.CameraAngleX)) + (p.Z * (float) Math.Cos(this.CameraAngleX));
// Rotate around Y axis.
var x2 = (p.X * (float) Math.Cos(this.CameraAngleY)) - (z1 * (float) Math.Sin(this.CameraAngleY));
var z2 = (p.X * (float) Math.Sin(this.CameraAngleY)) + (z1 * (float) Math.Cos(this.CameraAngleY));
var scale = this.CameraDistance / (this.CameraDistance + z2);
this.CubeProjected = new PointF
(
(x2 * scale * this.CubeSize) + (this.ClientSize.Width / 2),
(y1 * scale * this.CubeSize) + (this.ClientSize.Height / 2)
);
}
for (var i = 0; i < this.EdgesDimensionLength0; i++)
{
e.Graphics.DrawLine(Pens.White, this.CubeProjected [this.Edges [i, 0]], this.CubeProjected [this.Edges [i, 1]]);
}
this.Text = $@"AngleX = {this.CameraAngleX}, AngleY = {this.CameraAngleY}, Zoom = {this.CameraDistance}.";
base.OnPaint(e);
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... 2d-surface