title: Solving Billiard Shot Impulse Trajectory
body: <p>I'm using bullet to make a pool simulator and need to accurately simulate shots that are humanly possible. To find the impulse to apply to the cue ball I use the locations of the object ball, pocket center and cue ball.</p>
  
  <p><a href="https://i.stack.imgur.com/XFySK.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/XFySK.jpg" alt="Common shot scenario"></a><br>
  <sub>(source: <a href="http://www.poolplayers.com/wp-content/uploads/2013/03/372-TangentLine-2.jpg" rel="nofollow noreferrer">poolplayers.com</a>)</sub>  </p>
  
  <p>In situations where the motion path of the cue ball is similar to the object ball (a hit angle near 180 degrees), everything works fine and the object ball sinks in the pocket. But it seems that the more angular the shot path is, the greater the margin of error is for the impulse I'm generating. I've tried many things to fix this: adjust the ball's collision margin, scaling the world larger, turning off friction and restitution and lots of others but nothing seems to changes this behavior.</p>
  
  <p>Here are the relevant bits of my code:</p>
  
  <pre><code>//assume p = pocket center, b = object ball center, c = cue ball center
  
  //first find the position of the ghost ball, ie the target point of collision for the cue ball
  btVector3 ghostPos = b+(b-p).normalize()*(2.0f*BALL_RADIUS);
  
  //then use the normal between the ghostball and cue ball as the impulse, scaled by the shots total distance
  btVector3 cueImpulse = (ghostPos-c).normalize()*((p.distance(b)+ghostPos.distance(c))*HIT_RATIO);
  
  //finally apply the impulse to the cueball's center of mass (using general form of applyImpulse to later use rel_pos for english
  cueBallBody-&gt;applyImpulse(cueImpulse,btVector3());
  </code></pre>
  
  <p>Hopefully that's enough info. I've been struggling with this bug for a looong time and now this very large project I've been working on for almost two years is contingent on solving this problem! Even if you don't see what's wrong with my code, but have an alternative strategy for finding the impulse - I would LOVE to hear it because I'm afraid I don't have anymore ideas.</p>