Physics mouse impulse -

mouse_impulse_legacy.blend (552.5 KB)
2.5x

3.x+
mouse_impulse_weight.blend (1.0 MB)

3 Likes

openXR - Controller Impulse - UPBGE 0.3.6+

I will add the file in a moment

Awesome work man. Cant wait to test this out. But I new on this site and cant share my blends for others to test out, but I do got a link: https://drive.google.com/file/d/1kcMonBjGswDR5f4AaEjLs_9SZdvI9VrZ/view?usp=sharing

It s supposed to be a particle and a trail system.

Here is a video stating my problem.

For the direction indicator here some help:

Instead of numpy you can use mathutils and Gameobject features.
https://upbge.org/docs/latest/api/bge.types.KX_GameObject.html

To get the ground normal you have to use a raycast

Put this at the top
from mathutils import Vector

and in the main() of cubeLogic:

    # getting linear velocity vector
    lv = own.worldLinearVelocity.copy()
    lv[2] = 0  # get rid of z axis for smoother movement of the indicator when e.g. jumping
    
    if lv.magnitude > 0.5:
        other_object.alignAxisToVect(lv,0,1)  # align x axis to velocity vector

    # raycast onto ground to get hitnormal        
    oo_ray = other_object.rayCast(other_object.worldPosition+Vector([0,0,-1]),other_object.worldPosition, 0)
    if oo_ray[0] != None: 
        other_object.alignAxisToVect(oo_ray[2],2,1)  #align z axis to hitnormal
    else:
        other_object.alignAxisToVect(Vector([0,0,1]),2,1)  #align z axis to world z-axis
1 Like

As @musikai said, use mathutils instead of numpy if you can. You don’t need to use any arctan calculations to get euler angles to align to a vector, instead you can simply do own.worldLinearVelocity to get the mathutils vector object that is pointing towards your current linear velocity.

Using that, you can simply use alignAxisToVect to align to that vector, or alternatively use quaternion interpolation (slerp) which will give you a smoother rotation than alignAxisToVect (in my experience at least). I’ve attached an example for slerp below (it’s made for UPBGE 0.2.5, but the code should work in any version I think)

Generally, you want to avoid using euler angles whenever you can because gimbal lock can cause wacky issues, but sometimes it’s unavoidable.

rotateQuatExample.blend (725.7 KB)

1 Like

The alpha fading of your trail can be fixed by adding some nodes to the material shader:

1 Like

xr_impulse_test2.blend (1.0 MB)

