Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Вниз

3D колизии   Найти похожие ветки 

 
Goorus   (2004-04-13 16:36) [0]

ПОМОГИТЕ! :( Я уже два года бьюсь над одной, казалось бы элементарной задачей: проверка на столкновения/препятствия/колизии (называйте как хотите) в 3D. Поисковики не предлагать - пробывал, и не раз, так ничего и не нашёл :(

Вроде бы всё элементарно: сначала ищем пересечение линии пути с треугольниками( procedure Naskvoz ), а потом - близость к тем же треугольникам (function Blizko - по сути движени по нормали к поверхности), но при совпадении каких-то (неизвестных мне) условий, всё это оказывается бесполезным :(

Вот процедура из движка, которая должна не давать камере нарушать законы физики(в качестве параметров передаются изменение координат по X, Y, Z):


const

_X=0;
_Y=1;
_Z=2;

type

 TgFrac=Single; { Что бы можно было быстро сменить тип (повысить проиводительность или точность) }

TMap3D=record
 tr:TTriangleArr;
 n :array of Integer; // номер нормали в массиве
end;

 TVector=array[0..2]of TgFrac;
 TTriangle=Array[0..2]of TVector;

procedure TPhysGame3D.Camera_CheckOnCollision(const dx, dy, dz: TgFrac);
var    col_d,  dist:TgFrac;
col_n, ctr,       k:Integer;
   col_p, vn1, vn2:TVector;
vs, vf, vd, cp, vn:TVector;

procedure Naskvoz;
var i, c:Integer;
begin
 k:=0;
 repeat
  col_n:=-1;   col_d:=Camera_Size;
  // ищем ближайшее пересечение со стеной
  for i:=0 to High(map.tr) do begin
   if Camera_RayLineTriangle(vs, vd, map.tr[i],
      Normals[ map.n[i] ], dist, cp) then
   if dist<col_d then begin
    col_d:=dist;
    col_n:=i;
    col_p:=cp;
   end;
  end;
  // отталкиваем
  if col_n>=0 then begin
   Inc(k);
   if k>ctr then begin
    vf:=vs;
    vd:=Vector(0, 0, 0);
    col_n:=-100;
   end else begin
    vn:=Normals[ map.n[col_n] ];
    for c:=_X to _Z do begin
     if(col_p[c]>vs[c])
     then vf[c]:=col_p[c]-Abs(vn[c])*Camera_Size
     else vf[c]:=col_p[c]+Abs(vn[c])*Camera_Size;
    end;
    Vector_Minus(vf, vs, vd);
    k:=ctr+1;
   end;
  end;
 until(col_n<0);
end;

function Blizko:Boolean;
var i, c:Integer;
begin
 Result:=False;
 k:=0;
 repeat
  col_n:=-1;   col_d:=Camera_Size;
  // ищем ближайшее пересечение со стеной
  for i:=0 to High(map.tr) do begin
   vn1:=Vector_Scale(Normals[ map.n[i] ], +Camera_Size);
   vn2:=Vector_Scale(Normals[ map.n[i] ], -Camera_Size);
   if Camera_RayLineTriangle(vf, vn1, map.tr[i],
      Normals[ map.n[i] ], dist, cp) then
   begin
    if dist<col_d then begin
     col_d:=dist;
     col_n:=i;
     col_p:=cp;
    end;
   end else
   if Camera_RayLineTriangle(vf, vn2, map.tr[i],
      Normals[ map.n[i] ], dist, cp) then
   begin
    if dist<col_d then begin
     col_d:=dist;
     col_n:=i;
     col_p:=cp;
    end;
   end;
  end; // for i:=
  // отталкиваем
  if col_n>=0 then begin
   Result:=True;
   Inc(k);
   if(k>3)then begin
    vf:=vs;
    vd:=Vector(0, 0, 0);
    col_n:=-100;
   end else begin
    vn:=Normals[ map.n[col_n] ];
    for c:=_X to _Z do begin
     if(col_p[c]>vs[c])
     then vf[c]:=col_p[c]-Abs(vn[c])*Camera_Size
     else vf[c]:=col_p[c]+Abs(vn[c])*Camera_Size;
    end;
    Vector_Minus(vf, vs, vd);
   end;
  end;
 until(col_n<0);
end;

begin
ctr:=Length(map.tr);
if ctr<1 then Exit;
if ctr<>Length(map.n) then Exit;
if Length(normals)<1 then Exit;
vs:=Vector(Camera.X, Camera.Y, Camera.Z);
vd:=Vector(dx, dy, dz);
Vector_Plus(vs, vd, vf);

repeat
 // прохождение сквозь препятствия
 Naskvoz;
until Blizko=False;// близость к стене

Naskvoz; // для верности

Camera.X:=vf[_X];
Camera.Y:=vf[_Y];
Camera.Z:=vf[_Z];
end;

// эта процедура проверяет пересечение линии и шара

function TPhysGame3D.Camera_RayLineTriangle(const vStart, vMove: TVector;
 const tr: TTriangle; const Normal: TVector; var dist: TgFrac;
 var CollisionPoint: TVector): Boolean;

var t, u, v, det, invDet : Single;
v1, v2, qvec, tvec, pvec : TVector;
begin
Vector_Minus(tr[1], tr[0], v1);
Vector_Minus(tr[2], tr[0], v2);
Vector_Normal(vMove, v2, pvec);
det:=Vector_DotProduct(v1, pvec);
if((-EPSILON2<det)and(det<EPSILON2))then begin
 // линия параллельна плоскости треугольника
 Result:=False;
 Exit;
end;
invDet:=1/det;
Vector_Minus(vStart, tr[0], tvec);
u:=Vector_DotProduct(tvec, pvec)*invDet;
if (u<0)or(u>1) then Result:=False
else begin
 Vector_Normal(tvec, v1, qvec);
 v:=Vector_DotProduct(vMove, qvec)/det;
 Result:=(v>=0) and (u+v<=1);
 if Result then begin
  t:=Vector_DotProduct(v2, qvec)/det;
  if t>0 then begin
   Vector_Combine(vStart, vMove, 1, t, CollisionPoint);
   Vector_Minus(vStart, CollisionPoint, v1);
   dist:=Vector_Length(v1);
  end else Result:=False;
 end;
end;
end;



Если что не понятно - спрашивайте, только помогите.


 
Мараканец ©   (2004-04-13 16:46) [1]

вобщем так, что тебя не устраивает? объекты проваливаются друг в друга?


 
Мараканец ©   (2004-04-13 16:52) [2]

и вообще чего ты хочешь добиться? можно по-подробней какая у тебя сцена что должно быть и что получается????


 
miek ©   (2004-04-13 20:14) [3]

>Я уже два года бьюсь над одной, казалось бы элементарной задачей: проверка на столкновения/препятствия/колизии (называйте как хотите) в 3D

И еще столько же будешь биться. Задача не из простых.


 
Goorus   (2004-04-14 03:18) [4]

Сцена простая - куб, каждая грань которого - отдельный кубик(точнее параллелепипед).

Вообще процедура работает, но при небольшом тормозе (DeltaTime=100, на большее стоит ограничение) камера проходит через углы комнаты :(.

P.S. RayLinrTriangle - пересечени линии и треугольника(обшибся).


 
Мараканец ©   (2004-04-14 08:19) [5]

т.е. сцена у тебя расположена внутри куба? или ты хочешь чтоб камера не пролетала в куб?

мне чесно говоря лень разбираться в твоем коде....
и еще это что у тебя за Если DeltaTime = 100 - это медленно то скока у тебя стоит реально DeltaTime ?

{X(t); X(t+DeltaTime)} - вот кстати этот отрезок и нужно проверять на пересечение с треугольником.

кароче, пиши на мыло или ломись в аську я те возможно объясню что к чему, тут еще много вопросов может попутно возникнуть так что вот:

100065267
yarik@ross.usinsk.ru


 
Goorus   (2004-04-16 12:23) [6]

Ярик, не могу тебе письмо отправить, говрит нет пользователя с таким именем. Зарегись где-нибудь на mail.ru, а?


 
Goorus   (2004-04-17 11:12) [7]

Мараканец? Сервер почты выплюнул письмо назад и сказал, что у них такик нет. Проверь.



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.047 c
1-1090011418
Виталий
2004-07-17 00:56
2004.08.01
DLL


3-1089273635
AlexanderSK
2004-07-08 12:00
2004.08.01
Как узнать ключевые поля таблицы?


4-1087916842
NOX
2004-06-22 19:07
2004.08.01
как вытащить иконку из exe-файла?


1-1090157524
Wasya
2004-07-18 17:32
2004.08.01
RichEdit печать


1-1089847742
_Demik_
2004-07-15 03:29
2004.08.01
-= MainMenu =-





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский