Ray Casting for Drag/Drop in 2.53

Hi everyone,

I have a couple of questions:

  1. With generous help from the community(read Monster and Almost) here, I have this script that enables the dragging and dropping of objects. Here it is:
import GameLogic
import Rasterizer
import mousetools
from Mathutils import Vector

motionSpeed = 5
rotationSpeed = 5
#find point on 2D plane of fixed z
#that is between the camera and the hitposition
lowestLevel = 0.5 #this is the fixed z  value

#---- debugging function not really needed
def moveToTargetPosition(cont):
    '''
    Moves the owner of the controller to the position stored 
    in the property "targetPosition" of the owner of the first sensor.
    '''
    try:
        cont.owner.worldPosition = cont.sensors[0].owner["targetPosition"]
    except KeyError:
        pass
#---- utility function
def onePositive(cont):
    for sensor in cont.sensors:
        if sensor.positive:
            return True
    return False
#---- Just to make the cursor visible
def showMouse(cont):
    if not onePositive(cont):
        return
    Rasterizer.showMouse(1)
    print "show Mouse"
    
def hideMouse(cont):
    if not onePositive(cont):
        return
    Rasterizer.showMouse(0)
    print "hide Mouse"

#---- dragging functions        
def storeDraggedObject(own, hitObject):
    if hitObject != None and "drag" in hitObject: 
        own["draggedObject"] = hitObject
    else: 
        own["draggedObject"] = None

def getDraggedObject(own):
    try:
        return own["draggedObject"]
    except:
        return None

def getTargetPosition(overAny, restriction, axis):
    
    raySource = Vector(overAny.raySource)
    hitPosition = Vector(overAny.hitPosition)
    rayVector = hitPosition-raySource
    
    if not "drag" in overAny.hitObject \
    and hitPosition[axis] > restriction:
        targetPosition = hitPosition
    else:
        planeContactPoint = ( restriction-raySource[axis])/rayVector[axis]
        targetPosition = (rayVector*planeContactPoint) + raySource
        
    return targetPosition

#---- BGE callable functions
def startDrag(cont):
    overAny = cont.sensors["overAny"]
    activateDrag = cont.sensors["activateDrag"]
     
    if activateDrag.triggered: #just activated
        storeDraggedObject(cont.owner, overAny.hitObject)

def endDrag(cont):
    activateDrag = cont.sensors["activateDrag"]

    if not activateDrag.positive:# no dragging
        storeDraggedObject(cont.owner, None)
        return

def doDrag(cont):
    overAny = cont.sensors["overAny"]
    activateDrag = cont.sensors["activateDrag"]
    activateRotation = cont.sensors["activateRotation"]
    
    if not activateDrag.positive: #not active
        return
    
    draggedObject = getDraggedObject(cont.owner)
    if draggedObject == None:
        #Nothing to drag
        return

    if overAny.positive:
        restrictedAxis = cont.owner["restrictedAxis"]
        restriction = draggedObject.worldPosition[restrictedAxis]
        targetPosition = getTargetPosition(overAny, restriction, restrictedAxis)
        #just for debugging see moveToTargetPosition
        cont.owner["targetPosition"] = targetPosition
    else:
        return
    
    currentPosition = Vector(draggedObject.position)
    rayToWall = draggedObject.rayCast(targetPosition,draggedObject,0,'wall')
    
    if rayToWall[0] == None:
        targetPosition = targetPosition
    else:
        targetPosition = rayToWall[1]
        
    speed = motionSpeed
    
    vec = (targetPosition - currentPosition)*speed
    
    # only move in motion mode
    if not activateRotation.positive:
        draggedObject.setLinearVelocity(vec,0)

#---- All in one    
def dragDrop(cont):
    overAny = cont.sensors["overAny"]
    activateDrag = cont.sensors["activateDrag"] 
    activateRotation = cont.sensors["activateRotation"]
            
    if not activateDrag.positive:# no dragging
        endDrag(cont)
        return
    
    if activateDrag.triggered: #just activated
        startDrag(cont)
    
    if activateDrag.positive: #activate
        doDrag(cont)

Could someone please outline the changes I need to make to port this to 2.53?

  1. As for the algorithm itself, could someone dilineate what makes a ray casting algorithm faster / more efficient?

Thanks a lot,
Chirag

To convert to 2.53 you must:

  1. Change GameLogic to bge.logic

  2. Change Rasterizer to bge.render

  3. Change “from Mathutils import Vector” to “from mathutils import Vector”

  4. Change and .position attributes to .worldPosition

  5. Any functions that returned a list in 2.49 now return a vector, so .hitPosition, .raySouce, .worldPosition no longer need to be made Vectors because they already are.

Optimisation to the script:

  1. getDraggedObject(own) can be replaced with “draggedObject = cont.owner.get(“draggedObject”, None)”

Other than that it looks like a pretty good script. The ray casting can’t really be optimised by python, its coded in C so the performance can be expected to be pretty decent.

Thanks a lot :slight_smile:

Is there some place I can read about these functions to understand what happens under the hood better? I get the bigger picture rather crudely and the intricacies elude me.

For eg. I want to understand how the vector math behind raycasting works.
And the details behind hitob.
And what is meant by cont.owner[“restrictedAxis”]…I cant find where these things are defined. Is it like the “restrictedAxis” is a property of the owner?

Pardon the ignorance…I feel quite stupid :slight_smile:

Moguri has summed up the difference between 2.49 and 2.5 APIs:
http://blenderartists.org/forum/showthread.php?t=194907

If there is a specific function you are un-aware of you can look it up in the documentation, the documentation includes both the “normal blender” and the GE API. You should make sure you understand the difference in them. The bpy module is the normal blender module and bge is the GE module. All the other modules can be used by both APIs (mathutils, geometry ect)
http://www.blender.org/documentation/250PythonDoc/index.html

cont.owner[“retrictedAxis”] is exactly the property of the object set in the logic editor.

In regards to the ray casting and vector stuff, I am perhaps not the best person to answer that ^.^

P.S, you don’t sound ignorant at all, stupid in regards to the BGE API maybe but not ignorant