Автор: Пользователь скрыл имя, 12 Декабря 2011 в 11:48, курсовая работа
Моделирование водных поверхностей является сложной, но интересной задачей. Здесь можно выделить такие подзадачи, как моделирование небольших водоемов (с видимыми границами), для которых характерны небольшие изменения поверхности, то есть небольшие колебания, а также интерференция колебаний от нескольких всплесков и отраженных колебаний от границ; большие водные поверхности: здесь рассматривают небольшие поверхностные колебания (как правило, в этом случае можно обойтись изменениями лишь текстуры или нескольких текстур поверхности (Bump Mapping и др., см. далее) не деформируя непосредственно саму поверхность), небольшие колебания: в этом случае поверхность разбивается на треугольники, но достаточно большого размера и над поверхностью производят небольшие колебания, которые соответствуют, например, небольшим волнам, большие колебания: этот большие волны, брызги и др., здесь происходят значительные деформации водных поверхностей, которые достаточно сложно физически описываются, поэтому большие волны практически никогда не визуализируются.
//----------------------------
glTexCoord(Vec_X+j/(Segments-
glVertex3d((-0.5+FNodes[i,j].
glTexCoord(Vec_X+(j+1)/(
glVertex3d((-0.5+FNodes[i,j+1]
glTexCoord(Vec_X+(j+1)/(
glVertex3d((-0.5+FNodes[i+1,j+
end;
glEnd;
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
glTranslatef(0,0.1,0);
glBlendFunc(GL_DST_COLOR,GL_
end
else begin
glTranslatef(Position.X,
glBlendFunc(GL_SRC_ALPHA,GL_
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/(
glVertex3d((-0.5+FNodes[i,j].
glTexCoord(j/(Segments-1),(i+
glVertex3d((-0.5+FNodes[i+1,j]
glTexCoord((j+1)/(Segments-1),
glVertex3d((-0.5+FNodes[i+1,j+
//----------------------------
glTexCoord(j/(Segments-1),i/(
glVertex3d((-0.5+FNodes[i,j].
glTexCoord((j+1)/(Segments-1),
glVertex3d((-0.5+FNodes[i,j+1]
glTexCoord((j+1)/(Segments-1),
glVertex3d((-0.5+FNodes[i+1,j+
end;
glEnd;
glDisable(GL_BLEND);
glPopMatrix;
end;
procedure GetAngles(Vec_X,Vec_Y,Vec_Z:
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*
end;
procedure GetVectorByAngles(Angle_X,
begin
//Определим направление вектора по углам
Vec_Y:=sin(Angle_Y/180*pi);
Vec_X:=cos(Angle_Y/180*pi)*
Vec_Z:=cos(Angle_Y/180*pi)*
end;
procedure TGLWater.DrawWithHits(Cam_X,
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,
//Нормализуем "Нормаль"
Len:=Sqrt(Sqr(Normal_X)+Sqr(
Normal_X:=Normal_X/Len;
Normal_Y:=Normal_Y/Len;
Normal_Z:=Normal_Z/Len;
//Определим углы поворота нормали
GetAngles(Normal_X,Normal_Y,
//Определим векторы перпендикулярные нормали
GetVectorByAngles(Angle_X,
GetVectorByAngles(Angle_X-90,
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-
FHits[i].Coord.Y-Vec1_Y*
FHits[i].Coord.Z-Vec1_Z*
glTexCoord(1,0);
glVertex3f(FHits[i].Coord.X-
FHits[i].Coord.Y-Vec1_Y*
FHits[i].Coord.Z-Vec1_Z*
glTexCoord(1,1);
glVertex3f(FHits[i].Coord.X+
FHits[i].Coord.Y+Vec1_Y*
FHits[i].Coord.Z+Vec1_Z*
glTexCoord(0,1);
glVertex3f(FHits[i].Coord.X+
FHits[i].Coord.Y+Vec1_Y*
FHits[i].Coord.Z+Vec1_Z*
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,
//Определяем не пора ли
if FRandomForceRemainedTime<=0
then begin
while FRandomForceRemainedTime<=0 do
inc(FRandomForceRemainedTime,
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<=
then begin
Len:=sqrt(sqr(i/(Segments-1)-
CurLen:=sqrt(sqr(FNodes[i,j].
k:=round(((1-Len/CurLen)*
FNodes[i,j].F.X:=FNodes[i,j].
FNodes[i,j].F.Y:=FNodes[i,j].
FNodes[i,j].F.Z:=FNodes[i,j].
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].a.Y:=1/Mass*(
FNodes[i,j].a.Z:=1/Mass*(
SetVector(FNodes[i,j].F_ext, 0, 0, 0);
//Определим скорость. Делим на 1000, так как в мс
FNodes[i,j].v.X:=FNodes[i,j].
FNodes[i,j].v.Y:=FNodes[i,j].
FNodes[i,j].v.Z:=FNodes[i,j].
//Определим координаты узла
FNodes[i,j].Coord.X:=FNodes[i,
FNodes[i,j].Coord.Y:=FNodes[i,
FNodes[i,j].Coord.Z:=FNodes[i,
end;
//Получение
новых координат капель
for i:=0 to Length(FHits)-1 do
begin
//Определим скорость. Делим на 1000, так как в мс
FHits[i].v.Y:=FHits[i].v.Y+
//Определим координаты узла
FHits[i].Coord.X:=FHits[i].
FHits[i].Coord.Y:=FHits[i].
FHits[i].Coord.Z:=FHits[i].
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].
FHits[j-1].Coord.Y:=FHits[j].
FHits[j-1].Coord.Z:=FHits[j].
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)-
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);