Форум: "Игры";
Текущий архив: 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