forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   3D-программирование (http://forum.boolean.name/forumdisplay.php?f=12)
-   -   Гравитация (http://forum.boolean.name/showthread.php?t=4476)

dimond 18.09.2007 02:57

Гравитация
 
Есть player - точка, к которой привязана камера. Управление стандартное
по оси Y вращаем игрока, а по оси X камеру. Притяжение - перемещение по локальной(так надо см. далее) оси Y игрока MoveEntity Player,0,-1,0
И вот в чем проблема
Еще есть сфера - планета с координатами 0,0,0
Нужно чтобы ось игрока Y (высота) была направлена в центр планеты, где бы ни находился игрок.Планетарная гравитация в общем.
Point Entity для этой цели не подходит - он переворачивает ось Y на Z и на полюсах игрока начинает крутить. Пробовал через Atan2, но пока не получается. Может кто делал раньше такую систему?

Noah 18.09.2007 03:24

Re: Гравитация
 
Сам начинаю заного, пока свои соображения и воспоминания:

Эх.. так я не хотел (или давно мечтал) вскрыть старые архивы директорий Blitz`а! чтоб обнаружить, что моей первой демки там нет (( под новый год 2002ого, у меня убился хард.
По сути: делал в 3D от firstPerson: звезду, планету(сфера), станцию, кораблик, атмосфера планеты(ещё сферы). кораблик испытывал (g) мог летать под действием этой силы у поверхности планеты(сфера была ну очень большая)
Как: со своим разложением сил и преобразованием не мучайся, это где-то близко попыткам на Pascal`е свой 3D рендер сделать (поверь :) ), если память не изменяет я пользовался механизмом реляционных пространственных координат (встроенных в Blitz) и возможно дополнительным(к пивоту кораблика) пивотом для сил тяжести.
Поразмышляй на эту тему, докопаешься. У меня таки в конце концов заработало как часы.

Damp 18.09.2007 09:42

Re: Гравитация
 
Попробуй через AlignToVector типа :
AlignToVector cam, x2-x1 , y2-y1, z2-z1 , 2 , 0.1
где x1,x2... координаты камеры и планеты.

IGR 18.09.2007 11:01

Re: Гравитация
 
создай пивот, а к ннему уже привязу плеера !!
притяжение прописуй только доя пивота, плеер будет притягиваться сам собой !!
находи угол под которым находиться пивот по отношению к центру планеты, поворачуй пивот на этот угол и двигай его туда !!
надеюсь всё понятно !! :)

dimond 23.09.2007 04:49

Re: Гравитация
 
собрал через AlignToVector
для упрощения координаты планеты 0,0,0

dx#=EntityX(player,1)
dy#=EntityY(player,1)
dz#=EntityZ(player,1)
ln#=Sqr(dx*dx+dy*dy+dz*dz)
dx=dx/ln
dy=dy/ln
dz=dz/ln
AlignToVector player,dx,dy,dz,2,1

Теперь работает как надо, но есть две проблемы.

1) игрока тянет к полюсам, иду я к примеру от одного полюса к другому, до экватора игрок замедляется, а после ускоряет ход.

2) такая фишка как Collisions tplayer,tplanet,2,3 - "защита от скольжения вниз" не действует. Походу этот самый "вниз" глобальный, а нужно чтобы проверка была по локальной оси Y игрока. В итоге игрок скольэит так, если бы я писал Collisions tplayer,tplanet,2,2, особенно это заметно на рельефной местности.

пробовал так

If EntityCollided(player,tplanet) ClearCollisions():Collisions tplayer,tplanet,2,1

If move ClearCollisions():Collisions tplayer,tplanet,2,3

но думаю это не выход т.к. могут быть еще сторонние коллизии, не относящиеся к игроку (пуля-бот к примеру) а ClearCollisions() стирает все, но без нее нельзя применить новые установки.

еще записывал координаты игрока до UpdateWorld а потом после и вычислял разницу. И если игрок скользил сам, (работа коллизии) то получалось некоторое значение отличное от нуля, но так до ума это дело не довел.

Dream 23.09.2007 23:53

найди учебник за 10 клас там есть формула как раз для етого случая))я ей пользуюсь))удобно и просто)

у тебя движения через MoveEntity?если ды то немножко по другому но принцип тотже:
fx=sin(deltayaw(player,planet))*f#+(fx*1.75)
fy#=cos(deltayaw(player,planet))*f#+(fy*1.75)
Position entity player,enetityx(player)+fx#,entityy(player),entity x(player)+fz#
f#-сила притяжения у тебя она равна 1
ну ето для 2д системы но принцип тотже
конеч мож я че не правельно написал щас но я исправлю когда вспомню))

