Форум программистов, компьютерный форум, киберфорум
Delphi: Графика, звук, видео
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 09.03.2013
Сообщений: 17
1

Шумы Перлина

09.03.2013, 21:39. Показов 2514. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброе время суток!
Друзья, недавно начал изучать OpenGL на Delphi. Делаю программу, которая генерирует псевдо-случайные ландшафты через шум Перлина, но столкнулся с такой проблемой, что получается что-то непонятное. Подскажите, где ошибка? Почему рисует некорректный ландшафт? Вроде карта высот заполняется нормально...
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OpenGL;
 
const
 n=25; p=0.05;
 
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure SetDCPixelFormat;
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    dc:HDC;
    hrc:HGLRC;
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
  x,y:array [0..n-1] of GLFloat;
  z:array [0..n-1,0..n-1] of GLFloat;
  i,j,k:integer;
 
implementation
 
{$R *.dfm}
 
{Ãåíåðàöèÿ øóìà Ïåðëèíà}
function Noise(x,y:integer):single;
var
 n:integer;
begin
 n:=x + y*57;
 n:=(n shl 13) xor n;
 Result:=( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) and $7FFFFFFF) /1073741824.0);
end;
 
function Interpolate(a,b,x:Single):single;
var
 ft,f:Single;
begin
 ft:=x*3.1415927;
 f:= (1 - cos(ft)) * 0.5;
 Result:=a*(1-f) + b*f;
end;
 
function SmoothedNoise(x,y:single):single;
var
 corners:single;
 sides,center:Single;
begin
 corners:= ( Noise(round(x-1), round(y-1))+Noise(round(x+1), round(y-1))+Noise(round(x-1), round(y+1))+Noise(round(x+1), round(y+1)) ) / 16;
 sides:= ( Noise(Round(x-1), Round(y)) +Noise(Round(x+1),Round( y)) + Noise(Round(x),Round( y-1)) +Noise(Round(x), Round(y+1)) ) / 8;
 center:= Noise(Round(x),Round( y)) / 4;
 Result:=corners+sides+center;
end;
 
function CompleteNoise(x,y:single):Single;
var
 xint,yint:integer;
 xfrac,yfrac,v1,v2,v3,v4,i1,i2:Single;
begin
 xint:=trunc(x);
 xfrac:=frac(x);
 yint:=trunc(y);
 yfrac:=frac(y);
 
 v1 := SmoothedNoise(xint,yint);
 v2 := SmoothedNoise(xint + 1,yint);
 v3 := SmoothedNoise(xint,yint + 1);
 v4 := SmoothedNoise(xint + 1, yint + 1);
 
 i1 := Interpolate(v1,v2,xfrac);
 i2 := Interpolate(v3,v4 ,xfrac);
 Result:=Abs(Interpolate(i1,i2,yfrac));
end;
 
function PerlinNoisef(x,y,factor:Single):single;
var
 total,pres,freq,ampl:Single;
 i:integer;
begin
 total:=0;
 pres:=1.25*1;//presistance
 ampl:=2.5*1;//amplitude
 freq:=0.00001;//frquerncy
 x:=x+factor;
 y:=y+factor;
 for i:=0 to (12) do // octavs
 begin
  total :=total+ CompleteNoise(x*freq, y*freq) * ampl;
  ampl := ampl*pres;
  freq:=freq*2;
 end;
 total:=(total)*2;
 Result:=total;//Trunc(Total);
end;
 
{Óñòàíîâêà ôîðìàòà ïèêñåëÿ}
Procedure TForm1.SetDCPixelFormat;
var
  i:integer;
  pfd:TPixelFormatDescriptor;
begin
  FillChar(pfd,sizeOf(pfd),0);
  pfd.dwFlags:=pfd_Draw_to_Window  or  pfd_Support_OpenGL or       pfd_DoubleBuffer;
  i:=ChoosePixelFormat(dc,@pfd);
  SetPixelFormat(dc,i,@pfd);
  end;
 
  {Óñòàíîâêà ñåññèè óñòðîéñòâà è çàïîëíåíèå ìàññèâà âûñîò}
