FreeSpace Releases > Scripting Releases

atomspheric flight

**Nuke**:

ive been awake for like 2 days now developing this thing. i took a look at my old newtonian script, which had a bug that maybe broke colision detection. i was tinkering trying to fix it, i was unable to, but i thought it would be cool to try out some other features. started by adding lift and gravity forces in a hackish way, i didnt like it and got to thinking about adding drag. fortunately the drag equation was simple enough for me to handle. and i plugged it into the game without much hassle. it handled a tad more realistically (for atmo flight).

since there are 4 forces of flight, thrust, drag, lift and weight. i figured i was half way to making freeatmo1 :D. gravity was easy, i looked it up and realized i just needed to plug the ships mass into it to make it work more realistically. i spent most of today working on lift and tweaking vars. lift still isnt perfect but it works. theres something quirky about the direction of the force vector. according to nasa, lift is a force that needs to be perpendicular to the airflow and in the lift direction of the wing. however the function returns a number, and not a vector. needless to say i couldnt find an easy way to do this. multiplying the number by a ship's up vector didnt work to well, and wasnt perpendicular to airflow. tried using a matrix in 10 different ways. tried a cross product which got the best result, but the thing tends to wander and isnt always prependicular to airflow. maybe one of the physics nuts can look at it.

the script is simple, load a mission with some stationary stuff in it, maybe throw in a skybox or some terrain for orientation purposes (stay upright or you will fall like a brick, dont pull up too fast or you will stall). the physics vars are heavily commented to make tweaking a sinch. its set up to handle a ulysses right now. but any ship will work. only player ship gets affected so dont bother thowing in any bad guys. switch to external view to see the force vectors. ive also thrown airspeed and altitude indicators in as well so you can monitor your climb. have fun!

--- Code: ---#Global Hooks

$GameInit:

[

--[[=============================]]--

--[[======= function defs =======]]--

--[[=============================]]--

setscreenvars = function() --scalers and constants for multi res support

local w = gr.getScreenWidth()

local h = gr.getScreenHeight()

local cx = w/2

local cy = h/2

local wf = 0

local hf = 0

local awh = 0

local hires = false

if w >= 1024 then

wf = w / 1024

hf = h / 768

awh = (wf + hf) / 2

hires = true

else

wf = w / 640

hf = h / 480

awh = ((wf + hf) / 2) * 0.625

hires = false

end

return w,h,cx,cy,wf,hf,awh,hires

end

mousejoy = function() --mousejoy function, returns a value from -1 to 1 depending on the mouse's position

local X = io.getMouseX()

local Y = io.getMouseY()

if hires then

X = (X / 511.5) - 1

Y = (Y / 383.5) - 1

else

X = (X / 319.5) - 1

Y = (Y / 239.5) - 1

end

return X,Y

end

round = function(number) --rounds to nearest whole number, for some stupid reason, lua doesnt have this function

local W,F = math.modf(number)

if F < 0 then

if F <= -0.5 then W = W - 1 end

else

if F >= 0.5 then W = W + 1 end

end

return W

end

prograderet = function(x,y,vel)

x, y = x*wf, y*hf --round theese, our vector gets jumpy

gr.setColor(72,192,72,222)

gr.drawGradientLine(x + (12*awh), y + (12*awh), x + (6*awh), y + (6*awh) )

gr.drawGradientLine(x - (12*awh), y - (12*awh), x - (6*awh), y - (6*awh) )

gr.drawGradientLine(x - (12*awh), y + (12*awh), x - (6*awh), y + (6*awh) )

gr.drawGradientLine(x + (12*awh), y - (12*awh), x + (6*awh), y - (6*awh) )

vel = tostring(vel)

gr.setColor(128,192,128,222)

gr.drawString(vel, x - (gr.getStringWidth(vel) / 2), y - (2*awh) )

end

w,h,cx,cy,wf,hf,awh,hires = setscreenvars()

--[[=============================]]--

--[[======= physics specs =======]]--

--[[=============================]]--

--theese are for the ulysses, i picked this fighter because its essentially a flying wing.

--eventually i plan on making theese loadable via text file. yweek theese abit, try to

--make other profiles for other ships

--max thrust values in newtons, will load from file per ship eventually

--ramp the up thrust for ships without good wings will fly sorta like a helicopter

fd_thrust, rv_thrust, up_thrust, dn_thrust, lf_thrust, rt_thrust = 24000, 6000, 8000, 4000, 4000, 4000

--mass in kg

shp_mass = 5000

--cross-sections for drag area computation, area in square meters

--to figure these out, export the ship to max and maintain scale!. choose an orthagonal view

--for the plane you wish to work on first. top is xz, front is xy, and side is yz. flatten the

--ship to a plane using scale. if youre working on the xz plane you want to flatten by setting

--y to 0%. in other words scale the axis not in plane. then use the poly select tool (with ignore

--backfacing enabled) and select all visible polies and hit del. this leaves a flat cross

--section on the other side that you can measure. open the utilities panel and select measure.

--grab the number from the surface area field. hit undo a few times to restore your model.

--repeat for the other 2 planes.

xy_area = 27.28

xz_area = 104.77

yz_area = 55.09

--drag coefficient

drag_ce = 0.020 --about that of a cessna, more = less streamlined, a brick had a dce of about 2

--lift coefficient

--be careful with lift values, too much will throw you out of the level

lift_ce = 0.06 --a fighter jet uses about 0.3, but this is as high as i dare go more = more lift

--wing area

--sorta guesstimate this, its gonna be a number between 0 and xz_area. more = more lift

wing_area = 95 --the whole ship is a wing

--enviroment specs

--gravitational force per kg

--im using planer gravity right now, but may implement spherical gravity later on

grav_force = 9.78033 --earth grav

--atmospheric pressure kg/m^3

--eventually il throw in barametrics to simulate diferent density at diverent altitudes

atmo_pres = 1.293 --earth atmo at ground level at 0c

--no more physics vars to tweek, maybe more next time

wvel = ba.createVector(0,0,0)

]