-=SCiP=- 24.09.2007 01:51

Re: Гравитация
 
А вы попробуйте не с пивот а с самой камерой!
Я замечал фишку когда самеру переворачиваешь меняется координаты самого мира XYZ а камеры остается!
Т.Е. Если игрока будет тенуть вниз если TurnEntity перевернуть камеру то игрок полетит в другую сторону!

Damp 24.09.2007 09:13

Мне кажется это от того, что гравитация постоянно действует.
Попробуй проверять коллизию с землей и при коллизии отключать гравитацию.
А вообще-то должно и с PointEntity работать если создать плеера как чайлда планеты...

Напиши полностью свой код, посмотрим.

stone_evil 24.09.2007 09:51

Re: Гравитация
 
Не советую делать через AlignToVector, потому что по опыту глючный оператор. По-крайней мере, я для себя решил его в черный список записать.

Delta_Q 24.09.2007 13:27

Re: Гравитация
 
Я давно это делал вот фрагмент того как я реализовал гравитационное воздействие на кораблик (вырезано из общего кода):
Код:

Function FaindObjGrav(p.Player)
;Расчет гаравитационного воздействия на корабль
        If TimMS<MilliSecs() Then
                TimMS=MilliSecs()+C_Strob
                Obj=FaindDist(p)
                Di1#=EntityDistance# ( p\entity,planet(obj))
                A#=C_Koef*C_Grav#*(o.sb(Obj)\Mass/(Di1#*Di1#*1000000)) ;Домнажаю радиус на милион чтоб было норм в КМ
                vx#=EntityX#(planet(obj),True)
                vy#=EntityY#(planet(obj),True)
                vz#=EntityZ#(planet(obj),True)
                vx# = vx#/Di1#: vy# = vy#/Di1#: vz# = vz#/Di1#
                p\speedx#=vx#*A#+p\speedx#
                p\speedy#=vy#*A#+p\speedy#
                p\speedz#=vz#*A#+p\speedz#
                TranslateEntity p\world,-p\speedx#,-p\speedy#,-p\speedz#        ;move world       
        End If

End Function

