<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Pinball Physics</title>
		<link>http://www.allegro.cc/forums/view/588089</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Sat, 21 Oct 2006 22:10:29 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I&#39;m working on a simple Pinball game to help me learn and understand some of the 3d physics. I&#39;m struggling, but progressing.</p><p>What I have now is a ball that can interact with triangles. Adding a radius to the ball wass giving me problems.</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="c">// Vector is a class with 3 double vars and math functions to manipulate.</span></td></tr><tr><td class="number">2</td><td><span class="k1">double</span> Triangle::distance<span class="k2">(</span> Vector <span class="k3">&amp;</span>p <span class="k2">)</span></td></tr><tr><td class="number">3</td><td><span class="k2">{</span></td></tr><tr><td class="number">4</td><td>    <span class="c">// normal is the triangles normal vector</span></td></tr><tr><td class="number">5</td><td>    <span class="k1">return</span> this-&gt;normal.dotProduct<span class="k2">(</span> p <span class="k3">-</span> this-&gt;mid <span class="k2">)</span> <span class="k3">/</span> this-&gt;normal.getLength<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">6</td><td><span class="k2">}</span></td></tr><tr><td class="number">7</td><td>&#160;</td></tr><tr><td class="number">8</td><td><span class="k1">double</span> Triangle::angleBetween<span class="k2">(</span> Vector <span class="k3">&amp;</span>p <span class="k2">)</span></td></tr><tr><td class="number">9</td><td><span class="k2">{</span></td></tr><tr><td class="number">10</td><td>    <span class="k1">return</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_46.html" target="_blank">asin</a><span class="k2">(</span> <span class="k2">(</span> this-&gt;normal.dotProduct<span class="k2">(</span> p <span class="k2">)</span> <span class="k3">/</span> <span class="k2">(</span> this-&gt;normal.getLength<span class="k2">(</span><span class="k2">)</span> <span class="k3">*</span> p.getLength<span class="k2">(</span><span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">11</td><td><span class="k2">}</span></td></tr><tr><td class="number">12</td><td>&#160;</td></tr><tr><td class="number">13</td><td><span class="c">// p is ball pos</span></td></tr><tr><td class="number">14</td><td><span class="c">// v is ball vel</span></td></tr><tr><td class="number">15</td><td><span class="c">// newball is the new position if collision</span></td></tr><tr><td class="number">16</td><td><span class="c">// radius is radius of the ball</span></td></tr><tr><td class="number">17</td><td><span class="k1">bool</span> Triangle::isPossible<span class="k2">(</span> Vector <span class="k3">&amp;</span>p, Vector <span class="k3">&amp;</span>v, Vector <span class="k3">&amp;</span>newball, <span class="k1">double</span> radius <span class="k2">)</span></td></tr><tr><td class="number">18</td><td><span class="k2">{</span></td></tr><tr><td class="number">19</td><td>    <span class="k1">static</span> <span class="k1">double</span> plen<span class="k2">;</span></td></tr><tr><td class="number">20</td><td>    <span class="k1">static</span> <span class="k1">double</span> len<span class="k2">;</span></td></tr><tr><td class="number">21</td><td>    <span class="k1">static</span> Vector vhat<span class="k2">;</span></td></tr><tr><td class="number">22</td><td>    <span class="k1">static</span> Vector pv<span class="k2">;</span></td></tr><tr><td class="number">23</td><td>    </td></tr><tr><td class="number">24</td><td>    <span class="c">// current position plus velocity</span></td></tr><tr><td class="number">25</td><td>    <span class="c">// this will be the new position if there wasn't a hit</span></td></tr><tr><td class="number">26</td><td>    pv <span class="k3">=</span> p <span class="k3">+</span> v<span class="k2">;</span></td></tr><tr><td class="number">27</td><td>&#160;</td></tr><tr><td class="number">28</td><td>    <span class="c">// unit of velocity</span></td></tr><tr><td class="number">29</td><td>    vhat <span class="k3">=</span> v.normalize<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">30</td><td>&#160;</td></tr><tr><td class="number">31</td><td>    <span class="c">// VZERO 1e-9</span></td></tr><tr><td class="number">32</td><td>    <span class="k1">if</span> <span class="k2">(</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span> this-&gt;normal.dotProduct<span class="k2">(</span> vhat <span class="k2">)</span> <span class="k2">)</span> <span class="k3">&lt;</span><span class="k3">=</span> VZERO <span class="k2">)</span></td></tr><tr><td class="number">33</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">34</td><td>        <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">35</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">36</td><td>&#160;</td></tr><tr><td class="number">37</td><td>    <span class="c">// length of ball from plane</span></td></tr><tr><td class="number">38</td><td>    plen <span class="k3">=</span> this-&gt;distance<span class="k2">(</span> p <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">39</td><td>&#160;</td></tr><tr><td class="number">40</td><td>    <span class="c">// length of new position from plane</span></td></tr><tr><td class="number">41</td><td>    len <span class="k3">=</span> this-&gt;distance<span class="k2">(</span> pv <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">42</td><td>&#160;</td></tr><tr><td class="number">43</td><td>    <span class="k1">if</span> <span class="k2">(</span> plen <span class="k3">&gt;</span><span class="k3">=</span> radius <span class="k3">&amp;</span><span class="k3">&amp;</span> len <span class="k3">&lt;</span> radius <span class="k2">)</span></td></tr><tr><td class="number">44</td><td>    <span class="k2">{</span> </td></tr><tr><td class="number">45</td><td>        newball <span class="k3">=</span> pv <span class="k3">-</span> <span class="k2">(</span> vhat <span class="k3">*</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span> <span class="k2">(</span> radius <span class="k3">-</span> len <span class="k2">)</span> <span class="k3">/</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_728.html" target="_blank">sin</a><span class="k2">(</span> this-&gt;angleBetween<span class="k2">(</span> <span class="k3">-</span>v <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">46</td><td>&#160;</td></tr><tr><td class="number">47</td><td>        <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">48</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">49</td><td>&#160;</td></tr><tr><td class="number">50</td><td>    <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">51</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

This code gives me the correct position of where the ball will hit the plane. And the new velocity is calculated as such. 
</p><div class="source-code snippet"><div class="inner"><pre><span class="c">// d is the magnitude of the new velocity</span>
<span class="c">// if vel magnitude was 20 but we only moved 15 </span>
<span class="c">// then the new magnitude is of length 5</span>
this-&gt;vel <span class="k3">=</span> <span class="k2">(</span> <span class="k2">(</span> tri-&gt;normal <span class="k3">*</span>
                tri-&gt;normal.dotProduct<span class="k2">(</span> <span class="k3">-</span>this-&gt;vel <span class="k2">)</span> <span class="k3">*</span>
                <span class="n">2</span>.<span class="n">0</span> <span class="k2">)</span> <span class="k3">+</span>
              this-&gt;vel <span class="k2">)</span>.normalize<span class="k2">(</span><span class="k2">)</span> <span class="k3">*</span> d<span class="k2">;</span>
</pre></div></div><p>

There is a slight problem in that if the ball is just on the edges of 2 joined triangles then it will pass thru sometimes.</p><p>Also what I need now is a good tutorial on &#39;rolling ball physics&#39; (I can&#39;t seem to find any good ones). </p><p>And some ides on how to incorporate friction, gravity, ...</p><p>Any help would be great.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Wed, 18 Oct 2006 07:36:56 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I don&#39;t know of any rolling ball physics tutorials, but google might find you something.  </p><p><span class="source-code">newball <span class="k3">=</span> pv <span class="k3">-</span> <span class="k2">(</span> vhat <span class="k3">*</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span> <span class="k2">(</span> radius <span class="k3">-</span> len <span class="k2">)</span> <span class="k3">/</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_728.html" target="_blank">sin</a><span class="k2">(</span> this-&gt;angleBetween<span class="k2">(</span> <span class="k3">-</span>v <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></span><br />Um... what exactly is that doing?  Shouldn&#39;t the new ball position just be:<br /><span class="source-code">newball <span class="k3">=</span> pv <span class="k3">+</span> this-&gt;normal <span class="k3">*</span> <span class="n">2</span>.<span class="n">0</span> <span class="k3">*</span> <span class="k2">(</span>radius <span class="k3">-</span> len<span class="k2">)</span><span class="k2">;</span><span class="c">//assumes normal is a unit vector</span></span><br />Based upon the theory that, after the ball hit the surface, it bounced, and the distance it bounced is equal to how far it would have gone through the surface if it hadn&#39;t bounced?  (note that the 2.0 in there should be the same as the 2.0 in your velocity calculation... if elasticity changes, both numbers should change)<br />edit: Just saw this:</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
This code gives me the correct position of where the ball will hit the plane. And the new velocity is calculated as such.
</p></div></div><p>
When modified for finding the point of collision, I end up with something like this:</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">float</span> tick_fraction <span class="k3">=</span> <span class="n">1</span> <span class="k3">-</span> <span class="k2">(</span>len-radius<span class="k2">)</span> <span class="k3">/</span> <span class="k2">(</span>plen-len<span class="k2">)</span><span class="k2">;</span><span class="c">//time before collision</span>
newball <span class="k3">=</span> p <span class="k3">+</span> tick_fraction <span class="k3">*</span> v<span class="k2">;</span><span class="c">//position at that time</span>
</pre></div></div><p>


Friction... any time there&#39;s an impact, you want to get a velocity portion normal to the polygon and a velocity portion in-plane (perpendicular to the normal) of the polygon... and the friction applies a force the ball in the opposite direction of the in-plane velocity component, proportional to... I&#39;m not precisely sure, probably proportional to the in-plane velocity and some kind of surface parameter.  Once you add friction though, you&#39;ll also need to add spin, because the friction force is applied at the point of contact in a direction not pointing towards the center of the ball, so spin is imparted.  And once there&#39;s spin, you calculate friction for motion due to spin also... at that point, the in-plane velocity is the sum of the regular in-plane velocity and the portion due to spin, which, if I were to guess of the top of my head, might be cross product of the normal vector with the axi of spin, multiplied by the magnitude of the spin and the radius.  Don&#39;t quote me on that, I probably got it wrong.  Also, you might want some kind of threshold between static friction and dynamic friction.  </p><p>Gravity seems fairly straightforward, just add it to the velocity vector every tick.  Though you might need some kind of weird optimizations for dealing with continuous rolling contact with a surface once gravity is in.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
There is a slight problem in that if the ball is just on the edges of 2 joined triangles then it will pass thru sometimes.
</p></div></div><p>
Um... I don&#39;t see any code that deals with triangles really, what I see mostly looks like it deals with infinite planes.  Maybe you have code for discarding infinite-plane collisions where the contact point isn&#39;t on triangle, and you&#39;re not showing that code here?  If so, your problem could be that you&#39;re not accounting for collision that occur when the edge of the ball touches one of the triangle edges, such that the ball penetrates the infinite plane before it touches the triangle.  For that you&#39;d need to have something for colliding a line with a sphere, which doesn&#39;t sound too hard (equivalent to a cylinder with a point, after all), and maybe also something to deal with collisions with the corners of the triangle.  If that&#39;s not your issue, maybe you have rounding problems, dunno.  </p><p>Also, is Triangle::normal normalized?  If not, why?  If so, why divide by it&#39;s length in Triangle::distance?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Wed, 18 Oct 2006 10:28:54 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Shouldn&#39;t the new ball position just be:<br />newball = pv + this-&gt;normal * 2.0 * (radius - len);
</p></div></div><p>

