Vizard 7 » Reference » Physics » Physics shapes
7.5

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