Function FaindDist(p.Player)
;Функция поискаближайшего объекта
Dist#=EntityDistance#( p\entity,planet(i))
For i=0 To NumPlanet-2
                Di1#=EntityDistance#( p\entity,planet(i))
                Di2#=EntityDistance#( p\entity,planet(i+1))
                If (Dist#>Di1# Or Dist#>Di2#)
                        If Di1#<=Di2#
                                Dist#=Di1#
                                Obj=i
                        Else If Di2#<Dist#
                                Dist#=Di2#
                                Obj=i+1
                        EndIf
                EndIf
        Next
        Return Obj
End Function

Это точно работало и работало как реальная физика... Нужно занть массу планеты массу корабля...
Функция FaindDist анализировало ближайшее крупное тело в космосе т.е. А FaindObjGrav уже расчитывало ускорение которое задовалось телу...
ВОбщем эими двумя функиями мне удалось сделать модель при которой можно было выводить корабль на орбиту и он уже по законами притяжения мог вращаться по орбите.

Есть одно но, я это делал для Солнечной системы в натуральную величину и поэтому пришлось делать финт ушами: Сам корабль всегда имел координату 0,0,0 а двигал я в сцене все небесные тела.

dimanche13 24.09.2007 13:42

Re: Гравитация
 

тэг код закрывается так [/code]

Damp 24.09.2007 14:00

Re: Гравитация
 
Незнаю... надо смотреть код автора.
Я бы наверно оттолкнулся от:
planet=CreateSphere()
ship=CreateCube(planet)
Цикл:
PointEntity ship,planet
MoveEntity ship,0,0,gravity

dimond 26.09.2007 05:18

Re: Гравитация
 
Цитата:

Сообщение от Damp
Мне кажется это от того, что гравитация постоянно действует.
Попробуй проверять коллизию с землей и при коллизии отключать гравитацию.
А вообще-то должно и с PointEntity работать если создать плеера как чайлда планеты...

Напиши полностью свой код, посмотрим.

если EntityCollided(Player,tplanet) то gravity=0 иначе gravity=-.6

игрок столкнулся с землей и остановился. Но без движения нет и коллизии - включается gravity.
Получается как бы сказать дрожжание, игрок будет неизбежно скользить.
Гравитацию лучше совсем не трогать, иначе может быть ситуация если игрок взберется на холм, то уже не спустится с него.

PointEntity - действует по каким-то другим принципам, тут проблема с полюсами
причем чем ближе игрок к полюсу, тем
не это не описать это видеть надо.

Код:

Graphics3D 800,600,32,2
SetBuffer BackBuffer()
SeedRnd MilliSecs()
If Windowed3D() HidePointer

Const TPLayer%=1,Tplanet%=2

Global Player=CreatePivot()
PositionEntity Player,0,410,0
EntityType Player,TPlayer
EntityRadius Player,6

Global cam=CreateCamera(Player)
CameraClsColor cam,100,120,160

Global light=CreateLight()

Global planet=CreateSphere(64)
ScaleMesh planet,400,400,400
EntityType planet,Tplanet

tex=CreateTexture(64,64,1+8)
LockBuffer TextureBuffer(tex)
For i=0 To 4000
    WritePixelFast Rand(0,63),Rand(0,63),$FF80BC40,TextureBuffer(tex)
Next
UnlockBuffer TextureBuffer(tex)
ScaleTexture tex,.01,.01
EntityTexture planet,tex
FreeTexture tex

gravity#=-.6

Collisions TPlayer,Tplanet,2,3

While Not KeyHit(1)
    TurnEntity cam,MouseYSpeed()*.2,0,0
    TurnEntity player,0,-MouseXSpeed()*.2,0
    MoveMouse GraphicsWidth()*.5,GraphicsHeight()*.5

    move=0
    If KeyDown(200) MoveEntity player,0,0,1 move=1
    If KeyDown(208) MoveEntity player,0,0,-1 move=1
    If KeyDown(205) MoveEntity player,1,0,0 move=1
    If KeyDown(203) MoveEntity player,-1,0,0 move=1
    If MouseDown(2) MoveEntity player,0,8,0

    dx#=EntityX(player,1)
    dy#=EntityY(player,1)
    dz#=EntityZ(player,1)
    ;ln#=Sqr(dx*dx+dy*dy+dz*dz)
    ln#=EntityDistance(Player,planet)
    dx=dx/ln
    dy=dy/ln
    dz=dz/ln
    AlignToVector player,dx,dy,dz,2,1

    ;так пока реализована проверка на столкновение
    If EntityCollided(player,Tplanet) ClearCollisions():Collisions TPlayer,Tplanet,2,1
    If move ClearCollisions():Collisions TPlayer,Tplanet,2,3

    MoveEntity player,0,gravity,0
    UpdateWorld
    RenderWorld

    Text GraphicsWidth()*.5,GraphicsHeight()*.5,"+",1,1
 
    Flip
Wend
End

Извините что кривой код, это пока так, набросок.

Damp 26.09.2007 09:19

Re: Гравитация
 
Ок, вечерком заценм.

Damp 26.09.2007 13:24

Re: Гравитация
 
Было немного времени свободного днем, заценил твой код... впринципе все правильно (тока плэера бы сделать чайлдом планеты), но если еще есть желание глянь
http://damp.ucoz.ru/Planet.rar
Ато уж который день в бошке крутится эта планетарная гравитация :)
---
Правда не от первого лица (исправить легко), как ты хотел, просто со стороны легче лаги заметить.

dimond 29.09.2007 05:21

Re: Гравитация
 
Ок посмотрим.

В моем коде вместо сферы для лучшей наглядности загрузить меш
Создаем Geosphere(Геосфера) в 3dsmax, Radius:200, Segments:8 и модифицируем с помощью Noise, scale:100, Strength:60, для создания холмов и впадин.
Грузим в игрулину - создается эффект бесконечного ландшафта, и что "земля" круглая, совсем не заметно.

от позиционирования игрока относительно полигона с которым он коллизит, я отказался, т.к. это не соответствует принципам гравитации (я так делал, и у меня игрок лазил по стенам и потолку, а это не совсем нормально)

Alex_Noc 02.10.2007 12:13

Re: Гравитация
 
А попробуй тупо в центр планеты пивот поставь (она же идеально круглая) , в точку перса поставь тоже пивот и припаренть его к пивоту в центре планеты :) , и управляй поворотом пивота который в центр планеты поставил :) , ну и соответственно скорость поворота подбери :) Таким образом перс всегда будет наклонен под тем углом под которым ты его поставишь :) , а т.е в центр планеты :)
( Ну это конечно если совсем тупо делать :) )

Delta_Q 02.10.2007 18:12

Re: Гравитация
 
