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

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

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

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

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

kurs.doc

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

                        //----------------------------------------------------------------

                        glTexCoord(Vec_X+j/(Segments-1),Vec_Y+i/(Segments-1));

                        glVertex3d((-0.5+FNodes[i,j].Coord.X)*Width,     FNodes[i,j].Coord.Y,     (-0.5+FNodes[i,j].Coord.Z)*Height);

                        glTexCoord(Vec_X+(j+1)/(Segments-1),Vec_Y+i/(Segments-1));

                        glVertex3d((-0.5+FNodes[i,j+1].Coord.X)*Width,   FNodes[i,j+1].Coord.Y,   (-0.5+FNodes[i,j+1].Coord.Z)*Height);

                        glTexCoord(Vec_X+(j+1)/(Segments-1),Vec_Y+(i+1)/(Segments-1));

                        glVertex3d((-0.5+FNodes[i+1,j+1].Coord.X)*Width, FNodes[i+1,j+1].Coord.Y, (-0.5+FNodes[i+1,j+1].Coord.Z)*Height);

                   end;

                 glEnd;

                 glDisable(GL_BLEND);

                 glEnable(GL_LIGHTING);

                 glTranslatef(0,0.1,0);

                 glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);

              end

         else begin

                   glTranslatef(Position.X,Position.Y,Position.Z);

                   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

              end;

       //Применим текстуру

       TexWater.ApplyTexture;

       //Активируем прозрачность

       glEnable(GL_BLEND);

       //Нарисуем треугольниками воду

       glBegin(GL_TRIANGLES);

         for i:=0 to Segments-2 do

         for j:=0 to Segments-2 do

         begin

              glTexCoord(j/(Segments-1),i/(Segments-1));

              glVertex3d((-0.5+FNodes[i,j].Coord.X)*Width,     FNodes[i,j].Coord.Y,     (-0.5+FNodes[i,j].Coord.Z)*Height);

              glTexCoord(j/(Segments-1),(i+1)/(Segments-1));

              glVertex3d((-0.5+FNodes[i+1,j].Coord.X)*Width,   FNodes[i+1,j].Coord.Y,   (-0.5+FNodes[i+1,j].Coord.Z)*Height);

              glTexCoord((j+1)/(Segments-1),(i+1)/(Segments-1));

              glVertex3d((-0.5+FNodes[i+1,j+1].Coord.X)*Width, FNodes[i+1,j+1].Coord.Y, (-0.5+FNodes[i+1,j+1].Coord.Z)*Height);

              //----------------------------------------------------------------

              glTexCoord(j/(Segments-1),i/(Segments-1));

              glVertex3d((-0.5+FNodes[i,j].Coord.X)*Width,     FNodes[i,j].Coord.Y,     (-0.5+FNodes[i,j].Coord.Z)*Height);

              glTexCoord((j+1)/(Segments-1),i/(Segments-1));

              glVertex3d((-0.5+FNodes[i,j+1].Coord.X)*Width,   FNodes[i,j+1].Coord.Y,   (-0.5+FNodes[i,j+1].Coord.Z)*Height);

              glTexCoord((j+1)/(Segments-1),(i+1)/(Segments-1));

              glVertex3d((-0.5+FNodes[i+1,j+1].Coord.X)*Width, FNodes[i+1,j+1].Coord.Y, (-0.5+FNodes[i+1,j+1].Coord.Z)*Height);

         end;

       glEnd;

     glDisable(GL_BLEND);

     glPopMatrix;

end;

procedure GetAngles(Vec_X,Vec_Y,Vec_Z:Double;var Angle_X,Angle_Y:Double);

begin

     //Определим углы поворота вектора

     Angle_Y:=arcsin(Vec_Y)/pi*180;

     if Vec_X>0

       then Angle_X:=arcsin(Vec_Z)/pi*180

       else if Vec_Z>0

              then Angle_X:=arccos(Vec_X)/pi*180

              else Angle_X:=180-arcsin(Vec_Z)/pi*180;

end;

procedure GetVectorByAngles(Angle_X,Angle_Y:Double;var Vec_X,Vec_Y,Vec_Z:Double);

begin

     //Определим  направление вектора по углам

     Vec_Y:=sin(Angle_Y/180*pi);

     Vec_X:=cos(Angle_Y/180*pi)*cos(Angle_X/180*pi);

     Vec_Z:=cos(Angle_Y/180*pi)*sin(Angle_X/180*pi);

end;

procedure   TGLWater.DrawWithHits(Cam_X,Cam_Y,Cam_Z,Normal_X,Normal_Y,Normal_Z:Double);

var

   Len:Double;

   Angle_X,Angle_Y:Double;

   Vec1_X,Vec1_Y,Vec1_Z:Double;

   Vec2_X,Vec2_Y,Vec2_Z:Double;

   i:Integer;

begin

     Draw(Cam_X,Cam_Y,Cam_Z);

     //Нарисуем всплески

     //Запомнем  матрицу

     glPushMatrix;

     glTranslatef(Position.X,Position.Y,Position.Z);

     //Нормализуем "Нормаль"

     Len:=Sqrt(Sqr(Normal_X)+Sqr(Normal_Y)+Sqr(Normal_Z));

     Normal_X:=Normal_X/Len;

     Normal_Y:=Normal_Y/Len;

     Normal_Z:=Normal_Z/Len;

     //Определим углы поворота нормали

     GetAngles(Normal_X,Normal_Y,Normal_Z,Angle_X,Angle_Y);

     //Определим векторы перпендикулярные нормали

     GetVectorByAngles(Angle_X,Angle_Y+90,Vec1_X,Vec1_Y,Vec1_Z);

     GetVectorByAngles(Angle_X-90,Angle_Y,Vec2_X,Vec2_Y,Vec2_Z);

     FTexHits.ApplyTexture;

     glEnable(GL_BLEND);

     glBlendFunc(GL_ONE,GL_ONE);

     glBegin(GL_QUADS);

       for i:=0 to Length(FHits)-1 do

       begin

            glTexCoord(0,0);

            glVertex3f(FHits[i].Coord.X-Vec1_X*FHitsSize/2-Vec2_X*FHitsSize/2,

                       FHits[i].Coord.Y-Vec1_Y*FHitsSize/2-Vec2_Y*FHitsSize/2,

                       FHits[i].Coord.Z-Vec1_Z*FHitsSize/2-Vec2_Z*FHitsSize/2);

            glTexCoord(1,0);

            glVertex3f(FHits[i].Coord.X-Vec1_X*FHitsSize/2+Vec2_X*FHitsSize/2,

                       FHits[i].Coord.Y-Vec1_Y*FHitsSize/2+Vec2_Y*FHitsSize/2,

                       FHits[i].Coord.Z-Vec1_Z*FHitsSize/2+Vec2_Z*FHitsSize/2);

            glTexCoord(1,1);

            glVertex3f(FHits[i].Coord.X+Vec1_X*FHitsSize/2+Vec2_X*FHitsSize/2,

                       FHits[i].Coord.Y+Vec1_Y*FHitsSize/2+Vec2_Y*FHitsSize/2,

                       FHits[i].Coord.Z+Vec1_Z*FHitsSize/2+Vec2_Z*FHitsSize/2);

            glTexCoord(0,1);

            glVertex3f(FHits[i].Coord.X+Vec1_X*FHitsSize/2-Vec2_X*FHitsSize/2,

                       FHits[i].Coord.Y+Vec1_Y*FHitsSize/2-Vec2_Y*FHitsSize/2,

                       FHits[i].Coord.Z+Vec1_Z*FHitsSize/2-Vec2_Z*FHitsSize/2);

       end;

    glEnd;

     glDisable(GL_BLEND);

     glPopMatrix;

end;

procedure   TGLWater.Animation(const Deltatime_ms:Integer);

var

   i,j: Integer;

   g,h: Integer;

   Len,CurLen,k:Double;

