mouse_impulse_legacy.blend (552.5 KB)
2.5x
3.x+
mouse_impulse_weight.blend (1.0 MB)
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
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)
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
Sorry we abused your thread.
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:
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.
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)
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