procedure TForm1.FormCreate(Sender: TObject);
var fac:Real;
begin
   fac:=Random(1000);
   dc:=GetDC(handle);
   SetDCPixelFormat;
   hrc:=wglCreateContext(dc);
   wglMakeCurrent(dc,hrc);
 
    for i:=0 to n-1 do
      begin
        x[i]:=i*p-1;
        y[i]:=x[i];
      end;
 
     for i:=1 to n-2 do
     for j:=1 to n-2 do
       z[i,j]:=PerlinNoisef(i,j,fac);
 
    for k:=1 to 5 do
     for i:=1 to n-2 do
     for j:=1 to n-2 do
     z[i,j]:=(z[i-1,j-1]+z[i-1,j]+z[i-1,j+1]+z[i,j-1]+
        z[i,j]+z[i,j+1]+z[i+1,j-1]+z[i+1,j]+z[i+1,j+1])/9;
end;
 
{ðåíäåðèíã}
procedure TForm1.FormPaint(Sender: TObject);
var
   i,j:GLInt;
begin
    glpushmatrix;
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(Gl_Color_Buffer_Bit or GL_DEPTH_Buffer_Bit);
     for i:=0 to n-1 do
     for j:=0 to n-2 do
    begin
   glBegin(Gl_Line_loop);
     glVertex3f(x[i],y[j],z[i,j]);
     glVertex3f(x[i+1],y[j],z[i+1,j]);
     glVertex3f(x[i],y[j+1],z[i,j+1]);
     glVertex3f(x[i+1],y[j+1],z[i+1,j+1]);
   glend;
 end;
   SwapBuffers(dc);
   glpopmatrix;
end;
 
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  wrkX, wrkY: Integer;
begin
  wrkX:=1; wrkY:=1;
If down then begin
   glRotatef(X-wrkX, 0.0, 1.0, 0.0);
   glRotatef(Y-wrkY, 1.0, 0.0, 0.0);
   InvalidateRect(Handle, nil, False);
   wrkX:=X;
   wrkY:=Y;
end;
end;
 
end.
Если повертеть, то получится нечто невнятно-кубическое (скрин во вложении).
 Комментарий модератора 
Перенёс в раздел: "Delphi: графика, звук, видео".
Миниатюры
Шумы Перлина  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.03.2013, 21:39
Ответы с готовыми решениями:

Шумы Перлина
Мне в Универе дали индивидуальное задание, написать простенькую "матрицу ландшафта" используя шумы...

Массив с шумом перлина
Здравствуйте! Есть задача: числа 0,1,2,3 и двухмерный массив размером 100 на 100 Нужно...

Шум перлина: карта нормалей
Здравствуйте, подскажите пожалуйста как сделать карту нормалей для шума перлина? Я написал...

Реализовать двумерный список с шумом Перлина
Здравствуйте! Задача заключается такая: На прикрепленной картинке шум Перлина. Мне нужно...

7
3419 / 1606 / 236
Регистрация: 26.02.2009
Сообщений: 7,854
Записей в блоге: 5
11.03.2013, 17:53 2
А где glViewport? Посмотрите внимательнее на примеры... хотя бы здесь https://www.cyberforum.ru/grap... 83413.html
Ключевая строка начинается с FormResize
Что должно в итоге получится 3D-ладшафт?
0
0 / 0 / 0
Регистрация: 09.03.2013
Сообщений: 17
11.03.2013, 18:08  [ТС] 3
По идеи, результатом должна быть некая карта высот, которая при ее выводе через элементы OpenGL должна рисовать ландшафт (заранее неизвестный) через треугольные примитивы
0
risenow
11.03.2013, 22:15 4
k:=1 to 5 do
for i:=1 to n-2 do
for j:=1 to n-2 do
z[i,j]:=(z[i-1,j-1]+z[i-1,j]+z[i-1,j+1]+z[i,j-1]+
z[i,j]+z[i,j+1]+z[i+1,j-1]+z[i+1,j]+z[i+1,j+1])/9;

