get hit normal of ray and use to align object to "local gravity"


import bge
cont = bge.logic.getCurrentController()
from mathutils import Vector
own = cont.owner
scene = bge.logic.getCurrentScene()
sen = cont.sensors["Ray"]


# get the normal of object face
face_normal = sen.hitNormal


own['Normal']=str(face_normal)
target = sen.hitobject


axisZ = face_normal
quat = axisZ.rotation_difference(Vector((0,0,1)))
vec = Vector(quat.to_euler())
vecmag = vec.magnitude
torque = own['Force']*1


own.applyTorque(torque*vec*vecmag,0)



axisZ = face_normal is the line that needs work

the hit normal is a list, and I need a axis derived from it,

any help would be appreciated.

code


import bge


# get player and cube
scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
player = cont.owner
cube = scene.objects['Cube']


# cast ray
hitNormal = player.rayCast(cube, player)[2]


# make gravity vector
gravityVec = -hitNormal
gravityVec.magnitude = 9.8


# apply gravity to player
player.applyForce(gravityVec)

axisZ = own.worldOrientation.col[2] #needs replaced
quat = axisZ.rotation_difference(Vector((0,0,1)))
vec = Vector(quat.to_euler())
vecmag = vec.magnitude
torque = own['Force']*1

the section # needs replaced, needs the hitNormal to set a axis of rotation that is the normals axis.

import bge
from mathutils import Vector

get player and cube

scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
player = cont.owner
cube = scene.objects[‘Cube’]

cast ray

hitNormal = player.rayCast(cube, player)[2]
hitNormal2 = player.rayCast(cube, player)[0]

make gravity vector

gravityVec = -hitNormal
gravityVec.magnitude = 9.8

apply gravity to player

player.applyForce(gravityVec)

axisZ = hitNormal2 #needs replaced
quat = axisZ.rotation_difference(Vector((0,0,1)))
vec = Vector(quat.to_euler())
vecmag = vec.magnitude
torque = player[‘Force’]1
player.setAngularVelocity((0,0,0),0)
player.applyTorque(torque
vec*vecmag,0)

is what I have now, but the hit normal is not a vector, how would I build a vector using Player and hitNormal?

Why are you using comments? Nothing is less maintained then comments.

As you are using this comments to describe what code is supposed to do, you can simply place this code into a function and give the function the describing name you have in the comment:


import bge
import mathutils

Z_AXIS = 2

def applyForceTowardsCubesNormalAsGravityAndAlignToCubeNormal():
    owner = bge.logic.getCurrentController().owner
    cube = owner.scene.objects['Cube']


    groundNormal = player.rayCast(cube, player)[2]

    owner.applyForce(  convertToGravity(groundNormal ) )
    owner.alignAxisToVect( mathutils.Vector(groundNormal) , Z_AXIS, 1.0) 


def convertToGravity(hitNormal):
    gravityVec = -hitNormal
    gravityVec.magnitude = 9.8


I guess you want to use torque rather than alignAxisToVect
so you replace the call to
owner.alignAxisToVect(mathutils.Vector(groundNormal), Z_AXIS, 1.0)
with a call to an own function
applyRotationToVector(owner, mathutils.Vector(groundNormal), Z_AXIS, 1.0)


def applyRotationToVector(gameObject, targetDirection, localAxisId, strength):
   ...

As KX_GameObject does not return a Vector object but a list, you need to convert the list to a vector with


mathutils.Vector(list)

it is a shame this option is not documented in the API docs.

thanks monster, that does look nice,
I am still learning “neatness”

that was one of raco’s old scripts I was attempting to add to,

if you use ray of brick you not need of rayCast, just transform the hitNormal that return from the ray in to a vector.


import bge
from mathutils import Vector




scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()




own = cont.owner
sen = cont.sensors[0]


hitNormal = sen.hitNormal
if hitNormal: # check before if the ray hit something
    
    hitNormal = Vector(hitNormal) # transform in to Vector
    axisZ = own.worldOrientation.col[2]
    v1 = axisZ
    v2 = hitNormal
    rotDif = Vector(v1.rotation_difference(v2).to_euler())
    rot = own.localAngularVelocity
    rot += rotDif * 0.50 #"elasticity"
    rot *= 0.98 # inertia
    
    own.applyForce(-hitNormal*9.8)#gravity to the normal

PS: there some bugs…(depend how is the rotation)

got it :smiley:

local vs globalAngularVelocity

Attachments

Fixed.blend (449 KB)