Цитата(18192123 @ 20.04.2007 8:11)
Почему никто не хочет мне этого объяснить на моём примере?
Я хочу сделать сама, но мне нужно вначале понять, как начинать, а начинать нужно с взятия нормалей, нахождения их векторного произведения и нормирования полученного вектора....
Ну не пойму я, как выбрать в начале вектора!
( а в программе, которую оставил Malice для меня всё не понятно! Да и объёмчик внушительный!)
Сейчас я всё попробую объяснить на конкретном примере=)
Для начала я бы модифицировал сам пример для большего удобства работы.
Вообще я писал бы на объектах=), но не всё сразу.
Во первых описал бы типы:
Код
type
TPoint3d = record {Трёхмерная точка}
case byte of
0: (x, y, z: real); {заданная либо тремя координатами в отдельных полях записи}
1: (v: array[0..2] of real); {либо тремя элементами массива. Тогда 0й-x, 1й-y...}
end;
TNumLine = array[0..1] of integer; {тип, хранящий пару номеров вершин одного ребра}
TNumPlane = array[0..2] of integer; {тип, хранящий тройку номеров вершин одной грани}
TTetra = record {Тип, описывающий тетраэдр}
Points: array[0..3] of TPoint3d; {Все четыре вершины тетраэдра}
Edges: array[0..5] of TNumLine; {Все шесть ребер тетраэдра,
заданные парами номеров соединяемых ребрами вершин из массива Points}
Planes: array[0..3] of TNumPlane; {Все четыре треугольных грани тетраэдра.
Каждая грань задана тройкой номеров вершин, входящих в неё. Номера вершин
в соответствии с массивом Points.}
end;
тогда наш тетраэдр будет задан следующей типизованной константой:
Код
const
Tetra: TTetra = (
Points: ( {Все точки тетраэдра}
(X: -1; Y: -1; Z: -1), {0}
(X: -1; Y: -1; Z: 1), {1}
(X: -1; Y: 1; Z: -1), {2}
(X: -1; Y: 1; Z: 1));{3}
Edges: ( {Все рёбра тетраэдра}
(0, 1),
(0, 2),
(0, 3),
(1, 2),
(2, 3),
(3, 1));
Planes: ( {Все грани тетраэдра}
(0, 1, 2), {внимание! грани лучше задавать так, чтобы если смотреть на них}
(0, 2, 3), {снаружи, то точки обхода грани шли против часовой стрелки}
(0, 3, 1), {зачем это надо скажу ниже}
(1, 2, 3))
);
Тепрь бы я написал функции перевода координат из трёхмерных в экранные.
По-хорошему это надо делать с помощью афинных преобразований, но для начала сойдёт и выкорчевывание кода из привелённой выше по форуму программки.
Я обещал рассказать зачем надо обходить грани против часовой стрелки.
По порядку.
Грань -- это плоскость. Она задана тремя точками не лежащими на одной прямой.
К любой плоскости можно построить нормаль.
Любая точка -- это вектор. Положим все знакомы с операциями сложения/вычитания векторов, а также с операцией их векторного умножения.
Итак, плоскость задана тремя точками (векторами) a, b и c.
У нашего тетраэдра грани имеют две стороны: лицевую и изнаночную.
Положим точки a, b и c, если смотреть на грань с лицевой стороны расположены так, что двигаясь от a к b, от b к c и от c к a мы двигаемся против часовой стрелки.
Получаем два вектора: (ab)=b-a и (ac)=c-a. Векторное произведение v=(ab)*(ac) -- это вектор, перпендикулярный плоскости (abc). Прчем по правилу буравчика он будет смотреть из плоскости в нашу сторону, то есть в сторону лицевой стороны. Если нормировать этот вектор n=v/|v|, то получим как раз нормаль к плоскости abc.
Кстати, я не проверял координаты точек, которыми задан тетраэдр. Очень может быть, что они как раз не удовлетворяют требованию обхода против часовой стрелки. Я полагал, что нулевая точка тетраэдра -- это его вершина, а три другие в основании.
Так что нужно проверить, чтобы это было именно так.
Для первого раза хватит?
Потом дальше расскажу, если всё ещё интересно=).
P.S.
Я приношу свои извинения, если ошибся в синтаксисе. Писал прямо в браузере, и мог опечататься. К тому же сто лет не открывал Турбо Паскаля.