$simulation:

[

player = mn.Ships["Alpha 1"]

--first lets do thrust, its longer due to tweaked input code

if player:isValid() then

tvec = ba.createVector(0,0,0)

--tvec.x = player.Physics.SideThrust

--tvec.y = player.Physics.VerticalThrust

tvec.x, tvec.y = mousejoy() --more usefull cause you can set lift to an arbitrary amount

tvec.y = -tvec.y

tvec.z = player.Physics.ForwardThrust

if tvec.x > 0 then

tvec.x = tvec.x * lf_thrust

else

tvec.x = tvec.x * rt_thrust

end

if tvec.y > 0 then

tvec.y = tvec.y * up_thrust

else

tvec.y = tvec.y * dn_thrust

end

if tvec.z > 0 then

tvec.z = tvec.z * fd_thrust

else

tvec.z = tvec.z * rv_thrust

end

tvec = player.Orientation:unrotateVector(tvec) --convert local vector to world space

--first compute some important data

local wvel_len = wvel:getMagnitude()

local wvel_sqrd = wvel_len * wvel_len

if wvel_len > 0 then wvel_len_f = 1 / wvel_len else wvel_len_f = 1 end --avoid div by zero error

local wvel_norm = wvel * wvel_len_f

local wvel_norm_rot = player.Orientation:rotateVector(wvel_norm)

--lets do drag, figure out how much area is hitting the wind

--scale cross sections by components of the normalized, rotated velocity vector

local area = xy_area * math.abs(wvel_norm_rot.z) +

xz_area * math.abs(wvel_norm_rot.y) +

yz_area * math.abs(wvel_norm_rot.x)

--lets plug the drag equasion

local drag = drag_ce * area * 0.5 * atmo_pres * wvel_sqrd

dvec = (wvel_norm * -1) * drag

--now for lift

local lift = lift_ce * wing_area * 0.5 * atmo_pres * wvel_sqrd

lvec = wvel_norm:getCrossProduct(player.Orientation:unrotateVector(ba.createVector(1, 0, 0)))

lvec = lvec * lift

--gravity is really easy

gvec = ba.createVector(0,-grav_force ,0) * shp_mass

--add em up to get our total force vector

fvec = tvec + dvec + lvec + gvec

--factor in mass

local massfactor = 1 / shp_mass

fvec2 = fvec * massfactor

--add to velocity

wvel = wvel + fvec2

--adjust for frametime

local wvel_timescaled = wvel * ba.getFrametime()

--use it

Vx,Vy = (player.Position + wvel):getScreenCoords()

velmag = wvel:getMagnitude()

player.Position = player.Position + wvel_timescaled

player.Physics.Velocity = wvel

end

]

$Hud:

[

if player:isValid() then

gr.setColor(255,0,0,255)

gr.drawString("Thrust: "..math.ceil(tvec.x).." ' "..math.ceil(tvec.y).." ' "..math.ceil(tvec.z))

gr.setColor(0,255,0,255)

gr.drawString("Drag: "..math.ceil(dvec.x).." ' "..math.ceil(dvec.y).." ' "..math.ceil(dvec.z))

gr.setColor(0,0,255,255)

gr.drawString("Lift: "..math.ceil(lvec.x).." ' "..math.ceil(lvec.y).." ' "..math.ceil(lvec.z))

gr.setColor(255,255,0,255)

gr.drawString("Weight: "..math.ceil(gvec.x).." ' "..math.ceil(gvec.y).." ' "..math.ceil(gvec.z))

gr.setColor(0,255,255,255)

gr.drawString("Total: "..math.ceil(fvec.x).." ' "..math.ceil(fvec.y).." ' "..math.ceil(fvec.z))

gr.drawCircle(5, io.getMouseX()*wf, io.getMouseY()*hf)

gr.setColor(0,0,0,255)

gr.drawString("Altitude: "..math.ceil(player.Position.y + 50000))

gr.drawString("Airspeed: "..math.ceil(wvel:getMagnitude()))

local X,Y = player.Position:getScreenCoords()

if X then

X,Y=X*wf,Y*hf

local XX,YY = (player.Position + (tvec*0.001)):getScreenCoords()

gr.setColor(255,0,0,255)

if XX then gr.drawLine(X,Y,XX*wf,YY*hf) end

XX,YY = (player.Position + (dvec*0.001)):getScreenCoords()

gr.setColor(0,255,0,255)

if XX then gr.drawLine(X,Y,XX*wf,YY*hf) end

XX,YY = (player.Position + (lvec*0.001)):getScreenCoords()

gr.setColor(0,0,255,255)

if XX then gr.drawLine(X,Y,XX*wf,YY*hf) end

XX,YY = (player.Position + (gvec*0.001)):getScreenCoords()

gr.setColor(255,255,0,255)

if XX then gr.drawLine(X,Y,XX*wf,YY*hf) end

XX,YY = (player.Position + (fvec*0.001)):getScreenCoords()

gr.setColor(255,255,255,255)

if XX then gr.drawLine(X,Y,XX*wf,YY*hf) end

end

if Vx then prograderet( Vx, Vy, round(velmag) ) end

end

]

#End

--- End code ---

**WMCoolmon**:

It seemed a little weird. I tried using an Orion as a point of reference, and noted collision didn't work. I also had trouble diving - it seemed like I continued getting lift even when I was pointed down.

Also to round a number you should be able to do math.floor(n+0.5)

Very nice though, this could get very interesting. :D

**Wanderer**:

If you want to keep collision detection working then for heavens sake do not use position data.

Its the exact same reason why i had to implement velocity based barriers to the corridor mode.

Hmmm...

Also is the lift (as a force pointing upwards) 'attenuated' with the ships orientation?

And hmm.. have you given any thoughts about using or setting up terminal velocity (though that would also need to be attenuated with ships orientation...)?

**Nuke**:

one of the reaons i tweak position data direactl is cause the gamev

--- Quote from: WMCoolmon on December 15, 2007, 03:36:59 am ---It seemed a little weird. I tried using an Orion as a point of reference, and noted collision didn't work. I also had trouble diving - it seemed like I continued getting lift even when I was pointed down.

Also to round a number you should be able to do math.floor(n+0.5)

Very nice though, this could get very interesting. :D

--- End quote ---

that round func is old, most of the timei just use ceil. its probly lrft over from my old newtonian script. i expected colisions to be borked, as im still hacking position data. wvel is a valid replacement velocity though. i just need a way to tell freespace not to screw with my velocity. i tried using the on frame state hook and it worked about the same way. i eventually said **** it, im uncommenting the hack.

--- Quote from: Wanderer on December 15, 2007, 04:10:38 am ---If you want to keep collision detection working then for heavens sake do not use position data.

Its the exact same reason why i had to implement velocity based barriers to the corridor mode.

Hmmm...

Also is the lift (as a force pointing upwards) 'attenuated' with the ships orientation?

And hmm.. have you given any thoughts about using or setting up terminal velocity (though that would also need to be attenuated with ships orientation...)?

--- End quote ---

terminal velocity seems to work as a product of the drag function. the drag force is fairly accurate. it will be even more accurate when i account for barometrics and lift induced drag.

part of the drag equation needs to know how much surface area is exposed to flow. i calculate that by rotating a normalized velocity vector to model space. i use that vector's individual components as scalers. the z axis scales the frontal area, the y axis the top down area, and x scales side area. i sum the result to get a rough approximation of how much surface area the airflow must interact with. drag_ce is the co-efficient, a magic number which covers all the stuff tht needs t be determined experimentally. but in practice a blunt object has a higher value, small numbers are more streamlined. so a cessna is about 0.028, and a borg cube would be > 1 or more around 2.

this is only a subsonic equation however. for supersonic flight, you need to account for shock forces. should allow an adama manuver at least :D

lift still dont work right. the force is applied in the wrong direction first of all. lift force is apllied along the cross product of velocity and a world space side vector. lift seems to be all over the place. i tried simply multiplying lift by normalized velocity, and flipping z and y. but that didnt work either. im also seeing excessive horizontal component. aoa needs to be accounted for. if you try to fly straight up, instead of stalling, you just sorta hover there and climb slowly, which shouldnt be possible considering how little thrus im using. fighter jets produce thrust in terms oof hundreds of thousands of newtons. a mere 32000 newtons shouldnt be capable of that. im probibly gonna use a world space velocity normal as a scaler again, seemed to work well for drag.

**Wanderer**:

--- Quote from: Nuke on December 15, 2007, 05:34:29 am ---one of the reaons i tweak position data direactl is cause the gamev

--- End quote ---

Yes, but still it breaks stuff and there is no way of avoiding it.

Navigation

[0] Message Index

[#] Next page

Go to full version