Code archives/3D Graphics - Maths/Gravity
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
A simple 3D demo of gravitation in minib3d. Two bodies with different masses affect each other using Newton's law of universal gravitation formula which is F=G*((M1*M2)/rē). Includes a single surface path visualization using quads to see the objects gravitation influence.![]() In this demo I've used the mass of our sun for the star and the mass of our planet. You can interact with some F-keys and you can use the mouse to rotate and zoom the scene: F1 = Star's mass multiplied by factor 10 F2 = Planet's mass multiplied by factor 100.000 F3 = new random Planet vector Arrow keys = change mass of star / planet In the source, you can play around with the "correction" Constant and different movement speeds in the mxp/myp/mzp variables to get different results. For understanding the mechanics behind this demo here is a simplified version of it: | |||||
SuperStrict
Framework sidesign.minib3d
Graphics3D DesktopWidth(), DesktopHeight(), 32, 1
SeedRnd MilliSecs()
' center mouse
MoveMouse GraphicsWidth() * 0.4, GraphicsHeight() * 0.6
' ------------------------------------------------------------------------------------------------
' Constants
' ------------------------------------------------------------------------------------------------
Const Starmass:Double = 1.9884 * 10 ^ 30
Const PlanetMass:Double = 5.974 * 10 ^ 24
Const g:Double = 6.674 * 10 ^ -11
Const correction:Double = 10 ^ 21
' basic movespeed of star
Global mxs:Double = 0.0
Global mys:Double = 0.0
Global mzs:Double = 0.0
' basic movespeed of planet
Global mxp:Double = 0.0
Global myp:Double = 0.0
Global mzp:Double = 0.1153
' ------------------------------------------------------------------------------------------------
' Variables
' ------------------------------------------------------------------------------------------------
Local vx1:Double
Local vx2:Double
Local vy1:Double
Local vy2:Double
Local vz1:Double
Local vz2:Double
Local massfactor_s:Float = 1.0
Local massfactor_p:Float = 1.0
' ------------------------------------------------------------------------------------------------
' Light
' ------------------------------------------------------------------------------------------------
CreateLight(2)
AmbientLight 32, 32, 32
' ------------------------------------------------------------------------------------------------
' Star
' ------------------------------------------------------------------------------------------------
Local star:TEntity = CreatePivot()
Local star0:TSprite = CreateSprite(star)
Local star1:TSprite = CreateSprite(star)
Local star2:TSprite = CreateSprite(star)
Local star3:TSprite = CreateSprite(star)
ScaleSprite star0, 1, 1
ScaleSprite star1, 2, 2
ScaleSprite star2, 4, 4
ScaleSprite star3, 8, 8
EntityColor star0, 255, 255, 255
EntityColor star1, 255, 192, 128
EntityColor star2, 255, 255, 224
EntityColor star3, 255, 255, 224
EntityAlpha star0, 1
EntityAlpha star1, 1
EntityAlpha star2, 0.75
EntityAlpha star3, 0.5
EntityFX star0, 1
EntityFX star1, 1
EntityFX star2, 1
EntityFX star3, 1
EntityBlend star0, 3
EntityBlend star1, 3
EntityBlend star2, 3
EntityBlend star3, 3
EntityOrder star0, -1
EntityOrder star1, -2
EntityOrder star2, -3
EntityOrder star3, -4
Local startex:TTexture = CreateSunTexture()
EntityTexture star0, startex
EntityTexture star1, startex
EntityTexture star2, startex
EntityTexture star3, startex
' ------------------------------------------------------------------------------------------------
' Planet
' ------------------------------------------------------------------------------------------------
Local planet:TMesh = CreateSphere(32)
EntityFX planet, 2
UpdateMesh(planet, 255, 128, 0)
PositionEntity planet, -25, 0, 0
ScaleEntity planet, 0.5, 0.5, 0.5
' ------------------------------------------------------------------------------------------------
' Camera
' ------------------------------------------------------------------------------------------------
Local campivot:TPivot = CreatePivot(star)
Local cam:TCamera = CreateCamera(campivot)
PositionEntity cam, 0, 0, -40
CameraRange cam, 0.1, 10000
' ------------------------------------------------------------------------------------------------
' Star Ecliptic
' ------------------------------------------------------------------------------------------------
Local ecliptic:TEntity = CreateCube(star)
EntityFX ecliptic, 1 + 16
EntityAlpha ecliptic, 0.25
EntityColor ecliptic, 0, 0, 255
ScaleEntity ecliptic, 50, 10 ^ -10, 50
Local raster:TTexture = CreateRasterTexture()
EntityTexture ecliptic, raster
ScaleTexture raster, 1.0 / 50, 1.0 / 50
PositionTexture raster, 0.5, 0.5
EntityBlend ecliptic, 3
' ------------------------------------------------------------------------------------------------
' Path
' ------------------------------------------------------------------------------------------------
Global path:TMesh = CreateMesh()
Global surf:TSurface = CreateSurface(path)
EntityFX path, 1 + 2
' ------------------------------------------------------------------------------------------------
' Main loop
' ------------------------------------------------------------------------------------------------
While Not AppTerminate()
If KeyHit(KEY_ESCAPE) Then End
If KeyHit(KEY_F1) Then massfactor_s = 10.0
If KeyHit(KEY_F2) Then massfactor_p = 100000.0
If KeyHit(KEY_F3) Then
mxp = Rnd(-0.1, 0.1)
myp = Rnd(-0.1, 0.1)
mzp = Rnd(-0.1, 0.1)
For Local P:TQuad = EachIn TQuad.List
P.Remove
Next
FreeEntity path
path = CreateMesh()
surf = CreateSurface(path)
EntityFX path, 1 + 2
EndIf
massfactor_s:+((KeyDown(KEY_UP) - KeyDown(KEY_DOWN)) / 100.0)
massfactor_p:+((KeyDown(KEY_RIGHT) - KeyDown(KEY_LEFT)) * 1000.0)
' calc distance
Local d:Double = EntityDistance(planet, star)
' calc gravitational force using newtons formula
Local F:Double = (g * starmass * massfactor_s * planetmass * massfactor_p) / (d * d)
' adjust force to scene
F:/correction
' get coordinates of objects
Local x1:Double = EntityX(star)
Local x2:Double = EntityX(planet)
Local y1:Double = EntityY(star)
Local y2:Double = EntityY(planet)
Local z1:Double = EntityZ(star)
Local z2:Double = EntityZ(planet)
' delta position
Local dx:Double = x1 - x2
Local dy:Double = y1 - y2
Local dz:Double = z1 - z2
' delta vector
Local dv1:Double = F / (starmass * massfactor_s)
Local dv2:Double = F / (planetmass * massfactor_p)
' new vector
vx1 = vx1 - dv1 * dx
vx2 = vx2 + dv2 * dx
vy1 = vy1 - dv1 * dy
vy2 = vy2 + dv2 * dy
vz1 = vz1 - dv1 * dz
vz2 = vz2 + dv2 * dz
' move star
MoveEntity star, mxs + vx1, mys + vy1, mzs + vz1
' move planet
MoveEntity planet, mxp + vx2, myp + vy2, mzp + vz2
' camera movement
If EntityDistance(cam, star) > 10 Then TranslateEntity cam, 0, 0, MouseDown(1) - MouseDown(2) Else TranslateEntity cam, 0, 0, -1
RotateEntity campivot, Normalize(MouseY(), 0, GraphicsHeight() - 1, -90, 90), Normalize(MouseX(), 0, GraphicsWidth() - 1, 180, -180), 0
PointEntity cam, campivot
' add star path quads
Local P:TQuad
P = New TQuad
P.x = EntityX(star)
P.y = EntityY(star)
P.z = EntityZ(star)
P.scalex = 0.05
P.scaley = 0.05
P.RGB = [255, 255, 0]
P.mesh = path
P.surf = surf
P.add()
' add planet path quads
P = New TQuad
P.x = EntityX(planet)
P.y = EntityY(planet)
P.z = EntityZ(planet)
P.scalex = 0.05
P.scaley = 0.05
P.RGB = [255, 128, 0]
P.mesh = path
P.surf = surf
P.add()
' face all path quads to cam
For P:TQuad = EachIn TQuad.List
P.Update(cam)
Next
RenderWorld
' 2D output
BeginMax2D()
DrawText "Distance..........: " + d, 0, 0
DrawText "Force.............: " + F, 0, 15
DrawText "Force Star........: " + dv1, 0, 30
DrawText "Force Planet......: " + dv2, 0, 45
DrawText "Move X............: " + vx2, 0, 60
DrawText "Move Y............: " + vy2, 0, 75
DrawText "Star Mass Factor..: " + massfactor_s, 0, 90
DrawText "Planet Mass Factor: " + massfactor_p, 0, 105
EndMax2D()
Flip
Wend
End
' ------------------------------------------------------------------------------------------------
' Normalize value
' ------------------------------------------------------------------------------------------------
Function Normalize:Float(value:Float = 128.0, value_min:Float = 0.0, value_max:Float = 255.0, norm_min:Float = 0.0, norm_max:Float = 1.0, limit:Int = False)
' normalize
Local result:Float=((value-value_min)/(value_max-value_min))*(norm_max-norm_min)+norm_min
' limit
If value>norm_max Then value=norm_max Else If value<norm_min Then value=norm_min
Return result
End Function
' ------------------------------------------------------------------------------------------------
' Create Raster Texture
' ------------------------------------------------------------------------------------------------
Function CreateRasterTexture:TTexture()
Local tex:TTexture = CreateTexture(64, 64, 1)
BeginMax2D()
Cls
SetColor 64, 64, 64
DrawRect 0, 0, 63, 63
SetColor 255, 255, 255
DrawLine 0, 0, 63, 0
DrawLine 0, 0, 0, 63
DrawLine 0, 63, 63, 63
DrawLine 63, 63, 63, 0
EndMax2D()
BackBufferToTex(tex, 0)
Return tex
End Function
' ------------------------------------------------------------------------------------------------
' Create Sun Texture
' ------------------------------------------------------------------------------------------------
Function CreateSunTexture:TTexture()
Local pixmap:TPixmap = CreatePixmap(256, 256, PF_RGBA8888)
Local i:Float, j:Int, col:Int, rgb:Int
For j = 0 To 255
col=255-j
If col > 255 Then col = 255
rgb=col*$1000000+col*$10000+col*$100+col
For i=0 To 360 Step 0.1
WritePixel(pixmap, 128 + (Sin(i) * j * 0.5), 128 + (Cos(i) * j * 0.5), rgb)
Next
Next
Local tex:TTexture = LoadTexturePixmap(pixmap, 2)
Return tex
End Function
' ------------------------------------------------------------------------------------------------
' Colorize mesh vertex colors
' ------------------------------------------------------------------------------------------------
Function UpdateMesh(mesh:TMesh, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)
Local surf:TSurface = GetSurface(mesh, 1)
For Local v:Int = 0 To CountVertices(surf) - 1
VertexColor surf, v, r, g, b, a
Next
End Function
' ------------------------------------------------------------------------------------------------
' Quad Type Library
' ------------------------------------------------------------------------------------------------
Type TQuad
Field x:Float = 0.0 ' position x
Field y:Float = 0.0 ' position y
Field z:Float = 0.0 ' position z
Field scalex:Float = 1.0 ' current size X
Field scaley:Float = 1.0 ' current size Y
Field RGB:Int[] = [255, 255, 255, 255] ' star vertex color
Field Alpha:Float = 1.0 ' vertex alpha
Field v:Int = 0 ' vertex counter
Field mesh:TMesh = Null ' mesh pointer
Field surf:TSurface = Null ' surface pointer
Global List:TList = CreateList()
' --------------------------------------------------------------------------------------------
' METHOD: Create new Object in TList
' --------------------------------------------------------------------------------------------
Method New()
ListAddLast(List, Self)
End Method
' --------------------------------------------------------------------------------------------
' METHOD: Remove Object in TList
' --------------------------------------------------------------------------------------------
Method Remove()
ListRemove(List, Self)
End Method
' --------------------------------------------------------------------------------------------
' METHOD: Add new Quad
' --------------------------------------------------------------------------------------------
Method Add(col:Int = 0, row:Int = 0)
' surface setup
If surf = Null Then surf = surf
If v + 4 > 32768 Then
v = 0
surf = CreateSurface(mesh)
EndIf
' add Vertices
Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)
' color vertices
VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha
' connect triangles
AddTriangle surf, V0, V1, V2
AddTriangle surf, V0, V2, V3
VertexTexCoords surf, V0, col + 1, row
VertexTexCoords surf, V1, col + 1, row + 1
VertexTexCoords surf, V2, col, row + 1
VertexTexCoords surf, V3, col, row
' increase vertex counter
If v >= 4 Then v = V0 + 4 Else v = V0
End Method
' --------------------------------------------------------------------------------------------
' METHOD: Update a Quad
' --------------------------------------------------------------------------------------------
Method Update(target:TEntity)
TFormVector scalex, 0, 0, target, Null
Local X1:Float = TFormedX()
Local Y1:Float = TFormedY()
Local Z1:Float = TFormedZ()
TFormVector 0, scaley, 0, target, Null
Local X2:Float = TFormedX()
Local Y2:Float = TFormedY()
Local Z2:Float = TFormedZ()
' set vertices
VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2
' set colors
VertexColor surf, v + 0, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, v + 1, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, v + 2, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, v + 3, RGB[0], RGB[1], RGB[2], Alpha
End Method
End Type
' ----------------------------------------------------------------------------
' Load a pixmap to a brush
' ----------------------------------------------------------------------------
Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags:Int=1,u_scale:Float=1.0,v_scale:Float=1.0)
Return PixTBrush.LoadBrushPixmap(pixmapin,flags,u_scale,v_scale)
End Function
' ----------------------------------------------------------------------------
' Load a pixmap to a texture
' ----------------------------------------------------------------------------
Function LoadTexturePixmap:TTexture(pixmapin:TPixmap,flags:Int=1)
Return PixTTexture.LoadTexturePixmap(pixmapin,flags)
End Function
Type PixTBrush Extends TBrush
Function LoadBrushPixmap:TBrush(pixmapin:TPixmap,flags:Int=1,u_scale:Float=1.0,v_scale:Float=1.0)
Local brush:TBrush=New TBrush
brush.tex[0]=PixTTexture.LoadTexturePixmap:TTexture(pixmapin,flags)
brush.no_texs=1
brush.tex[0].u_scale#=u_scale#
brush.tex[0].v_scale#=v_scale#
Return brush
End Function
End Type
Type PixTTexture Extends TTexture
Function LoadTexturePixMap:TTexture(pixmapin:TPixmap,flags:Int=1,tex:TTexture=Null)
Return LoadAnimTexturePixMap:TTexture(pixmapin,flags,0,0,0,1,tex)
End Function
Function LoadAnimTexturePixMap:TTexture(pixmapin:TPixmap,flags:Int,frame_width:Int,frame_height:Int,first_frame:Int,frame_count:Int,tex:TTexture=Null)
Local pixmapFileName:String="pixmap"+MilliSecs()+Rnd()
If flags&128 Then Return LoadCubeMapTexture(pixmapFileName$,flags,tex)
If tex = Null Then tex:TTexture = New TTexture
tex.file:String=pixmapFileName
tex.file_abs:String=pixmapFileName
' set tex.flags before TexInList
tex.flags=flags
tex.FilterFlags()
' check to see if texture with same properties exists already, if so return existing texture
Local old_tex:TTexture
old_tex=tex.TexInList()
If old_tex<>Null And old_tex<>tex
Return old_tex
Else
If old_tex<>tex
ListAddLast(tex_list,tex)
EndIf
EndIf
' load pixmap
tex.pixmap = CopyPixmap(pixmapin)
' check to see if pixmap contain alpha layer, set alpha_present to true if so (do this before converting)
Local alpha_present:Int=False
If tex.pixmap.format=PF_RGBA8888 Or tex.pixmap.format=PF_BGRA8888 Or tex.pixmap.format=PF_A8 Then alpha_present=True
' convert pixmap to appropriate format
If tex.pixmap.format<>PF_RGBA8888
tex.pixmap=tex.pixmap.Convert(PF_RGBA8888)
EndIf
' if alpha flag is true and pixmap doesn't contain alpha info, apply alpha based on color values
If tex.flags&2 And alpha_present=False
tex.pixmap=ApplyAlpha(tex.pixmap)
EndIf
' if mask flag is true, mask pixmap
If tex.flags&4
tex.pixmap=MaskPixmap(tex.pixmap,0,0,0)
EndIf
' ---
' if tex not anim tex, get frame width and height
If frame_width=0 And frame_height=0
frame_width=tex.pixmap.width
frame_height=tex.pixmap.height
EndIf
' ---
tex.no_frames=frame_count
tex.gltex=tex.gltex[..tex.no_frames]
' ---
' pixmap -> tex
Local xframes:Int=tex.pixmap.width/frame_width
Local yframes:Int=tex.pixmap.height/frame_height
Local startx:Int=first_frame Mod xframes
Local starty:Int=(first_frame/yframes) Mod yframes
Local x:Int=startx
Local y:Int=starty
Local pixmap:TPixmap
For Local i:Int=0 To tex.no_frames-1
' get static pixmap window. when resize pixmap is called new pixmap will be returned.
pixmap=tex.pixmap.Window(x*frame_width,y*frame_height,frame_width,frame_height)
x=x+1
If x>=xframes
x=0
y=y+1
EndIf
' ---
pixmap=AdjustPixmap(pixmap)
tex.width=pixmap.width
tex.height=pixmap.height
Local width:Int=pixmap.width
Local height:Int=pixmap.height
Local name:Int
glGenTextures 1,Varptr name
glBindtexture GL_TEXTURE_2D,name
Local mipmap:Int
If tex.flags&8 Then mipmap=True
Local mip_level:Int=0
Repeat
glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
If Not mipmap Then Exit
If width=1 And height=1 Exit
If width>1 width:/2
If height>1 height:/2
pixmap=ResizePixmap(pixmap,width,height)
mip_level:+1
Forever
tex.no_mipmaps=mip_level
tex.gltex[i]=name
Next
Return tex
End Function
End Type |
Comments
None.
Code Archives Forum
