Сообщение от NitE
ну вот ябы сделал конус, припарентил-бы его к голове бота, сделалбы колизийй с игроком, если коллизится то типа заметил
|
Зачем же извращатся так

Как-то мне приходилось решать эту задачу. Математика выручила

Надо найти скалярное произведение вектора между наблюдающим и наблюдаемым обьектов и вектора из матрицы трансформации наблюдаемого обьекта:

Local xang#, yang#
Local what%, from%, temp#, view#, dist#
Graphics3D(800, 600, 0, 2)
SetBuffer(BackBuffer())
;Наблюдаемый обьект
what = CreateSphere()
PositionEntity(what, 0.0, 0.0, 5.0)
;Наблюдающий обьект (для наглядности - камера)
from = CreateCamera()
;Угол обзора +\- 25 градусов
;косинус нужен т.к. сравниваем со скалярным произведением (фактически косинусом угла между векторами)
view = Cos(25)
;Квадат дистанции "видимости" (сравнивать будет тоже с квадратом для оптимизации)
dist = 100 ;10 ^ 2
;Для наглядности установим такой же угол обзора у камеры
CameraZoom(from, 1.0 / Tan(25))
Repeat
;Управление камерой
;-------------------------------------
xang = xang - MouseXSpeed() * 0.35
yang = yang + MouseYSpeed() * 0.35
MoveMouse(400, 300)
xang = xang - Int(xang * 0.00277778) * 360.0
If (xang < 0.0) Then
xang = 360 + xang
EndIf
If (yang > +85.0) Then
yang = +85.0
EndIf
If (yang < -85.0) Then
yang = -85.0
EndIf
RotateEntity(from, yang, xang, 0.0)
If (KeyDown(200)) Then
MoveEntity(from, 0.0, 0.0, +0.5)
EndIf
If (KeyDown(208)) Then
MoveEntity(from, 0.0, 0.0, -0.5)
EndIf
;-------------------------------------
RenderWorld()
;-------------------------------------
;Матрица трансформации
; 0 1 2
;0 xx xy xz \
;1 yx yy yz - матрица трансформации (поворот + масштаб)
;2 zx zy zz /
;3 tx ty tz - вектор сдвига
;Вектор из from в what
xsub = EntityX(what) - EntityX(from);GetMatElement(what, 3, 0) - GetMatElement(from, 3, 0)
ysub = EntityY(what) - EntityY(from);GetMatElement(what, 3, 1) - GetMatElement(from, 3, 1)
zsub = EntityZ(what) - EntityZ(from);GetMatElement(what, 3, 2) - GetMatElement(from, 3, 2)
;Квадрат длины вектора (квадрат дистанции между обьектами)
temp = xsub * xsub + ysub * ysub + zsub * zsub
;Проверяем квадрат дистанции
If (temp < dist) Then
Text(10, 10, "Центр обьекта на расстоянии обзора")
;Обьект на расстоянии видимости, можно вычислять дальше
;квадратный корень и обратная величина(чтобы заменить деления умножениями)
temp = 1.0 / Sqr(temp)
;Нормализация
xsub = xsub * temp
ysub = ysub * temp
zsub = zsub * temp
;Скалярное произведение с последней строкой from матрицы трансформации
temp = xsub * GetMatElement(from, 2, 0) + ysub * GetMatElement(from, 2, 1) + zsub * GetMatElement(from, 2, 2)
;Сравниваем углы и выводим сообщение
If (temp > view) Then
Text(10, 20, "Центр обьекта в поле зрения")
EndIf
EndIf
;-------------------------------------
Flip()
Until (KeyDown(1))
End
лучше заюзать вариант на С, т.к. квадратный корень и деление не есть хорошо и можно заменить их быстрым float-magic трюком
extern long entity_in_view(float *from, float *what, float dist, float view) {
float xsub, ysub, zsub, temp, half;
long conv;
xsub = what[16] - from[16];
ysub = what[17] - from[17];
zsub = what[18] - from[18];
temp = xsub * xsub + ysub * ysub + zsub * zsub;
if (dist < dist) {
half = temp * 0.5F;
conv = *(long*)&temp;
conv = 0x5F3759DF - (conv >> 1);
temp = *(float*)&conv;
temp = temp * (1.5F - half * temp * temp);
xsub *= temp;
ysub *= temp;
zsub *= temp;
return ((xsub * from[28] + ysub * from[29] + zsub * from[30]) > view) ? 1 : 0;
}
return 0;
}
И на PureBasic, кому С не в радость
Structure FPTR
f.f[0]
EndStructure
ProcedureDLL entity_in_view(*from.FPTR, *what.FPTR, dist.f, view.f)
Static xsub.f, ysub.f, zsub.f, temp.f, half.f, conv, *int.LONG, *flt.FLOAT
xsub = *what\f[16] - *from\f[16]
ysub = *what\f[17] - *from\f[17]
zsub = *what\f[18] - *from\f[18]
temp = xsub * xsub + ysub * ysub + zsub * zsub
If (temp < dist)
half = temp * 0.5
*int = @temp
conv = *int\l
conv = $5F3759DF - (conv >> 1)
*flt = @conv
temp = *flt\f
temp * (1.5 - half * temp * temp)
xsub * temp
ysub * temp
zsub * temp
temp = xsub * *from\f[28] + ysub * *from\f[29] + zsub * *from\f[30]
If (temp > view)
ProcedureReturn 1
EndIf
EndIf
ProcedureReturn 0
EndProcedure
правка: опечатка