1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><title>Collision and Intersection</title><link rel="stylesheet" href="./asciidoctor.css">
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
- <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/jme3/advanced/collision_and_intersection.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/jme3/advanced/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"></div><h1>Collision and Intersection</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#collidable">Collidable</a><ul class="sectlevel2"><li><a href="#code-sample">Code Sample</a></li></ul></li><li><a href="#bounding-volumes">Bounding Volumes</a><ul class="sectlevel2"><li><a href="#usage">Usage</a></li></ul></li><li><a href="#mesh-and-scene-graph-collision">Mesh and Scene Graph Collision</a></li><li><a href="#intersection">Intersection</a></li></ul></div></div><div id="content"><div id="preamble"><div class="sectionbody"><div class="paragraph"><p>The term collision can be used to refer to <a href="../../jme3/advanced/physics_listeners.html">physical interactions</a> (where <a href="../../jme3/advanced/physics.html">physical objects</a> collide, push and bump off one another), and also to non-physical <em>intersections</em> in 3D space. This article is about the non-physical (mathematical) collisions.</p></div>
- <div class="paragraph"><p>Non-physical collision detection is interesting because it uses less computing resources than physical collision detection. The non-physical calculations are faster because they do not have any side effects such as pushing other objects or bumping off of them. Tasks such as <a href="../../jme3/advanced/mouse_picking.html">mouse picking</a> are easily implemented using mathematical techniques such as ray casting and intersections. Experienced developers optimize their games by finding ways to simulate certain (otherwise expensive physical) interactions in a non-physical way.</p></div>
- <div class="paragraph"><p><strong>Example:</strong> One example for an optimization is a physical vehicle’s wheels. You could make the wheels fully physical disks, and have jME calculate every tiny force – sounds very accurate? It’s total overkill and too slow for a racing game. A more performant solution is to cast four invisible rays down from the vehicle and calculate the intersections with the floor. These non-physical wheels require (in the simplest case) only four calculations per tick to achieve an effect that players can hardly distinguish from the real thing.</p></div></div></div>
- <div class="sect2"><h3 id="collidable">Collidable</h3><div class="paragraph"><p>The interface com.jme3.collision.Collidable declares one method that returns how many collisions were found between two Collidables: <code>collideWith(Collidable other, CollisionResults results)</code>.</p></div>
- <div class="ulist"><ul><li><p>A <code>com.jme3.collision.CollisionResults</code> object is an ArrayList of comparable <code>com.jme3.collision.CollisionResult</code> objects.</p></li><li><p>You can iterate over the CollisionResults to identify the other parties involved in the collision. +Note that jME counts <em>all</em> collisions, this means a ray intersecting a box will be counted as two hits, one on the front where the ray enters, and one on the back where the ray exits.</p></li></ul></div>
- <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 100%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>CollisionResults Method</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Usage</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>size()</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the number of CollisionResult objects.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getClosestCollision()</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the CollisionResult with the lowest distance.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getFarthestCollision()</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the CollisionResult with the farthest distance.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getCollision(i)</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the CollisionResult at index i.</p></div></div></td></tr></tbody></table>
- <div class="paragraph"><p>A CollisionResult object contains information about the second party of the collision event.</p></div>
- <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 50%;"><col style="width: 50%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">CollisionResult Method</th><th class="tableblock halign-left valign-top">Usage</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getContactPoint()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the contact point coordinate on the second party, as Vector3f.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getContactNormal()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the Normal vector at the contact point, as Vector3f.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getDistance()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the distance between the Collidable and the second party, as float.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getGeometry()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the Geometry of the second party.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getTriangle(t)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Binds t to the triangle t on the second party’s mesh that was hit.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>getTriangleIndex()</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Returns the index of the triangle on the second party’s mesh that was hit.</p></div></div></td></tr></tbody></table>
- <div class="sect2"><h3 id="code-sample">Code Sample</h3><div class="paragraph"><p>Assume you have two collidables a and b and want to detect collisions between them. The collision parties can be Geometries, Nodes with Geometries attached (including the rootNode), Planes, Quads, Lines, or Rays. An important restriction is that you can only collide geometry vs bounding volumes or rays. (This means for example that a must be of Type Node or Geometry and b respectively of Type BoundingBox, BoundingSphere or Ray.)</p></div>
- <div class="paragraph"><p>The following code snippet can be triggered by listeners (e.g. after an input action such as a click), or timed in the update loop.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> <span class="comment">// Calculate detection results</span>
- CollisionResults results = <span class="keyword">new</span> CollisionResults();
- a.collideWith(b, results);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Number of Collisions between</span><span class="delimiter">"</span></span> +
- a.getName()+ <span class="string"><span class="delimiter">"</span><span class="content"> and </span><span class="delimiter">"</span></span> + b.getName() + <span class="string"><span class="delimiter">"</span><span class="content">: </span><span class="delimiter">"</span></span> + results.size());
- <span class="comment">// Use the results</span>
- <span class="keyword">if</span> (results.size() > <span class="integer">0</span>) {
- <span class="comment">// how to react when a collision was detected</span>
- CollisionResult closest = results.getClosestCollision();
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">What was hit? </span><span class="delimiter">"</span></span> + closest.getGeometry().getName() );
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Where was it hit? </span><span class="delimiter">"</span></span> + closest.getContactPoint() );
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Distance? </span><span class="delimiter">"</span></span> + closest.getDistance() );
- } <span class="keyword">else</span> {
- <span class="comment">// how to react when no collision occured</span>
- }
- }</code></pre></div></div>
- <div class="paragraph"><p>You can also loop over all results and trigger different reactions depending on what was hit and where it was hit. In this example, we simply print info about them.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> <span class="comment">// Calculate Results</span>
- CollisionResults results = <span class="keyword">new</span> CollisionResults();
- a.collideWith(b, results);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Number of Collisions between</span><span class="delimiter">"</span></span> + a.getName()+ <span class="string"><span class="delimiter">"</span><span class="content"> and </span><span class="delimiter">"</span></span>
- + b.getName() <span class="string"><span class="delimiter">"</span><span class="content"> : </span><span class="delimiter">"</span></span> + results.size());
- <span class="comment">// Use the results</span>
- <span class="keyword">for</span> (<span class="type">int</span> i = <span class="integer">0</span>; i < results.size(); i++) {
- <span class="comment">// For each hit, we know distance, impact point, name of geometry.</span>
- <span class="type">float</span> dist = results.getCollision(i).getDistance();
- Vector3f pt = results.getCollision(i).getContactPoint();
- <span class="predefined-type">String</span> party = results.getCollision(i).getGeometry().getName();
- <span class="type">int</span> tri = results.getCollision(i).getTriangleIndex();
- Vector3f norm = results.getCollision(i).getTriangle(<span class="keyword">new</span> Triangle()).getNormal();
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content">Details of Collision #</span><span class="delimiter">"</span></span> + i + <span class="string"><span class="delimiter">"</span><span class="content">:</span><span class="delimiter">"</span></span>);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content"> Party </span><span class="delimiter">"</span></span> + party + <span class="string"><span class="delimiter">"</span><span class="content"> was hit at </span><span class="delimiter">"</span></span> + pt + <span class="string"><span class="delimiter">"</span><span class="content">, </span><span class="delimiter">"</span></span> + dist + <span class="string"><span class="delimiter">"</span><span class="content"> wu away.</span><span class="delimiter">"</span></span>);
- <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">"</span><span class="content"> The hit triangle #</span><span class="delimiter">"</span></span> + tri + <span class="string"><span class="delimiter">"</span><span class="content"> has a normal vector of </span><span class="delimiter">"</span></span> + norm);
- }</code></pre></div></div>
- <div class="paragraph"><p>Knowing the distance of the collisions is useful for example when you intersect Lines and Rays with other objects.</p></div></div></div>
- <div class="sect2"><h3 id="bounding-volumes">Bounding Volumes</h3><div class="paragraph"><p>A <code>com.jme3.bounding.BoundingVolume</code> is an interface for dealing with containment of a collection of points. All BoundingVolumes are <code>Collidable</code> and are used as optimization to calculate non-physical collisions more quickly: It’s always faster to calculate an intersection between simple shapes like spheres and boxes than between complex shapes like models.</p></div>
- <div class="paragraph"><p>jME3 computes bounding volumes for all objects. These bounding volumes are later used for frustum culling, which is making sure only objects visible on-screen are actually sent for rendering.</p></div>
- <div class="paragraph"><p>All fast-paced action and shooter games use BoundingVolumes as an optimization. Wrap all complex models into simpler shapes – in the end, you get equally useful collision detection results, but faster. <a href="http://en.wikipedia.org/wiki/Bounding_volume">More about bounding volumes…​</a></p></div>
- <div class="paragraph"><p>Supported types:</p></div>
- <div style="text-align: right;" class="imageblock"><div class="content"><img src="http://www.jmonkeyengine.com/jme/wiki-data/userref/capsule.png" alt="Capsule" height="110"></div></div>
- <div class="ulist"><ul><li><p>Type.AABB = Axis-aligned bounding box, that means it doesn’t rotate, which makes it less precise. A <code>com.jme3.bounding.BoundingBox</code> is an axis-aligned cuboid used as a container for a group of vertices of a piece of geometry. A BoundingBox has a center and extents from that center along the x, y and z axis. This is the default bounding volume, since it is fairly fast to generate and gives better accuracy than the bounding sphere.</p></li><li><p>Type.Sphere: <code>com.jme3.bounding.BoundingSphere</code> is a sphere used as a container for a group of vertices of a piece of geometry. A BoundingSphere has a center and a radius.</p></li><li><p>Type.OBB = Oriented bounding box. This bounding box is more precise because it can rotate with its content, but is computationally more expensive. (Currently not supported.)</p></li><li><p>Type.Capsule = Cylinder with rounded ends, also called “swept sphere. Typically used for mobile characters. (Currently not supported.)</p></li></ul></div>
- <div class="admonitionblock note"><table><tr><td class="icon"><i class="fa icon-note" title="Note"></i></td><td class="content"><div class="paragraph"><p>Note: If you are looking for bounding volumes for physical objects, use <a href="../../jme3/advanced/physics.html">CollisionShapes</a>.</p></div></td></tr></table></div>
- <div class="sect2"><h3 id="usage">Usage</h3><div class="paragraph"><p>For example you can use Bounding Volumes on custom meshes, or complex non-physical shapes.</p></div>
- <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">mesh.setBound(<span class="keyword">new</span> BoundingSphere());
- mesh.updateBound();</code></pre></div></div></div></div>
- <div class="sect1"><h2 id="mesh-and-scene-graph-collision">Mesh and Scene Graph Collision</h2><div class="sectionbody"><div class="paragraph"><p>One of the supported <code>Collidable`s are meshes and scene graph objects. To execute a collision detection query against a scene graph, use `Spatial.collideWith()</code>. This will traverse the scene graph and return any mesh collisions that were detected. Note that the first collision against a particular scene graph may take a long time, this is because a special data structure called <a href="http://en.wikipedia.org/wiki/Bounding_interval_hierarchy">|Bounding Interval Hierarchy (BIH)</a> needs to be generated for the meshes. At a later point, the mesh could change and the BIH tree would become out of date, in that case, call <a href="http://jmonkeyengine.org/javadoc/com/jme3/scene/Mesh.html#createCollisionData()">Mesh.createCollisionData()</a> on the changed mesh to update the BIH tree.</p></div></div></div>
- <div class="sect1"><h2 id="intersection">Intersection</h2><div class="sectionbody"><div class="paragraph"><p>A <code>com.jme3.math.Ray</code> is an infinite line with a beginning, a direction, and no end; whereas a <code>com.jme3.math.Line</code> is an infinite line with only a direction (no beginning, no end).</p></div>
- <div class="paragraph"><p>Rays are used to perform line-of-sight calculations. This means you can detect what users were “aiming at when they clicked or pressed a key. You can also use this to detect whether game characters can see something (or someone) or not.</p></div>
- <div class="ulist"><ul><li><p><strong>Click to select:</strong> You can determine what a user has clicked by casting a ray from the camera forward in the direction of the camera. Now identify the closest collision of the ray with the rootNode, and you have the clicked object.</p></li><li><p><strong>Line of sight:</strong> Cast a ray from a player in the direction of another player. Then you detect all collisions of this ray with other entities (walls versus foliage versus window panes) and use this to calculate how likely it is that one can see the other.</p></li></ul></div>
- <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>These simple but powerful ray-surface intersection tests are called Ray Casting. As opposed to the more advanced Ray Tracing technique, Ray Casting does not follow the ray’s reflection after the first hit – the ray just goes straight on.</p></div></td></tr></table></div>
- <div class="paragraph"><p>Learn the details of how to implement <a href="../../jme3/advanced/mouse_picking.html">Mouse Picking</a> here.
- '''</p></div>
- <div class="paragraph"><p>TODO:</p></div>
- <div class="ulist"><ul><li><p>Bounding Interval Hierarchy (<code>com.jme3.collision.bih.BIHNode</code>)</p></li><li><p>com.jme3.scene.CollisionData</p></li></ul></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2016-07-22 07:15:15 UTC</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
- apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
- indexName: 'jmonkeyengine',
- inputSelector: '#doc-search',
- debug: false // Set debug to true if you want to inspect the dropdown
- });</script></body></html>
|