import bpy,bge,math,mathutils
Vector = mathutils.Vector
Quaternion  = mathutils.Quaternion
xr = bpy.context.window_manager.xr_session_state
cont = bge.logic.getCurrentController()
own = cont.owner
if cont.sensors['Always'].positive:
    if own['TimeR']>0:
        own['TimeR']-=1
    if own['TimeL']>0:
        own['TimeL']-=1    
    if xr:
        Loc1 = xr.controller_grip_location_get(bpy.context,0)
        Rot1 = Quaternion(xr.controller_grip_rotation_get(bpy.context,1)).to_matrix()
        
        Loc2 = xr.controller_grip_location_get(bpy.context,1)
        Rot2 = Quaternion(xr.controller_grip_rotation_get(bpy.context,0)).to_matrix()
        sca = Vector([1,1,1])
        
        control_matL = mathutils.Matrix.LocRotScale(Loc1, Rot2, sca)
        
        control_matR = mathutils.Matrix.LocRotScale(Loc2, Rot1, sca)
        
        triggerR = xr.action_state_get(bpy.context,'blender_default','teleport',"/user/hand/right")
        triggerL = xr.action_state_get(bpy.context,'blender_default','teleport',"/user/hand/left")
        
        if triggerR[0]>.5:
            #print('fire')
            if 'GrabbedR' not in own and own['TimeR']==0:
                start = Loc2 
                end =  Loc2 + (Rot1 @ Vector([0,-25,0]))
                bge.render.drawLine(end,start,(0,0,1))
                ray = own.rayCast(end,start,0,"Phys",0,0,0)
                
                own.scene.objects['Plane'].worldPosition = start
                E = end
                own.scene.objects['Plane'].visible = True
                if ray[0]:
                    E = ray[1]
                    #print('hit')
                    own['TimeR']=15
                    grab = ray[0]
                    rotDiff = Rot1 @ ray[0].worldOrientation
                    localOb = ray[0].worldTransform.inverted() @ ray[1]
                     
                    control_local = control_matR.inverted() @ ray[1]
                    own['GrabbedR'] = [ grab, rotDiff, localOb, control_local]
                    print('set')
                diff_P = E-start
                D = diff_P.magnitude
                own.scene.objects['Plane'].localScale = [1,D,1]
                own.scene.objects['Plane'].alignAxisToVect(diff_P.normalized(),1,1)   
        else:
            own.scene.objects['Plane'].visible = False
            if 'GrabbedR' in own:
                del own['GrabbedR']        
        if 'GrabbedR' in own:
            own.scene.objects['Plane'].worldPosition = Loc2
            world =  own['GrabbedR'][0].worldTransform @ own['GrabbedR'][2]
            ang = -(Loc2-world).normalized()
            own.scene.objects['Plane'].alignAxisToVect(ang,1,1)
            var = .1
            if  own['GrabbedR'][3].length>3:
                 own['GrabbedR'][3]*=.95
            else:
                var = .25     
            
            c_pos = control_matR @ own['GrabbedR'][3]
             
             
            V=world-c_pos
            own['GrabbedR'][0].applyImpulse(world, -V*((V.length*V.length)*.25))
            own['GrabbedR'][0].applyForce((0,0,9.8*own['GrabbedR'][0].mass*.5),0)
            own['GrabbedR'][0].worldLinearVelocity*=.925
            rot = Rot1 @ own['GrabbedR'][1]
            own['GrabbedR'][0].worldOrientation =  own['GrabbedR'][0].worldOrientation.lerp(rot,var)     
            own['GrabbedR'][0].worldAngularVelocity*=.925
            
        if triggerL[0]>.5:
            #print('fire2')
            if 'GrabbedL' not in own and own['TimeL']==0:
                start = Loc1 
                end =  Loc1 + (Rot2 @ Vector([0,-25,0]))
                bge.render.drawLine(end,start,(0,0,1))
                ray = own.rayCast(end,start,0,"Phys",0,0,0)
                
                own.scene.objects['Plane2'].worldPosition = start
                E = end
                own.scene.objects['Plane2'].visible = True
                if ray[0]:
                    E = ray[1]
                    #print('hit2')
                    own['TimeL']=15
                    grab = ray[0]
                    rotDiff = Rot2 @ ray[0].worldOrientation
                    localOb = ray[0].worldTransform.inverted() @ ray[1]
                     
                    control_local = control_matL.inverted() @ ray[1]
                    own['GrabbedL'] = [ grab, rotDiff, localOb, control_local]
                    print('set')
                diff_P = E-start
                D = diff_P.magnitude
                own.scene.objects['Plane2'].localScale = [1,D,1]
                own.scene.objects['Plane2'].alignAxisToVect(diff_P.normalized(),1,1)   
        else:
            own.scene.objects['Plane2'].visible = False
            if 'GrabbedL' in own:
                del own['GrabbedL']        
        if 'GrabbedL' in own:
            own.scene.objects['Plane2'].worldPosition = Loc1
            world =  own['GrabbedL'][0].worldTransform @ own['GrabbedL'][2]
            ang = -(Loc1-world).normalized()
            own.scene.objects['Plane2'].alignAxisToVect(ang,1,1)
            
            var = .1
            if  own['GrabbedL'][3].length>3:
                 own['GrabbedL'][3]*=.95
            else:
                var =.25     
            c_pos = control_matL @ own['GrabbedL'][3]
             
             
            V=world-c_pos
            own['GrabbedL'][0].applyImpulse(world, -V*((V.length*V.length)*.25))
            own['GrabbedL'][0].applyForce((0,0,9.8*own['GrabbedL'][0].mass*.5),0)
            own['GrabbedL'][0].worldLinearVelocity*=.925      
            rot = Rot1 @ own['GrabbedL'][1]
            own['GrabbedL'][0].worldOrientation =  own['GrabbedL'][0].worldOrientation.lerp(rot,var)     
            own['GrabbedL'][0].worldAngularVelocity*=.925
                
            
        
                            
1 Like

Sorry we abused your thread. :ninja:
Anim8D_Ideas better opens his own thread in

or


Finally (after 1 and 2 answered above) for question 3 about the force fields:
I think I see an effect if I set Distance in the Force Field Properties of the Dirt to something higher than 0:
grafik

oh, this quat-rotation works great, much better than alignAxisToVect, especially for 3rd person 180degree turns!! Thanks for the blend!!!

if you all were talking about physics mice it would be different,

you sort of thread jacked me.

:expressionless:

1 Like

haha, good idea to actually try your file!
It’s fun and has much to explore!
Reducing the damping by increasing the values feels nice and more directly :

         own['target'][0].worldLinearVelocity = world*.9
         own['target'][0].worldAngularVelocity*=.9

But then the steady mouse up-motion also speeds up.
removing
var=var*var*var*var
helps.

Draw line color looks nice reddish this way and prevents zero division:

         value = 1  
         if diff.length>0: value = 1/diff.length
         bge.render.drawLine(world,mouse2,(1,value,value))

Holy s*** - This is an awesome Juggler-Game!!!
Thanks for these gems!

PS: max velocity = 20 on the cubes makes it easier
mouse_impulse_weight2.blend (982.5 KB)

1 Like

I’ll probably make a separate thread for this, since it seems to be useful

I guess it might also be good to prevent collisions with a character mesh, maybe with collision groups so you can avoid the exploit in a lot of Source games where the player just jumps on the item they are grabbing. Problem is, if you use disableDynamics() then you can’t apply forces and impulses so groups are needed. Is there any API to add and remove objects to a new collision group? Or does it have to be done ahead of time