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

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

> Закраска по методу Гуро и Фонга
18192123
сообщение 16.04.2007 21:41
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Мне нужно изобразить тетраэдр , выполнить закраску Фонга относительно выбранного источника света, разработать процедуру управления скоростью вращения тела с одинаковыми ускорениями по осям и обеспечения перехода на низкозатратную процедуру Гуро и далее на закраску с использованием таблиц освещенности при увеличении угловых скоростей вращения.

Вот... Не знаю даже, с чего начать... Теорию по методам закраски изучила.... но с таким никогда не сталкивалась, поэтому с реализацией большие проблемы....

вот на что думаю опираться:
1. Получить нормаль грани: выбрать два вектора, лежащие в этой грани и найти их векторное произведение, нормировать этот вектор.
2. Записать найденные нормали граней в массив (normg[i]). Чтобы определить нормаль каждой вершины, определяем из таблицы граней для каждой вершины, какие грани в ней сходятся, и для этих найденных граней их нормали суммируем, а сумму нор-мируем (массив normv[i]).
3. Алгоритм Гуро. После того, как нормали вершин найдены, вы-числяем согласно модели освещения освещенность каждой вершины и записываем освещенности в массив освещенностей. Этот массив будет использоваться в процедуре рисования грани.
Алгоритм Фонга. Координаты найденных нормалей вершин пе-реводятся в сферические координаты, так что нормали представле-ны двумя числами типа byte. Нормали в таком виде будут использо-ваны процедурой рисования грани.
4. Реализовать процедуру рисования грани, для чего необходимо провести интерполяцию для определения освещенности (в ме-тоде Гуро) и нормали (в методе Фонга) для каждой точки гра-ни.
Закраску граней можно произвести путем заполнения внутренней области этой грани отрезками прямых, параллельных оси OX. Для этого найдем вершины грани с наименьшей и наибольшей координатой Y.
В качестве начальной возьмем вершину с наименьшей координатой Y. Разобьем условно множество ребер, составляющих грань, на две группы – левую и правую. Будем по очереди брать одно ребро из левой и одно из правой части, т.е. всегда работать с парой ребер. Выбор ребер может производиться следующим образом: сначала берем в качестве левого ребра ребро, начинающееся в начальной вершине и заканчиваю-щееся в следующей по порядку при обходе влево. Это ребро (l0,lk). Аналогично, в качестве первого правого ребра – ребро (r0,rk). Теперь в цикле будем строить прямые, параллельные оси X, начиная с прямой Y = Ymin, каждый раз увеличивая ординату. Для каждой этой прямой бу-дем находить точки пересечения с нашей парой боковых ребер. Если одно из боковых ребер не имеет точки пересечения с этой прямой, то его отбрасываем и берем следующее из его группы (левой или правой).
Если точки пересечения найдены, то найдем, какая часть левого и правого ребра пройдена, это значение запишется соответственно в пе-ременные tl и tr. Значение переменных tl и tr используется на первом шаге билинейной интерполяции в методе Гуро для нахождения осве-щенности в точках пересечения прямой, параллельной оси Х, и ребер, а в методе Фонга для определения нормалей тела в этих точках. Второй шаг интерполяции ведется аналогично, только вдоль отрезка, заключен-ного между парой ребер. Таким образом, вычисляется необходимая ин-формация для каждой точки грани.

но как всё это реализовать - не знаю! С чего начинать! Может быть кто-нибудь может привести реализацию методов закраски?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
2 страниц V  1 2 >  
 Ответить  Открыть новую тему 
Ответов(1 - 19)
18192123
сообщение 17.04.2007 20:52
Сообщение #2


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


получилось нарисовать фигуру и вращать её, вот только с соединениями линий - путаница.... где ошибка?

uses Graph,crt;
const tetr: array[0..11] of real =
(-1,-1,-1,-1,-1,1,-1,1,-1,
-1,1,1);
line_: array[0..11] of integer = (0,1,0,4,0,2,1,3,1,5,2,3);
var xt,yt,zt:real;
x,y,z:real;
sx,sy,sx1,sy1,p,zoom: integer;

procedure draw(color:byte);
begin
for p:=0 to 5 do begin
sx:=round(zoom*tetr[line_[p*2]*3])+260;
sy:=round(zoom*tetr[line_[p*2]*3+1])+300;
sx1:=round(zoom*tetr[line_[p*2+1]*3])+260;
sy1:=round(zoom*tetr[line_[p*2+1]*3+1])+300;
setcolor(color);
line(SX,SY,sx1,sy1);
end;
end;

