Визуализация воды

Автор: Пользователь скрыл имя, 12 Декабря 2011 в 11:48, курсовая работа

Описание работы

Моделирование водных поверхностей является сложной, но интересной задачей. Здесь можно выделить такие подзадачи, как моделирование небольших водоемов (с видимыми границами), для которых характерны небольшие изменения поверхности, то есть небольшие колебания, а также интерференция колебаний от нескольких всплесков и отраженных колебаний от границ; большие водные поверхности: здесь рассматривают небольшие поверхностные колебания (как правило, в этом случае можно обойтись изменениями лишь текстуры или нескольких текстур поверхности (Bump Mapping и др., см. далее) не деформируя непосредственно саму поверхность), небольшие колебания: в этом случае поверхность разбивается на треугольники, но достаточно большого размера и над поверхностью производят небольшие колебания, которые соответствуют, например, небольшим волнам, большие колебания: этот большие волны, брызги и др., здесь происходят значительные деформации водных поверхностей, которые достаточно сложно физически описываются, поэтому большие волны практически никогда не визуализируются.

Работа содержит 1 файл

kurs.doc

— 428.50 Кб (Скачать)

     glGetDoublev (GL_MODELVIEW_MATRIX, @mvMatrix);

     glGetDoublev (GL_PROJECTION_MATRIX, @ProjMatrix);

     // viewport[3] - высота окна в пикселях

     RealY := viewport[3] - Y - 1;

     glReadPixels(X, RealY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @Zval);

     gluUnProject (X, RealY, Zval,@mvMatrix, @ProjMatrix, @Viewport, wx, wy, wz);

     if (wx<100) and (wx>-100) and (wz<100) and (wz>-100)

       then begin

                 if (MainForm.ShowBoxCheckBox.Checked)and((wx>89) or (wx<-89) or (wz>89) and (wz<-89))

                   then exit;

                 if MainForm.ShowGroundCheckBox.Checked

                   then begin

                             //Определим в какую ячейку  земли попадает точка (wx,wy,wz)

                             tx:=wx;

                             tz:=wz;

                             g:=0;

                             while tx>-100+200/(GroundSegment-1) do

                             begin

                                  tx:=tx-200/(GroundSegment-1);

                                  inc(g);

                             end;

                            h:=0;

                             while tz>-100+200/(GroundSegment-1) do

                             begin

                                  tz:=tz-200/(GroundSegment-1);

                                  inc(h);

                             end;

                             //Точка должна быть выше земли

                             if (wy<GroundMas[g,h]+1)and(GroundMas[g,h]>0)or

                                (wy<GroundMas[g+1,h]+1)and(GroundMas[g+1,h]>0)or

                                (wy<GroundMas[g,h+1]+1)and(GroundMas[g,h+1]>0)or

                                (wy<GroundMas[g+1,h+1]+1)and(GroundMas[g+1,h+1]>0)

                               then exit;

                        end;

                 //Чтобы всплески были видны,  иначе они будут сразу же исчезать

                 if wy<1

                   then wy:=1;

                 Water.AddHits(wx,wy,wz,Power,Radius);

            end;

end;

procedure TMainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

     if (ssRight in Shift)and(HitsEnableCheckBox.Checked)

       then AddHits(X,Y,HitsPowerEdit.Value,HitsRadiusEdit.Value);

end;

procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

  Y: Integer);

begin

     if ssLeft in Shift

       then begin

                 //Поворот камеры

                 Cam_Angle_X:=Cam_Angle_X+x-mx;

                 Cam_Angle_Y:=Cam_Angle_Y+y-my;

                 if Cam_Angle_Y<-89

                   then Cam_Angle_Y:=-89;

                 if Cam_Angle_Y>89

                   then Cam_Angle_Y:=89;

                 ResetCamCoords;

                 Resize;

            end;

     mx:=X;

     my:=Y;

end;

procedure TMainForm.FormResize(Sender: TObject);

begin

     //Устанавливае размер окна OpenGL

     glViewport(0, 0, ClientWidth-PageControl.Width, ClientHeight);

     glMatrixMode(GL_PROJECTION);

     glLoadIdentity();

     gluPerspective(30, 1.25, 1,1000);

     //Ставим камеру

     GLULookAt(Cam_X,Cam_Y,Cam_Z,Target_X,Target_Y,Target_Z,0,1,0);

     glMatrixMode(GL_MODELVIEW);

end;

procedure TMainForm.HitsCountEditChange(Sender: TObject);

begin

     Water.HitsCount:=round(HitsCountEdit.Value);

end;

procedure TMainForm.HitsGravityEditChange(Sender: TObject);

begin

     Water.Gravity:=HitsGravityEdit.Value;

end;

procedure TMainForm.HitsSizeEditChange(Sender: TObject);

begin

     Water.HitsSize:=HitsSizeEdit.Value;

end;

procedure TMainForm.KeyTimerTimer(Sender: TObject);

var

   speed:Single;

   Vect,Temp:TGLArrayf3;

   Rad:Single;

