Показать сообщение отдельно
Старый 15.04.2020, 02:28   #5
leshiyru70
AnyKey`щик
 
Аватар для leshiyru70
 
Регистрация: 20.01.2019
Адрес: Томск
Сообщений: 6
Написано 2 полезных сообщений
(для 3 пользователей)
Ответ: Как вычислить 2D координату курсора в 3D мире?

Вот моя попытка соорудить что-то вроде определителя 3D координаты под курсором мыши. Пока есть недостатки. Для нормального вычисления нельзя вращать камеру по XY осям, так-как сбиваются координаты. Есть ощущение что решение этого недостатка где-то рядом, не пока не могу сообразить где. Если вас не затруднит взгляните на код. Может будут какие-либо советы, предложения. Буду весьма благодарен. Спасибо.

P.S. Управление камерой на стрелочках и правые шифт и контрол. Вращение по Z оси=7 и 9 на NUM PAD, то бишь ЦИФРОКЛАВА. ))



; перечень работоспособных разрешений всегда должны быть 4/3
; 640,480 \ 800,600 \ 1024,768
camW=800: camH=600

Graphics3D camW,camH,32,2
SetBuffer BackBuffer ()

; стартовое позиционирование камеры XYZ
camX#=0: camY#=0: camZ#=-40
cam = CreateCamera()
PositionEntity cam,camX,camY,camZ

; стартовое вращение камеры по осям XYZ
anglX#=0: anglY#=0: anglZ#=0
RotateEntity cam,anglX#,anglY#,anglZ#,True

; стартовая дистанция до 3Д точки
distance#=-40

; для наглядности сфера будет прикреплена к курсору
sph=CreateSphere (4)
ScaleEntity sph,2,2,2

arial20=LoadFont ("arial",20)
SetFont arial20

; основной цикл ====================================
While Not KeyDown(1)
mx=MouseX(): my=MouseY()



; изменения позиции камеры
If KeyDown (203) Then camX=camX-1; (Left)
If KeyDown (205) Then camX=camX+1; (Right)
If KeyDown (200) Then camZ=camZ-1; (Up)
If KeyDown (20 Then camZ=camZ+1; (Down)
If KeyDown (54) Then camY=camY+1; (r Shift)
If KeyDown (157) Then camY=camY-1; (r Cntrl)
PositionEntity cam,camX,camY,camZ

; вращение камеры по XYZ оси
; кроме оси Z пока вращать нельзя (СБОЙ НАВЕДЕНИЯ)
; If KeyDown (72) Then anglX=anglX-1; (
; If KeyDown (80) Then anglX=anglX+1; (2)
; If KeyDown (75) Then anglY=anglY-1; (4)
; If KeyDown (77) Then anglY=anglY+1; (6)
If KeyDown (71) Then anglZ=anglZ-1; (7) работает нормально
If KeyDown (73) Then anglZ=anglZ+1; (9) работает нормально
RotateEntity cam,anglX,anglY,anglZ


; что-бы не делать вычислений в пустую
If oldmxy<>mx+my+camX+camY+camZ+anglX+anglY+anglZ Then
oldmxy=mx+my+camX+camY+camZ+anglX+anglY+anglZ

XYZ$=FF_2Dto3D(cam,camW,camH,distance); XYZ$=полученные результаты

; передача результата от функции происходит в тексте "\"=разделитель между параметрами
oldi=1: kol=0
For i=1 To Len(XYZ$)
If Mid$(XYZ$,i,1)="\" Then
If kol=0 Then pxx#=Mid$(XYZ$,oldi,i-1) ; получина X координата
If kol=1 Then pyy#=Mid$(XYZ$,oldi,i-1) ; получина Y координата
If kol=2 Then pzz#=Mid$(XYZ$,oldi,i-1) ; получина Z координата
oldi=i+1: kol=kol+1
EndIf
Next
EndIf

PositionEntity sph,pxx,pyy,pzz,True

RenderWorld

Color 250,250,0: Rect mx-8,my-8,16,16,0

Color 250,250,250
Text 400,0,"X\Y\Z координаты сферы="+XYZ$,True

CXYZ$=camX+"\"+camY+"\"+camZ
Text 400,20,"X\Y\Z координаты камеры="+CXYZ$,True

CAXYZ$=anglX+"\"+anglY+"\"+anglZ
Text 400,40,"X\Y\Z вращение камеры="+CAXYZ$,True
Flip
Wend
End
; ================================================



; ----------------------------------------------------------------------------------
; ПЕРЕВОД ПОЗИЦИИ 2Д КУРСОРА В 3Д КООРДИНАТУ
; cam=личный номер камеры, camW,camH=разрешение экрана,
; distance#=предполагаемая дистанция до 3Д точки
Function FF_2Dto3D$(cam,camW,camH,distance#)
mx=MouseX(): my=MouseY()

; определяю местоположения камеры
camX#=EntityX#(cam)
camY#=EntityY#(cam)
camZ#=EntityZ#(cam)
; поворот камеры по осям XYZ
anglX#=EntityPitch#(cam)
anglY#=EntityYaw#(cam)
anglZ#=EntityRoll#(cam)

; вычисляю шаг движения 3Д точки с учётом дистанции до камеры
; разрешение всегда должно иметь соотношение сторон 4/3 для правильной работы.
ccz#=(camW/4)/((distance/2)+(camZ/2))

; смещаю нулевую координату курсора в центр экрана
cx#=(camW/2)-mx
cy#=(camH/2)-my

; вычисляю новую 3Д координату по отношению к позиции камеры
ccx#=camX+cx/ccz
ccy#=camY-cy/ccz

; узнаю дистанцию и угол между камерой и 3Д точкой
alldist#=FF_getdist#(camX,camY,ccx,ccy,1)
allug#=FF_getdist#(camX,camY,ccx,ccy,2)+anglZ

; вычисляю координаты новой точки зная угол и дистанцию
pxx#=camX+Sin(allug)*alldist
pyy#=camY-Cos(allug)*alldist
pzz#=-distance

; передаю XYZ координаты для использования
XYZ$=pxx+"\"+pyy+"\"+pzz+"\"
Return XYZ$

End Function
; ----------------------------------------------------------------------------------



; _____________________________________________
; ЗАМЕР ДИСТАНЦИИ И УГЛА между точками
; px,py,pxx,pyy=первая и вторая точки измерения
; direc=1 возврат дистанции direc=2 возврат угла 0=верх 90=право и т д по Ч стрелке
Function FF_getdist#(px#,py#,pxx#,pyy#,direc)

dx#=pxx#-px#
dy#=pyy#-py#

; вычисляю дистанцию между координатами
If direc=1 Then dist#=Sqr((dx#*dx#)+(dy#*dy#))

; определяю угол между точками от px,py и к pxx,pyy
If direc=2
dist#=180+ATan2(dx#,dy#): dist#=360-dist#
EndIf

Return dist#
End Function
; ---------------------------------------------------------------------------------UOTE][/quote][/quote]
__________________
(Offline)
 
Ответить с цитированием