procedure calc;
begin
for p:=0 to 3 do begin
Yt := tetr[p*3+1] * COS(X) - tetr[p*3+2] * SIN(X);
Zt := tetr[p*3+1] * SIN(X) + tetr[p*3+2] * COS(X);
tetr[p*3+1] := Yt;
tetr[p*3+2] := Zt;

Xt := tetr[p*3] * COS(Y) - tetr[p*3+2] * SIN(Y);
Zt := tetr[p*3] * SIN(Y) + tetr[p*3+2] * COS(Y);
tetr[p*3] := Xt;
tetr[p*3+2] := Zt;

Xt := tetr[p*3] * COS(Z) - tetr[p*3+1] * SIN(Z);
Yt := tetr[p*3] * SIN(Z) + tetr[p*3+1] * COS(Z);
tetr[p*3] := Xt;
tetr[p*3+1] := Yt;
end;
end;


var
gd,gm:integer;
t:char;
begin
gd:=detect; initgraph(gd,gm,'');
Z := 0.1;
Y := 0.1;
X := 0.1;
zoom:=70;

repeat
draw(15);
delay(20000);
draw(0);
calc;
if keypressed then begin
t:=readkey;
case t of
'=':zoom:=zoom+1; {+}
'-': zoom:=zoom-1;{-}
end;
end
until t=#13;;
closegraph;
end.





Сообщение отредактировано: 18192123 - 17.04.2007 21:00
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 17.04.2007 22:53
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


а как выбрать источник света и как с ним работать?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 17.04.2007 23:07
Сообщение #4


Гость






Марина, загляни вот сюда:
Dasaev Demo Guide v1.1

Там у него описывается работа с закрасками и по Гуро и по Фонгу...
 К началу страницы 
+ Ответить 
18192123
сообщение 18.04.2007 14:18
Сообщение #5


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Цитата(volvo @ 18.04.2007 0:07) *

Марина, загляни вот сюда:
Dasaev Demo Guide v1.1

Там у него описывается работа с закрасками и по Гуро и по Фонгу...

зашла по ссылке, скачала архив, но там полная ерунда - нужные файлы, где должны быть исходники, содержат только набор разных символов!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 18.04.2007 19:55
Сообщение #6


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


а может есть ещё что-то такое?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 19.04.2007 12:10
Сообщение #7


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Нашла вот такую программу для закраски тетраэдра:


program lab5;
uses graph,crt;
const n=8;
procedure draw;
label
nextj;
type
tetr=array[1..n] of record x,y,z:integer end;
const
verts : tetr=(
(x:-1; y:1; z:1),
(x:1; y:1; z:1),
(x:-1; y:1; z:-1),
(x:-1; y:-1; z:1),
(x:1;y:-1;z:-1),
(x:1;y:-1;z:1),
(x:1;y:1;z:-1),
(x:-1;y:-1;z:-1) );
g:array[1..n,1..4] of shortint=
(
(1,4,2,3),
(1,3,2,4),
(3,4,2,1),
(4,1,3,2),
(2,4,1,3),
(3,2,4,1),
(2,4,3,1),
(4,1,2,3));
var
alfa,beta,gamma,
teta,
dt:real;
c:tetr;
procedure rotate(var x,y,z:integer);
var
cost,sint,one_cost,aone_cost,bone_cost,gsint:real;
xn,yn,zn:integer;
begin
cost:=cos(teta);
sint:=sin(teta);
one_cost:=1.0-cost;
aone_cost:=alfa*one_cost;
bone_cost:=beta*one_cost;
gsint:=gamma*sint;

xn:=trunc(
x*(cost +alfa*aone_cost)+
y*(gsint +beta *aone_cost)+
z*(-beta*sint +gamma*aone_cost));
yn:=trunc(
x*(-gsint+ beta*aone_cost)+
y*(cost +beta*bone_cost)+
z*(alfa*sint + gamma*bone_cost));
zn:=trunc(
x*(beta*sint + gamma*aone_cost)+
y*(-alfa*sint +gamma *bone_cost)+
z*(-beta*sint +gamma*one_cost));
x:=xn;y:=yn;z:=zn;
end;
function minz:integer;
var j,m:integer;
begin
m:=1;
for j:=1 to n do
if c[j].z<c[m].z then m:=j;
minz:=m;
end;
var
pnts:array[1..n] of record
x,y:integer end ;
min:integer;
x0,y0:integer;
a:integer;
i,j,k:integer;
page:word;
begin
page:=0;
x0:=300;
y0:=150;
a:=70;
alfa:=0.6;
beta:=0.7;
gamma:=sqrt(1.0-alfa*alfa-beta*beta);
teta:=0;
dt:=2*pi/100; for i:=1 to n do
begin
c[i].x:=verts[i].x*a;
c[i].y:=verts[i].y*a;
c[i].z:=verts[i].y*a;
rotate(c[i].x,c[i].y,c[i].z)
end;
min:=minz;
setvisualpage((page+1)mod 2);
for k:=0 to 2500 do
begin
setactivepage(page);
for j:=1 to 8 do
begin
for i:=1 to 5 do if min=g[j,i] then goto nextj;
for i:=1 to 5 do
begin
pnts[i].x:=x0+c[g[j,i]].x;
pnts[i].y:=y0+trunc(0.775*c[g[j,i]].y)
end;
setfillstyle(solidfill,word(j+4));
fillpoly(3,pnts) ; delay(100);
nextj:
end;
setvisualpage(page);
setactivepage((page+1)mod 2);
for i:=1 to n do
begin
c[i].x:=verts[i].x*a;
c[i].y:=verts[i].y*a;
c[i].z:=verts[i].z*a;
rotate(c[i].x,c[i].y,c[i].z)
end;
min:=minz;cleardevice;
teta:=teta+dt;
page:=(page+1)mod 2;
if keypressed then
exit;
end;
end;
var drv,mode:integer;
begin
drv:=ega;
mode:=egahi;
initgraph(drv,mode,'');
draw;
closegraph;
end.




