Open topic with navigation
Physics Shapes
Physics shapes is what becomes of a node3d object once it has a collision
area defined. When a node3d object has a collision area defined it gains
certain properties that allows it to interact with forces as well as other
physics objects.
Physics objects can be created by the following methods:
collideBox
The collision area around the object is a
box that is structured to fit as close as possible around the object.
Optionally an x,y,z component can be added to define the size of the box.
ground = viz.add('tut_ground.wrl') # Add ground
ground.collidePlane() #
Make collideable plane
logo = viz.add('logo.wrl',pos=[0,2,6],euler=[0,0,30]) # Add logo
logo.collideBox(bounce=1.5) # Collide and make it bounce a bit
logo.add('box.wrl',alpha=.2,scale=logo.getBoundingBox(viz.REL_LOCAL).size)
# Show bounding area
Note: The last line is only there to show
what the collision area looks like. It is not necessary for the creation
of the physics object and only works with objects that are centered at
0,0,0.
collideSphere
The collision area around the object is a
sphere which can take an optional radius parameter. See how the following
varies from the previous:
ground = viz.add('tut_ground.wrl') # Add ground
ground.collidePlane() #
Make collideable plane
logo = viz.add('logo.wrl',pos=[0,2,6],euler=[0,0,30]) # Add logo
logo.collideSphere(bounce=1.5) # Collide and make it bounce a bit
scale = max(logo.getBoundingBox(viz.REL_LOCAL).size)/2.*10 # Calculate scale
logo.add('white_ball.wrl',alpha=.2,scale=[scale,scale,scale])
# Show bounding area
Note: The last 2 lines
are only there to show what the collision area looks like. With this notice
how the scale is calculated for the collision area of a sphere. Vizard
internally creates a bounding box around the object and then takes 1/2
the max of height, width, and depth to be used as the radius. Since the
radius of white_ball is .1 the scale must be 10 times the radius.
collideCapsule
The collision area around
the object is a sphere with a cylinder inserted between the two halves
of the sphere. The collideCapsule method calculates the length of the
cylinder along the object's z-axis, so to use this the elongation must
be along the object's z-axis.
ground = viz.add('tut_ground.wrl') # Add ground
ground.collidePlane() #
Make collideable plane
logo = viz.add('logo.wrl',pos=[0,2,8],euler=[0,89,30],scale=[.5,.5,3]) # Add logo
logo.collideCapsule(bounce=1.5) # Collide and make it bounce a bit
Note: There is no simple
way to build the visualization of a collision area for a capsule. However
the radius of the sphere that is used for the ends is calculated by taking
1/2 the max of the objects width, and height. The length the of cylinder
is then the objects depth minus the diameter of the sphere.
collideMesh
The collide mesh builds
the collision area of the object exactly as the object itself is built.
Collide
mesh objects are unaffected by forces and can only provide a solid collision
area for other objects. The following example demonstrates this:
viz.phys.setGravity(0,-9.8/6,0)
#Half Gravity
ground = viz.add('tut_ground.wrl') # Add ground
ground.collidePlane() #
Make collideable plane
logo = viz.add('logo.wrl',pos=[0,1,6])
# Add logo
logo.collideMesh(bounce=1.5) # Collide and make it bounce a bit
for x in range(10):
for
z in range(10):
ball = viz.add('white_ball.wrl',pos=[-.5+.1*x,2.5+.1*z,6],scale=[.5,.5,.5])
ball.collideSphere()
collidePlane
Collide plane creates a collision plane based
on the objects initial position. The collision plane does not move with
the object so should only be called once the object is in the appropriate
place.
viz.phys.setGravity(0,-9.8/6,0)
#Half Gravity
ground1 = viz.add('tut_ground.wrl',euler=[0,0,-30])
r = viz.Matrix.euler(0,0,-30).getUp() # Calculate
Normal
r.append(0)
# Add length
ground1.collidePlane(*r) # Collide
Plane
ground2 = viz.add('tut_ground.wrl',euler=[0,0,30])
r = viz.Matrix.euler(0,0,30).getUp() # Calculate normal from euler.
r.append(0)
# Add length
ground2.collidePlane(*r) # Collide
Plane
for x in range(10):
for
z in range(10):
ball = viz.add('white_ball.wrl',pos=[-.5+.1*x,2.5+.1*z,6+.01*z],scale=[.5,.5,.5])
ball.collideSphere()
collideCopy
Collide copy performs
exactly as it seems it should. Once an collision area is defined for an
object, duplicating the collision area is as simple as calling collideCopy
on the new object using the old object as the parameter.
In the following example
a collision area is defined for one table, and then copied to the next:
table = viz.add('table.wrl',pos=[0,3,6.5],euler=[90,45,90]) # Add table
table.collideBox(node='Leg1') # Define
table.collideBox(node='Leg2') # collision
table.collideBox(node='Leg3') # area
table.collideBox(node='Leg4') # for
table.collideBox(node='Top') # parts
table.disable(viz.DYNAMICS) # Disable
dynamics
table2 = viz.add('table.wrl',pos=[0,1,6.5],euler=[90,45,90]) # Add second table
table2.collideCopy(table) # Copy collision
properties
for x in range(10):
for
z in range(10):
ball = viz.add('white_ball.wrl',pos=[-.5+.1*x,2.5+.1*z,6+.01*z],scale=[.5,.5,.5])
ball.collideSphere()
collideNone
This function removes and previously defined
collision area. This in turn disables physics on the object.
logo = viz.add('logo.wrl',pos=[0,1,6])
# Add logo
logo.collideMesh(bounce=1.5) # Collide and make it bounce a bit
logo.collideNone()
Invisible Physics Shapes
Turing a node's visibility off disables its physics. If you want to
retain the physics of a node and not have it appear there are two options:
1. Use a nested object
Create a group and add the object you wish
to set invisible to it. Enable physics on the root object and then disable
visibility on the child object.
2. Disable rendering and
depth_write
Create the object as normal and then assuming
the object is named "a":
a.disable(viz.RENDERING)
a.disable(viz.DEPTH_WRITE)
Disabling Dynamic Forces and Collisions
The physics of a node are controlled through two properties, dynamics
and contacts which are enabled by default. When dynamics is enabled the
node reacts to forces such as gravity. When contacts is enabled collisions
may occur. In
order for these properties to have any effect physics must be enabled
on the node.
Example 1 - Disabling contacts before enabling
physics
import viz
viz.go()
viz.clearcolor(viz.GRAY)
viz.phys.enable() # Enable
physics
ground = viz.add('tut_ground.wrl') # Add ground
ground.collidePlane() #
Make collideable plane
ball = viz.add('ball.wrl',pos=(0,1.8,6)) # Add a ball
ball.disable(viz.CONTACTS) #
Disable collisions
ballPhys = ball.collideSphere(bounce=1.5) # Define ball's physical
properties (enables physics)
# This example shows the ball pass through the ground plane.
Example 2 - Disabling dynamics before enabling
physics
import viz
viz.go()
viz.clearcolor(viz.GRAY)
viz.phys.enable() # Enable
physics
ground = viz.add('tut_ground.wrl') # Add ground
ground.collidePlane() #
Make collideable plane
ball = viz.add('ball.wrl',pos=(0,1.8,6)) # Add a ball
ball.disable(viz.DYNAMICS) #
Disable dynamics
ballPhys = ball.collideSphere(bounce=1.5) # Define ball's physical
properties (enables physics)
# In this example the ball does not
fall due to gravity once physics is enabled.
See also
In this section:
Physics basics
Physics Shapes - In depth discussion of the
collide methods.
Forces - More detail on applyForce and applyTorque.
Joints - In depth overview of the joint types.
Motors - In depth explanation of how each motor
works with each joint.
Physics Command Table
Other sections:
Tutorial: Physics
Event Reference
Example scripts:
Basic physics
Tracking an object
Collision plane
Callbacks & complex shapes
Forces & materials