No, it wouldn&#39;t.</p><p>Look at bottom left of picture: </p><p> <br /><span class="remote-thumbnail"><span class="json">{"name":"590331","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/3\/f396971a547a904313dbab2a7284106d.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/3\/f396971a547a904313dbab2a7284106d"}</span><img src="http://www.allegro.cc//djungxnpq2nug.cloudfront.net/image/cache/f/3/f396971a547a904313dbab2a7284106d-240.jpg" alt="590331" width="240" height="180" /></span></p><p>R is radius<br />L is len<br />P1 is p + v and is too close to plane<br />P2 is where it needs to be</p><p>D0 != ( R - L )</p><p>Using trig: sin( angle ) = y / h;</p><p>or h = y / sin( angle )<br />or D0 = ( R - L ) / sin( angle )</p><div class="source-code snippet"><div class="inner"><pre>newlength <span class="k3">=</span> <span class="k2">(</span> <span class="k2">(</span> radius <span class="k3">-</span> len <span class="k2">)</span> <span class="k3">/</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_728.html" target="_blank">sin</a><span class="k2">(</span> this-&gt;angleBetween<span class="k2">(</span> <span class="k3">-</span>v <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span>
newball <span class="k3">=</span> pv <span class="k3">-</span> <span class="k2">(</span> vhat <span class="k3">*</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span> newlength <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>

Yes, &#39;isPossible&#39; deals with infinite planes.<br />Here is the code for the collision of the triangle.
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">bool</span> Triangle::collision<span class="k2">(</span> Vector <span class="k3">&amp;</span>p, Vector <span class="k3">&amp;</span>v, Vector <span class="k3">&amp;</span>newball, <span class="k1">double</span> radius <span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    <span class="k1">static</span> <span class="k1">int</span> vv<span class="k2">[</span> <span class="n">3</span> <span class="k2">]</span><span class="k2">[</span> <span class="n">2</span> <span class="k2">]</span> <span class="k3">=</span> </td></tr><tr><td class="number">4</td><td>    <span class="k2">{</span> </td></tr><tr><td class="number">5</td><td>        <span class="k2">{</span> <span class="n">1</span>, <span class="n">2</span> <span class="k2">}</span>,</td></tr><tr><td class="number">6</td><td>        <span class="k2">{</span> <span class="n">2</span>, <span class="n">0</span> <span class="k2">}</span>,</td></tr><tr><td class="number">7</td><td>        <span class="k2">{</span> <span class="n">0</span>, <span class="n">1</span> <span class="k2">}</span></td></tr><tr><td class="number">8</td><td>    <span class="k2">}</span><span class="k2">;</span></td></tr><tr><td class="number">9</td><td>    <span class="k1">static</span> Vector v1<span class="k2">;</span></td></tr><tr><td class="number">10</td><td>    <span class="k1">static</span> Vector v2<span class="k2">;</span></td></tr><tr><td class="number">11</td><td>&#160;</td></tr><tr><td class="number">12</td><td>    <span class="c">// does the ball hit the triangle's plane</span></td></tr><tr><td class="number">13</td><td>    <span class="k1">if</span> <span class="k2">(</span> this-&gt;isPossible<span class="k2">(</span> p, v, newball, radius <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">14</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">15</td><td>        <span class="c">// this tells if the spot it hit is outside the triangle</span></td></tr><tr><td class="number">16</td><td>        <span class="k1">for</span> <span class="k2">(</span> <span class="k1">int</span> i <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span> i <span class="k3">&lt;</span> <span class="n">3</span><span class="k2">;</span> i<span class="k3">+</span><span class="k3">+</span> <span class="k2">)</span></td></tr><tr><td class="number">17</td><td>        <span class="k2">{</span></td></tr><tr><td class="number">18</td><td>            v1 <span class="k3">=</span> this-&gt;vector<span class="k2">[</span> vv<span class="k2">[</span> i <span class="k2">]</span><span class="k2">[</span> <span class="n">0</span> <span class="k2">]</span> <span class="k2">]</span> <span class="k3">-</span> newball<span class="k2">;</span></td></tr><tr><td class="number">19</td><td>            v2 <span class="k3">=</span> this-&gt;vector<span class="k2">[</span> vv<span class="k2">[</span> i <span class="k2">]</span><span class="k2">[</span> <span class="n">1</span> <span class="k2">]</span> <span class="k2">]</span> <span class="k3">-</span> newball<span class="k2">;</span></td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td>            <span class="k1">if</span> <span class="k2">(</span> this-&gt;normal.dotProduct<span class="k2">(</span> v1.crossProduct<span class="k2">(</span> v2 <span class="k2">)</span> <span class="k2">)</span> <span class="k3">&lt;</span> <span class="k3">-</span>VZERO <span class="k2">)</span></td></tr><tr><td class="number">22</td><td>            <span class="k2">{</span></td></tr><tr><td class="number">23</td><td>                <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">24</td><td>            <span class="k2">}</span></td></tr><tr><td class="number">25</td><td>        <span class="k2">}</span></td></tr><tr><td class="number">26</td><td>&#160;</td></tr><tr><td class="number">27</td><td>        <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">28</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">29</td><td>&#160;</td></tr><tr><td class="number">30</td><td>    <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">31</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Wed, 18 Oct 2006 19:37:25 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Hm... I stand by my original equations.  </p><p>In your diagram, I&#39;m interpretting the following:<br />P0 = position at time 0<br />P1 = position at time 1 if collision is ignored<br />P2 = position at time T, when the collision occurs (0 &lt;= T &lt; 1)<br />P3 = position at time 1, with collision taken into account</p><p>The initial formula I gave<br />pv + this-&gt;normal * 2.0 * (radius - len);<br />is for P3</p><p>The formula I added a few minutes after then:<br />float tick_fraction = 1 - (len-radius) / (plen-len);<br />newball = p + tick_fraction * v;//position at that time<br />is for P2 (and also T)</p><p>Hm... actually, on closer look, I believe that your formula yields the same results as my second formula.  I got confused with the trig there.  I still think my formula is superior, as it is faster and uses no trig <img src="http://www.allegro.cc/forums/smileys/smiley.gif" alt=":)" /></p><p>edit:<br />(added extra excuse above) (revised excuse)<br />Also, that additional code confirms that the problem is that you aren&#39;t handling collisions with the edges, and thus you should have balls passing through polygon boundaries on convex surfaces (though not concave ones).  You need to add a second check, to see if the ball hits any of the edges.  <br />edit2:<br />For an example, consider this 2 dimensional case:<br />Your ball is at (0,2) at time 0.  Its velocity is (0,-5).  There is a line segment begining at (sqrt(2)/2,0) and extending rightwards to (5,0).  The ball has radius 1.  Your algorithm finds that it hit the infinite line at point (0,0), but that that lies outside of the line segment, because the X coordinate, 0, is less than the line segments lowest X coordinate, which is sqrt(2)/2, and ignores the collision with the infinite line.  However, at time 0.2+0.2*sqrt(2)/2, the ball hits the edge of the line segment and deflects such that its new velocity should be... um... it would take me a bit to calculate that (edit3: new velocity is (-5,0)).  But, it does deflect at that time.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Wed, 18 Oct 2006 20:23:10 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I still think my formula is superior, as it is faster and uses no trig
</p></div></div><p>
You would think it, but it&#39;s not. Mainly because I&#39;m not worried about P3. The ball needs to be placed at P2. You can&#39;t just put the ball at P3 after a collision because there might be another collision inbetween P2 and P3. </p><p>_move is called recursively until the magnitude of velocity is zero.
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">void</span> Ball::_move<span class="k2">(</span><span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    <span class="k1">int</span> i <span class="k3">=</span> <span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">4</td><td>    <span class="k1">bool</span> hit <span class="k3">=</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">5</td><td>    Vector newPos<span class="k2">;</span></td></tr><tr><td class="number">6</td><td>&#160;</td></tr><tr><td class="number">7</td><td>    <span class="k1">for</span> <span class="k2">(</span> std::list<span class="k3">&lt;</span>Triangle&gt;::iterator it <span class="k3">=</span> triList.tlist.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> it <span class="k3">!</span><span class="k3">=</span> triList.tlist.end<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> it<span class="k3">+</span><span class="k3">+</span> <span class="k2">)</span></td></tr><tr><td class="number">8</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">9</td><td>        Triangle <span class="k3">*</span>t <span class="k3">=</span> <span class="k3">&amp;</span><span class="k2">(</span><span class="k3">*</span>it<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td>&#160;</td></tr><tr><td class="number">11</td><td>        <span class="k1">if</span> <span class="k2">(</span> <a href="http://www.allegro.cc/manual/key" target="_blank"><span class="a">key</span></a><span class="k2">[</span> KEY_ESC <span class="k2">]</span> <span class="k2">)</span> <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">12</td><td>&#160;</td></tr><tr><td class="number">13</td><td>        hit <span class="k3">=</span> t-&gt;collision<span class="k2">(</span> this-&gt;pos,</td></tr><tr><td class="number">14</td><td>                            this-&gt;vel,</td></tr><tr><td class="number">15</td><td>                            newPos,</td></tr><tr><td class="number">16</td><td>                            this-&gt;radius <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">17</td><td>&#160;</td></tr><tr><td class="number">18</td><td>        <span class="k1">if</span> <span class="k2">(</span> hit <span class="k2">)</span></td></tr><tr><td class="number">19</td><td>        <span class="k2">{</span></td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td>            <span class="k1">double</span> d <span class="k3">=</span> <span class="k2">(</span> this-&gt;vel.getLength<span class="k2">(</span><span class="k2">)</span> <span class="k3">-</span></td></tr><tr><td class="number">22</td><td>                         <span class="k2">(</span> this-&gt;pos <span class="k3">-</span> newPos <span class="k2">)</span>.getLength<span class="k2">(</span><span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">23</td><td>&#160;</td></tr><tr><td class="number">24</td><td>            this-&gt;pos <span class="k3">=</span> newPos<span class="k2">;</span></td></tr><tr><td class="number">25</td><td>&#160;</td></tr><tr><td class="number">26</td><td>            <span class="k1">if</span> <span class="k2">(</span> d <span class="k3">&lt;</span><span class="k3">=</span> VZERO <span class="k2">)</span></td></tr><tr><td class="number">27</td><td>            <span class="k2">{</span></td></tr><tr><td class="number">28</td><td>                this-&gt;vel.zero<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">29</td><td>            <span class="k2">}</span></td></tr><tr><td class="number">30</td><td>            <span class="k1">else</span></td></tr><tr><td class="number">31</td><td>            <span class="k2">{</span></td></tr><tr><td class="number">32</td><td>                this-&gt;vel <span class="k3">=</span> <span class="k2">(</span> <span class="k2">(</span> t-&gt;normal <span class="k3">*</span></td></tr><tr><td class="number">33</td><td>                                t-&gt;normal.dotProduct<span class="k2">(</span> <span class="k3">-</span>this-&gt;vel <span class="k2">)</span> <span class="k3">*</span></td></tr><tr><td class="number">34</td><td>                                <span class="n">2</span>.<span class="n">0</span> <span class="k2">)</span> <span class="k3">+</span></td></tr><tr><td class="number">35</td><td>                              this-&gt;vel <span class="k2">)</span>.normalize<span class="k2">(</span><span class="k2">)</span> <span class="k3">*</span> d<span class="k2">;</span></td></tr><tr><td class="number">36</td><td>                this-&gt;_move<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">37</td><td>            <span class="k2">}</span></td></tr><tr><td class="number">38</td><td>&#160;</td></tr><tr><td class="number">39</td><td>            <span class="k1">return</span><span class="k2">;</span></td></tr><tr><td class="number">40</td><td>        <span class="k2">}</span></td></tr><tr><td class="number">41</td><td>&#160;</td></tr><tr><td class="number">42</td><td>        i<span class="k3">+</span><span class="k3">+</span><span class="k2">;</span></td></tr><tr><td class="number">43</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">44</td><td>&#160;</td></tr><tr><td class="number">45</td><td>    this-&gt;pos <span class="k3">+</span><span class="k3">=</span> this-&gt;vel<span class="k2">;</span></td></tr><tr><td class="number">46</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You need to add a second check, to see if the ball hits any of the edges.
</p></div></div><p>
That&#39;s what I&#39;m not sure about.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Wed, 18 Oct 2006 21:07:32 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
You would think it, but it&#39;s not. Mainly because I&#39;m not worried about P3. The ball needs to be placed at P2. You can&#39;t just put the ball at P3 after a collision because there might be another collision inbetween P2 and P3.
</p></div></div><p>
You still seem to be ignoring my formula for P2 and T, which, as I mentioned, is faster and yields the same results.  But that&#39;s okay.  Some games do put the ball at P3 (or the rough equivalent) for speed or simplicity (or possibly even stability) reasons, but I guess that&#39;s not what you want.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
_move is called recursively until the magnitude of velocity is zero.
</p></div></div><p>
Minor stylistic points: what you called &quot;velocity&quot; in your code is what I would call a &quot;delta&quot; or &quot;movement&quot;.   I would have the functions return the time passed before collision rather than calculate that from the distance moved.  </p><p>Hm... actually... more importantly, the way you have that set up, I think it can pass through one triangle <b>before</b> hitting another, if the triangle it should have hit came later in the list than another triangle further along the path, thus skipping a collision.  I think you need to test against all possible triangles, find which one has the lowest time, apply that collision, then repeat.  Like this:</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="c">//returns true on a collision</span></td></tr><tr><td class="number">2</td><td><span class="c">//sets t to time until collision</span></td></tr><tr><td class="number">3</td><td><span class="c">//sets normal to the normal vector of the collision (which is a unit vector)</span></td></tr><tr><td class="number">4</td><td><span class="k1">bool</span> check_collision<span class="k2">(</span><span class="k1">const</span> Ball <span class="k3">&amp;</span>b, <span class="k1">const</span> Triangle <span class="k3">&amp;</span>t, Vector <span class="k3">&amp;</span>normal, <span class="k1">double</span> <span class="k3">&amp;</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">5</td><td>&#160;</td></tr><tr><td class="number">6</td><td><span class="k1">bool</span> find_earliest_collision<span class="k2">(</span><span class="k1">const</span> Ball <span class="k3">&amp;</span>b, <span class="k1">const</span> std::list<span class="k3">&lt;</span>Triangle&gt; triangles, Vector <span class="k3">&amp;</span>normal, <span class="k1">double</span> <span class="k3">&amp;</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a>, std::list<span class="k3">&lt;</span>Triangle&gt;::iterator which_tri<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">7</td><td>  <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="k3">=</span> <span class="n">9999999</span><span class="k2">;</span><span class="c">//number bigger than 1 (the maximum time), don't care beyond that</span></td></tr><tr><td class="number">8</td><td>  <span class="k1">double</span> current_t<span class="k2">;</span></td></tr><tr><td class="number">9</td><td>  Vector current_normal<span class="k2">;</span></td></tr><tr><td class="number">10</td><td>  <span class="k1">for</span> <span class="k2">(</span>it <span class="k3">=</span> triangles.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> it <span class="k3">!</span><span class="k3">=</span> triangles.end<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> it<span class="k3">+</span><span class="k3">+</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">11</td><td>    Vector normal<span class="k2">;</span></td></tr><tr><td class="number">12</td><td>    <span class="k1">double</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">13</td><td>    <span class="k1">if</span> <span class="k2">(</span>check_collision<span class="k2">(</span>b, <span class="k3">*</span>it, current_normal, current_t<span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">14</td><td>      <span class="k1">if</span> <span class="k2">(</span>current_t <span class="k3">&lt;</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="k3">&amp;</span><span class="k3">&amp;</span> current_t <span class="k3">&gt;</span> VZERO<span class="k2">)</span> <span class="k2">{</span><span class="c">//edit fixed var name</span></td></tr><tr><td class="number">15</td><td>        <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="k3">=</span> current_t<span class="k2">;</span></td></tr><tr><td class="number">16</td><td>        normal <span class="k3">=</span> current_normal<span class="k2">;</span></td></tr><tr><td class="number">17</td><td>        which_tri <span class="k3">=</span> it<span class="k2">;</span></td></tr><tr><td class="number">18</td><td>      <span class="k2">}</span></td></tr><tr><td class="number">19</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">20</td><td>  <span class="k2">}</span></td></tr><tr><td class="number">21</td><td>  <span class="k1">if</span> <span class="k2">(</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="k3">&lt;</span><span class="k3">=</span> <span class="n">1</span><span class="k2">)</span> <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">22</td><td>  <span class="k1">else</span> <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span><span class="c">//edit: added else condition</span></td></tr><tr><td class="number">23</td><td><span class="k2">}</span></td></tr><tr><td class="number">24</td><td>&#160;</td></tr><tr><td class="number">25</td><td><span class="k1">void</span> calculate_tick<span class="k2">(</span>Ball <span class="k3">&amp;</span>b, std::list<span class="k3">&lt;</span>Triangle&gt; triangles<span class="k2">)</span> <span class="k2">{</span><span class="c">//single time unit</span></td></tr><tr><td class="number">26</td><td>  <span class="k1">double</span> time_remaining <span class="k3">=</span> <span class="n">1</span><span class="k2">;</span></td></tr><tr><td class="number">27</td><td>  <span class="k1">double</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">28</td><td>  Vector Normal<span class="k2">;</span></td></tr><tr><td class="number">29</td><td>  std::list<span class="k3">&lt;</span>Triangle&gt;::iterator it<span class="k2">;</span></td></tr><tr><td class="number">30</td><td>  <span class="k1">while</span> <span class="k2">(</span>find_earliest_collision<span class="k2">(</span>b, <span class="k3">*</span>it, normal, delta_t, it<span class="k2">)</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">31</td><td>    <span class="k1">if</span> <span class="k2">(</span>delta_t <span class="k3">&lt;</span><span class="k3">=</span> time_remaining<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">32</td><td>      b.pos <span class="k3">+</span><span class="k3">=</span> b.vel <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">33</td><td>      b.vel <span class="k3">+</span><span class="k3">=</span> gravity <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">34</td><td>      b.vel <span class="k3">+</span><span class="k3">=</span> normal <span class="k3">*</span> <a href="http://www.allegro.cc/manual/dot_product" target="_blank"><span class="a">dot_product</span></a><span class="k2">(</span>b.vel, normal<span class="k2">)</span> <span class="k3">*</span> <span class="k2">(</span><span class="n">1</span> <span class="k3">+</span> it-&gt;elasticity<span class="k2">)</span><span class="k2">;</span><span class="c">//made up elasticity as a use for the triangle iterator</span></td></tr><tr><td class="number">35</td><td>      time_remaining <span class="k3">-</span><span class="k3">=</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">36</td><td><span class="c">//edit: removed line that accidentally cut&amp;pasted in from another version of this function</span></td></tr><tr><td class="number">37</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">38</td><td>  <span class="k2">}</span></td></tr><tr><td class="number">39</td><td>  b.pos <span class="k3">+</span><span class="k3">=</span> time_remaining <span class="k3">*</span> b.vel<span class="k2">;</span></td></tr><tr><td class="number">40</td><td>  b.vel <span class="k3">+</span><span class="k3">=</span> time_remaining <span class="k3">*</span> gravity<span class="k2">;</span></td></tr><tr><td class="number">41</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

My earlier statement that all you needed for gravity was to add the gravity vector to the velocity vector every tick was based upon the assumption that you didn&#39;t need more accuracy than the typical game.  If you want total accuracy w/ gravity, then you have to resolve you collision equations assuming a parabolic movement path (nasty!).  The above code attempts to make a compromise for decent gravity.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
That&#39;s what I&#39;m not sure about.
</p></div></div><p>
Which part?  I mean, are you unsure you need to add it, or are you unsure on sphere-line collision detection, or unsure on sphere-line velocity / angle calculations, or thinking there might be a better way, or what?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Wed, 18 Oct 2006 23:16:25 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Ok, I really appreciate your help. You gave me something to think about with that shortest time idea.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Minor stylistic points: what you called &quot;velocity&quot; in your code is what I would call a &quot;delta&quot; or &quot;movement&quot;
</p></div></div><p>
<a href="http://en.wikipedia.org/wiki/Velocity">Velocity</a> can also be defined as rate of change of displacement or just as the rate of displacement, depending on how the term displacement is used.</p><p>I don&#39;t want to upset you but I still think you have the wrong formula for P2.  
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="c">//Let's try some numbers:</span></td></tr><tr><td class="number">2</td><td>v <span class="k3">=</span> <span class="k2">(</span> <span class="n">17</span>.<span class="n">32</span>, <span class="n">10</span>.<span class="n">0</span>, <span class="n">0</span>.<span class="n">0</span> <span class="k2">)</span><span class="k2">:</span> v.len <span class="k3">=</span> <span class="n">20</span></td></tr><tr><td class="number">3</td><td>vhat <span class="k3">=</span> <span class="k2">(</span> <span class="n">0</span>.<span class="n">866</span>, <span class="n">0</span>.<span class="n">5</span>, <span class="n">0</span> <span class="k2">)</span> <span class="k2">:</span> vhat.len <span class="k3">=</span> <span class="n">1</span></td></tr><tr><td class="number">4</td><td>angle <span class="k3">=</span> <span class="n">30</span> <span class="c">// angle between</span></td></tr><tr><td class="number">5</td><td>radius <span class="k3">=</span> <span class="n">5</span></td></tr><tr><td class="number">6</td><td>len <span class="k3">=</span> <span class="n">2</span></td></tr><tr><td class="number">7</td><td>plen <span class="k3">=</span> <span class="n">22</span></td></tr><tr><td class="number">8</td><td>&#160;</td></tr><tr><td class="number">9</td><td><span class="k1">float</span> tick_fraction   <span class="k3">=</span> <span class="n">1</span> <span class="k3">-</span> <span class="k2">(</span>len-radius<span class="k2">)</span> <span class="k3">/</span> <span class="k2">(</span>plen-len<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td><span class="c">//float tick_fraction = 1 - (2-5) / (22-2) = 1.15</span></td></tr><tr><td class="number">11</td><td>&#160;</td></tr><tr><td class="number">12</td><td><span class="c">// newball = p + tick_fraction * v;</span></td></tr><tr><td class="number">13</td><td>vector v1 <span class="k3">=</span> tick_fraction <span class="k3">*</span> v<span class="k2">;</span></td></tr><tr><td class="number">14</td><td><span class="c">//     v1 = ( 1.15 * v ) = ( 19.92, 11.5, 0.0 ) : .len = 23.00</span></td></tr><tr><td class="number">15</td><td>newball <span class="k3">=</span> p <span class="k3">+</span> v1<span class="k2">;</span> <span class="k2">(</span>overshot<span class="k2">)</span></td></tr><tr><td class="number">16</td><td>&#160;</td></tr><tr><td class="number">17</td><td>&#160;</td></tr><tr><td class="number">18</td><td><span class="k1">double</span> d <span class="k3">=</span> <span class="k2">(</span> radius <span class="k3">-</span> len <span class="k2">)</span> <span class="k3">/</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_728.html" target="_blank">sin</a><span class="k2">(</span> this-&gt;angleBetween<span class="k2">(</span> <span class="k3">-</span>v <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">19</td><td><span class="c">//       = ( 5 - 2 ) / ( .5 ) = 6 </span></td></tr><tr><td class="number">20</td><td>&#160;</td></tr><tr><td class="number">21</td><td>vector v1 <span class="k3">=</span> v <span class="k3">-</span> <span class="k2">(</span> vhat <span class="k3">*</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span> d <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">22</td><td><span class="c">//        = ( 17.32, 10.00, 0.0 ) - ( 0.866, 0.5, 0 ) * 6 </span></td></tr><tr><td class="number">23</td><td><span class="c">//        = ( 12.124, 7.0, 0.0 ): .len = 14</span></td></tr><tr><td class="number">24</td><td>newball <span class="k3">=</span> p <span class="k3">+</span> v1<span class="k2">;</span></td></tr></tbody></table></div></div><p>

I did realize that my sin function will only work on planes perp to z. I need to work on that.</p><p>And I&#39;m unsure about the calculations. I don&#39;t know how to check for a collision against an edge.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Thu, 19 Oct 2006 05:55:40 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Ok, I really appreciate your help. You gave me something to think about with that shortest time idea.
</p></div></div><p>
Since you&#39;re trying (I think) to correctly handle arbitrary numbers of collisions per ball per tick, what I would call &quot;continuous time physics&quot;, I think that, or something like it, is essential.   </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Velocity [en.wikipedia.org] can also be defined as rate of change of displacement or just as the rate of displacement, depending on how the term displacement is used.
</p></div></div><p>
The issue I have is that the quantity you refer to as velocity, you then... break down, ablate, in such a manner that it&#39;s not really &quot;per unit of time&quot; anymore.  Just semantics, but something I shy away from for fear of getting confused.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I don&#39;t want to upset you but I still think you have the wrong formula for P2.
</p></div></div><p>
You&#39;re not likely to upset me.  <br />Hm... oops, sign error: for P2, I meant (radius-len) rather than (len-radius); tick_fraction is supposed to be between 0 and 1, the ratio of movement prior to penetration of the infinite plane to total movement, using only the portion in direction of the normal vector in order to simplify calculations.  At which point, the numbers are, (5 radius - 2 plen = 3 penetration in the direction of the normal vector) / (10 len - 2 plen = 8 movement in the direction of the normal vector), is 3/8, substracted from 1 is 5/8, 0.625, or 62.5% of the movement done prior to the collision.  Multiplied by the movement delta, yields (10.825,6.25,0), magnitude 12.5.  </p><p>Your formula looked at the penetration distance in the direction of the normal vector, ( radius - len ), and divided by the sin of the angle to convert to absolute distance, and multiplied by the direction vector, and ended up with (12.124, 7.0, 0), magnitude 14.  </p><p>Even with the sign error corrected, the two formula disagreed on the example numbers?  Why?  Because the example numbers are not internally consistent.  I believe you meant them to correspond to an example in which the plane is flat on the X-Z plane (ie in form Y = some constant), and the ball is vertically 10 units from the plane.  That example yeilds the angle you gave, and the plen you gave, but the len value should be zero in that case, not 2.  There is no possible plane &amp; position corresponding to that angle and len and plen and velocity.  If the value of len is corrected to 0, then both of our equations yield the same result: (8.66, 5.0, 0) : magnitude 10.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
And I&#39;m unsure about the calculations. I don&#39;t know how to check for a collision against an edge.
</p></div></div><p>
The math isn&#39;t pretty, and optimizing it may be quite difficult, but the basics are, I think, easier than the stuff you already have working.  It&#39;ll take me a bit to come up with some equations/code, I&#39;ll edit this post later to add some, or add another post if you&#39;ve replied.  <br />edit: Bleh.  I <b>thought</b> it was easier that the other stuff, but I haven&#39;t found an easy way to do it.  I started algebriacally, found it too messy, tried a little calc, decided I didn&#39;t know what I was doing, and finally resorted to using trig to transform the problem to two dimensions, then to one dimension, and finally in one dimension I can solve it.  I have a solution written up, but there&#39;s got to be an easier, simpler, faster way.  And it&#39;s still written up as a mixture of english, equations, and code, nothing consistent or readable.  Maybe you or someone else on this forum can come up with a simpler faster way, but this is what I have atm so:
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td>start with:</td></tr><tr><td class="number">2</td><td>&#160;</td></tr><tr><td class="number">3</td><td>line: <span class="n">2</span> endpoints, E1 <span class="k1">and</span> E2</td></tr><tr><td class="number">4</td><td>ball path: position <span class="k2">(</span>B<span class="k2">)</span> <span class="k1">and</span> velocity <span class="k2">(</span>V<span class="k2">)</span> <span class="k1">and</span> radius <span class="k2">(</span>R<span class="k2">)</span></td></tr><tr><td class="number">5</td><td>E1,E2,B, <span class="k1">and</span> V are <span class="n">3d</span> vectors, R is a scalar</td></tr><tr><td class="number">6</td><td>&#160;</td></tr><tr><td class="number">7</td><td><span class="n">2</span> dimensionalify it: <span class="k2">(</span>is that a word?<span class="k2">)</span></td></tr><tr><td class="number">8</td><td>&#160;</td></tr><tr><td class="number">9</td><td>pick an axi to eliminate... say, the Z axi</td></tr><tr><td class="number">10</td><td>you need to rotate the <a href="http://www.allegro.cc/manual/line" target="_blank"><span class="a">line</span></a> segment so that it falls on to the Z axi</td></tr><tr><td class="number">11</td><td><span class="k2">(</span>assuming that it doesn<span class="s">'t already - you should check that first)</span></td></tr><tr><td class="number">12</td><td><span class="s">in order to simplify, lets subtract E1 from B now, so that ball position is take the line delta D = E2 - E1</span></td></tr><tr><td class="number">13</td><td><span class="s">relative to it</span></td></tr><tr><td class="number">14</td><td><span class="s">cross product that with the Z axi to find an axi perp. to both</span></td></tr><tr><td class="number">15</td><td><span class="s">rotate everything around the resulting cross product by the angle between the Z axi and the line delta</span></td></tr><tr><td class="number">16</td><td><span class="s">now the line delta should align with the Z axi</span></td></tr><tr><td class="number">17</td><td><span class="s">so, you can now forget everything about the Z axi, and treat the problem as 2d</span></td></tr><tr><td class="number">18</td><td><span class="s">the endpoints are now identical on the X-Y plane</span></td></tr><tr><td class="number">19</td><td><span class="s">your velocity, projected into 2d, is now slower, etc</span></td></tr><tr><td class="number">20</td><td><span class="s">(make sure your velocity is still non-zero, otherwise no collision is possible)</span></td></tr><tr><td class="number">21</td><td><span class="s"></span></td></tr><tr><td class="number">22</td><td><span class="s">so now you have, in addition to the old stuff:</span></td></tr><tr><td class="number">23</td><td><span class="s"></span></td></tr><tr><td class="number">24</td><td><span class="s">D = E2 - E1</span></td></tr><tr><td class="number">25</td><td><span class="s">E'</span> <span class="k3">=</span> <span class="k2">(</span><span class="n">0</span>,<span class="n">0</span><span class="k2">)</span></td></tr><tr><td class="number">26</td><td>rotation_axi <span class="k3">=</span> <a href="http://www.allegro.cc/manual/cross_product" target="_blank"><span class="a">cross_product</span></a><span class="k2">(</span>D, Z_axi<span class="k2">)</span></td></tr><tr><td class="number">27</td><td>rotation_amount <span class="k3">=</span> <span class="k3">-</span>angle_between<span class="k2">(</span>D, Z_axi<span class="k2">)</span></td></tr><tr><td class="number">28</td><td><span class="c">//vector3 rotate3d( vector3 vect, vector3 axi, double radians );</span></td></tr><tr><td class="number">29</td><td><span class="c">//vector::vector2(const vector3 &amp;vect) : x(vect.x), y(vect.y) {}</span></td></tr><tr><td class="number">30</td><td>B<span class="s">' = vector2(rotate(B - E1, rotation_axi, rotation_amount));</span></td></tr><tr><td class="number">31</td><td><span class="s">V'</span> <span class="k3">=</span> vector2<span class="k2">(</span>rotate<span class="k2">(</span>V, rotation_axi, rotation_amount<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">32</td><td>Evertying with a <span class="s">' in the name is a 2d vector.  </span></td></tr><tr><td class="number">33</td><td><span class="s"></span></td></tr><tr><td class="number">34</td><td><span class="s">1 dimensionalify it: (is that a word?)</span></td></tr><tr><td class="number">35</td><td><span class="s"></span></td></tr><tr><td class="number">36</td><td><span class="s">rotate your coordinate system until the balls motion is on the X axi, straight right</span></td></tr><tr><td class="number">37</td><td><span class="s"></span></td></tr><tr><td class="number">38</td><td><span class="s">so no you have:</span></td></tr><tr><td class="number">39</td><td><span class="s"></span></td></tr><tr><td class="number">40</td><td><span class="s">//vector2 rotate2d( vector2 vect, double radians );</span></td></tr><tr><td class="number">41</td><td><span class="s">B'</span><span class="s">' = rotate2d( B'</span>, <span class="k3">-</span><a href="http://www.delorie.com/djgpp/doc/libc/libc_50.html" target="_blank">atan2</a><span class="k2">(</span>V<span class="s">'.y, V'</span>.x<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">42</td><td>V<span class="s">''</span> <span class="k3">=</span> magnitude<span class="k2">(</span>V<span class="s">') (a scalar now)</span></td></tr><tr><td class="number">43</td><td><span class="s"></span></td></tr><tr><td class="number">44</td><td><span class="s">solve for collision:</span></td></tr><tr><td class="number">45</td><td><span class="s"></span></td></tr><tr><td class="number">46</td><td><span class="s">at the collision time, the distance from the ball to origin (what used to be the infinite line) is equal to the balls radius.  </span></td></tr><tr><td class="number">47</td><td><span class="s">so... x^2 + y^2 = r^2... y is B'</span><span class="s">'.y, r is R, solve for x</span></td></tr><tr><td class="number">48</td><td><span class="s">x = +/- sqrt(R*r - B'</span><span class="s">'.y * B'</span><span class="s">'.y);</span></td></tr><tr><td class="number">49</td><td><span class="s">if the quantity in the sqrt is negative, no collision is possible</span></td></tr><tr><td class="number">50</td><td><span class="s">otherwise, use only the positive square root (or 0) for the X coordinate of the ball at the time of collision</span></td></tr><tr><td class="number">51</td><td><span class="s">edit: no wait, use the negative square root, not the positive... er... I think...</span></td></tr><tr><td class="number">52</td><td><span class="s">X'</span><span class="s">' = -sqrt(R*r - B'</span><span class="s">'.y * B'</span><span class="s">'.y);</span></td></tr><tr><td class="number">53</td><td><span class="s">now you need to make this useful, not just an X coordinate in some bizarre transformed space.  applying the reverse transformations doesn'</span>t appeal to me much.  so... find how <span class="k1">long</span> it took <span class="k1">for</span> the ball to travel to that point, by dividin the transformed distance by the transformed speed</td></tr><tr><td class="number">54</td><td>&#160;</td></tr><tr><td class="number">55</td><td>now you have:</td></tr><tr><td class="number">56</td><td>&#160;</td></tr><tr><td class="number">57</td><td>T <span class="k3">=</span> <span class="k2">(</span>X<span class="s">''</span> <span class="k3">-</span> B<span class="s">''</span>.x<span class="k2">)</span> <span class="k3">/</span> V<span class="s">''</span> <span class="k2">(</span>T is a scalar <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a><span class="k2">)</span></td></tr><tr><td class="number">58</td><td>&#160;</td></tr><tr><td class="number">59</td><td>back to working with untransformed coordinates:</td></tr><tr><td class="number">60</td><td>&#160;</td></tr><tr><td class="number">61</td><td>E <span class="k3">=</span> either E1 <span class="k1">or</span> E2, don<span class="s">'t care which</span></td></tr><tr><td class="number">62</td><td><span class="s">remember that D = E2 - E1</span></td></tr><tr><td class="number">63</td><td><span class="s">remember that B is the untransformed original position of the Ball</span></td></tr><tr><td class="number">64</td><td><span class="s">and V is the untransformed original velocity of the Ball</span></td></tr><tr><td class="number">65</td><td><span class="s">find an "origin" for the line, O = E - D * (E . D)</span></td></tr><tr><td class="number">66</td><td><span class="s">the center of the Ball at collision time, C = B + V * T</span></td></tr><tr><td class="number">67</td><td><span class="s">the point of intersection I = O + D * (C . D)</span></td></tr><tr><td class="number">68</td><td><span class="s">and it falls onto the segment if and only if </span></td></tr><tr><td class="number">69</td><td><span class="s">  (C . D) falls between (E1 . D) and (E2 . D)</span></td></tr><tr><td class="number">70</td><td><span class="s">the normal vector of the collision N = (B - I) / R</span></td></tr><tr><td class="number">71</td><td><span class="s"></span></td></tr><tr><td class="number">72</td><td><span class="s">my implimentation of rotate3d:</span></td></tr><tr><td class="number">73</td><td><span class="s">Vector3 rotate ( Vector3 vector, Vector3 axi, Angle angle ) {</span></td></tr><tr><td class="number">74</td><td><span class="s">  if (angle == 0) return vector;</span></td></tr><tr><td class="number">75</td><td><span class="s"></span></td></tr><tr><td class="number">76</td><td><span class="s">  double tmpd = magnitude_sqr(axi);</span></td></tr><tr><td class="number">77</td><td><span class="s">  if (tmpd != 1) axi /= std::sqrt(tmpd);</span></td></tr><tr><td class="number">78</td><td><span class="s">  //axi = unit_vector(axi);</span></td></tr><tr><td class="number">79</td><td><span class="s">  double co = dot_product(vector, axi);</span></td></tr><tr><td class="number">80</td><td><span class="s">  vector -= co * axi;</span></td></tr><tr><td class="number">81</td><td><span class="s">  double m = magnitude(vector);</span></td></tr><tr><td class="number">82</td><td><span class="s">  double zero = dot_product(vector, axi);</span></td></tr><tr><td class="number">83</td><td><span class="s">  Vector3 y = cross_product ( vector, axi );</span></td></tr><tr><td class="number">84</td><td><span class="s">  Vector3 n = vector * cos(angle) + y * sin(angle);</span></td></tr><tr><td class="number">85</td><td><span class="s">  vector = n + co * axi;</span></td></tr><tr><td class="number">86</td><td><span class="s">  return vector;</span></td></tr><tr><td class="number">87</td><td><span class="s">}</span></td></tr><tr><td class="number">88</td><td><span class="s"></span></td></tr><tr><td class="number">89</td><td><span class="s"></span></td></tr><tr><td class="number">90</td><td><span class="s"></span></td></tr><tr><td class="number">91</td><td><span class="s"></span></td></tr><tr><td class="number">92</td><td><span class="s">optimization: a semi-fast discard method for maybe half the lines and verticies</span></td></tr><tr><td class="number">93</td><td><span class="s">(not good optimization, but it'</span>s a start<span class="k2">)</span></td></tr><tr><td class="number">94</td><td>&#160;</td></tr><tr><td class="number">95</td><td><span class="k1">for</span> the <a href="http://www.allegro.cc/manual/line" target="_blank"><span class="a">line</span></a> segments: you can<span class="s">'t hit a line segment from the side of it that the</span></td></tr><tr><td class="number">96</td><td><span class="s">  triangle is on. so...</span></td></tr><tr><td class="number">97</td><td><span class="s">take the cross product of the normal vector and the line vector to get a </span></td></tr><tr><td class="number">98</td><td><span class="s">  vector perp to both. point outward from the triangle edge</span></td></tr><tr><td class="number">99</td><td><span class="s">subtract one of the line endpoints from the ball center to get a relative position</span></td></tr><tr><td class="number">100</td><td><span class="s">take the dot product of the relative position and the outward vector</span></td></tr><tr><td class="number">101</td><td><span class="s">if the result is negative, no collision is possible </span></td></tr><tr><td class="number">102</td><td><span class="s">  without passing through the triangle first</span></td></tr><tr><td class="number">103</td><td><span class="s">and if a collision with that edge is possible, then a collision with the opposite vertex</span></td></tr><tr><td class="number">104</td><td><span class="s">  is not possible</span></td></tr></tbody></table></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Thu, 19 Oct 2006 11:50:17 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
And I&#39;m unsure about the calculations. I don&#39;t know how to check for a collision against an edge.
</p></div></div><p>Let sphere pos = P; edge endpoints = E1 &amp; E2.  Then this should work (in pseudocode):
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">bool</span> checkCol<span class="k2">(</span>P, E1, E2<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">2</td><td>   toedge1 <span class="k3">=</span> P-E1<span class="k2">;</span></td></tr><tr><td class="number">3</td><td>   toedge2 <span class="k3">=</span> P-E2<span class="k2">;</span></td></tr><tr><td class="number">4</td><td>   <span class="k1">if</span> <span class="k2">(</span><a href="http://www.allegro.cc/manual/dot_product" target="_blank"><span class="a">dot_product</span></a><span class="k2">(</span>toedge1, toedge1<span class="k2">)</span> <span class="k3">&lt;</span> radius<span class="k3">*</span>radius <span class="k3">|</span><span class="k3">|</span> <a href="http://www.allegro.cc/manual/dot_product" target="_blank"><span class="a">dot_product</span></a><span class="k2">(</span>toedge2, toedge2<span class="k2">)</span> <span class="k3">&lt;</span> radius<span class="k3">*</span>radius<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">5</td><td>      <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span> <span class="c">// sphere collides with edge endpoints</span></td></tr><tr><td class="number">6</td><td>   <span class="k2">}</span> </td></tr><tr><td class="number">7</td><td>   edgevec <span class="k3">=</span> E2-E1<span class="k2">;</span></td></tr><tr><td class="number">8</td><td>   edgelen <span class="k3">=</span> mag<span class="k2">(</span>edgevec<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">9</td><td>   edgedir <span class="k3">=</span> edgevec <span class="k3">/</span> edgelen<span class="k2">;</span></td></tr><tr><td class="number">10</td><td>   proj_dist <span class="k3">=</span> <a href="http://www.allegro.cc/manual/dot_product" target="_blank"><span class="a">dot_product</span></a><span class="k2">(</span>edgedir, toedge2<span class="k2">)</span><span class="k2">;</span> <span class="c">// project to_sphere along edge</span></td></tr><tr><td class="number">11</td><td>   <span class="k1">if</span> <span class="k2">(</span>proj_dist <span class="k3">&lt;</span> <span class="n">0</span><span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">12</td><td>      <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">13</td><td>   <span class="k2">}</span></td></tr><tr><td class="number">14</td><td>   <span class="k1">if</span> <span class="k2">(</span>proj_dist <span class="k3">&gt;</span> edgelen<span class="k2">)</span> <span class="k2">{</span></td></tr><tr><td class="number">15</td><td>      <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">16</td><td>   <span class="k2">}</span></td></tr><tr><td class="number">17</td><td>   P_onE <span class="k3">=</span> E1 <span class="k3">+</span> proj_dist <span class="k3">*</span> edgedir<span class="k2">;</span></td></tr><tr><td class="number">18</td><td>   distToLine <span class="k3">=</span> mag<span class="k2">(</span>P-P_onE<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>   <span class="k1">if</span> <span class="k2">(</span>distToLine <span class="k3">&lt;</span> radius<span class="k2">)</span></td></tr><tr><td class="number">20</td><td>      <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">21</td><td>   <span class="k1">else</span></td></tr><tr><td class="number">22</td><td>      <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">23</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>
I think it should work, anyway.  Rush-typed from memory.  I&#39;m late to class!
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Zaphos)</author>
		<pubDate>Thu, 19 Oct 2006 17:55:06 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
I think it should work, anyway. Rush-typed from memory. I&#39;m late to class!
</p></div></div><p>
Yeah, it looks about right, but he&#39;s looking for a continuous time solution, not a single-point-in-time solution.  Or at least, his sphere-plane solution was using continuous time.  Perhaps once he realizes how nasty continuous time solutions can be he&#39;ll switch over to a discrete-time method or some hybrid.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Thu, 19 Oct 2006 18:15:14 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Thanks guys. I&#39;ll try that edge detection code.
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
but he&#39;s looking for a continuous time solution, not a single-point-in-time solution.
</p></div></div><p>
continuous-time? discrete-time? I don&#39;t understand. I am looking for single point in time solution.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Even with the sign error corrected, the two formula disagreed on the example numbers? Why? Because the example numbers are not internally consistent. I believe you meant them to correspond to an example in which the plane is flat on the X-Z plane (ie in form Y = some constant), and the ball is vertically 10 units from the plane. That example yeilds the angle you gave, and the plen you gave, but the len value should be zero in that case, not 2. There is no possible plane &amp; position corresponding to that angle and len and plen and velocity. If the value of len is corrected to 0, then both of our equations yield the same result: (8.66, 5.0, 0) : magnitude 10.
</p></div></div><p>


I messed up on the numbers sorry. After sitting there and coming up with some real numbers you are right. I just didn&#39;t see it until I did the math.</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td>P0 <span class="k3">=</span> position at <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="n">0</span></td></tr><tr><td class="number">2</td><td>P1 <span class="k3">=</span> position at <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="n">1</span> <span class="k1">if</span> collision is ignored</td></tr><tr><td class="number">3</td><td>P2 <span class="k3">=</span> position at <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> T, when the collision occurs <span class="k2">(</span><span class="n">0</span> <span class="k3">&lt;</span><span class="k3">=</span> T <span class="k3">&lt;</span> <span class="n">1</span><span class="k2">)</span></td></tr><tr><td class="number">4</td><td>P3 <span class="k3">=</span> position at <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a> <span class="n">1</span>, with collision taken into account</td></tr><tr><td class="number">5</td><td>&#160;</td></tr><tr><td class="number">6</td><td>With these numbers it will cross the horizontal <a href="http://www.allegro.cc/manual/triangle" target="_blank"><span class="a">triangle</span></a> plane at <span class="k2">(</span> <span class="n">0</span>, <span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span> </td></tr><tr><td class="number">7</td><td>&#160;</td></tr><tr><td class="number">8</td><td>v <span class="k3">=</span> <span class="k2">(</span> <span class="k3">-</span><span class="n">17</span>.<span class="n">32</span>, <span class="k3">-</span><span class="n">10</span>.<span class="n">0</span>, <span class="n">0</span>.<span class="n">0</span> <span class="k2">)</span><span class="k2">:</span> v.len <span class="k3">=</span> <span class="n">20</span></td></tr><tr><td class="number">9</td><td>vhat <span class="k3">=</span> <span class="k2">(</span> <span class="k3">-</span><span class="n">0</span>.<span class="n">866</span>, <span class="k3">-</span><span class="n">0</span>.<span class="n">5</span>, <span class="n">0</span>.<span class="n">0</span> <span class="k2">)</span><span class="k2">:</span> vhat.len <span class="k3">=</span> <span class="n">1</span></td></tr><tr><td class="number">10</td><td>angle <span class="k3">=</span> <span class="n">30</span> <span class="c">// angle between</span></td></tr><tr><td class="number">11</td><td>&#160;</td></tr><tr><td class="number">12</td><td>P0 <span class="k3">=</span> <span class="k2">(</span> <span class="n">20</span>.<span class="n">78</span>, <span class="n">12</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span> <span class="c">// distance of 12.0 (plen)</span></td></tr><tr><td class="number">13</td><td>P1 <span class="k3">=</span> <span class="k2">(</span>  <span class="n">3</span>.<span class="n">46</span>,  <span class="n">2</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">}</span> <span class="c">// distance of 2.0 (len)</span></td></tr><tr><td class="number">14</td><td>P2 <span class="k3">=</span> <span class="k2">(</span> <span class="n">8</span>.<span class="n">656</span>,  <span class="n">5</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span> <span class="c">// distance of 5 (radius)</span></td></tr><tr><td class="number">15</td><td>P3 <span class="k3">=</span> <span class="k2">(</span>  <span class="n">3</span>.<span class="n">46</span>,  <span class="n">8</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span></td></tr><tr><td class="number">16</td><td>&#160;</td></tr><tr><td class="number">17</td><td><span class="k1">float</span> tick_fraction <span class="k3">=</span> <span class="n">1</span><span class="k3">-</span><span class="k2">(</span>radius-len<span class="k2">)</span><span class="k3">/</span><span class="k2">(</span>plen-len<span class="k2">)</span> </td></tr><tr><td class="number">18</td><td>                    <span class="k3">=</span> <span class="n">1</span><span class="k3">-</span><span class="k2">(</span><span class="n">5</span><span class="k3">-</span><span class="n">2</span><span class="k2">)</span><span class="k3">/</span><span class="k2">(</span><span class="n">12</span><span class="k3">-</span><span class="n">2</span><span class="k2">)</span> <span class="k3">=</span> <span class="n">0</span>.<span class="n">7</span></td></tr><tr><td class="number">19</td><td>&#160;</td></tr><tr><td class="number">20</td><td>newball <span class="k3">=</span> p <span class="k3">+</span> tick_fraction <span class="k3">*</span> v</td></tr><tr><td class="number">21</td><td>        <span class="k3">=</span> <span class="k2">(</span> <span class="n">20</span>.<span class="n">78</span>, <span class="n">12</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span> <span class="k3">+</span> <span class="k2">(</span><span class="n">0</span>.<span class="n">7</span><span class="k2">)</span><span class="k3">*</span><span class="k2">(</span> <span class="k3">-</span><span class="n">17</span>.<span class="n">32</span>, <span class="k3">-</span><span class="n">10</span>.<span class="n">0</span>, <span class="n">0</span>.<span class="n">0</span> <span class="k2">)</span> </td></tr><tr><td class="number">22</td><td>        <span class="k3">=</span> <span class="k2">(</span> <span class="n">8</span>.<span class="n">656</span>,  <span class="n">5</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span></td></tr><tr><td class="number">23</td><td>&#160;</td></tr><tr><td class="number">24</td><td>&#160;</td></tr><tr><td class="number">25</td><td>newlength <span class="k3">=</span> <span class="k2">(</span> <span class="k2">(</span> radius <span class="k3">-</span> len <span class="k2">)</span> <span class="k3">/</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_728.html" target="_blank">sin</a><span class="k2">(</span> this-&gt;angleBetween<span class="k2">(</span> <span class="k3">-</span>v <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">26</td><td>          <span class="k3">=</span> <span class="k2">(</span> <span class="k2">(</span> <span class="n">5</span> <span class="k3">-</span> <span class="n">2</span> <span class="k2">)</span> <span class="k3">/</span> .<span class="n">5</span> <span class="k3">=</span> <span class="n">6</span></td></tr><tr><td class="number">27</td><td>&#160;</td></tr><tr><td class="number">28</td><td>newball <span class="k3">=</span> p <span class="k3">+</span> v <span class="k3">-</span> <span class="k2">(</span> vhat <span class="k3">*</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_303.html" target="_blank">fabs</a><span class="k2">(</span> newlength <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">29</td><td>        <span class="k3">=</span> <span class="k2">(</span> <span class="n">20</span>.<span class="n">78</span>, <span class="n">12</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span> <span class="k3">+</span> <span class="k2">(</span> <span class="k3">-</span><span class="n">17</span>.<span class="n">32</span>, <span class="k3">-</span><span class="n">10</span>.<span class="n">0</span>, <span class="n">0</span>.<span class="n">0</span> <span class="k2">)</span> <span class="k3">-</span> <span class="k2">(</span> <span class="k2">(</span> <span class="k3">-</span><span class="n">0</span>.<span class="n">866</span>, <span class="k3">-</span><span class="n">0</span>.<span class="n">5</span>, <span class="n">0</span>.<span class="n">0</span> <span class="k2">)</span> <span class="k3">*</span> <span class="n">6</span> <span class="k2">)</span> </td></tr><tr><td class="number">30</td><td>        <span class="k3">=</span> <span class="k2">(</span> <span class="n">8</span>.<span class="n">656</span>,  <span class="n">5</span>.<span class="n">0</span>, <span class="n">0</span> <span class="k2">)</span></td></tr></tbody></table></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Thu, 19 Oct 2006 18:42:31 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Discrete Time Physics vs Continuous Time Physics</p><p>In the simplest case of game programming, time is broken into fixed-size slices, movement equations are handled via Eulers method, and collisions are detected in a manner independant of velocities.  In short, details smaller than the time slice size just aren&#39;t worried about.  Precision is inversely proportional to the size of the timeslice (called &quot;delta_t&quot; in this example).  
</p><div class="source-code snippet"><div class="inner"><pre><span class="c">//typical discrete time aproximations</span>
Vector old_position <span class="k3">=</span> position<span class="k2">;</span>
position <span class="k3">+</span><span class="k3">=</span> velocity <span class="k3">*</span> delta_t<span class="k2">;</span>
velocity <span class="k3">+</span><span class="k3">=</span> acceleration <span class="k3">*</span> delta_t<span class="k2">;</span>
Obj <span class="k3">*</span>obj <span class="k3">=</span> find_collision<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
<span class="k1">if</span> <span class="k2">(</span>obj<span class="k2">)</span> <span class="k2">{</span>
  position <span class="k3">=</span> old_position<span class="k2">;</span>
  handle_collision<span class="k2">(</span>obj<span class="k2">)</span><span class="k2">;</span>
<span class="k2">}</span>
</pre></div></div><p>
The function find_collision in the above sample might not even look at the objects velocity, merely position and shape.  In some implementations, like the one above, when an object overlaps with another, it is simply moved to its previous position to prevent the overlap.  In other implementations, the overlap may be allowed, permiting the bounce mechanics to seperate them on the next tick.  Other implementations might use a limited continuous time solution in which the handling of collisions was exact so long as each object collided with no more than one other object per tick, or might search for a non-overlapping position, either by a binary search along the initial trajectory, by a random search along the new trajectory or old trajectory, or some other thing.  In some implementations small fast moving objects accidentally pass through narrow objecst somtimes.  Well, there&#39;s a lot of variations, most of which improve accuracy in some circumstances, but the key point is that precision of most of the mechanics is limited by a time slice size.  </p><p>edit: The sort of math specific to discrete time stuff is the sort of math that might be covered in a class called &quot;Numerical Methods&quot;.  Solutions found (aproximated) by discrete time methods would usually not be acceptable in, say, a physics class.  </p><p>In a continuous time simulation, on the other hand, precision (at least of the continuous time portions) is independant of the time slice size, and usually attempts to follow exact solutions rather than aproximations.  Collision detection functions always use the velocities, and the resulting formulas can be extremely complicated if anything more than the simplest primitives are involved.  Continuous time solutions are generally more complicated and more difficult to optimize.  They tend to be slower for complex systems, but can be faster for simple systems.  </p><p>Why did I think you were trying for continuous time physics?  Your plane-sphere collision function works on continuous time at least for single-sphere-plane-pairs (ie you detected collisions not merely at a single point in time, but at any time within a specified range of time), and used an exact solution independant of time slice size.  You didn&#39;t like putting the ball at the endpoint of the bounce in case it hit something else within the same time slice (which would have made it dependant upon tick length).  Your collision checking loop restarted itself when a collision was found.  The system you were looking at seemed fairly simple - only the ball had a velocity, and it was perfectly symmetric, and it only collided with one kind of shape.  All things that are pretty much required in continuous time solutions, and, while sometimes used in discrete time simulations, not particularly widespread so far as I know.  </p><p>Anyway, if you aren&#39;t looking for continous time solutions, disregard most of the code I&#39;ve posted; the loop that made sure that collisions were handled in the physically correct order and sphere-line collision function were both intended for continuous-time calculations, and needlessly complicated and slow for the average game.  Though, even in that code, gravity was aproximated discretely due to the excesive complexity of doing it exactly.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Thu, 19 Oct 2006 19:45:16 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I think I understand better. I would rather have discrete. </p><p>EDIT:<br />Everthing seems to be working but a couple of problems. I attached an exe. </p><p>Assume 0 at bottom of screen</p><p>1. If I drop the ball at 100 when it hits the ground it should come back to 100, but it&#39;s going past 100 to approx 105. The next bounce ...</p><p>The velocity(delta) is increasing
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">while</span><span class="k2">(</span> <span class="k2">(</span> tri <span class="k3">=</span> this-&gt;findEarliestCollision<span class="k2">(</span> ball, delta_t <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    <span class="k1">if</span> <span class="k2">(</span> <a href="http://www.allegro.cc/manual/key" target="_blank"><span class="a">key</span></a><span class="k2">[</span> KEY_ESC <span class="k2">]</span> <span class="k2">)</span> <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">4</td><td>&#160;</td></tr><tr><td class="number">5</td><td>    <span class="k1">if</span> <span class="k2">(</span> delta_t <span class="k3">&lt;</span><span class="k3">=</span> time_remaining <span class="k2">)</span> </td></tr><tr><td class="number">6</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">7</td><td>        ball.pos <span class="k3">+</span><span class="k3">=</span> ball.vel <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">8</td><td>        ball.vel <span class="k3">+</span><span class="k3">=</span> gravity <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">9</td><td>&#160;</td></tr><tr><td class="number">10</td><td>        ball.vel <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> tri-&gt;normal <span class="k3">*</span> </td></tr><tr><td class="number">11</td><td>                        tri-&gt;normal.dotProduct<span class="k2">(</span> <span class="k3">-</span>ball.vel <span class="k2">)</span> <span class="k3">*</span> </td></tr><tr><td class="number">12</td><td>                        <span class="n">2</span>.<span class="n">0</span> <span class="k3">*</span> </td></tr><tr><td class="number">13</td><td>                        <span class="k2">(</span> <span class="n">1</span>.<span class="n">0</span> <span class="k3">+</span> tri-&gt;elasticity <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">14</td><td>&#160;</td></tr><tr><td class="number">15</td><td>        time_remaining <span class="k3">-</span><span class="k3">=</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">16</td><td>&#160;</td></tr><tr><td class="number">17</td><td>        tsel <span class="k3">=</span> tri<span class="k2">;</span></td></tr><tr><td class="number">18</td><td>        hit <span class="k3">=</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">20</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

2. I&#39;m having trouble with the edges. Here is that pseudo code turned into code.
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">bool</span> Triangle::checkEdge<span class="k2">(</span> <span class="k1">const</span> Ball <span class="k3">&amp;</span>ball, <span class="k1">const</span> Vector <span class="k3">&amp;</span>edge1, <span class="k1">const</span> Vector edge2 <span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    Vector toEdge1 <span class="k3">=</span> ball.pos <span class="k3">-</span> edge1<span class="k2">;</span></td></tr><tr><td class="number">4</td><td>    Vector toEdge2 <span class="k3">=</span> ball.pos <span class="k3">-</span> edge2<span class="k2">;</span></td></tr><tr><td class="number">5</td><td>&#160;</td></tr><tr><td class="number">6</td><td>    <span class="k1">if</span> <span class="k2">(</span> toEdge1.getSquaredLength<span class="k2">(</span><span class="k2">)</span> <span class="k3">&lt;</span> <span class="k2">(</span> ball.radius <span class="k3">*</span> ball.radius <span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span></td></tr><tr><td class="number">7</td><td>         toEdge2.getSquaredLength<span class="k2">(</span><span class="k2">)</span> <span class="k3">&lt;</span> <span class="k2">(</span> ball.radius <span class="k3">*</span> ball.radius <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">8</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">9</td><td>        <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td>    <span class="k2">}</span> </td></tr><tr><td class="number">11</td><td>&#160;</td></tr><tr><td class="number">12</td><td>    Vector edge <span class="k3">=</span> edge2 <span class="k3">-</span> edge1<span class="k2">;</span></td></tr><tr><td class="number">13</td><td>    <span class="k1">double</span> elen <span class="k3">=</span> edge.getLength<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">14</td><td>    Vector edir <span class="k3">=</span> edge <span class="k3">/</span> elen<span class="k2">;</span></td></tr><tr><td class="number">15</td><td>&#160;</td></tr><tr><td class="number">16</td><td>&#160;</td></tr><tr><td class="number">17</td><td>    <span class="k1">double</span> pdist <span class="k3">=</span> edir.dotProduct<span class="k2">(</span> toEdge2 <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">18</td><td>&#160;</td></tr><tr><td class="number">19</td><td>    <span class="k1">if</span> <span class="k2">(</span> pdist <span class="k3">&lt;</span> <span class="n">0</span>.<span class="n">0</span> <span class="k3">|</span><span class="k3">|</span></td></tr><tr><td class="number">20</td><td>         pdist <span class="k3">&gt;</span> elen <span class="k2">)</span> </td></tr><tr><td class="number">21</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">22</td><td>        <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">23</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">24</td><td>&#160;</td></tr><tr><td class="number">25</td><td>   Vector P_onE <span class="k3">=</span> edge1 <span class="k3">+</span> edir <span class="k3">*</span> pdist<span class="k2">;</span></td></tr><tr><td class="number">26</td><td>   <span class="k1">double</span> distToLine <span class="k3">=</span> <span class="k2">(</span> ball.pos <span class="k3">-</span> P_onE <span class="k2">)</span>.getLength<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">27</td><td>   </td></tr><tr><td class="number">28</td><td>   <span class="k1">return</span> <span class="k2">(</span> distToLine <span class="k3">&lt;</span> ball.radius <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">29</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Fri, 20 Oct 2006 18:42:29 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Didn&#39;t notice the edit for a while, thought the thread was dead.  </p><p>Comments:<br />1.  More code is always helps.  Well, usually.  I&#39;ve already gotten into trouble making assumptions/guesses about the nature of code not posted here.  <br />2.  You have a &quot;2.0 * (1.0 + tri-&gt;elasticity)&quot;.  That should probably be either &quot;2.0&quot; or &quot;(1.0 + tri-&gt;elasticity)&quot;, but not the product of the two, as the total is supposed to work out a number between 1.0 (totally inelastic) and 2.0 (perfectly elastic).  However, that probably shouldn&#39;t cause your problem, as it should produce a very different result if tri-&gt;elasticity was anything more than 0.1 or so, and no problem if tri-&gt;elasticity is 0.  If tri-&gt;elasticity was 0.01, that would produce the gradual speedup, though.  <br />3.  In the case of a collision with a corner, the normal vector is not equal to the normal vector of the triangle, but instead the normal vector of the line from the corner to the center of the ball.  But, that shouldn&#39;t cause any of your problems, I think.  Just in case, you might put in a check on a corner collision to discard it if the dot product of the balls velocity and the triangles normal vector is positive.  <br />4.  In your checkEdge(), try changing <br /><span class="source-code"><span class="k1">double</span> pdist <span class="k3">=</span> edir.dotProduct<span class="k2">(</span> toEdge2 <span class="k2">)</span><span class="k2">;</span></span>to<span class="source-code"><span class="k1">double</span> pdist <span class="k3">=</span> edir.dotProduct<span class="k2">(</span> toEdge1 <span class="k2">)</span><span class="k2">;</span></span></p><p>edit: hm... for the slow speedup, try this:
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">while</span><span class="k2">(</span> <span class="k2">(</span> tri <span class="k3">=</span> this-&gt;findEarliestCollision<span class="k2">(</span> ball, delta_t <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    <span class="k1">if</span> <span class="k2">(</span> <a href="http://www.allegro.cc/manual/key" target="_blank"><span class="a">key</span></a><span class="k2">[</span> KEY_ESC <span class="k2">]</span> <span class="k2">)</span> <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">4</td><td>&#160;</td></tr><tr><td class="number">5</td><td>    <span class="k1">if</span> <span class="k2">(</span> delta_t <span class="k3">&lt;</span><span class="k3">=</span> time_remaining <span class="k2">)</span> </td></tr><tr><td class="number">6</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">7</td><td>        ball.pos <span class="k3">+</span><span class="k3">=</span> ball.vel <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">8</td><td>        ball.vel <span class="k3">+</span><span class="k3">=</span> gravity <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">9</td><td>&#160;</td></tr><tr><td class="number">10</td><td>        ball.vel <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> tri-&gt;normal <span class="k3">*</span> </td></tr><tr><td class="number">11</td><td>                        tri-&gt;normal.dotProduct<span class="k2">(</span> <span class="k3">-</span>ball.vel <span class="k2">)</span> <span class="k3">*</span> </td></tr><tr><td class="number">12</td><td>                        <span class="n">2</span>.<span class="n">0</span> <span class="k3">*</span> </td></tr><tr><td class="number">13</td><td>                        <span class="k2">(</span> <span class="n">1</span>.<span class="n">0</span> <span class="k3">+</span> tri-&gt;elasticity <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">14</td><td>&#160;</td></tr><tr><td class="number">15</td><td>        time_remaining <span class="k3">-</span><span class="k3">=</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">16</td><td>&#160;</td></tr><tr><td class="number">17</td><td>        tsel <span class="k3">=</span> tri<span class="k2">;</span></td></tr><tr><td class="number">18</td><td>        hit <span class="k3">=</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">20</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>
to this:
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">while</span><span class="k2">(</span> <span class="k2">(</span> tri <span class="k3">=</span> this-&gt;findEarliestCollision<span class="k2">(</span> ball, delta_t <span class="k2">)</span> <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    <span class="k1">if</span> <span class="k2">(</span> <a href="http://www.allegro.cc/manual/key" target="_blank"><span class="a">key</span></a><span class="k2">[</span> KEY_ESC <span class="k2">]</span> <span class="k2">)</span> <span class="k1">break</span><span class="k2">;</span></td></tr><tr><td class="number">4</td><td>&#160;</td></tr><tr><td class="number">5</td><td>    <span class="k1">if</span> <span class="k2">(</span> delta_t <span class="k3">&lt;</span><span class="k3">=</span> time_remaining <span class="k2">)</span> </td></tr><tr><td class="number">6</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">7</td><td>        ball.pos <span class="k3">+</span><span class="k3">=</span> ball.vel <span class="k3">*</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">8</td><td> </td></tr><tr><td class="number">9</td><td>        ball.vel <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> tri-&gt;normal <span class="k3">*</span> </td></tr><tr><td class="number">10</td><td>                        tri-&gt;normal.dotProduct<span class="k2">(</span> <span class="k3">-</span>ball.vel <span class="k2">)</span> <span class="k3">*</span> </td></tr><tr><td class="number">11</td><td>                        <span class="n">2</span>.<span class="n">0</span> <span class="k3">*</span> </td></tr><tr><td class="number">12</td><td>                        <span class="k2">(</span> <span class="n">1</span>.<span class="n">0</span> <span class="k3">+</span> tri-&gt;elasticity <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">13</td><td>&#160;</td></tr><tr><td class="number">14</td><td>        time_remaining <span class="k3">-</span><span class="k3">=</span> delta_t<span class="k2">;</span></td></tr><tr><td class="number">15</td><td>&#160;</td></tr><tr><td class="number">16</td><td>        tsel <span class="k3">=</span> tri<span class="k2">;</span></td></tr><tr><td class="number">17</td><td>        hit <span class="k3">=</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">18</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">19</td><td><span class="k2">}</span></td></tr><tr><td class="number">20</td><td>ball.vel <span class="k3">+</span><span class="k3">=</span> gravity <span class="k3">*</span> whatever<span class="k2">;</span><span class="c">//whatever = initial value of delta_t, probably 1.0</span></td></tr></tbody></table></div></div><p>
I know I kinda recommended the former as more accurate, but it&#39;s concievable it introduced some kind of subtle bias in favor of bouncing up higher or lower than the fall down... need to think about it for a bit.  <br />edit2: also, post more code.  At least a little bit before and after loop on findEarliestCollision(), and whatever calls checkEdge()
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Fri, 20 Oct 2006 20:32:09 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Since I was the last to post, I had to edit then bump.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
1. More code is always helps.
</p></div></div><p>
I&#39;ve attached all the code.</p><p>2. At the moment tri-&gt;elasticity is set to zero<br />I&#39;ve been trying all sorts of ideas. I had one where:<br />dropped at Y<br />bounce 1 reached Y + X( some amount )<br />bounce 2 reached Y<br />bounce 3 reached Y + X( some amount )<br />bounce 4 reached Y</p><p>The problem lies in that the magnitude of vel when it hit should have the same magnitude of bounce but it is not.</p><p>3. changing <br /><span class="source-code"><span class="k1">double</span> pdist <span class="k3">=</span> edir.dotProduct<span class="k2">(</span> toEdge2 <span class="k2">)</span><span class="k2">;</span></span><br />to <br /><span class="source-code"><span class="k1">double</span> pdist <span class="k3">=</span> edir.dotProduct<span class="k2">(</span> toEdge1 <span class="k2">)</span><span class="k2">;</span></span><br />had not effect</p><p>I&#39;ll be gone for a few hours so anything you could help with would be great.<br />Thanks.</p><p>EDIT:<br />Saw your edit after you posted and the change didn&#39;t fix it. It was still too much.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Fri, 20 Oct 2006 20:59:15 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Hmm, the program also fails to detect collision with the circle in the center, if you drop the ball below that circle and let the ball bounce up in to it ... which is weird, any you should probably look in to that.</p><p>Also, eventually the ball escaped through the arc&#39;ed top corner of the playing field when I left it to just go for a while.  It looked like it saw the collision -- there was a bit of red marking the spot where the ball flew through.  Might want to look in to that.</p><p>From my observations, most of the detection problems do seem related to the handling of collision-with-point issues.  You may want to store vertex normals (which would be nice for rendering it pretty later, anyway, right?).
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
you might put in a check on a corner collision to discard it if the dot product of the balls velocity and the triangles normal vector is positive.
</p></div></div><p>I suppose that might work -- the hope being that if you discard this collision, you&#39;ll find (and react to) the collision with the &#39;more relevant&#39; edge?  Wouldn&#39;t look quite as good as reacting with some average vertex normal, I think, though.<br />edit2: Not sure about the collision with points issue, actually.</p><p>edit:
</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
The problem lies in that the magnitude of vel when it hit should have the same magnitude of bounce but it is not.
</p></div></div><p>The thing is that you&#39;re using simple Euler integration for everything, and the way it works out is that the accel due to gravity is either too much or too little depending on when you apply it.  So, what I&#39;m saying specifically about your code is, you have this:
</p><div class="source-code snippet"><div class="inner"><pre>    ball.pos <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> ball.vel <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
    ball.vel <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> gravity <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
That will always bounce to high.  This, on the other hand:
</p><div class="source-code snippet"><div class="inner"><pre>    ball.vel <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> gravity <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
    ball.pos <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> ball.vel <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>That will always bounce too low.<br />The &#39;correct&#39; solution would probably look like this:
</p><div class="source-code snippet"><div class="inner"><pre>   ball.vel <span class="k3">+</span><span class="k3">=</span> .<span class="n">5</span> <span class="k3">*</span> <span class="k2">(</span> gravity <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
   ball.pos <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> ball.vel <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
   ball.vel <span class="k3">+</span><span class="k3">=</span> .<span class="n">5</span> <span class="k3">*</span> <span class="k2">(</span> gravity <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
But to be on the save side you might want to weight it more like .6 to .4 ...
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Zaphos)</author>
		<pubDate>Fri, 20 Oct 2006 21:07:19 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Changing the gravity stuff fixed the bouncing problem.  The change is removing the &quot;ball.vel += gravity * delta_t;&quot; that happened per collision and changing the per-tick one from &quot;ball.vel += gravity * time_remaining;&quot; to &quot;ball.vel += gravity * 1.0&quot;.  </p><p>That causes a decrease in the accuracy of simulation, but it&#39;s well worth it to eliminate the higher bounces.  They were happening because a subtle issue in when gravity was accounted for.  If you want to keep the accuracy while still eliminating the higher bounces, the possibilities that occur to me include<br />A. force gravity updates at peaks of ballistic paths.  This makes the loop that calls findEarliestCollision a little more complicated, but not insanely complicated.  <br />B. switching the collision detection to looking at parabolic paths instead of linear.  That would make checkCollision much more complicated, but would improve accuracy significantly.  <br />Probably neither are worth it to you.  </p><p>For the collisions with the center circle thingy, try these changes:<br />1.  in checkCollision(), you return checkInside() if you think there&#39;s any chance of a planar collision.  Instead, do an if (checkInside()) return true, and if there&#39;s not a planar collision continue on to the checkEdge calls.  <br />2.  If you do get a true value from checkEdge, and return it, t, never gets set, so findEarliestCollision disregards it because it fails the t &gt; VZERO check.  Setting to some arbitrary value like 0.01 will force it to work, though defeating the point of some of that logic.  <br />3. I also added these three lines to checkCollision, otherwise some strange things happened when the ball rolled around on the circle in the middle.  <br /><span class="source-code">	<span class="k1">if</span> <span class="k2">(</span> plen <span class="k3">&lt;</span><span class="k3">=</span> len <span class="k2">)</span> <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></span>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Fri, 20 Oct 2006 22:44:51 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The gravity works now. All I did was change 
</p><div class="source-code snippet"><div class="inner"><pre>ball.vel <span class="k3">+</span><span class="k3">=</span> .<span class="n">5</span> <span class="k3">*</span> <span class="k2">(</span> gravity <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
ball.pos <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> ball.vel <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
ball.vel <span class="k3">+</span><span class="k3">=</span> .<span class="n">5</span> <span class="k3">*</span> <span class="k2">(</span> gravity <span class="k3">*</span> time_remaining <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
I left in the 
</p><div class="source-code snippet"><div class="inner"><pre>ball.vel <span class="k3">+</span><span class="k3">=</span> gravity <span class="k3">*</span> delta_t<span class="k2">;</span>
</pre></div></div><p>
because it works better that way.</p><p>The top of the circle is where two planes come together, so it&#39;s the edge problem again. </p><p>I&#39;ll work on the edge problem. Thanks for the help.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Sat, 21 Oct 2006 02:37:50 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>When I do that on my version, and set the ball to bouncing vertically, it very gradually increases in bounce height, maybe 1% every 5 bounces.  Perhaps I changed something else?  </p><p>The edge problem is fixed in my version, with the changes described previously.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Sat, 21 Oct 2006 11:47:57 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>You&#39;re right. It does change slightly.</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
the changes described previously
</p></div></div><p>
Which &#39;previously&#39;?<br />Could you post your edge code?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (DanielH)</author>
		<pubDate>Sat, 21 Oct 2006 19:01:23 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
When I do that on my version, and set the ball to bouncing vertically, it very gradually increases in bounce height, maybe 1% every 5 bounces. Perhaps I changed something else?
</p></div></div><p>
Strange... now I don&#39;t get that anymore.  I&#39;m not sure what changed, but it now seems to work perfectly with that, whereas before it would keep bouncing faster with that.  Maybe I screwed up or fixed something else and forgot about it.  </p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
Which &#39;previously&#39;?<br />Could you post your edge code?
</p></div></div><p>
Sure.  The &#39;previously&#39; was this:</p><div class="quote_container"><div class="title">Quote:</div><div class="quote"><p>
For the collisions with the center circle thingy, try these changes:<br />1. in checkCollision(), you return checkInside() if you think there&#39;s any chance of a planar collision. Instead, do an if (checkInside()) return true, and if there&#39;s not a planar collision continue on to the checkEdge calls.<br />2. If you do get a true value from checkEdge, and return it, t, never gets set, so findEarliestCollision disregards it because it fails the t &gt; VZERO check. Setting to some arbitrary value like 0.01 will force it to work, though defeating the point of some of that logic.<br />3. I also added these three lines to checkCollision, otherwise some strange things happened when the ball rolled around on the circle in the middle.</p><p>	if ( plen &lt;= len ) return false;
</p></div></div><p>
code is this:
</p><div class="source-code"><div class="toolbar"></div><div class="inner"><table width="100%"><tbody><tr><td class="number">1</td><td><span class="k1">bool</span> Triangle::checkCollision<span class="k2">(</span> <span class="k1">const</span> Ball <span class="k3">&amp;</span>ball, <span class="k1">double</span> <span class="k3">&amp;</span>t <span class="k2">)</span></td></tr><tr><td class="number">2</td><td><span class="k2">{</span></td></tr><tr><td class="number">3</td><td>    <span class="k1">static</span> Ball newBall<span class="k2">;</span></td></tr><tr><td class="number">4</td><td>    <span class="k1">static</span> <span class="k1">double</span> plen <span class="k3">=</span> <span class="n">0</span>.<span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">5</td><td>    <span class="k1">static</span> <span class="k1">double</span> len <span class="k3">=</span> <span class="n">0</span>.<span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">6</td><td>&#160;</td></tr><tr><td class="number">7</td><td>    t <span class="k3">=</span> <span class="n">0</span>.<span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">8</td><td>&#160;</td></tr><tr><td class="number">9</td><td>    plen <span class="k3">=</span> this-&gt;distance<span class="k2">(</span> ball.pos <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">10</td><td>    len <span class="k3">=</span> this-&gt;distance<span class="k2">(</span> ball.pos <span class="k3">+</span> ball.vel <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">11</td><td>&#160;</td></tr><tr><td class="number">12</td><td>  <span class="k1">if</span> <span class="k2">(</span> plen <span class="k3">&lt;</span><span class="k3">=</span> len <span class="k2">)</span> <span class="k1">return</span> <span class="k1">false</span><span class="k2">;</span></td></tr><tr><td class="number">13</td><td><span class="c">//  if ( len &gt; ball.radius) return false;</span></td></tr><tr><td class="number">14</td><td><span class="c">//  if ( plen &lt; 0 ) return false;</span></td></tr><tr><td class="number">15</td><td>&#160;</td></tr><tr><td class="number">16</td><td>    <span class="k1">if</span> <span class="k2">(</span> plen <span class="k3">&gt;</span><span class="k3">=</span> ball.radius <span class="k3">&amp;</span><span class="k3">&amp;</span> len <span class="k3">&lt;</span> ball.radius <span class="k2">)</span></td></tr><tr><td class="number">17</td><td>    <span class="k2">{</span> </td></tr><tr><td class="number">18</td><td>        t <span class="k3">=</span> <span class="n">1</span>.<span class="n">0</span> <span class="k3">-</span> <span class="k2">(</span> <span class="k2">(</span> ball.radius <span class="k3">-</span> len <span class="k2">)</span> <span class="k3">/</span> <span class="k2">(</span> plen <span class="k3">-</span> len <span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">19</td><td>       </td></tr><tr><td class="number">20</td><td>        newBall.pos <span class="k3">=</span> ball.pos <span class="k3">+</span> ball.vel <span class="k3">*</span> t<span class="k2">;</span></td></tr><tr><td class="number">21</td><td>        newBall.vel <span class="k3">=</span> ball.vel<span class="k2">;</span></td></tr><tr><td class="number">22</td><td>        newBall.radius <span class="k3">=</span> ball.radius<span class="k2">;</span></td></tr><tr><td class="number">23</td><td>&#160;</td></tr><tr><td class="number">24</td><td>        <span class="k1">if</span> <span class="k2">(</span>this-&gt;checkInside<span class="k2">(</span> newBall <span class="k2">)</span><span class="k2">)</span> <span class="k1">return</span> <span class="k1">true</span><span class="k2">;</span></td></tr><tr><td class="number">25</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">26</td><td>&#160;</td></tr><tr><td class="number">27</td><td>  t <span class="k3">=</span> <span class="n">0</span>.<span class="n">01</span><span class="k2">;</span></td></tr><tr><td class="number">28</td><td>  <span class="k1">return</span></td></tr><tr><td class="number">29</td><td>           this-&gt;checkEdge<span class="k2">(</span> ball, this-&gt;vector<span class="k2">[</span> <span class="n">2</span> <span class="k2">]</span>, this-&gt;vector<span class="k2">[</span> <span class="n">1</span> <span class="k2">]</span> <span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span></td></tr><tr><td class="number">30</td><td>           this-&gt;checkEdge<span class="k2">(</span> ball, this-&gt;vector<span class="k2">[</span> <span class="n">1</span> <span class="k2">]</span>, this-&gt;vector<span class="k2">[</span> <span class="n">0</span> <span class="k2">]</span> <span class="k2">)</span> <span class="k3">|</span><span class="k3">|</span></td></tr><tr><td class="number">31</td><td>           this-&gt;checkEdge<span class="k2">(</span> ball, this-&gt;vector<span class="k2">[</span> <span class="n">0</span> <span class="k2">]</span>, this-&gt;vector<span class="k2">[</span> <span class="n">2</span> <span class="k2">]</span> <span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">32</td><td><span class="k2">}</span></td></tr><tr><td class="number">33</td><td>Triangle <span class="k3">*</span>TList::findEarliestCollision<span class="k2">(</span> <span class="k1">const</span> Ball <span class="k3">&amp;</span>ball, <span class="k1">double</span> <span class="k3">&amp;</span>delta_t <span class="k2">)</span></td></tr><tr><td class="number">34</td><td><span class="k2">{</span></td></tr><tr><td class="number">35</td><td>    Triangle <span class="k3">*</span>temp <span class="k3">=</span> NULL<span class="k2">;</span></td></tr><tr><td class="number">36</td><td>    std::list<span class="k3">&lt;</span>Triangle&gt;::iterator it<span class="k2">;</span></td></tr><tr><td class="number">37</td><td>    <span class="k1">double</span> currentT <span class="k3">=</span> <span class="n">0</span>.<span class="n">0</span><span class="k2">;</span></td></tr><tr><td class="number">38</td><td>&#160;</td></tr><tr><td class="number">39</td><td>    <span class="k1">for</span> <span class="k2">(</span> it <span class="k3">=</span> this-&gt;tlist.begin<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> it <span class="k3">!</span><span class="k3">=</span> this-&gt;tlist.end<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span> it<span class="k3">+</span><span class="k3">+</span> <span class="k2">)</span></td></tr><tr><td class="number">40</td><td>    <span class="k2">{</span></td></tr><tr><td class="number">41</td><td>        <span class="k1">if</span> <span class="k2">(</span> <span class="k2">(</span><span class="k3">*</span>it<span class="k2">)</span>.checkCollision<span class="k2">(</span> ball, currentT <span class="k2">)</span> <span class="k2">)</span></td></tr><tr><td class="number">42</td><td>        <span class="k2">{</span></td></tr><tr><td class="number">43</td><td>            <span class="k1">if</span> <span class="k2">(</span> currentT <span class="k3">&lt;</span> delta_t <span class="k3">&amp;</span><span class="k3">&amp;</span></td></tr><tr><td class="number">44</td><td>                 currentT <span class="k3">&gt;</span> VZERO <span class="k2">)</span></td></tr><tr><td class="number">45</td><td>            <span class="k2">{</span></td></tr><tr><td class="number">46</td><td>                delta_t <span class="k3">=</span> currentT<span class="k2">;</span></td></tr><tr><td class="number">47</td><td>                temp <span class="k3">=</span> <span class="k3">&amp;</span><span class="k2">(</span><span class="k3">*</span>it<span class="k2">)</span><span class="k2">;</span></td></tr><tr><td class="number">48</td><td>            <span class="k2">}</span></td></tr><tr><td class="number">49</td><td>        <span class="k2">}</span></td></tr><tr><td class="number">50</td><td>    <span class="k2">}</span></td></tr><tr><td class="number">51</td><td>&#160;</td></tr><tr><td class="number">52</td><td>  <span class="k1">return</span> temp<span class="k2">;</span></td></tr><tr><td class="number">53</td><td><span class="k2">}</span></td></tr></tbody></table></div></div><p>

And the total code that I&#39;m using atm is attached to this post
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (orz)</author>
		<pubDate>Sat, 21 Oct 2006 20:43:03 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Also worth noting -- when you start working with non-elastic walls (or even just partially elastic walls), you&#39;ll want to add a line in calculate tick to make sure the ball gets &#39;pushed out&#39; of walls that it is inside.  This:
</p><div class="source-code snippet"><div class="inner"><pre>            ball.vel <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> tri-&gt;normal <span class="k3">*</span> 
                          tri-&gt;normal.dotProduct<span class="k2">(</span> <span class="k3">-</span>ball.vel <span class="k2">)</span> <span class="k3">*</span> 
                          <span class="k2">(</span><span class="n">1</span> <span class="k3">+</span> tri-&gt;elasticity<span class="k2">)</span> <span class="k2">)</span><span class="k2">;</span> <span class="c">// after this line </span>
            ball.pos <span class="k3">+</span><span class="k3">=</span> <span class="k2">(</span> tri-&gt;normal <span class="k3">*</span> .<span class="n">5</span> <span class="k2">)</span><span class="k2">;</span> <span class="c">// put this line</span>
</pre></div></div><p>
should do the trick.  Otherwise the ball will slowly merge whatever it&#39;s sliding on.</p><p>edit:<br />Also (this doesn&#39;t really matter, but) there&#39;s a bit of sloppiness left over from the code I gave for checking edges.  In &quot;Triangle::checkEdge&quot;, this:
</p><div class="source-code snippet"><div class="inner"><pre>   <span class="k1">double</span> distToLine <span class="k3">=</span> <span class="k2">(</span> ball.pos <span class="k3">-</span> P_onE <span class="k2">)</span>.getLength<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
   
   <span class="k1">return</span> <span class="k2">(</span> distToLine <span class="k3">&lt;</span> ball.radius <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>
has no particular reason not to be written as this:
</p><div class="source-code snippet"><div class="inner"><pre>   <span class="k1">double</span> distToLineSq <span class="k3">=</span> <span class="k2">(</span> ball.pos <span class="k3">-</span> P_onE <span class="k2">)</span>.getSquaredLength<span class="k2">(</span><span class="k2">)</span><span class="k2">;</span>
   
   <span class="k1">return</span> <span class="k2">(</span> distToLineSq <span class="k3">&lt;</span> ball.radius <span class="k3">*</span> ball.radius <span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>(and that would be more consistent with the rest of the code, which was written to avoid sqrt.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Zaphos)</author>
		<pubDate>Sat, 21 Oct 2006 22:10:29 +0000</pubDate>
	</item>
</rss>
