IPB
ЛогинПароль:

> Внимание! Действует предмодерация

Подраздел FAQ (ЧАВО, ЧАстые ВОпросы) предназначен для размещения готовых рабочих программ, реализаций алгоритмов. Это нечто вроде справочника, он наполнялся в течение 2000х годов. Ваши вопросы, особенно просьбы решить задачу, не пройдут предмодерацию. Те, кто наполнял раздел, уже не заходят на форум, а с теми, кто на форуме сейчас, лучше начинать общение в других разделах. В частности, решение задач — здесь.

 
 Ответить  Открыть новую тему 
> 3d графика. АЗЫ для написания с нуля.
сообщение
Сообщение #1


Ищущий истину
******

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Репутация: -  45  +


3D графика.
Основная задача при выводе 3D графики на экран является преобразование 3 координат в две,
т.к. на экран мы можем вывести лишь 2 координаты.
Учитывая, что "структуры данных+ алгоритмы= программы", определимся сначала со структурами данных.

Что такое 3D объект? Наиболее просто себе его представить в виде совокупности точек, комбинируя которые в
пары или по тройкам можно в дальнейшем получать соответственно "проволочные модели"* или "полигонные модели"*.
То есть для работы с 3D объектами для начала подойдет просто массив точек.
array[1..n] of record x,y,z:double end; 
или
array[1..n1*3]of double 

В первом случае задан массив точек (record~point) а во втором массив координат, который надо интерплитировать так:
( (x1,y1,z1),(x2,y2,z2), ... ,(xi,yi,zi), ... ,(xn,yn,zn) )

То есть каждые 3 элемента массива- точка. Второй способ мне кажется удобнее при работе, поэтому примеры будут с ним.

Для вывода на экран объекта, будем использовать следующие известные формулы:

Yt = Y * COS(Xan) - Z * SIN(Xan)
Zt = Y * SIN(Xan) + Z * COS(Xan)
Y = Yt
Z = Zt
Xt = X * COS(Yan) - Z * SIN(Yan)
Zt = X * SIN(Yan) + Z * COS(Yan)
X = Xt
Z = Zt
Xt = X * COS(Zan) - Y * SIN(Zan)
Yt = X * SIN(Zan) + Y * COS(Zan)
X = Xt <--это выводим
Y = Yt <--это выводим

то есть для каждой точки мы должны вычислить X и Y, и вывести на экран.

Вот простой пример программы, демонстирущий вращение и изменение размеров. Весь код с коментариями.

uses Graph,crt;
const {хотя это и константы, но поскольку у них описан тип, они представляют из себя переменные}
{координаты объекта (куба) (подробно: точка1_x, точка1_y,
точка1_z, точка2_x, точка2_y, ...)}
cube: array[0..23] of real = {8 точек * 3 координаты(X,Y,Z) = 24 номера}
(-1,-1,-1,-1,-1,1,-1,1,-1,
-1,1,1,1,-1,-1,1,-1,1,
1,1,-1,1,1,1);
lindex: array[0..23] of integer = {12 линий * 2 точки для линии = }
(0,1,0,4,0,2,1,3,1,5,2,3, {24 номера}
2,6,3,7,4,5,4,6,5,7,6,7); {для каждой линии устанавливается связь
между 2 точками, то есть (точка #0 с точкой #1, ...)}
var xt,yt,zt:real; {временные точки}
xan,yan,zan:real; {Углы вращения для осей X,Y,Z соответсвенно }
sx,sy,sx1,sy1,p,zoom: integer; {Экранные координаты X,Y}

procedure draw(color:byte); {Процедура для рисования куба.
куб рисует цветом color, таким образом,
для закрашивания куба, следует задать
цвет фона -0 (черный) }
begin
for p:=0 to 11 do begin {цикл для всех 12 линий}
{считаем, что куб повернут как нам нужно, и мы просто выводим его _ребра_
переменная zoom необходима для простого управления размера куба на экране. }
sx:=round(zoom*cube[lindex[p*2]*3])+160; {x координата для точки #1}
sy:=round(zoom*cube[lindex[p*2]*3+1])+100; {y кордината для точки #1}
sx1:=round(zoom*cube[lindex[p*2+1]*3])+160; {x координата для точки #2}
sy1:=round(zoom*cube[lindex[p*2+1]*3+1])+100; {y координата для точки #2}
setcolor(color); {устанавливаем цвет для рисования}
line(SX,SY,sx1,sy1); {рисуем линю}
end;
end;

procedure calc; {вычисляет новые величины коордианат после шага поворота}
begin
for p:=0 to 7 do begin {повторение для всех 8 точек куба.}
Yt := cube[p*3+1] * COS(Xan) - cube[p*3+2] * SIN(Xan); {прочитаем старые величины со таблицы координат,}
Zt := cube[p*3+1] * SIN(Xan) + cube[p*3+2] * COS(Xan); {поворачиваем вокруг оси X}
cube[p*3+1] := Yt; {Пишем новые значения координат в таблицу координат}
cube[p*3+2] := Zt;

Xt := cube[p*3] * COS(Yan) - cube[p*3+2] * SIN(Yan); {аналогично как выше, для Y }
Zt := cube[p*3] * SIN(Yan) + cube[p*3+2] * COS(Yan);
cube[p*3] := Xt; {сохраняем новые значения }
cube[p*3+2] := Zt;

Xt := cube[p*3] * COS(Zan) - cube[p*3+1] * SIN(Zan); {для оси Z}
Yt := cube[p*3] * SIN(Zan) + cube[p*3+1] * COS(Zan);
cube[p*3] := Xt;
cube[p*3+1] := Yt;
end;
end;


var
gd,gm:integer;
t:char;
begin
gd:=detect; initgraph(gd,gm,''); {инициализация граф. режима}
Zan := 0.1; {вращение вокруг оси Z этим углом}
Yan := 0.02; {вращение вокруг оси Y этим углом}
Xan := 0.02; {вращение вокруг оси X этим углом}
zoom:=30; {размер куба. (не забываем что мы его описали как единичный куб,
и на экране он будет точкой без увеличения :)}
{вращение}
repeat {цикл ...}
draw(15); {выводим куб}
delay(2000); {ждем... внимательно с задержкой...}
draw(0); {зарисовываем куб}
calc; {вычислыем новые координаты}
if keypressed then begin {если нажата клавиша }
t:=readkey;
case t of
'=':zoom:=zoom+1; {+} {увеличиваем куб}
'-': zoom:=zoom-1;{-} {уменьшаем }
end;
end
until t=#13;; {... до нажатия клавиши ENTER}
closegraph; {возвращаем в текстовый режим}
end.


--------------------
Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 9.08.2022 18:46
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name