begin

     //Клавиши  управления камерой

     Vect[0]:=Target_X-Cam_X;

     Vect[1]:=0;

     Vect[2]:=Target_Z-Cam_Z;

     Rad:=Sqrt(Sqr(Cam_X-Target_X)+Sqr(Cam_Z-Target_Z));

     Vect[0]:=Vect[0]/Rad;

     Vect[1]:=Vect[1]/Rad;

     Vect[2]:=Vect[2]/Rad;

     if IsKeyDown(VK_SHIFT)

       then speed:=5

       else if IsKeyDown(VK_Control)

              then speed:=1

              else speed:=3;

     if IsKeyDown('Q')

       then begin

                 Cam_Y:=Cam_Y+speed;

                 Target_Y:=Target_Y+speed;

                 Resize;

                 MainForm.SetFocus;

            end;

     if IsKeyDown('E')

       then begin

                 Cam_Y:=Cam_Y-speed;

                 Target_Y:=Target_Y-speed;

                 Resize;

            end;

     if IsKeyDown('W')

       then begin

                 Cam_X:=Cam_X+Vect[0]*speed;

                 Cam_Z:=Cam_Z+Vect[2]*speed;

                 Target_X:=Target_X+Vect[0]*speed;

                 Target_Z:=Target_Z+Vect[2]*speed;

                 Resize;

            end;

     if IsKeyDown('S')

       then begin

                 Cam_X:=Cam_X-Vect[0]*speed;

                 Cam_Z:=Cam_Z-Vect[2]*speed;

                 Target_X:=Target_X-Vect[0]*speed;

                 Target_Z:=Target_Z-Vect[2]*speed;

                 Resize;

            end;

     Temp[0]:=-Vect[2];

     Temp[2]:=Vect[0];

     Vect[0]:=Temp[0];

     Vect[2]:=Temp[2];

     if IsKeyDown('D')

       then begin

                 Cam_X:=Cam_X+Vect[0]*speed;

                 Cam_Z:=Cam_Z+Vect[2]*speed;

                 Target_X:=Target_X+Vect[0]*speed;

                 Target_Z:=Target_Z+Vect[2]*speed;

                 Resize;

            end;

     if IsKeyDown('A')

       then begin

                 Cam_X:=Cam_X-Vect[0]*speed;

                 Cam_Z:=Cam_Z-Vect[2]*speed;

                 Target_X:=Target_X-Vect[0]*speed;

                 Target_Z:=Target_Z-Vect[2]*speed;

                 Resize;

            end;

end;

procedure TMainForm.WaterAlphaEditChange(Sender: TObject);

begin

     Water.Alpha:=WaterAlphaEdit.Value;

end;

procedure TMainForm.WaterCompressCoefEditChange(Sender: TObject);

begin

     Water.CompressCoef:=WaterCompressCoefEdit.Value;

end;

procedure TMainForm.WaterDempfCoefEditChange(Sender: TObject);

begin

     Water.DempfCoef:=WaterDempfCoefEdit.Value;

end;

procedure TMainForm.WaterMassEditChange(Sender: TObject);

begin

     Water.Mass:=WaterMassEdit.Value;

end;

procedure TMainForm.WaterMaxForceEditChange(Sender: TObject);

begin

     Water.MaxForce:=WaterMaxForceEdit.Value;

end;

procedure TMainForm.WaterMaxForceYEditChange(Sender: TObject);

begin

     Water.MaxForce_Y:=WaterMaxForceYEdit.Value;

end;

procedure TMainForm.WaterRandomForceTimeEditChange(Sender: TObject);

begin

     Water.RandomForceTime:=round(WaterRandomForceTimeEdit.Value);

end;

procedure TMainForm.WaterRelaxBtnClick(Sender: TObject);

var

   i,j: Integer;

begin

     for i:=0 to Water.Segments-1 do

     for j:=0 to Water.Segments-1 do

     begin

          SetVector(Water.Nodes[i,j].F,     0,              0, 0);

          SetVector(Water.Nodes[i,j].F_ext, 0,              0, 0);

          SetVector(Water.Nodes[i,j].Coord, j/(Water.Segments-1), 0, i/(Water.Segments-1));

          SetVector(Water.Nodes[i,j].a,     0,              0, 0);

          SetVector(Water.Nodes[i,j].v,     0,              0, 0);

     end;

end;

procedure TMainForm.WaterSegmentsEditChange(Sender: TObject);

begin

     Water.Segments:=round(WaterSegmentsEdit.Value);

end;

procedure TMainForm.WaterUseBumpCheckBoxClick(Sender: TObject);

begin

     Water.UseBumping:=WaterUseBumpCheckBox.Checked;

end;

procedure TMainForm.WaterUseRandomForceCheckBoxClick(Sender: TObject);

begin

     Water.UseRandomForce:=WaterUseRandomForceCheckBox.Checked;

end;

procedure TMainForm.DrawTimerTimer(Sender: TObject);

var

   NewTime : cardinal;

begin

     //Определим время между кадрами

     NewTime := TimeGetTime;

     Water.Animation(NewTime-CurTime);

     Draw;

     CurTime:=NewTime;

end;

procedure DrawBox(Pos_X,Pos_Y,Pos_Z,Width,Height,Depth:Double);

begin

     glPushMatrix;

    //Рисует кубик

     glTranslatef(Pos_X,Pos_Y,Pos_Z);

     glBegin(GL_QUADS);

       //Низ

       glTexCoord(0,0);

       glVertex(-Width, 0, -Depth);

       glTexCoord(1,0);

       glVertex( Width, 0, -Depth);

       glTexCoord(1,1);

       glVertex( Width, 0,  Depth);

       glTexCoord(0,1);

       glVertex(-Width, 0,  Depth);

       //Верх

       glTexCoord(0,0);

       glVertex(-Width, Height, -Depth);

       glTexCoord(1,0);

       glVertex( Width, Height, -Depth);

       glTexCoord(1,1);

       glVertex( Width, Height, Depth);

       glTexCoord(0,1);

       glVertex(-Width, Height,  Depth);

       //Лево

       glTexCoord(0,0);

Информация о работе Визуализация воды