мне здесь не понятно назначение функции minz, а также что хранится в этом массиве записей и для чего это нужно:

pnts:array[1..n] of record
x,y:integer end ;



а самое главное - не понятна главная часть процедуры Рисование(procedure draw;), каким образом там производится рисование и закраска? пожалуйста, объясните основные моменты этого куска!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 19.04.2007 18:19
Сообщение #8


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Если тетраэдр с его вершинами и сторонами задаётся таким образом (см. код), то как выбрать два вектора, лежащие в какой-то грани и так для всех граней?

tetr=array[1..n] of record x,y,z:integer end;
const
verts : tetr=(
(x:-1; y:1; z:1),
(x:1; y:1; z:1),
(x:-1; y:1; z:-1),
(x:-1; y:-1; z:1),
(x:1;y:-1;z:-1),
(x:1;y:-1;z:1),
(x:1;y:1;z:-1),
(x:-1;y:-1;z:-1) );
g:array[1..n,1..4] of shortint=
(
(1,4,2,3),
(1,3,2,4),
(3,4,2,1),
(4,1,3,2),
(2,4,1,3),
(3,2,4,1),
(2,4,3,1),
(4,1,2,3));




Сообщение отредактировано: 18192123 - 19.04.2007 21:25
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 19.04.2007 21:49
Сообщение #9


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


и что значит "нормировать" вектор? ( как это производится?)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Malice
сообщение 19.04.2007 21:55
Сообщение #10


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

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


Вот еще с далеких фидошных времен откопался примерчик заливки по фонгу, думаю поможет: Прикрепленный файл  PHONG.RAR ( 9.58 килобайт ) Кол-во скачиваний: 486
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 19.04.2007 23:26
Сообщение #11


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Цитата(Malice @ 19.04.2007 22:55) *

Вот еще с далеких фидошных времен откопался примерчик заливки по фонгу, думаю поможет: Прикрепленный файл  PHONG.RAR ( 9.58 килобайт ) Кол-во скачиваний: 486


Спасибо!
Но лучше уж я с чистого листа начну....
Вопросы из сообщений 8 и 9 до сих пор для меня не ясны...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 20.04.2007 8:11
Сообщение #12


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Цитата(18192123 @ 20.04.2007 0:26) *

Спасибо!
Но лучше уж я с чистого листа начну....
Вопросы из сообщений 8 и 9 до сих пор для меня не ясны...

Почему никто не хочет мне этого объяснить на моём примере?
Я хочу сделать сама, но мне нужно вначале понять, как начинать, а начинать нужно с взятия нормалей, нахождения их векторного произведения и нормирования полученного вектора....
Ну не пойму я, как выбрать в начале вектора!
( а в программе, которую оставил Malice для меня всё не понятно! Да и объёмчик внушительный!)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 20.04.2007 8:18
Сообщение #13


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

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


Цитата(18192123 @ 19.04.2007 22:49) *

и что значит "нормировать" вектор? ( как это производится?)

Я думаю, нормировать - это значит сделать так, чтобы его длина была равна 1, сохранив направление прежним.


Добавлено через 2 мин.
Цитата(18192123 @ 19.04.2007 19:19) *

задаётся таким образом (см. код),

Мне непонятен способ задания тетраедра. Это вершины? или что?
Поясни, пожалуйста.


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 20.04.2007 8:21
Сообщение #14


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Цитата(Lapp @ 20.04.2007 9:18) *

