OpenMods / OpenBlocks

Random collection of blocks
Other
298 stars 149 forks source link

Item cannon ignores Y pos #686

Closed applejag closed 9 years ago

applejag commented 9 years ago

The item cannons calculation for the cursor is somewhat wrong, it can focus on the pointed block but only in the x and z axis it seems.

If I point at a block at x20 y80 z50 and x20 y120 z50 there's barely any differance.

I looked at the source (link) but I am not that good with math so I don't understand the majority of it :laughing: I guess the HOURS_WASTED_ON_CANNON_LOGIC variable can be incremented :stuck_out_tongue:

No but jokes aside if someone with more experience in trigonometry (or whatever the subject is called) could aid with making the algorithm also consider the Y height difference.

I did find this algorithm (link) made by SethBling (ported by Hellsing on the bukkit forums) and it was made for calculating the velocity of throwing potions at a target. I bet it could be ported to suit the item cannon, and I tried but I don't know what I did wrong because it's so hard to get right (I barley know what I'm doing...).

It would be awesome if someone could do this 'cause it's very annoying to try to get the arc to hit the target as it is right now.

Ty for readin :smiley:

nevercast commented 9 years ago

I originally did a lot of code with this, and I do believe boq and Mikee tweaked and tidied A LOT of it after I stopped working on OpenBlocks.

The cannon has always been a joy of mine in this mod though, so from my dusty bookmark bar I give you this resource.

https://web.archive.org/web/20131228043850/http://morgan-davidson.com/2012/06/19/3d-projectile-trajectory-prediction/

Web Archive used as Morgan Davidson's blog seems to be gone. This is a fantastic article on this exact issue and I tested his examples and they worked perfectly in all cases that the cannon should. I however never had the motivation or the spare time to dedicate a cannon logic rewrite.

This article should be everything you need to know (Provided your math skill is sufficient) to implement a fully fixed cannon. Alternatively anyone else can.

boq commented 9 years ago

Main problem with cannon is that it tries to predict path of real items (i.e. simulated by Minecraft) by shadowing calculations with it's own code. Since both algorithms use Euler (Verlet?) method with rather big time step, numerical errors are significant and two paths (actual and simulated) are different.

It could be solved, if only acting force was gravity - then differential equation of trajectory would be solvable (parabola, with well defined parameters). But there is also air drag, that causes equation to be analytically unsolvable (so no y = f(t) solution is know), so numerical calculations are needed.

Again, I repeat: main problem is not the general algorithm of calculation (which is known), but numerical errors cumulating differently in both calculations. We could easily write better algorithm (mid-point? RKIV?), but that wouldn't predict actual item path.

(Also, with just numerical calculations it's impossible to calculate parameters needed for projectile to reach point, so multiple test simulations are needed).

Anyway, my plan for cannon (which was in my backlog for more than year now): scrap all code, drop air resistance (so we have parabola) and make projectile that follows f(x) path. That way I could have exact solution and give users method to precisely select middle- and endpoint.

PS. Natural expansion of this idea is "magic gun", that follows splines (that would make air tunnels for items possible).

nevercast commented 9 years ago

I'm pretty sure we scrapped air drag to make this solvable. It uses its own item entity in flight that has no drag. Then the item is onGround it unpacks back in to ItemEntity. That's how I remember doing it a year or more ago.

I tried to solve for air resistance but my knowledge was either lacking or the solution was non-convergable. Either way I know at one point we certainly removed air resistance to enable it to be parabolic. However last I checked it disregards height difference as it only solved to when vertical velocity is 0 (top of parabola) and didn't consider change in height. That is where I left it. Any change after then I have not kept up to date with

nevercast commented 9 years ago

One thing you can observe is that it solves the path accurately in all directions (if you look at the simulated line, which does use a large step but is close enough to hit a vacuum hopper). If you target a point with an increased Y value the path will intersect the center of the block at the same Y value as the cannon with good enough accuracy. So its proven that it can solve the parobola somewhat accurately. The path however does not intersect the target block.

boq commented 9 years ago

Maybe there are some bugs in targeting itself. It's old code. Anyway, as long as there are actual numerical simulations (even if it's parabola), it will be mess. With predefined trajectory I can just use simple geometry/algebra to find solution.

EDIT: of course, I have ~30 other items in my backlog and hardly any time to implement one of them.

applejag commented 9 years ago

@nevercast Ok so I looked at the link you gave and tried it in unity and it worked wonderfully :smiley: . Now is the question how do I get it to work with the item cannon?

I am currently coding this in lua using computercraft for easier prototyping, here's the current code:

local cannon = peripheral.find("openblocks_cannon")

-- vars
local from = vector.new(0,0,0)
local to = vector.new(-5,0,-5)
local lob = 2 -- time it takes
local gravity = vector.new(0,0.8 * 0.05,0)

--(( START OF CALCULATION ))--

local function calculateVelocity()
  local physicsTimestep = 1/20
  local timestepsPerSecond = 20

  -- By default we set n so our projectile
  -- will reach our target point in 1 second
  local n = lob * timestepsPerSecond

  local a = gravity * physicsTimestep * physicsTimestep
  local p = to
  local s = from

  local velocity = (s + ((a * (n*n + n)) / 2) - p) * -1/n

  -- This will give use velocity per timestep
  -- The physics engine expects velocity per second
  return velocity / physicsTimestep
end

--(( END OF CALCULATION ))--

-- calc pitch & yaw
local vel = calculateVelocity()
local pitch = math.deg(math.atan2(math.sqrt(vel.z^2+vel.x^2),vel.y))
local yaw = math.deg(math.atan2(vel.z,vel.x))
local speed = lob --vel:length()

cannon.setPitch(pitch) print("pitch="..pitch)
cannon.setYaw(yaw) print("yaw="..yaw)
cannon.setSpeed(speed) print("speed="..speed)

Now it seems to not behave as it should. I am having a hard time calibrating it so it shoots where it's supposed to. Also Idk what value I am supposed to use on the cannon speed. I guess the lob value but maybe it's the magnitude (vel:length) of the vector?

nevercast commented 9 years ago

Speed should be the velocity. It's the m/s speed of the ItemEntity as it leaves the cannon.

nevercast commented 9 years ago

Note: Nor I or boq are likely to implement this, myself because I have other things going on that aren't OpenBlocks, and boq's backlog.

This will require a community PR, which we always encourage.

nevercast commented 9 years ago

This will be completed today.

applejag commented 9 years ago

Yess you're my hero mate =D