Skip to content
Häfner edited this page Apr 2, 2021 · 5 revisions

The Snapping Engine is a module that allows to introduce much more complex interaction in a virtual scene than just drag and drop. It extends drag and drop by applying custom snapping rules to the dragged object. This makes positioning objects easy and precise. Another important benefit is the snapping callback which allows the application to use a snap as a trigger, for example for configuration systems or production processes. There is an snapping example, snapping.pvr.

To setup the snapping do:

import VR

if hasattr(VR, 'scene'): VR.scene.destroy()
VR.scene = VR.Object('scene', 'light')

VR.snapping = VR.SnappingEngine()
VR.snapping.enableGhosts(True)

Use VR.snapping.addObject(obj, 0) to add objects to the snapping engine, the second parameter is a group ID, this allows to apply different snapping rules to each objects group.

Here is an example scene:

def addBlock(p, c):
	box = VR.Geometry('block')
	box.setPrimitive('Box 1 1 1 1 1 1')
	box.setColor(c)
	box.setPose(p)
	box.setPickable(True)
	VR.scene.addChild(box)
	VR.snapping.addObject(box, 0)
	return box
	
def addBrickAnchor(brick, pos, g, sg): # we use different g and sg for top and bottom anchors
	a = VR.Transform('anchor')
	a.setFrom(pos)
	brick.addChild(a)
	VR.snapping.addObjectAnchor(brick, a, g, sg)

def addBrick(p):
	brick = VR.Geometry('brick')
	brick.setPrimitive('Box 1 0.6 0.5 1 1 1')
	brick.setColor('white')
	brick.setFrom(p)
	brick.setPickable(True)
	VR.scene.addChild(brick)
	VR.snapping.addObject(brick, 1) # put in grp 1 to only snap with other bricks
	addBrickAnchor(brick, [-0.25, 0.3, 0], 0, 1)
	addBrickAnchor(brick, [ 0.25, 0.3, 0], 0, 1)
	addBrickAnchor(brick, [-0.25,-0.3, 0], 1, 0)
	addBrickAnchor(brick, [ 0.25,-0.3, 0], 1, 0)
	p = VR.Pose() # default pose
	VR.snapping.addRule('POINT', 'POINT', p, p, 1.0, 1, brick)
	
	
# create scene

b1 = addBlock(VR.Pose([0,0,0], [0,0,-1], [0,1,0]), 'red')
b2 = addBlock(VR.Pose([2,0,0], [0,0,-1], [0,1,0]), 'green')
b3 = addBlock(VR.Pose([0,2,0], [0,0,-1], [0,1,0]), 'orange')

for i in range(1,5):
	addBrick([-i*0.8-1,0,i])

This scene also uses VR.snapping.addObjectAnchor(obj, anchor, group, snapgroup). This allows to add transforms, anchors, to the object which are used for snapping instead of the object coordinate system. group and snapgroup are IDs for the anchor, the first one is the group ID of the anchor, the second one is the groupID of anchors this anchor snapps to. This is NOT related to the object group IDs.

Here come a few examples of snapping rules:

# snap to global origin
p = VR.Pose() # default pose
VR.snapping.addRule('POINT', 'POINT', p, p, 1.2, 0)

# snap on top of red cube
VR.snapping.addRule('POINT', 'POINT', VR.Pose([0,1.0,0]), p, 1.2, 0, b1)

# snap right of red cube
VR.snapping.addRule('POINT', 'POINT', VR.Pose([1.0,0,0]), VR.Pose([0,0,0],[1,0,1]), 1.2, 0, b1)

the first two parameters define the type of snapping, POINT, LINE or PLANE:

  • the first is the translation snapping
  • the second is the orientation snapping, only POINT is supported for now!

the next two parameters are poses that define the snapping positions:

  • the first pose defines the translation primitive
    • for a POINT it defines the position
    • for a LINE it defines a line point and line direction
    • for a PLANE it defines a plane point and plane normal
  • the second pose defines the orientation primitive
    • for a POINT it defines a fixed orientation when snapping

the fifth parameter is the snapping distance.

the sixth parameter is a group ID, the rule applies to the snapping objects in the same group.

the last parameter is optional and defines a local referential for the snapping rule.

Clone this wiki locally