begin

     if FUseRandomForce

       then begin

                 //Определим оставшееся время до изменения внешней силы

                 dec(FRandomForceRemainedTime,Deltatime_ms); 

                 //Определяем не пора ли изменить  внешнее воздействие

                 if FRandomForceRemainedTime<=0

                   then begin

                             while FRandomForceRemainedTime<=0 do

                             inc(FRandomForceRemainedTime,FRandomForceTime); 

                             RandomForce;

                        end;

            end;

     //Определим внутренную силу натяжения каждого узла

     for i:=1 to Segments-2 do

     for j:=1 to Segments-2 do

     begin

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

          for g:=i-1 to i+1 do

          for h:=j-1 to j+1 do

          if (g>=0)and(h>=0)and(g<=Segments-1)and(h<=Segments-1)

            then begin

                      Len:=sqrt(sqr(i/(Segments-1)-g/(Segments-1))+sqr(j/(Segments-1)-h/(Segments-1)));

                      CurLen:=sqrt(sqr(FNodes[i,j].Coord.X-FNodes[g,h].Coord.X)+sqr(FNodes[i,j].Coord.Y-FNodes[g,h].Coord.Y)+sqr(FNodes[i,j].Coord.Z-FNodes[g,h].Coord.Z));

                      k:=round(((1-Len/CurLen)*CompressCoef)*1000000)*0.000001;

                      FNodes[i,j].F.X:=FNodes[i,j].F.X+k*(FNodes[i,j].Coord.X-FNodes[g,h].Coord.X);

                      FNodes[i,j].F.Y:=FNodes[i,j].F.Y+k*(FNodes[i,j].Coord.Y-FNodes[g,h].Coord.Y);

                      FNodes[i,j].F.Z:=FNodes[i,j].F.Z+k*(FNodes[i,j].Coord.Z-FNodes[g,h].Coord.Z);

                 end;

     end;

     //Получение  новых координат узлов

     for i:=1 to Segments-2 do

     for j:=1 to Segments-2 do

     begin

          //Вычислим ускорение

          FNodes[i,j].a.X:=1/Mass*(FNodes[i,j].F_ext.X-DempfCoef*FNodes[i,j].v.X-FNodes[i,j].F.X);

          FNodes[i,j].a.Y:=1/Mass*(FNodes[i,j].F_ext.Y-DempfCoef*FNodes[i,j].v.Y-FNodes[i,j].F.Y);

          FNodes[i,j].a.Z:=1/Mass*(FNodes[i,j].F_ext.Z-DempfCoef*FNodes[i,j].v.Z-FNodes[i,j].F.Z);

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

          //Определим скорость. Делим на 1000, так как в мс

          FNodes[i,j].v.X:=FNodes[i,j].v.X+FNodes[i,j].a.X*Deltatime_ms/1000;

          FNodes[i,j].v.Y:=FNodes[i,j].v.Y+FNodes[i,j].a.Y*Deltatime_ms/1000;

          FNodes[i,j].v.Z:=FNodes[i,j].v.Z+FNodes[i,j].a.Z*Deltatime_ms/1000;

          //Определим координаты узла

          FNodes[i,j].Coord.X:=FNodes[i,j].Coord.X+FNodes[i,j].v.X*Deltatime_ms/1000;

          FNodes[i,j].Coord.Y:=FNodes[i,j].Coord.Y+FNodes[i,j].v.Y*Deltatime_ms/1000;

          FNodes[i,j].Coord.Z:=FNodes[i,j].Coord.Z+FNodes[i,j].v.Z*Deltatime_ms/1000;

     end;

     //Получение  новых координат капель всплеска

     for i:=0 to Length(FHits)-1 do

     begin

          //Определим скорость. Делим на 1000, так как в мс

          FHits[i].v.Y:=FHits[i].v.Y+FGravity*Deltatime_ms/1000;

          //Определим координаты узла

          FHits[i].Coord.X:=FHits[i].Coord.X+FHits[i].v.X*Deltatime_ms/1000;

          FHits[i].Coord.Y:=FHits[i].Coord.Y+FHits[i].v.Y*Deltatime_ms/1000;

          FHits[i].Coord.Z:=FHits[i].Coord.Z+FHits[i].v.Z*Deltatime_ms/1000;

     end;

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

     i:=0;

     while i<Length(FHits)-1 do

     if FHits[i].Coord.Y<FPosition.Y

       then begin

                 for j:=i+1 to Length(FHits)-1 do

                 begin

                      FHits[j-1].Coord.X:=FHits[j].Coord.X;

                      FHits[j-1].Coord.Y:=FHits[j].Coord.Y;

                      FHits[j-1].Coord.Z:=FHits[j].Coord.Z;

                      FHits[j-1].v.X:=FHits[j].v.X;

                      FHits[j-1].v.Y:=FHits[j].v.Y;

                      FHits[j-1].v.Z:=FHits[j].v.Z;

                 end;

                 SetLength(FHits,Length(FHits)-1);

            end

       else inc(i);

end;

procedure   TGLWater.RandomForce;

var

   i,j: Integer;

begin

     //Установка случайной внешней силы

     for i:=0 to Segments-1 do

     for j:=0 to Segments-1 do

     SetVector(FNodes[i,j].F_ext, (-0.5+random)*MaxForce, (-0.5+random)*MaxForce_Y, (-0.5+random)*MaxForce);

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