Консультация № 196958
04.11.2019, 22:21
0.00 руб.
1 2 1
Здравствуйте! У меня возникли сложности с таким вопросом:
Необходимо реализовать программу удаления невидимых граней с помощью z-буфера. Имеется код с реализованным построчным проходом, но есть непонятные моменты, а именно вот эта проверка
// Проверяем попадает ли пиксель в треугольник
if (x >= (y - triangle.b1) / triangle.k1)
{
if ((triangle.sign2 == true && y < triangle.k2 * x + triangle.b2) || (triangle.sign2 == false && y > triangle.k2 * x + triangle.b2))
{
if ((triangle.sign3 == true && y < triangle.k3 * x + triangle.b3) || (triangle.sign3 == false && y > triangle.k3 * x + triangle.b3))



Приложение:
public partial class Form1 : Form
{

private int CountFigures;
private List<Triangle> Triangles;
private Graphics G;
private Random R;

private double ZBuffer;
private Color FrameBuffer;
private int Conva;

public Form1()
{
InitializeComponent();

G = CreateGraphics();
R = new Random(unchecked((int)DateTime.Now.Ticks));
CountFigures = R.Next(3, 4);
Triangles = new List<Triangle>();
Conva = 150;

}

private void Exit(object sender, EventArgs e) => Close();

//Отрисовка полигонов
private void DrawVertices()
{
var width = Width / 2;
var height = Height / 2;
//для каждой фигуры
foreach (var triangle in Triangles)
{
var pen = new Pen(triangle.Color, 2);
G.DrawLine(pen, (float)triangle.Point[0].X + width, (float)triangle.Point[0].Y + height, (float)triangle.Point[1].X + width, (float)triangle.Point[1].Y + height);
G.DrawLine(pen, (float)triangle.Point[0].X + width, (float)triangle.Point[0].Y + height, (float)triangle.Point[2].X + width, (float)triangle.Point[2].Y + height);
G.DrawLine(pen, (float)triangle.Point[2].X + width, (float)triangle.Point[2].Y + height, (float)triangle.Point[1].X + width, (float)triangle.Point[1].Y + height);
}
}

private void button1_Click(object sender, EventArgs e)
{
button2.Visible = true;
button1.Visible = false;

//Генерация полигонов
G.Clear(BackColor);
Triangles.Clear();

// Создаем новые фигуры
for (var i = 0; i < CountFigures; i++)
{
Triangles.Add(new Triangle());
}

// Добавляем цвет и точки фигуры
foreach (var triangle in Triangles)
{
//случайный цвет
triangle.Color = Color.FromArgb(R.Next(0, 256), R.Next(0, 256), R.Next(0, 256));
//генерация точек полигона
triangle.Point = new Point3D[3];
for (var j = 0; j < 3; j++)
{
triangle.Point[j] = new Point3D
{
X = R.Next(-Conva, Conva),
Y = R.Next(-Conva, Conva),
Z = R.Next(-Conva * 2, Conva * 2)
};
}

// ax + by + cz + d
// Определение коэффициентов уравнения плоскости по методу Ньюэла
triangle.A = triangle.Point[0].Y * (triangle.Point[1].Z - triangle.Point[2].Z) + triangle.Point[1].Y * (triangle.Point[2].Z - triangle.Point[0].Z) + triangle.Point[2].Y * (triangle.Point[0].Z - triangle.Point[1].Z);
triangle.B = triangle.Point[0].Z * (triangle.Point[1].X - triangle.Point[2].X) + triangle.Point[1].Z * (triangle.Point[2].X - triangle.Point[0].X) + triangle.Point[2].Z * (triangle.Point[0].X - triangle.Point[1].X);
triangle.C = triangle.Point[0].X * (triangle.Point[1].Y - triangle.Point[2].Y) + triangle.Point[1].X * (triangle.Point[2].Y - triangle.Point[0].Y) + triangle.Point[2].X * (triangle.Point[0].Y - triangle.Point[1].Y);
triangle.D = -(triangle.Point[0].X * (triangle.Point[1].Y * triangle.Point[2].Z - triangle.Point[2].Y * triangle.Point[1].Z) +
triangle.Point[1].X * (triangle.Point[2].Y * triangle.Point[0].Z - triangle.Point[0].Y * triangle.Point[2].Z) +
triangle.Point[2].X * (triangle.Point[0].Y * triangle.Point[1].Z - triangle.Point[1].Y * triangle.Point[0].Z));

triangle.Sort();

listBox1.Items.Add(new MyListBoxItem(triangle.Color, " X = " + triangle.Point[0].X + "Y = " + triangle.Point[0].Y));
listBox1.Items.Add(new MyListBoxItem(triangle.Color, " X = " + triangle.Point[1].X + "Y = " + triangle.Point[1].Y));
listBox1.Items.Add(new MyListBoxItem(triangle.Color, " X = " + triangle.Point[2].X + "Y = " + triangle.Point[2].Y));
}
DrawVertices();
}

private void button2_Click(object sender, EventArgs e)
{
var width = Width / 2;
var height = Height / 2;

//Раскрашиваем построчно
for (var y = -Conva; y < Conva; y++)
{
for (var x = -Conva; x < Conva; x++)
{
FrameBuffer = Color.White;
//Инициализация матрицы значений
ZBuffer = -100500000000;
foreach (var triangle in Triangles)
{


// Проверяем попадает ли пиксель в треугольник
if (x >= (y - triangle.b1) / triangle.k1)
{
if ((triangle.sign2 == true && y < triangle.k2 * x + triangle.b2) || (triangle.sign2 == false && y > triangle.k2 * x + triangle.b2))
{
if ((triangle.sign3 == true && y < triangle.k3 * x + triangle.b3) || (triangle.sign3 == false && y > triangle.k3 * x + triangle.b3))
{
// Расчитываем z-буффер по формуле плоскости
// вычисляем глубину каждого пикселя
// z расстояние до камеры
var z = (int)((-triangle.D - triangle.A * x - triangle.B * y) / triangle.C);
if (ZBuffer < z)
{
//Меняем значение буфера и рисуем пиксель
ZBuffer = z;
FrameBuffer = triangle.Color;
}
}
}
}
}
//Раскрашиваем пиксель
var pen = new Pen(FrameBuffer, 1);

//Закрашивание
G.DrawEllipse(pen, x + width, y + height, 1, 1);
G.DrawRectangle(pen, x + width, height + Conva + 10, 1, 10);
}
}
}

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
MyListBoxItem item = listBox1.Items[e.Index] as MyListBoxItem; // Get the current item and cast it to MyListBoxItem
if (item != null)
{
e.Graphics.DrawString( // Draw the appropriate text in the ListBox
item.Message, // The message linked to the item
listBox1.Font, // Take the font from the listbox
new SolidBrush(item.ItemColor), // Set the color
0, // X pixel coordinate
e.Index * listBox1.ItemHeight // Y pixel coordinate. Multiply the index by the ItemHeight defined in the listbox.
);
}
}
}

public class MyListBoxItem
{
public MyListBoxItem(Color c, string m)
{
ItemColor = c;
Message = m;
}
public Color ItemColor { get; set; }
public string Message { get; set; }
}
Прикрепленные файлы:
3b4cf3035e6f9572d3983f641a38ce40768fd8ac.rar

Обсуждение

давно
Советник
400484
472
05.11.2019, 12:37
общий
Код:

// Проверяем попадает ли пиксель в треугольник
if (x >= (y - triangle.b1) / triangle.k1)
{
if ((triangle.sign2 == true && y < triangle.k2 * x + triangle.b2) || (triangle.sign2 == false && y > triangle.k2 * x + triangle.b2))
{
if ((triangle.sign3 == true && y < triangle.k3 * x + triangle.b3) || (triangle.sign3 == false && y > triangle.k3 * x + triangle.b3))

Тут как указано в комментарии идет проверка на нахождение точки в треугольнике, приведенного к плоскости X-Y. Из трехмерной системы, проецируется на двухмерную.

Раскраска идет построчно, как в телевизоре. Как только точка оказывается в плоскости треугольника, происходит изменение белого цвета на цвет треугольника. Слева на право, сверху - вниз.
Прикрепленные файлы:
00ef5c513e997f6021891568c2fe76a7.jpg
давно
Советник
400484
472
11.11.2019, 09:15
общий
это ответ
Здравствуйте, Kseniia!
Код:

// Проверяем попадает ли пиксель в треугольник
if (x >= (y - triangle.b1) / triangle.k1)
{
if ((triangle.sign2 == true && y < triangle.k2 * x + triangle.b2) || (triangle.sign2 == false && y > triangle.k2 * x + triangle.b2))
{
if ((triangle.sign3 == true && y < triangle.k3 * x + triangle.b3) || (triangle.sign3 == false && y > triangle.k3 * x + triangle.b3))

Тут как указано в комментарии идет проверка на нахождение точки в треугольнике, приведенного к плоскости X-Y. Из трехмерной системы, проецируется на двухмерную.

Раскраска идет построчно, как в телевизоре. Как только точка оказывается в плоскости треугольника, происходит изменение белого цвета на цвет треугольника. Слева на право, сверху - вниз.
Прикрепленные файлы:
238a3aba84d21eb1b95e6d17dc2bb40df7b6f944.jpg
Форма ответа