FreeSpace Releases > Scripting Releases

atomspheric flight

**Nuke**:

well i got lift to work, sorta. it now can take angle of attack into account. though im not sure how accurate my aoa value is. its sorta hacked in there. the flight model is sorta acting like a flight model now. i switched the physics vars over to the perseus, got rid of the reverse, vertical and lateral thrust forces, as they were throwing everything off, they can easily be turned back on once the flight model improves.

im still experiencing alot of horizontal lift component. the ship handles more like a helicopter than an airplane. the flight model is also lift happy. that ****ed up yaw axis that freespace uses gets really annoying here. i tried to remove it with scripting, but that didnt work. i know the wing commander people want that gone. not only does it interfere with flight as it is, but when i go to implement newtonian rotations and control surfaces, i will not be able to get axis data independant of eachother. when i check rotational velocity desired, any desired yaw from the yaw axis will also copy itself to the bank axis. i might just assign yaw to a mouse axis and take bank from the yaw axis. this is ok because i usually play flight sims more comfortably with roll on the x axis.

also added some standard aviation gauges to the data printout, suck as airspeed, vertical speed, and angle of attack. also im still waiting for a certain resident finnish physics nut to correct my physics errors :D

--- 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

normalize = function(v)

vlen = v:getMagnitude()

if vlen > 0 then vlen = 1 / vlen else vlen = 1 end

return v * vlen

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

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 --ulysses

--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

--pegasus

fd_thrust, rv_thrust, up_thrust, dn_thrust, lf_thrust, rt_thrust = 80000, 0, 0, 0, 0, 0

shp_mass = 12000

xy_area = 30.68

xz_area = 158.51

yz_area = 65.76

drag_ce = 0.035

lift_ce = 0.02

wing_area = 120

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

wvel_len = wvel:getMagnitude()

local wvel_sqrd = wvel_len * wvel_len

local wvel_norm = normalize(wvel)

local wvel_norm_rot = player.Orientation:rotateVector(wvel_norm) --normalized velocity in model space

local wvel_norm_rot_no_z = wvel_norm_rot

wvel_norm_rot_no_z.z = 0

wvel_norm_rot_no_z = normalize(wvel_norm_rot_no_z)

angle_of_attack = -math.asin(wvel_norm_rot.y)

skid_angle = math.asin(wvel_norm_rot.x)

--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

local aoa_mat = ba.createOrientation(angle_of_attack,0,0)

lift_ref_vec = ( player.Orientation*aoa_mat):unrotateVector(ba.createVector(0,1,0))

lvec = lift_ref_vec * 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

player.Position = player.Position + wvel_timescaled

player.Physics.Velocity = wvel --id rather not do this you know

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(128,128,128,255)

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

gr.drawString("Airspeed: "..math.ceil(wvel_len))

gr.drawString("Vert Spd: "..math.ceil(wvel.z))

gr.drawString("AoA: "..math.deg(angle_of_attack))

gr.drawString("Skid: "..math.deg(skid_angle))

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

if X then

X,Y=X*wf,Y*hf

local XX,YY = (player.Position + (tvec*0.0003)):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.0003)):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.0003)):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.0003)):getScreenCoords()

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

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

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

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

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

end

X,Y = (player.Position + wvel):getScreenCoords()

if X then prograderet( X, Y, math.ceil(wvel_len)) end

end

]

#End

--- End code ---

**WMCoolmon**:

--- Quote from: Nuke on December 16, 2007, 06:44:07 am --- that ****ed up yaw axis that freespace uses gets really annoying here. i tried to remove it with scripting, but that didnt work. i know the wing commander people want that gone. not only does it interfere with flight as it is, but when i go to implement newtonian rotations and control surfaces, i will not be able to get axis data independant of eachother. when i check rotational velocity desired, any desired yaw from the yaw axis will also copy itself to the bank axis.

--- End quote ---

I've added a "Banking constant" field that should allow you to scale the amount of banking a ship does. The default is "0.5", and setting it to 0 should turn it off. I've tested it and it does seem to work. :p

"$Banking Constant:" is right after "$Rotdamp:" in ships.tbl

You can also change it dynamically with the BankingConstant variable in the scripting "physics" handle.

http://fs2source.warpcore.org/exes/latest/C12272007d.zip

I consider this a preliminary implementation. I could turn these into vectors for all three rotational axis to make it less specialized, if there's a reason to. All the code is doing is this:

--- Code: ---#ifdef BANK_WHEN_TURN

// To change direction of bank, negate the whole expression.

// To increase magnitude of banking, decrease denominator.

// Adam: The following statement is all the math for banking while turning.

delta_bank = - (ci->heading * pi->max_rotvel.xyz.y) * pi->delta_bank_const;

#else

delta_bank = 0.0f;

#endif

pi->desired_rotvel.xyz.z = ci->bank * pi->max_rotvel.xyz.z + delta_bank;

--- End code ---

BANK_WHEN_TURN is always defined so it's really only calculating this:

--- Code: ---delta_bank = - (ci->heading * pi->max_rotvel.xyz.y) * pi->delta_bank_const;

pi->desired_rotvel.xyz.z = ci->bank * pi->max_rotvel.xyz.z + delta_bank;

--- End code ---

where pi->delta_bank_const has been, up to this point, 0.5.

**Nuke**:

ah cool, very useful.

i added some preliminary barometrics as well as max and min angle of attack settings.

i probably spent maybe 6 hours reading up on the barometric formula. not only is there a very complex formula to calculate are density at altitude, but theres also a table for changes in factors for different layers of the atmosphere. i only implemented the sea level row. but i think there are those who could use atmospheric layers. particularly a certain bsg episode depicts flying in a layered atmosphere. so you could use layers not only to simulate earthlike atmosphere, but also have a layer of doom that you cant escape from (due to skyrocketing atmospheric density and the velocity raping drag that ensues). this can be left open for further development.

the aoa limiter essentially scales back your lift coefficient when your angle of attack gets too high or too low. according to airfoil simulation, lift coefficient does change during flight and part of it is due to aoa. however realistically the lift coefficient is more on a gradient than a flat line between max and min. so tomorrow il consider adding that gradient. lift coefficient needs to clime as it reaches the max stall angle and drop as it reaches the minimum with the neutral angle, where the calculated coefficient best matches the one set in the physics parameters, lies directly in between. si if your max aoa is 20 degrees, your minimum is -10, and your aoa is 5, then the lift_ce var will equal the aoa compensated lift coefficient. for negative angle of attack the lift coefficient may actually goes negative and will reach a negative stall at some point, where your lift_ce begins to return to zero.

another thing i will implement in the future is wing induced drag. this will require a wing chord and/or span variables. since wing area is already specified, i could just add one and calculate the other. and once all those features are in, il start working on newtonian torque. lack of torque effects is what causes that excessive horizontal lift component it seems. realistically an aircraft rudder cant produce enough torque to overcome the air pressures along the fusalage that want to keep it pointing into the wind. so pilots have to roll before theres enough force from the horizontal lift component to help the turn along. besides your passengers would hate you if you skid turned excessively :D.

*edit*

silly me, forgot to post the update

--- 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

normalize = function(v)

vlen = v:getMagnitude()

if vlen > 0 then vlen = 1 / vlen else vlen = 1 end

return v * vlen

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

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 =======]]--

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

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

--[[environmental vars]]--

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

--alot more stuff here, alot of it i dont get, but was required for the barometric formula. many

--of these values are based on the international standard atmosphere, which are used to calibrate

--altimeters and other gauges in aircraft, aparently theres a table for different atmospheric

--layers, each with their own set of variables. so i might eventually allow a user to specify

--as many layers as they want. for example a mission in a gas giant might want a layer that

--you cant get out of (i think this happened in bsg, hint hint).

ter_base_lvl = -2000 --height of terrain model placement in fred, m

grav_accel = 9.78033 --acceleration of gravity, m/s^2

std_atmo_density = 1.293 --standard pressure at sea level, kg/m^3

std_temp = 288.15 --standard tempurature at sea level, kelvin

std_temp_lapse = 0.0065 --rate of tempurature loss starting at sea level and going up, kelvins/meter

atmo_mass = 0.0289644 --mass of atmosphere, kg/molar

gas_const = 8.31432 --universal gas constant, N·m / (mol·K), whatever the **** that means

--eventually i will support spherical gravity and atmosphere for some small scale launch,

--re-entry, and orbital manuvers. maybe il even support multiple spheres in a mission.

--the model is fully newtonian once lift and drag get zeroed out.

--ive added vars for more ships you can play around with, just remove the comment tags --[[ ]]-- from

--the ship specs you want to use all area values are actual ship cross sectional area, wing area is

--the area of any lifting surfaces, such as wings (in case of serapis and perseus), or lifting bodys

--(ulysses, pegasus). alternatively you can use a large up_thrust value to get helicopter style

--flight (erinyes). mass is ship volume * 100kg (assuming 100kg per cubic meter volume).

--thrust and coefficient values are ones which i find work well with the ship, however they are not

--perfect. there is a probability that one of the forces will overpower the others and youl get thrown

--out of the mission area. barometrics has reduced instances of getting tossed, however it can still

--happen. i attempted to use an airfoil simulation program on cross sections from actual fs models, in

--order to compute coefficients, usually with limited success (usually the program choked on my dxfs).

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

--[[instructions for computing area values in 3dsmax]]--

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

--to determine cross-section areas for drag area computation, export the ship to max and

--maintain scale! you may want to run mesh smooth on your models firsty, 3 iterations with

--smooth group seams enabled tends to work well. choose an orthagonal view for the plane you

--wish to work on first. remember that conversion might switch axis order, so tetermine cross

--sections on the freespace coordanate system (x, y, z = side, up, front). 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. measuring both sides or not flattening

--would create more drag than your ship should actually create. 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.

--for wing area, use the bottom view, select only lifting surfaces, such as wings. be sure to keep

--ignore backfacing on. you may need to use ctrl to select multiple sections. once thats done

--select 'invert selection' from the edit menu and hit delete. flatten the model as above.

--then go to measure and get the surface area value.

--you may also want to note the volume from the measure pane. you can then multiply it by a standard

--density value (i used 100 kg per cubic meter of ship). this lets massive ships actually feel massive

--remember that under newtonian, massive ships require more thrust.

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

--[[ship physics vars]]--

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

--[[

--ulysses, jumpy little bastard and not the best aircraft either

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

shp_mass = 12169 --mas in kg, im using model volume of 121.69 * 100kg (assuming 100 kg per cubic meter of volume)

xy_area = 24.59 --area of frontal cross section for drag computation, square meters

xz_area = 104.26 --area of top down cross section for drag computation, m^2

yz_area = 53.72 --area of side cross section for drag computation, m^2

drag_ce = 0.0073 --drag coefficient, lower number = less drag, reccomend value between 0 and 2

lift_ce = 0.6 --lift coefficient, higher number = more lift, reccomend value between 0 and 0.1

wing_area = 52.59 --area of wings from top down perspective, square meters, recomend value less than xz_area

aoa_max = 15 --maximum angle of attack, angle relative to velocity that wings stop producing lift, degrees

aoa_min = -5 --minimum angle of attack, degrees

]]--

--[[

--serapis, handles better in the upper atmosphere

fd_thrust, rv_thrust, up_thrust, dn_thrust, lf_thrust, rt_thrust = 95000, 1000, 2000, 1000, 1000, 1000

shp_mass = 25327

xy_area = 44.59

xz_area = 170.8

yz_area = 76.93

drag_ce = 0.0123

lift_ce = 0.055

wing_area = 49.68

aoa_max = 20

aoa_min = -10

]]--

--

--perseus, sleek and fast and lots of lift

fd_thrust, rv_thrust, up_thrust, dn_thrust, lf_thrust, rt_thrust = 110000, 2000 ,1000, 1000, 1000, 1000

shp_mass = 10449

xy_area = 25.01

xz_area = 66.49

yz_area = 74.35

drag_ce = 0.04

lift_ce = 0.132

wing_area = 9.89

aoa_max = 30

aoa_min = -15

--

--[[

--pegasus, a good example of a stall happy physics profile

fd_thrust, rv_thrust, up_thrust, dn_thrust, lf_thrust, rt_thrust = 100000, 0, 0, 0, 0, 0

shp_mass = 37565

xy_area = 27.3

xz_area = 155.78

yz_area = 62.69

drag_ce = 0.035

lift_ce = 0.1

wing_area = 120

aoa_max = 20

aoa_min = -5

]]--

--[[

--erinyes, essentially no wings, so i gave it alot of vertical thrust

fd_thrust, rv_thrust, up_thrust, dn_thrust, lf_thrust, rt_thrust = 150000, 10000, 265000, 10000, 10000, 10000

shp_mass = 26954 --269.54

xy_area = 41.43

xz_area = 132.77

yz_area = 188.48

drag_ce = 0.03

lift_ce = 0.001

wing_area = 80.78 --its pods look somewhat lift capable, but lifting bodys tend to have sucky coefficients

aoa_max = 10

aoa_min = 0

]]--

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

init = false

]

$simulation:

[

player = mn.Ships["Alpha 1"]

if init == false then

if player:isValid() then player.Position = ba.createVector(0,0,0) end

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

init = true

end

--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

wvel_len = wvel:getMagnitude()

local wvel_sqrd = wvel_len * wvel_len

local wvel_norm = normalize(wvel)

local wvel_norm_rot = player.Orientation:rotateVector(wvel_norm) --normalized velocity in model space

local wvel_norm_rot_no_x = wvel_norm_rot

skid_angle = math.asin(wvel_norm_rot.x)

wvel_norm_rot_no_x.x = 0

wvel_norm_rot_no_x = normalize(wvel_norm_rot_no_x)

angle_of_attack = -math.asin(wvel_norm_rot.y)

aoa_deg = math.deg(angle_of_attack)

--baromatric formula, maybe

atmo_density = std_atmo_density * (std_temp/(std_temp+std_temp_lapse*((player.Position.y-ter_base_lvl)-0))) ^ ((grav_accel*atmo_mass)/(gas_const*std_temp_lapse))

--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_density * wvel_sqrd

dvec = (wvel_norm * -1) * drag

--now for lift

local lift_ce_adj

if aoa_deg <= aoa_max and aoa_deg >= aoa_min then

lift_ce_adj = lift_ce

elseif aoa_deg > aoa_max then

local excess_aoa = aoa_deg - aoa_max

lift_ce_adj = lift_ce / excess_aoa

elseif aoa_deg < aoa_min then

local excess_aoa = aoa_min - aoa_deg

lift_ce_adj = lift_ce / excess_aoa

else

lift_ce_adj = lift_ce

end

local lift = lift_ce_adj * wing_area * 0.5 * atmo_density * wvel_sqrd

local aoa_mat = ba.createOrientation(angle_of_attack,0,0)

lift_ref_vec = ( player.Orientation*aoa_mat):unrotateVector(ba.createVector(0,1,0))

lvec = lift_ref_vec * lift

--gravity is really easy

gvec = ba.createVector(0,-grav_accel ,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

player.Position = player.Position + wvel_timescaled

player.Physics.Velocity = wvel --id rather not do this you know

else

init = false

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(128,128,128,255)

gr.drawString("Altitude: "..math.ceil(player.Position.y-ter_base_lvl))

gr.drawString("Airspeed: "..math.ceil(wvel_len))

gr.drawString("Vert Spd: "..math.ceil(wvel.y))

gr.drawString("AoA: "..aoa_deg)

gr.drawString("Skid: "..math.deg(skid_angle))

gr.drawString("Air Dnsty: "..atmo_density)

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

if X then

X,Y=X*wf,Y*hf

local XX,YY = (player.Position + (tvec*0.0003)):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.0003)):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.0003)):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.0003)):getScreenCoords()

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

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

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

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

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

end

X,Y = (player.Position + wvel):getScreenCoords()

if X then prograderet( X, Y, math.ceil(wvel_len)) end

end

]

#End

--- End code ---

**Wanderer**:

I'm still going to say this one more time...

As long as you keep the system position vector based it is and won't ever be anything more than showcase or PoC. As it messes up far too many things elsewhere. For example landing (or crashing onto anything) is not even theoretically possible as the ship simply 'phases' or 'warps' through the surface. Same goes for 'midair' collisions or even weapons fire as the ships position is changed without moving the ship between these locations. Would it be based on velocities or something else that is used for moving the ship between the frames then it would be much better.

**WMCoolmon**:

What does it need to be non-Position based?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version