Проблема с масштабированием при проецировании 3D на 2D -поверхностьC#

Место общения программистов C#
Ответить
Anonymous
 Проблема с масштабированием при проецировании 3D на 2D -поверхность

Сообщение Anonymous »

Обратите внимание, что это учебное упражнение для меня, поэтому я не использую сторонние библиотеки или матричные преобразования, представленные в .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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»