Если делать будиш гравитацию то синхронизирую расчеты с таймером чтоб при разных загруженостях сцен она работала одинакого.

dimond 03.10.2007 02:38

Re: Гравитация
 
В том то и дело что планета не круглая это геосфера модифицированная с помощью noise

AnyWay 04.10.2007 17:03

Re: Гравитация
 
Цитата:

Сообщение от dimond
В том то и дело что планета не круглая это геосфера модифицированная с помощью noise

Alex_Noc правильно посоветовал. Дешево и сердито. А то что сфера - не сфера, это часный случай. Добавь постоянное перемещение по оси к центру планеты(пивоту)+коллизию с поверхностью. Если радиус сферы большой, то даже не придется вводить поправку на скорость поворота в зависимости от высоты.

H@NON 05.10.2007 13:17

Re: Гравитация
 
Вот, стырил от куда то пример:
Код:

;
; Gravity demo
;

;
; Set up
;

Graphics3D 1024,768

;
; Global Variables - needs some tidying
;
Global angle#, radius#
Global earthx#,earthy#,earthvelx#,earthvely#
Global earthangle#,earthradius#,earthrot#
Global earthforce#,eaccelx#,eaccely#
Global eradius#, eangle#

SetBuffer BackBuffer()
;
; camera
;
camera = CreateCamera()
CameraViewport camera,0,0,1024,768
CameraRange camera,2,2000
PositionEntity camera,0,-350,-100
RotateEntity camera,-40,0,0

AmbientLight(200,100,100)

light1=CreateLight(2)
light2=CreateLight(2)
light3=CreateLight(2)
light4=CreateLight(2)

LightColor light1,200,100,100
LightColor light3,200,100,100
LightColor light2,200,20,20
LightColor light4,200,20,20

PositionEntity light1,20,0,200
PositionEntity light2,0,-20,200
PositionEntity light3,-20,0,200
PositionEntity light4,0,20,200

SeedRnd MilliSecs()
;
; Particle type
;
Type Par
    Field xpos#,ypos#
    Field xvel#,yvel#
    Field xp
    Field mass#
End Type

;
; set up scenario initial conditions
;
Global sun = CreateSphere(32)
Global Earth = CreateSphere(32)

ScaleEntity sun,20,20,20
ScaleEntity Earth,5,5,5
EntityColor sun,255,255,0
EntityColor Earth,50,200,255
;suntex = LoadTexture("sun.jpg",1)
;earthtex = LoadTexture("earth.jpg",1)
sunangle# = 90.0
Const SUNMASS = 10000
Const EARTHMASS = 1000
Const Fieldx = 200
Const Fieldy = 200
; no of particles
Const Parcnt = 1000
Const G# = 0.000667
; Start limit distance from Sun
Const START = 80
earthx = 100
earthy = 100
earthvelx = 0.2
earthvely = -0.1

PositionEntity sun,0,0,200


PositionEntity Earth,earthx,earthy,200

;Create the Texture
width=1024
sptex = CreateTexture(width,width,1+8)
SetBuffer TextureBuffer(sptex)
For a = 1 To 200
    Plot Rand(0,width-1),Rand(0,width-1)
Next
SetBuffer BackBuffer()
TextureBlend sptex,5

;Create the Sphere
spbox = CreateSphere(5)
ScaleEntity spbox,1000,1000,1000
EntityTexture spbox,sptex
ScaleTexture sptex,.25,.5
EntityFX spbox,1
FlipMesh spbox
EntityOrder spbox,99999

;
; function to create particle
;


Function CreatePar()
    p.Par = New par
    p\xpos# = Rand(-Fieldx,Fieldx)
    p\ypos# = Rand(-Fieldy,Fieldy)
    If p\xpos > 0.0 And p\ypos > 0.0 And p\xpos < START And p\ypos < START
        p\xpos = START
        p\ypos = START
    ElseIf p\xpos < 0.0 And p\ypos < 0.0 And p\xpos > -START And p\ypos > -START
        p\xpos = -START
        p\ypos = -START
    ElseIf p\xpos > 0.0 And p\ypos < 0.0 And p\xpos < START And p\ypos > -START
        p\xpos = START
        p\ypos = -START
    ElseIf p\xpos < 0.0 And p\ypos > 0.0 And p\xpos > -START And p\ypos < START
        p\xpos = -START
        p\ypos = START
    EndIf

    If p\xpos > 0.0 And p\ypos > 0.0
        p\xvel = Rand(1,1.2)/10.0
        p\yvel = Rand(-1.2,-1)/10.0
    ElseIf p\xpos > 0.0 And p\ypos < 0.0
        p\xvel = Rand(-1.2,-1)/10.0
        p\yvel = Rand(-1.2,-1)/10.0
    ElseIf p\xpos < 0.0 And p\ypos < 0.0
        p\xvel = Rand(-1.2,-1)/10.0
        p\yvel = Rand(1,1.2)/10.0
    Else
        p\xvel = Rand(1,1.2)/10.0
        p\yvel = Rand(1,1.2)/10.0
    EndIf   
    p\mass = 5.0
    p\xp = CreateSphere()
    EntityColor p\xp,10,10,10
    EntityShininess p\xp,1.0