Вот это в случае с шумами НЕ нужно. Интерполяция идет в самом шуме Перлина, причем косинусная.
0 / 0 / 0
Регистрация: 09.03.2013
Сообщений: 17
11.03.2013, 23:03  [ТС] 5
так, покопался на форуме, нашел топик с похожей темой + перемещение в пространстве и получилась занятная вещь.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OpenGL, ExtCtrls, Math;
 
type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  User=record
    Position:record
      x,y,z:Single;
    end;
    Rotation:record
      y,zx:Single;
    end;
  end;
 
const W=0; n=100; p=0.05;
 
var
  Form1: TForm1;
  DC:HDC;
  HRC:HGLRC;
  Human:User;
  mt:gluInt;
  x,y:array [0..n-1] of GLFloat;
  z:array [0..n-1,0..n-1] of GLFloat;
  i,j,k:integer;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
const
  SPEED=0.2;
begin
  case key of
    27: Form1.Close;
    37: begin
          Human.Position.z:=Human.Position.z+
          sin(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x+
          cos(DegToRad(Human.Rotation.y))*SPEED;
        end;
    38: begin
          Human.Position.z:=Human.Position.z+
          cos(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x-
          sin(DegToRad(Human.Rotation.y))*SPEED;
        end;
    39: begin
          Human.Position.z:=Human.Position.z-
          sin(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x-
          cos(DegToRad(Human.Rotation.y))*SPEED;
        end;
    40: begin
          Human.Position.z:=Human.Position.z-
          cos(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x+
          sin(DegToRad(Human.Rotation.y))*SPEED;
        end;
  end;
end;
 
procedure SetDCPixelFormat;
var
  pfd:TPixelFormatDescriptor;
  nPixelFormat:Integer;
begin
  FillChar(pfd,SizeOf(pfd),0);
  pfd.dwFlags:=PFD_DRAW_TO_WINDOW or
               PFD_DOUBLEBUFFER or
               PFD_SUPPORT_OPENGL;
  nPixelFormat:=ChoosePixelFormat(DC,@pfd);
  SetPixelFormat(DC,nPixelFormat,@pfd);
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var i,j:GLInt;
begin
  DC:=GetDC(Handle);
  SetDCPixelFormat;
  HRC:=wglCreateContext(DC);
  wglMakeCurrent(DC,HRC);
  Form1.WindowState:=wsMaximized;
  ShowCursor(False);
  glClearColor(0.0,0.0,0.0,1.0);
  glEnable(GL_DEPTH_TEST);
  Randomize;
    for i:=0 to n-1 do    //заполнение опорных вершин
      begin
        x[i]:=i*p-1;
        y[i]:=x[i];
      end;
 
     for i:=1 to n-2 do     //заполнение карты высот "случайными" значениями
     for j:=1 to n-2 do
       z[i,j]:=2*random(2)-1;
     
    for k:=1 to 5 do                  //интерполяция значений карты высот
     for i:=1 to n-2 do
     for j:=1 to n-2 do
     z[i,j]:=(z[i-1,j-1]+z[i-1,j]+z[i-1,j+1]+z[i,j-1]+
        z[i,j]+z[i,j+1]+z[i+1,j-1]+z[i+1,j]+z[i+1,j+1])/9;
  with Human do
  begin
    with Position do
    begin
      x:=0;
      y:=-2.5;
      z:=-8;
    end;
    with Rotation do
    begin
      y:=0;
      zx:=45;
    end;
  end;
  SetCursorPos(Round(Form1.ClientWidth/2),
               Round(Form1.ClientHeight/2));
end;
 
 
procedure TForm1.FormPaint(Sender: TObject);
var
  ps:TPaintStruct;
  i,t:integer;
begin
  glpushmatrix;
  glClearColor(0.3,0.4,0.7,0.0);
  glClear(Gl_Color_Buffer_Bit or GL_DEPTH_Buffer_Bit);
  for i:=1 to n-1 do
   for j:=1 to n-2 do
    begin
    glBegin(Gl_Line_loop);
     glVertex3f(x[i],y[j],z[i,j]);
     glVertex3f(x[i+1],y[j],z[i+1,j]);
     glVertex3f(x[i],y[j+1],z[i,j+1]);
     glVertex3f(x[i+1],y[j+1],z[i+1,j+1]);
    glend;
    end;
  SwapBuffers(dc);
  glpopmatrix;
  BeginPaint(Handle,ps);
    glClear(GL_COLOR_BUFFER_BIT or
          GL_DEPTH_BUFFER_BIT);
    glLoadIdentity;
    glRotatef(Human.Rotation.zx,Abs(cos(DegToRad(Human.Rotation.y))),0,0);
    glRotatef(Human.Rotation.y,0,1,0);
    glTranslatef(Human.Position.x,
               Human.Position.y,
               Human.Position.z);
 
    glCallList(1);
  EndPaint(Handle,ps);
  SwapBuffers(DC);
end;
 
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  Divider=8;
begin
  Human.Rotation.y:=Human.Rotation.y+
      Round((Mouse.CursorPos.X-Round(Form1.ClientWidth/2))/Divider);
  if Human.Rotation.y>=360 then Human.Rotation.y:=0;
  if Human.Rotation.y<0 then Human.Rotation.y:=360;
 
  Human.Rotation.zx:=Human.Rotation.zx+
      Round((Mouse.CursorPos.Y-Round(Form1.ClientHeight/2))/Divider);
  if Human.Rotation.zx>90 then Human.Rotation.zx:=90;
  if Human.Rotation.zx<-90 then Human.Rotation.zx:=-90;
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(0,0);
  wglDeleteContext(HRC);
  ReleaseDC(Handle,DC);
  DeleteDC(DC);
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  SetCursorPos(Round(Form1.ClientWidth/2),
               Round(Form1.ClientHeight/2));
  InvalidateRect(Handle,nil,false);
end;
 
procedure TForm1.FormResize(Sender: TObject);
begin
  glViewport(0, 0, ClientWidth, ClientHeight);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(30.0, ClientWidth / ClientHeight, 0.1, 1000.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;
 
end.
но тут возникают следующие вопросы:
- как повернуть на 90 градусов поверхность glRotate (либо поменять расположение камеры через gluLookAt);
- как ограничить перемещение, т.е. (X,Y) мыши не больше заданных.
0
angstrom
12.03.2013, 00:07 6
...повернуть на 90 градусов...
В FormPaint, перед отрисовкой примитовов
0 / 0 / 0
Регистрация: 09.03.2013
Сообщений: 17
12.03.2013, 08:50  [ТС] 7
Спасибо, помогло)
А если в обработчик события OnKeyDown добавить

if (текущее положение <= максимального) then <выполнять перемещение>
else <текущее положение-1>

то по идеи, должно работать.
0
angstrom
12.03.2013, 13:00 8
В FormPaint используешь некую переменную для glRotate, в OnKeyDown вычисляешь её.
12.03.2013, 13:00
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.03.2013, 13:00
Помогаю со студенческими работами здесь

Как использовать функцию шума Перлина?
Доброго времени суток. Пытаюсь понять как использовать шум Перлина. После прочтения этой статьи...

использую шум Перлина и слетает хром и за-за нехватки памяти
Здравствуйте! Подскажите, пожалуйста, в чем проблема? нашел шум перлина на...

шумы ОУ OPA552UA
На OPA552UA собрана неинвертирующая схема с коэффициентом усиления 2.5 ...

Шумы квантования
Добрый вечер , возник следующий вопрос: Какова зависимость частоты гармонического сигнала и шума...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru