Physics File Format

From OLPC
Jump to: navigation, search

There has been some discussion on how to share 2D scenes between the various Physics frameworks, activities, etc. This is bug #7585.

Here is a proof of concept, presented here for the purposes of discussion. Comments, feedback, counter proposals are all welcome. See also Talk:Physics_File_Format

It was developed for the Mac OS X application Physix written by Jminor The format is XML and is meant to map directly to concepts, names and features of Box2D. It was inspired by a similar format made by ken [1] as part of the Elements project.

Here is a simple example:

<!-- Physix.app v1.0 -->
<world lowerBound="-10,-10" upperBound="14,18" gravity="0,-9.81">

	A square and circle balanced on a teeter-totter.

    <body name="window"><box size="4,3" sensor="1"/></body>

    <body name="ground" position="0,0" static="1">
        Make a hollow box that is 4 wide and 8 tall.  The upper half is off screen,
        so objects can go off the top, but they can't get away entirely.
        <box offset="0,4" size=".1,8"/>
        <box offset="2,0" size="4,.1"/>
        <box offset="4,4" size=".1,8"/>
        <box offset="2,8" size="4,.1"/>
    </body>
	
    <body name="pivot" position="2,0" static="1">
        <box size="1,1" rotation="45"/>
    </body>
    <body name="platform" position="2,.75">
        <box size="2,.2" density="2" restitution=".5" friction=".15"/>
    </body>
	<revoluteJoint body1="pivot" body2="platform" anchor="2,.65"/>
	
    <body name="box" position="1.5,3" rotation="0">
        <box size=".355,.355" rotation="0" density="1" restitution=".5" friction=".15"/>
    </body>
	
    <body name="circle" position="2.5,3">
        <circle radius=".2" density="1" restitution=".15" friction=".5"/>
    </body>
</world>

The defined tags, attributes and structure are as follows. Note that most attributes are given default values if they are not present in the XML. Most defaults are 0. All rotations are in degrees. All 2D vectors are specified as two numbers separated by a comma (see examples for clarity). Booleans are 0 or 1. Distances are measured in meters.

  • world
    • sleep = 0 or 1 indicating whether settled objects are allowed to sleep to save computation
    • lowerBound and upperBound = 2D vectors defining the lower and upper corners of the simulation's bounds (different from the visible window, see below)
    • attribute: gravity = 2D vector defining the value of gravity in meters per second per second (default = 0,-9.81 which is roughly Earth's gravity)
    • children: body, *joint or repeat elements
  • body
    • name = the name for this body. This is used when specifying the anchors for a joint.
    • static = boolean defining whether this body is fixed in place or a dynamic part of the simulation.
    • position = 2D vector for the origin/center of this body.
    • rotation = rotation in degrees.
    • children: 1 or more shapes (box, circle, polygon)
  • box, circle or polygon
    • density = density (kilograms per square meter?) of this shape (default = 1)
    • restitution = measure of how springy this shape is (usually between 0 and 1) (default = 0.15)
    • friction = measure of how rough or slippery this shape is (0 = very slick, 1 = very rough) (default = 0.5)
    • layers = which collision layers does this shape occupy (default = "A")
    • mask = which collision layers does this shape interact with (default = "ABCDEFGHIJKLMNOP")
    • sensor = boolean specifying whether this shape is used purely for sensing collisions or not (default = 0)
    • box also has these attributes
      • rotation = rotation in degrees.
      • size = 2D vector of width, height.
      • offset = 2D vector offset relative to the parent body (default 0,0)
    • circle also has these attributes
      • radius = distance from center to edge of the circle
    • polygon also has these attributes
      • vertices = list of 2D vectors specifying the points in this polygon. The list is a string of 2D vectors separated by spaces. (As of Box2D 2.0, the vertices should be in clockwise order and must be convex.)
      • offset = 2D vector offset relative to the parent body (default 0,0)
  • repeat = the children of this element are duplicated a number of times with an offset and/or rotation between each repetition
    • count = the number of repetitions (default = 1)
    • offset = 2D vector defining the offset applied between each repetition
    • center = 2D vector defining the base offset applied to the first repetition (in other words: the origin of the children)
    • rotation = rotation in degrees between each repetition
  • distanceJoint
    • body1 = the name of the body that one end of the joint is attached to (or "ground")
    • body2 = the name of the body that the other end of the joint is attached to (or "ground")
    • anchor1 = 2D vector of the world coordinates of the 1st end of the joint -- or the name of an object who's center is used as the 1st anchor
    • anchor2 = 2D vector of the world coordinates of the 2nd end of the joint -- or the name of an object who's center is used as the 2nd anchor
  • revoluteJoint
    • body1 = the name of the body that one end of the joint is attached to (or "ground")
    • body2 = the name of the body that the other end of the joint is attached to (or "ground")
    • anchor = 2D vector of the world coordinates of the joint -- or the name of an object who's center is used as the anchor point
    • torque = if this joint is a motor then it can apply this much angular force (default 0)
    • speed = if this joint is a motor then it tries to maintain this speed in degrees per second (default 0)
    • a revoluteJoint is a motor if either torque or speed are not 0.
  • window
    • to set the visible window to something other than the bounding box of the whole scene, make a box called "window" with sensor=1. This causes it not to render or interact with anything and will be used as the visible window when rendering.
  • room for improvements
    • add other supported joint types
    • allow polygons to be concave and oriented either way
    • add a grouping mechanism similar to repeat, but just for applying an xform to a group of objects (workaround is to use repeat with count=1)
    • add scale to repeat/group
    • add a way to specify default values for a group of bodies, shapes, etc.
    • allow joint anchors to be specified in world coordinates without naming the bodies (detect them at run time) - for an example of how to do this, see the JointUtils class in PulpFizz, which has methods to do this for revolute and distance joints (in Java).
    • formalize the way that named joint anchors work when multiple bodies have the same name (e.g. pick the last one with that name)
    • turn the special "window" object into a real element.
    • add text labels
    • add color, stroke, fill, etc.
    • add contact handling ability - need some sort of function callback system that can be specified from the XML (might be difficult to do in a cross-language manner, maybe provide some built in responses/triggers?)

See also: Talk:Physics_File_Format

Another example that uses nested repeat tags:

<!-- Physix.app v1.0 -->
<world lowerBound="-10,-10" upperBound="18,16" gravity="0,-9.81" sleep="1">
  <body name="window"><box size="8,6" sensor="1"/></body>

	Tower of bricks with a wrecking ball.

    <body name="border" position="0,0" static="1">
        <box offset="4,0" size="8,.1"/>
    </body>

    <body name="ball" position="2,2">
        <circle radius=".325" density="100" restitution=".95" friction=".5"/>
    </body>
	<distanceJoint body1="ground" body2="ball" anchor1="2,6" anchor2="2,2"/>

  <repeat count="6" center="2.75,0.05" offset="0,.75">
	  <repeat count="6" center="0,0.25" offset=".5,0">
		<body name="tall"><box size=".25,.5" density="10" friction=".95"/></body>
	  </repeat>
	  <repeat count="5" center="0.25,0.625" offset=".5,0">
		<body name="wide"><box size=".5,.25" density="10" friction=".95"/></body>
	  </repeat>
  </repeat>
  
</world>

...insert more examples...

For more examples see the files ending with .physix inside this source bundle [2]