End Function

;
; Update particle position
;
Function UpdatePar(p.Par)
    Local sunforce#,accelx#,accely#
    Local eforce#,accelex#,acceley#
    AngleSun p
    If radius < 20.0 Or radius > 500.0
        p\xvel = 0.0
        p\yvel = 0.0
        PositionEntity p\xp,0,0,200   
        Delete p
    Else
        Sunforce = (G * SUNMASS * p\mass) / (radius*radius)
        AngleEarth p
        If eradius < 5.0
            p\xvel = 0.0
            p\yvel = 0.0
            PositionEntity p\xp,0,0,200
            Delete p
        Else   
            eforce = (G * EARTHMASS * p\mass) / (eradius*eradius)
            accelx=-(sunforce/p\mass) * Cos(angle)
            accely=-(sunforce/p\mass) * Sin(angle)
            accelex =  -(eforce/p\mass) * Cos(eangle)
            acceley =  -(eforce/p\mass) * Sin(eangle)
            accelx = accelx + accelex
            accely = accely + acceley
            p\xvel = p\xvel+accelx
            p\yvel = p\yvel+accely
            p\xpos=p\xpos+p\xvel
            p\ypos=p\ypos+p\yvel
            PositionEntity p\xp,p\xpos,p\ypos,200
        EndIf
    EndIf
End Function

;
; Get angle + radius
;
Function AngleSun(p.Par)
    angle = ATan2(p\ypos,p\xpos)
    radius = EntityDistance(sun,p\xp)
End Function

Function AngleEarth(p.Par)
    eangle = ATan2(p\ypos-earthy,p\xpos-earthx)
    eradius = EntityDistance(Earth,p\xp)
End Function


   

   
;
; Create some particles
;
For i = 1 To Parcnt
    CreatePar
Next

;
; Main loop
;

While Not KeyHit(1)

;EntityTexture sun,suntex
;EntityTexture Earth,earthtex
;sunangle = sunangle + 0.1
;earthrot = earthrot+ 0.001
;RotateTexture suntex,sunangle
;TurnEntity Earth,0,earthrot,0

;
; Move Earth
;
    earthangle = ATan2(earthy,earthx)
    earthradius = Sqr(earthx*earthx+earthy*earthy)
    earthforce = (G * SUNMASS * EARTHMASS) / (earthradius*earthradius)
    eaccelx=-(earthforce/EARTHMASS) * Cos(earthangle)
    eaccely=-(earthforce/EARTHMASS) * Sin(earthangle)
    earthvelx = earthvelx+eaccelx
    earthvely = earthvely+eaccely
    earthx=earthx+earthvelx
    earthy=earthy+earthvely
    PositionEntity Earth,earthx,earthy,200

;
; Move particles
;

For p.Par = Each Par   
    UpdatePar p
Next
   
;
; Move Camera
; Cursor keys + A = zoom in , Z = zoom out
; , roll left . roll right
;
   
If KeyDown(200) Then
MoveEntity camera,0,3.6,0
TurnEntity camera,1,0,0
EndIf

If KeyDown(208) Then
MoveEntity camera,0,-3.6,0
TurnEntity camera,-1,0,0
EndIf

If KeyDown(203) Then
MoveEntity camera,3.6,0,0
TurnEntity camera,0,1.0,0
EndIf

If KeyDown(205) Then
MoveEntity camera,-3.6,0,0
TurnEntity camera,0,-1.0,0
EndIf

If KeyDown(30) Then
MoveEntity camera,0,0,1.0
EndIf

If KeyDown(44) Then
MoveEntity camera,0,0,-1.0
EndIf

If KeyDown(51) Then
TurnEntity camera,0,0,1
EndIf

If KeyDown(52) Then
TurnEntity camera,0,0,-1
EndIf

UpdateWorld
RenderWorld

Flip

Wend
End



Часовой пояс GMT +4, время: 02:10.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot