icarusuk 0 Posted February 13, 2003 LoL thats some funky graph doodles, done in MSPaint?  Hehehe. My full script (thats over 4 pages long so itsnt posed here) can accurately aim at a moving target or group.  It adjusts for launcher / target height (not with the pathetic select 2 rubbish, but using ASLheight).  And it works really well.  If only for this drag thing it would be finished. Id rather not drop bombs straight, with my script you can see and hear them coming, it looks quite stunning indeed  Esspecially with smoke munitions leaving an arc of green smoke in the sky Incidently, the script can be altered through parsing a variable that alters the time of flight. A longer time gives a high arc, which I small time gives a much shallower arc. Will working out the time of flight and adjusting work? Share this post Link to post Share on other sites
Prospero 1 Posted February 13, 2003 OFP's weather-wind - remember the "rubbing" argument in the drop function, for example - may also influence the motion of the sim-types used for shells / rockets. I haven't done any experiments, so I'm simply mentioning it as it occurs. It could be one factor responsible for the "inconsistencies" mentioned. It is measurable though (at least, I'm sure a reasonably accurate estimation is possible) via script. Prospero Share this post Link to post Share on other sites
icarusuk 0 Posted February 13, 2003 Ahh yes, rubbing. Makes some nifty smoke effects I sent Suma a PM asking if its possible to let us in on the proper model that they used, Im not expecting a reply, but at least I tried. Share this post Link to post Share on other sites
Prospero 1 Posted February 24, 2003 I mentioned a "display script" for the framework flight-model code I posted earlier in this thread. So, for the sake of completeness, here's an example of one which takes care of the NED to ENU conversion without having to resort back to Euler angles. I use it to display objects made out of lots of separate spherical objects - driven by the flight-model script. Also note that a trigger called "base" needs to be created (one way or another) for this script to work as intended. The "mysphere" object is just a custom sphere created using O2. ---------- s1 = "mysphere" camcreate [0, 0, 0] s2 = "mysphere" camcreate [0, 0, 0] s3 = "mysphere" camcreate [0, 0, 0] s4 = "mysphere" camcreate [0, 0, 0] s5 = "mysphere" camcreate [0, 0, 0] s6 = "mysphere" camcreate [0, 0, 0] s7 = "mysphere" camcreate [0, 0, 0] s8 = "mysphere" camcreate [0, 0, 0] s9 = "mysphere" camcreate [0, 0, 0] s10 = "mysphere" camcreate [0, 0, 0] s11 = "mysphere" camcreate [0, 0, 0] ; Vectors in ENU. _v1 = [0, 0, 0] _v2 = [0, 1, 0] _v3 = [1, 0, 0] _v4 = [0, -1, 0] _v5 = [-1, 0, 0] _v6 = [0, 0, 1] _v7 = [0, 0, -1] _v8 = [0.325, 1, 0] _v9 = [-0.325, 1, 0] _v10 = [0, 1, 0.325] _v11 = [0, -3, 0] _vs = [_v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9, _v10, _v11] _nvs = count _vs _n = 0 #lp1 _ip = Output ; Position in ENU (remember that the z value represents absolute height here). _x = _ip select 4 _y = _ip select 3 _z = -(_ip select 5) ; The Direction Cosine Matrix. Note that this is the NED DCM. We don't want to have to rebuild it from scratch for ENU. Instead, when we come to apply it to the ENU vectors, we'll perform the necessary conversion as we go. _m11 = _ip select 9 _m12 = _ip select 10 _m13 = _ip select 11 _m21 = _ip select 12 _m22 = _ip select 13 _m23 = _ip select 14 _m31 = _ip select 15 _m32 = _ip select 16 _m33 = _ip select 17 ; Transform the vectors. _tvs = [] #lp2 _v = _vs select _n _x1 = _v select 0 _y1 = _v select 1 _z1 = _v select 2 ; Apply the inverse (or transpose) of the DCM. Also swap the x and y terms and change the sign of the z term as we go. _x2 = _y1 * _m11 + _x1 * _m21 - _z1 * _m31 _y2 = _y1 * _m12 + _x1 * _m22 - _z1 * _m32 _z2 = _y1 * _m13 + _x1 * _m23 - _z1 * _m33 base setpos [_y2 + _x, _x2 + _y, 0] _v = [_y2 + _x, _x2 + _y, -_z2 + _z + (getpos base select 2)] _tvs = _tvs + [_v] _n = _n + 1 ?(_n < _nvs): goto "lp2" _n = 0 ; The array named tvs now contains all the vectors transformed appropriately for ENU, including an offset to account for the (quite probably differing) height of the ground under each position. So all that remains is to place the objects into OFP world-space in the normal way. s1 setpos (_tvs select 0) s2 setpos (_tvs select 1) s3 setpos (_tvs select 2) s4 setpos (_tvs select 3) s5 setpos (_tvs select 4) s6 setpos (_tvs select 5) s7 setpos (_tvs select 6) s8 setpos (_tvs select 7) s9 setpos (_tvs select 8) s10 setpos (_tvs select 9) s11 setpos (_tvs select 10) ; In ENU, remember that a positive yaw is nose left, NOT right. It is effectively minus (compass) heading. hint format ["yaw %1\npitch %2\nroll %3\n", -deg(_ip select 8), deg(_ip select 7), deg(_ip select 6)] ~0.001 goto "lp1" ---------- Prospero Share this post Link to post Share on other sites
Quantum 0 Posted March 13, 2003 I've been trying to do this the old fashioned way apparently.  Though I do have a small result set I'd like you guys to look at and tell me what you think. The code used is </span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE"> ;Calculate the necessary x,y,z velocity vectors for firing a projectile ;Quantum ; ; src is the firing unit pos array, tgt is the destination pos array ; rounds is the number to fire, ; elevation angle ; dir is direction of course ; initvel is the horizontal velocity ; initvo refers to the vertical offset where the round is camcreate'd (off the ground) ; --------------------------------- _src = _this select 0 _tgt = _this select 1 _elevation = _this select 2 _rounds = _this select 3 _roundtype = _this select 4 _velinit = _this select 5 _initvo = _this select 6 ; --------------------------------- ; break down the pos arrays _srcx = _src select 0 _srcy = _src select 1 _tgtx = _tgt select 0 _tgty = _tgt select 1 ; some good ol fashion math _diffx = _tgtx - _srcx _diffy = _tgty - _srcy ;[west,"HQ"] sidechat format["diffs:%1,%2",_diffx,_diffy] _xsqrd = _diffx ^ 2 _ysqrd = _diffy ^ 2 _range = sqrt(_xsqrd+_ysqrd) ; determine the angle to target as THETA ; THETA = arctan(x/y) for direction _preangle = atan(_diffx/_diffy) ; now which quandrant are we in? ?(_diffy < 0):_theta=180+_preangle ?(_diffy >= 0):_theta=360+_preangle ?(_theta > 360):_theta=_theta-360 ?(_theta < 0):_theta=_theta+360 [west,"HQ"] sidechat format["dir:%1 range:%2",_theta,_range] ; ; setup the vectors ; Theta determines direction, PHI determines elevation ; The magnitude of the first vector is the requested Velocity ; The base of this triangle represents the hypotenus of the direction vector ; so we calculate the Z (verticle axis) first ; _velOY = _velinit * sin(_elevation) _velOX = _velinit * cos(_elevation) ; velOX is now the hypotenus (magnitude) of the direction vector ; so get the x,y components from it _velx = sin(_theta) * _velOX _vely = cos(_theta) * _velOX ; _fullstr = format["Vector info OY:%1 OX:%2 X:%3 Y:%4",_velOY,_velOX,_velx,_vely] [west,"HQ"] sidechat _fullstr ; so the full vector is [_velx,_vely,_velOY] _op = _roundtype camcreate[_srcx,_srcy,_initvo] _op setdir _theta _op setvelocity[_velx,_vely,_velOY] [west,"HQ"] sidechat "Artillery round fired" ; _counter = 0 #loop _oppos = getpos _op _px = _oppos select 0 _py = _oppos select 1 _diffx = (_px - _srcx) _diffy = (_py - _srcy) _travel = sqrt(_diffx^2 + _diffy^2) ;hint format["travel: %1\ndamage: %2",_travel,damage _op] ~0.1 _counter = _counter + 0.1 _opd = damage _op ?(_op == _op):goto "loop" [west,"HQ"] sidechat format["final x:%1 y:%2",_px,_py] ~2 _fullstr = format["velinit: %1\ntravel:%2\ntime:%3\ndmg:%4\nelevation:%5",_velinit,_travel,_counter,_opd,_elevation] hint _fullstr _op = nil exit <span id='postcolor'> Using this I built a table. Theta = 45 (tested values are avg's, about 5-6 test shots)     tested  tested | calculated values are Vo    range  time   |  Voy   Time   Rng    Rng Error% ----------------------------------------------------------- 30    89    4.1     21.21  4.32   91.83     3 45    185   6.5     31.82  6.49   206.63    10 60    315   8.5     42.42  8.6    367      14 75    473   10.5    53.01  10.82  573      17 90    620   12     63.63  12.98  826      24 105   779    13.5    74.24  15.15  1125     30 120   963    14     84.84  17.3   1469     34 at theta=45 Voy = Vox so Vox is not in the table You can see in my code I get the proper vectors first for elevation, then using the base I build the x,y vectors. Looking at the hint/chat output, all the vectors are correct.  It's the error rate that get's flaky.  There is some inherent error in the tested values because I couldn't get good timings with a delay of <0.1.  But these results, even with a 1% error still show a definite reduction in range and time. When the Tof (time of flight) approaches 18 secs the code still works, but of course the shell has exceeded it's Ttl (time to live) so there is never an impact. I was hoping to build an elevation chart for some of the add arty pieces out there, like the M101 and the M109.  Looking at their initspeed's it appears it would be useless to do so for such high speeds.  The best range at 200m/s is around 1800m.  Not a great distance.  The M109v2(Heat) fires at 900m/s, even with a calculated elevation of 10degrees the round would fly off the map.  At 45d elevation the round takes well over a minute just to reach it's apex. With an ~20sec Ttl and this ever elusive (-vt), will using real pieces for artillery work?  Sure you can use the 900m/s initspeed's, but your trajectory is so shallow that it kind of defeats the idea of dropping shells from above, especially to clear buildings.. my 2 cents, Quantum Share this post Link to post Share on other sites
Doolittle 0 Posted March 13, 2003 Quantum, looks good. Don't forget you can use the atan2 function and you don't have to worry about quadrants. Doolittle Share this post Link to post Share on other sites
Quantum 0 Posted March 25, 2003 Didn't know if the whole arty thing was said and done, but I went ahead and addressed an earlier comment in one of these messages about handling the TTL of 'shell' objects by recreating it downrange.  So here it is (hope it's not too big and forgive me for all the comments, I wrote this for my use but also to teach a friend): </span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE"> ; MidFlightRound  (commented out the wazoo) ; Quantum ; The purpose is to create a projectile somewhere ; along it's trajectory mitigating the TTL of 'shell' objects. ; *********************************************************************************** ; TRAJECTORY MATH AND SCRIPT APPROACH DEFINITIONS ; *********************************************************************************** ; Ideally, this script should be called right after the artillery unit performs the 'FIRE' ; action. That way you get the sound effect of the gun firing and then this script handles ; the round. ; The reason for this script is to address the TTL (time-to-live) issues with ammo types ; inherited from the 'shell' object.  Since an object of type 'shell' has a TTL = 20 secs, ; we need to recreate the shell anytime we know the time will exceed the TTL. ; Using addon artillery pieces is the definitive reason behind this script. ; ALL addons intended to be used as artillery suffer from this TTL restriction. ; Firing a 'shell' object at actual military velocities (such as initspeed=900 m/s) means ; the round would be off the map at an elevation as little as 5 degrees (henceforth just d). ; Such shallow trajectories are very rarely, if ever, used in actually battlefield deployments. ; The idea is to arc the round high enough to make the range required but also to come in ; at such an angle as to miss any obstructions between the artillery piece and the intended ; impact location.  In order to best represent this in OFP's engine we need to precalculate the ; actual trajectory values and determine if the round, at the defined initial velocities ; (the horizontal and vertical components), would exceed the TTL before the round is to impact. ; It's all about the math.  Since we don't need to be concerned with the actual artillery piece, ; we hand in the 'shell' type defined in the addons cpp file and do the math. ; For the enlightenment of the uninitiated I will put down the base math required and my approach. ; These are the standard trajectory formulas from any decent physics book. ; Vo = initspeed = desired muzzle velocity of the round you want to create (velocities in m/s) ; T = time in seconds ; g = gravity  (I presume to be 9.8m/s^2, though I've never read it in the forums) ; V(horizontal h) = Vo * sin(elevation)   V(vertical v) = Vo * cos(elevation) ; Hmax (maximum height reached) = (2 * Vv^2) / 2g ; Tof (Time of flight) = (2 * Vv) / g ; Vt (vertical velocity at time T) = Vv - (g * T) ; [now for the FUN formula, range.  this is gonna take a little space to make it look good] ;               2 * Vo^2 * sin (2 * elevation) ;    Range (R) =  --------------------------------- ;                        g ; H (height) = Vv * T - (0.5 * g * T^2) ; D (distance) = Vh * T  (no minus anything because gravity doesnt change horizontal velocity) ; So the order of business is to; ; ; A) Calculate Vy and use it to calculate the Tof ; If Tof>19s then just calculate the position on the trajectory at (Tof - 19s) and place ; the round there, give it the right velocity vectors and let it go. ; THIS is the best and still correct method. ;  If Tof<19 then don't do anything.  The reasoning is, this script is ; intended to be used in conjunction with the actual artillery piece.  If the artillery round ; fired by the actual artillery object has a Tof < 19 then let the artillery round do it's ; thing and don't worry about it. Otherwise, create the damn thing somewhere downrange. ; B) Use Tif (Time in flight) = (Tof - 19s), plug it into the first 2 formulas we need to ; solve for; ; D and H (so we know how far away and how high the round should be) ; C) Solve Vh anv Vv (so we know how fast the round should be travelling when it's created) ; Theta and Phi are commonly used as references to angles, I will adhere to this defacto standard. ; Theta will represent the direction angle (x,y) in the horizontal plane. ; Phi will represent the elevation ( adjacent segment [x,y], z) in the vertical plane. ; Theta will determine the [x,y] horizontal location on the map at range D from it's origin. ; position x = (sin(Theta) * D) + (starting point x = from position select 0) ; position y = (cos(Theta) * D) + (starting point y = from position select 1) ; position z = H + (starting point z = vertical offset) ; Phi is used in calculating the initial Vh and Vv, which are then used for the setvelocity vector. ; D) Delay creating the round downrange until Tif has expired. This makes the round arrive at the ; time it would have if the games Ttl were not an issue.  So artillery rounds still take time ; to reach their target and you still have a really good chance of hearing them buzz over your ; head (at least, I hope so. I wrote this intro before coding it as a guideline to myself). ; E) CamCreate[x,y,z] the round at the correct coordinates ; F) SetVelocity[x,y,z] with the right velocity vectors ; G) FINALLY!  let the game engine have it's way with our creation ; H) Shout profanity as you watch your round pummel the target. ; *********************************************************************************** ;  CODE STARTS HERE ; *********************************************************************************** ; frompos the x,y,z position where the round is created ; topos the x,y,z position where we want the round to land ; initvel the muzzle velocity of the round,  This should equal the addons intended initspeed ; so the downrange velocity vectors are correct.  When the round is created I give it ; the setvelocity vector based off of initvel, as it should be. ; elevation the muzzle elevation at source. (this is really fudge-factored, because the round is ; created near the artillery piece, not necessarily at the end of the muzzle) ; vertoffset the vertical offset where the round is created. ; round the type of object to create (something derived from 'shell' would be nice) ; timeoff the amount of time prior to impact you want to create the new round.  If 0, then the ; round is created at the impact point. Remember not to set this higher than 20, because ; at 20+ seconds prior to impact the round will exceed the Ttl live and not impact! ; The other thing is, you probably want to be closer to 18 seconds to impact, that will ; give you a 2 second buffer in case the engine happens to count fast :) _frompos = _this select 0 _topos = _this select 1 _initvel = _this select 2 _Phi = _this select 3 _VertOffset = _this select 4 _round = _this select 5 _TimeOff = _this select 6 ; Get the initial velocity vectors and see if Tof > 19s. ; Theta determines direction, PHI determines elevation ; The magnitude of the first vector is the requested Velocity ; The base of this triangle represents the hypotenus of the direction vector ; so we calculate the Z (verticle axis) first ; ; velOY is the vertical velocity ; velOX is the horizontal velocity  (we use these for Vv and Vh as defined above) _velOY = _initvel * sin(_Phi) _velOX = _initvel * cos(_Phi) ; check the Tof  (again, I am assuming g=9.8) _Tof = (2 * _velOY) / 9.8 papabear sidechat format["Time of flight: %1",_Tof] ; If Tof < _TimeOff seconds then exit, we don't need to do anything. ; If you want to test lower Tof's, just comment it out. ;?(_Tof < _TimeOff):exit ; delay just a short bit to give the real artillery round time to clear the area ~0.1 ; at this point Tof > _TimeOff seconds, so let's get Tif (= Tof - _TimeOff) _Tif = _Tof - _TimeOff ; If you set _Tif = 0 here, the round will start at Time=0 in the trajectory, which will ; start the round at the beginning of it's trajectory.  The round will then travel along it's ; normal trajectory and impact as long as the dreaded Ttl is not exceeded. ; You can set this to any time.  It is the time in flight of the round, so Tif=2 means start ; the round where it would be 2 seconds into it's trajectory.  The tricky thing here, is if ; you are using an extremely shallow elevation and/or very low initial velocity, you could be ; starting the round AFTER it would have impacted.  Be sure you don't! ; Uncomment the line below to do this, mainly for testing. ;_Tif = 4 ; let's figure out the distance the round will have traveled at time Tif and it's altitude (height) ; H (height) = Vv * T - (0.5 * g * T^2) ; D (distance) = Vh * T  (I copied this from above to keep it fresh in your mind) ; For our caculations, _Tif represents time T _Distance = _velOX * _Tif _Height = (_velOY * _Tif) - (0.5 * 9.8 * _Tif^2) ; We now know how far it's traveled and how high it should be.  So we need to know how fast it's ; going in the vertical plane.  Is it climbing or falling at Tif?  Well, let's see, that's ; Vt (velocity at time T) = Vv - (g * T) _velVert = _velOY - (9.8 * _Tif) ; and Vh doesn't change. Well, I don't know what air resistance coefficient OFP uses, so I just ; start the round with the "no air resistance" horizontal velocity, which is the initial ; horizontal velocity _velHor = _velOx ; With all these vector components we can now construct the pre-creation parameters. Namely ; the actual game [x,y,z] arrays. ; First we need to know the direction the round was fired.  We get that by doing simple trig ; using our source position as the origin and the target position as the [x,y] ; break down the position arrays _srcx = _frompos select 0 _srcy = _frompos select 1 _tgtx = _topos select 0 _tgty = _topos select 1 ; some good ol fashion math _diffx = _tgtx - _srcx _diffy = _tgty - _srcy _xsqrd = _diffx ^ 2 _ysqrd = _diffy ^ 2 _RangeToTarget = sqrt(_xsqrd+_ysqrd) ; determine the angle to target as THETA ; THETA = arctan(x/y) for direction _preangle = atan(_diffx/_diffy) ; now which quandrant are we in? ?(_diffy < 0):_Theta=180+_preangle ?(_diffy >= 0):_Theta=360+_preangle ; correct for negative directions and directions over 360 ?(_Theta > 360):_Theta=_Theta-360 ?(_Theta < 0):_Theta=360+_Theta ; _Theta is our direction.  So let's figure out where in the game ([x,y,z]) world it would be. ; I realize I keep changing the reference to height with a simple reassignment, but it's for the ; sake of explaining what, why and how. ; The actual X,Y position is simply the direction * magnitude(_Distance) _preposX = sin(_theta) * _Distance _preposY = cos(_theta) * _Distance ; To get the starting coordinates, we need to add in the starting location of the arty piece ; the round was "started" from. _posX = _srcx + _preposX _posY = _srcy + _preposY _posZ = _Height + _VertOffset ; the full position vector is [_posX,_posY,_posZ] ; We now know where to place the round.  Let's figure out the velocity vectors.  These vectors will ; tell the round how fast to go and in what direction. ; Since we know the magnitudes of both the horizontal and vertical components, we use a little ; more trig to calculate the x,y,z. ; X and Y are in the horizontal plane, so the vector _velHor tells us the magnitude, which is the ; same as the hypotenus. So to get X and Y...... ; Trig hats on = true _velX = sin(_Theta) * _velHor _velY = cos(_Theta) * _velHor ; and the Z component is just _velVert.  This is true because the Z axis is not based off the direction ; our projectile is traveling, it merely tells us if it's climbing or falling. _velZ = _velVert ; the full velocity vector is [_velX,_velY,_velZ] ; Lets wait for Tif before creating the round ~_Tif ; Create the round _op = _round camcreate[_posX,_posY,_posZ] ; Point it in the direction of travel. (Remeber, there is no PITCH command, we can only tell the round ; it's horizontal orientation) _op setdir _Theta ; Start it flying _op setvelocity[_velX,_velY,_velZ] ; Now let the game engine take over, we're done! exit <span id='postcolor'> Works like you expect.  I still have the pressing question of what gravitational constant they use.  Since they do alter the trajectory effectively by a different G value and/or -Vh over time (simulating air resistance).  Guess the BIS guys never gave the final answer to that, at least not in this thread. Hope it's not beating that dead horse too bad.  Was not my intention. Share this post Link to post Share on other sites
Doolittle 0 Posted March 25, 2003 No, you're not beating a dead horse...that's neat what you've done. </span><table border="0" align="center" width="95%" cellpadding="3" cellspacing="1"><tr><td>Code Sample </td></tr><tr><td id="CODE">_shell = "Barrel4" createVehicle [_src select 0, _src select 1, 1] _shell setVelocity [_vx, _vz, _vy] "GrenadeHand" createVehicle _src player sideChat "FIRE" <span id='postcolor'> I ended up writing a little script that fires a barrel...then it makes an explosion when the barrel hits the ground. Â This way, you don't have to worry about a 20 second limit, the barrel lasts forever until you delete it....and most importantly, drag seems not to effect the barrel nearly as much as shells. Â Different objects in the game you use go different distances, like a phone flies further. Â I found the barrel to be the one object which was getting the closest to where I wanted the shell to land. Â In order to negate the air friction problem, I just made a marker on the map that showed where you wanted to hit, & where the "shell" actually hit...this way the human running the script could do their own calculating to hit stuff. Doolittle Share this post Link to post Share on other sites