PageRenderTime 63ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/zoo/jME_physics/src/com/jmex/physics/PhysicsDebugger.java

https://github.com/ModularRoboticsLab/ussr
Java | 349 lines | 234 code | 38 blank | 77 comment | 36 complexity | bef051c55470c29af8877a50ae475572 MD5 | raw file
  1. /*
  2. * Copyright (c) 2005-2007 jME Physics 2
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jME Physics 2' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jmex.physics;
  33. import com.jme.math.Vector3f;
  34. import com.jme.renderer.ColorRGBA;
  35. import com.jme.renderer.Renderer;
  36. import com.jme.scene.Geometry;
  37. import com.jme.scene.Line;
  38. import com.jme.scene.Node;
  39. import com.jme.scene.Spatial;
  40. import com.jme.scene.state.LightState;
  41. import com.jme.scene.state.RenderState;
  42. import com.jme.scene.state.WireframeState;
  43. import com.jme.scene.state.ZBufferState;
  44. import com.jme.util.geom.BufferUtils;
  45. /**
  46. * Analoguous to {@link com.jme.util.geom.Debugger} this class can be used to view physics data such as physics
  47. * collision bounds, velocity and forces.
  48. *
  49. * @author Irrisor
  50. */
  51. public class PhysicsDebugger {
  52. private static final float CROSS_SIZE_PERCENTAGE = 0.1f;
  53. protected PhysicsDebugger() {
  54. }
  55. /**
  56. * Draw all info available for the physics nodes in the specified space.
  57. *
  58. * @param space what to draw info for
  59. * @param renderer where to draw
  60. */
  61. public static void drawPhysics( PhysicsSpace space, Renderer renderer ) {
  62. for ( PhysicsNode physicsNode : space.getNodes() ) {
  63. drawPhysics( physicsNode, renderer );
  64. }
  65. for ( Joint joint : space.getJoints() ) {
  66. drawJoint( joint, renderer );
  67. }
  68. space.drawImplementationSpecificPhysics( renderer );
  69. }
  70. /**
  71. * Draw all info available for the physics node.
  72. *
  73. * @param physicsNode what to draw info for
  74. * @param renderer where to draw
  75. */
  76. public static void drawPhysics( PhysicsNode physicsNode, Renderer renderer ) {
  77. physicsNode.drawDebugInfo( renderer );
  78. }
  79. /**
  80. * Draw all info available for the physics geometry.
  81. *
  82. * @param physicsCollisionGeometry what to draw info for
  83. * @param renderer where to draw
  84. */
  85. public static void drawPhysics( PhysicsCollisionGeometry physicsCollisionGeometry, Renderer renderer ) {
  86. physicsCollisionGeometry.drawDebugShape( physicsCollisionGeometry.getPhysicsNode(), renderer );
  87. }
  88. private static void drawJoint( Joint joint, Renderer renderer ) {
  89. Vector3f center = tmp2;
  90. joint.getAnchor( center );
  91. DynamicPhysicsNode node1;
  92. DynamicPhysicsNode node2;
  93. switch ( joint.getNodes().size() ) {
  94. case 1:
  95. node1 = joint.getNodes().get( 0 );
  96. node2 = null;
  97. break;
  98. case 2:
  99. node1 = joint.getNodes().get( 0 );
  100. node2 = joint.getNodes().get( 1 );
  101. node1.getWorldRotation().multLocal( center );
  102. center.addLocal( node1.getWorldTranslation() );
  103. break;
  104. default:
  105. // not connected (or more than 2 - not allowed!)
  106. return;
  107. }
  108. drawCross( center, 1, renderer, COLOR_JOINT, 3 );
  109. line.setLineWidth( 1 );
  110. for ( DynamicPhysicsNode node : joint.getNodes() ) {
  111. lineFrom( center );
  112. lineTo( node.getWorldTranslation() );
  113. line.draw( renderer );
  114. }
  115. for ( JointAxis axis : joint.getAxes() ) {
  116. Vector3f direction = tmp3;
  117. axis.getDirection( direction );
  118. if ( node2 != null ) {
  119. if ( !axis.isRelativeToSecondObject() ) {
  120. node1.getWorldRotation().multLocal( direction );
  121. }
  122. else {
  123. node2.getWorldRotation().multLocal( direction );
  124. }
  125. }
  126. Vector3f target = tmp4;
  127. line.setLineWidth( 2 );
  128. if ( axis.isTranslationalAxis() ) {
  129. lineFrom( center );
  130. lineTo( target.set( center ).addLocal( direction ) );
  131. line.draw( renderer );
  132. }
  133. line.setLineWidth( 3 );
  134. if ( axis.isRotationalAxis() ) {
  135. lineFrom( center );
  136. lineTo( target.set( center ).subtractLocal( direction ) );
  137. line.draw( renderer );
  138. }
  139. }
  140. }
  141. /**
  142. * Draw all info available for the specified PhysicsNode.
  143. *
  144. * @param physicsNode what to draw
  145. * @param renderer where to draw
  146. */
  147. static void drawCollisionGeometry( PhysicsNode physicsNode, Renderer renderer ) {
  148. for ( int i = physicsNode.getQuantity() - 1; i >= 0; i-- ) {
  149. Spatial child = physicsNode.getChild( i );
  150. if ( child instanceof PhysicsCollisionGeometry ) {
  151. PhysicsCollisionGeometry collisionGeometry = (PhysicsCollisionGeometry) child;
  152. collisionGeometry.drawDebugShape( physicsNode, renderer );
  153. }
  154. }
  155. }
  156. private static WireframeState boundsWireState;
  157. private static ZBufferState boundsZState;
  158. private static void applyStates( Renderer r ) {
  159. for ( int x = 0; x < Renderer.defaultStateList.length; x++ ) {
  160. if ( x != RenderState.RS_ZBUFFER && x != RenderState.RS_WIREFRAME ) {
  161. Renderer.defaultStateList[x].apply();
  162. }
  163. }
  164. if ( boundsWireState == null ) {
  165. boundsWireState = r.createWireframeState();
  166. boundsZState = r.createZBufferState();
  167. }
  168. boundsWireState.apply();
  169. boundsZState.apply();
  170. }
  171. private static Line line;
  172. static {
  173. Vector3f[] points = {new Vector3f(), new Vector3f()};
  174. line = new Line( "line", points, null, null, null );
  175. line.setRenderQueueMode( Renderer.QUEUE_SKIP );
  176. line.setColorBuffer( null );
  177. line.setLightCombineMode( Spatial.LightCombineMode.Off );
  178. line.updateRenderState();
  179. }
  180. public static final ColorRGBA COLOR_ACTIVE = new ColorRGBA( 0.0f, 0.0f, 1.0f, 1 );
  181. public static final ColorRGBA COLOR_ACTIVE_RESTING = new ColorRGBA( 0.5f, 0.5f, 1.0f, 1 );
  182. public static final ColorRGBA COLOR_INACTIVE = new ColorRGBA( 0.2f, 0.0f, 0.0f, 1 );
  183. public static final ColorRGBA COLOR_CENTER = new ColorRGBA( 0, 0.6f, 0, 1 );
  184. public static final ColorRGBA COLOR_CENTER_OF_MASS = new ColorRGBA( 0.6f, 0, 0, 1 );
  185. public static final ColorRGBA COLOR_JOINT = new ColorRGBA( 0.6f, 0.6f, 0, 1 );
  186. private static final Vector3f tmp = new Vector3f();
  187. private static final Vector3f tmp2 = new Vector3f();
  188. private static final Vector3f tmp3 = new Vector3f();
  189. private static final Vector3f tmp4 = new Vector3f();
  190. private static final ColorRGBA color = new ColorRGBA();
  191. public static void drawDebugShape( Spatial debugShape, Vector3f geometryPivot, PhysicsCollisionGeometry geometry,
  192. Renderer renderer, float approximateVisualSize ) {
  193. PhysicsNode physicsNode = geometry.getPhysicsNode();
  194. applyStates( renderer );
  195. if ( physicsNode == null || physicsNode.isActive() ) {
  196. if ( geometry.getPhysicsNode().isResting() )
  197. {
  198. setColor( debugShape, COLOR_ACTIVE_RESTING );
  199. }
  200. else
  201. {
  202. setColor( debugShape, COLOR_ACTIVE );
  203. }
  204. geometry.getMaterial().getDebugColor( color );
  205. line.setDefaultColor( color );
  206. }
  207. else {
  208. setColor( debugShape, COLOR_INACTIVE );
  209. line.setDefaultColor( COLOR_INACTIVE );
  210. }
  211. if ( physicsNode != null ) {
  212. // draw line from geometry to center of node
  213. Vector3f center = physicsNode.getWorldTranslation();
  214. lineFrom( center );
  215. lineTo( geometryPivot );
  216. line.draw( renderer );
  217. // cross at center
  218. float length = Math.max( tmp.set( center ).subtractLocal( geometryPivot ).length(), approximateVisualSize );
  219. drawCross( center, length, renderer, COLOR_CENTER, 3 );
  220. if ( physicsNode instanceof DynamicPhysicsNode )
  221. {
  222. DynamicPhysicsNode dynamicPhysicsNode = (DynamicPhysicsNode) physicsNode;
  223. // cross at center of mass
  224. dynamicPhysicsNode.getCenterOfMass( tmp2 );
  225. if ( !tmp2.equals( Vector3f.ZERO ) )
  226. {
  227. drawCross( physicsNode.localToWorld( tmp2, tmp2 ), length, renderer, COLOR_CENTER_OF_MASS, 3 );
  228. }
  229. }
  230. }
  231. boundsWireState.apply(); // to clear line width
  232. if ( debugShape != null ) {
  233. debugShape.draw( renderer );
  234. }
  235. }
  236. public static void drawCross( Vector3f center, float length, Renderer renderer, ColorRGBA color, int lineWidth ) {
  237. line.setDefaultColor( color );
  238. line.setLineWidth( lineWidth );
  239. float crossSize = CROSS_SIZE_PERCENTAGE * length;
  240. lineFrom( tmp.set( center ).addLocal( crossSize, 0, 0 ) );
  241. lineTo( tmp.set( center ).addLocal( -crossSize, 0, 0 ) );
  242. line.draw( renderer );
  243. lineFrom( tmp.set( center ).addLocal( 0, crossSize, 0 ) );
  244. lineTo( tmp.set( center ).addLocal( 0, -crossSize, 0 ) );
  245. line.draw( renderer );
  246. lineFrom( tmp.set( center ).addLocal( 0, 0, crossSize ) );
  247. lineTo( tmp.set( center ).addLocal( 0, 0, -crossSize ) );
  248. line.draw( renderer );
  249. }
  250. private static void setColor( Spatial debugShape, ColorRGBA color ) {
  251. if ( debugShape instanceof Geometry ) {
  252. Geometry triMesh = (Geometry) debugShape;
  253. triMesh.setDefaultColor( color );
  254. triMesh.setColorBuffer( null );
  255. } else if ( debugShape instanceof Node ) {
  256. Node node = (Node) debugShape;
  257. for ( int i = node.getQuantity() - 1; i >= 0; i-- ) {
  258. Spatial child = node.getChild( i );
  259. setColor( child, color );
  260. }
  261. }
  262. }
  263. private static final Vector3f ARROWHEAD_AXIS = new Vector3f( 1, 0, 0.0001f );
  264. /**
  265. * Draws an arrow in specified color. Should be called directly _after_ {@link #drawDebugShape} only!
  266. *
  267. * @param from starting point of the arrow
  268. * @param to target point of the arrow
  269. * @param color of the arrow
  270. * @param renderer where to draw to
  271. */
  272. public static void drawArrow( Vector3f from, Vector3f to, ColorRGBA color, Renderer renderer ) {
  273. Vector3f direction = tmp.set( to ).subtractLocal( from );
  274. float length = direction.length();
  275. if ( length > 0 ) {
  276. direction.divide( length );
  277. line.setDefaultColor( color );
  278. line.setLineWidth( 1 );
  279. lineFrom( from );
  280. lineTo( to );
  281. line.draw( renderer );
  282. // draw arrow head
  283. float size = Math.min( 0.3f, length / 2 );
  284. Vector3f dir1 = tmp2.set( direction ).cross( ARROWHEAD_AXIS ).normalizeLocal().multLocal( size );
  285. Vector3f dir2 = tmp3.set( direction ).cross( dir1 ).normalizeLocal().multLocal( size );
  286. direction.multLocal( 0.2f );
  287. lineFrom( tmp4.set( to ).subtractLocal( direction ).addLocal( dir1 ) );
  288. line.draw( renderer );
  289. lineFrom( tmp4.set( to ).subtractLocal( direction ).subtractLocal( dir1 ) );
  290. line.draw( renderer );
  291. lineFrom( tmp4.set( to ).subtractLocal( direction ).addLocal( dir2 ) );
  292. line.draw( renderer );
  293. lineFrom( tmp4.set( to ).subtractLocal( direction ).subtractLocal( dir2 ) );
  294. line.draw( renderer );
  295. }
  296. }
  297. private static void lineTo( Vector3f geometryPivot ) {
  298. BufferUtils.setInBuffer( geometryPivot, line.getVertexBuffer( ), 1 );
  299. }
  300. private static void lineFrom( Vector3f from ) {
  301. BufferUtils.setInBuffer( from, line.getVertexBuffer( ), 0 );
  302. }
  303. public static void setupDebugGeom( Geometry debugShape ) {
  304. debugShape.setRenderQueueMode( Renderer.QUEUE_SKIP );
  305. debugShape.setColorBuffer( null );
  306. debugShape.setLightCombineMode( Spatial.LightCombineMode.Off );
  307. }
  308. }
  309. /*
  310. * $log$
  311. */