Я думаю, нормировать - это значит сделать так, чтобы его длина была равна 1, сохранив направление прежним.

blink.gif никогда о таком не слышала...а можно показать на примере, как это сделать?

Добавлено через 7 мин.
Цитата(Lapp @ 20.04.2007 9:18) *


Мне непонятен способ задания тетраедра. Это вершины? или что?
Поясни, пожалуйста.

х, у, z - это вершины
g:array[1..n,1..4] - линии

но мне кажется ,что лучше задавать эти величины так ,как я пыталась выше (не совсем удачно..)

const tetr: array[0..11] of real =
(-1,-1,-1,-1,-1,1,-1,1,-1,
-1,1,1);
line_: array[0..11] of integer = (0,1,0,4,0,2,1,3,1,5,2,3);



у меня тут линий не хватает вроде...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 20.04.2007 8:37
Сообщение #15


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

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


Цитата(18192123 @ 20.04.2007 9:21) *

blink.gif никогда о таком не слышала...а можно показать на примере, как это сделать?

Ai'=Ai/|A|

Остальное позже. Машина в ремонте, автобус уходит.. smile.gif


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 20.04.2007 8:48
Сообщение #16


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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


Цитата(Lapp @ 20.04.2007 9:37) *

Ai'=Ai/|A|

Остальное позже. Машина в ремонте, автобус уходит.. smile.gif


|A| - поясни пожалуйста, это модуль чего? (без i)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Lapp
сообщение 20.04.2007 10:53
Сообщение #17


Уникум
*******

Группа: Модераторы
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

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


Цитата(18192123 @ 20.04.2007 9:48) *

|A| - поясни пожалуйста, это модуль чего? (без i)

Модуль вектора А.


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Malice
сообщение 20.04.2007 15:49
Сообщение #18


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

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


Цитата(18192123 @ 19.04.2007 13:10) *

мне здесь не понятно назначение функции minz

поиск минимальной Z-координаты

Цитата(18192123 @ 19.04.2007 13:10) *

а также что хранится в этом массиве записей и для чего это нужно:

pnts:array[1..n] of record
x,y:integer end ;


а самое главное - не понятна главная часть процедуры Рисование(procedure draw;), каким образом там производится рисование и закраска? пожалуйста, объясните основные моменты этого куска!

pnts- массив всех вершин грани, используется для функции FillPoly, которая выполняет заливку.

Цитата
икогда о таком не слышала...а можно показать на примере, как это сделать?

находишь длину вектора нормали и дельшь все его координаты на длину. Получается вектор длиной =1.

Цитата
у меня тут линий не хватает вроде...

Как бы да smile.gif У тебя всего 4 точки (0..3), а в описаниях граней присутствуют цифры 4 и 5 smile.gif
Вот так попробуй чтоли:
array[0..11] of real =   (1,0,0, 0,1,0, 0,0,1, -0.5,-0.5,-0.5);
line_:array[0..11] of integer = (0,1, 0,2, 0,3, 1,2, 1,3, 2,3);
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
18192123
сообщение 23.04.2007 21:32
Сообщение #19


Профи
****

Группа: Пользователи
Сообщений: 920
Пол: Женский
Реальное имя: Марина

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



procedure draw(color:byte);
begin
for p:=0 to 5 do begin
sx:=round(zoom*tetr[line_[p*2]*3])+260;
sy:=round(zoom*tetr[line_[p*2]*3+1])+300;
sx1:=round(zoom*tetr[line_[p*2+1]*3])+260;
sy1:=round(zoom*tetr[line_[p*2+1]*3+1])+300;
setcolor(color);
line(SX,SY,sx1,sy1);
end;



кусок программы из 2-го поста
что значат такие записи
tetr[line_[p*2]*3])+260
tetr[line_[p*2]*3+1])+300
tetr[line_[p*2+1]*3])+260
tetr[line_[p*2+1]*3+1])+300

а именно, не пойму, для чего *2, *3, прибавляем 1 в разных местах???
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
Malice
сообщение 23.04.2007 22:34
Сообщение #20


Профи
****

Группа: Пользователи
Сообщений: 705
Пол: Мужской

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


Цитата(18192123 @ 23.04.2007 22:32) *

а именно, не пойму, для чего *2, *3, прибавляем 1 в разных местах???

Что ж тут не понятного ? Массив Line_ заполнен так [что соединяем, с чем, что, с чем, ..] т.е. на четных местах стоих первая точка, на нечетных - вторая. По-этому p*2-четная точка, p*2+1 следующая, т.е. с которой соединение.
Массив tetr так [x, y, z, x,y,z, и т.д.], принцип тот же..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

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

 



- Текстовая версия 20.07.2025 6:31
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"