Hi all,
I have been trying to get a sphere to roll in the direction of the camera, similar to how BB8 from Star Wars or a Sphero ball.
self.character.setHpr(self.character,0,self.z_velocity *-5 *deltaTime * (math.cos(math.radians(self.playerBase.getH()))),(self.z_velocity * deltaTime *5* (-math.sin(math.radians(self.playerBase.getH())))))
One thing to note is that they work perfectly individually, so If roll is set to 0, the ball would rotate perfectly in the pitch axis whereas if pitch is set to 0 in the command above and roll remains unchanged, it would roll perfectly, if I combine the two movements it wouldnât work and the rotation is a bit wonky.
The full code is available here, specifically player.py
(code above is at line 250), and once again, if any parts of the code needs explaining, I am happy to clarify them 
In that case, why not set its HPR relative to the camera, rather than relative to the character?
If you want to prevent skipping when the camera is rotated without the ball being updated, you might be able to get the characterâs relative HPR, modify that, and then set the result relatively. Iâm not sure that this will work, but it seems like it might.
Otherwise, some quaternion-based rotation should work, using the cameraâs coordinate-vectors as axes.
2 Likes
I agree with @Thaumaturge , though make your code easier to read.
will have a go at implementing this, thanks! 
1 Like
Still no luck 
self.playerHolder.setY(self.playerBase, (self.z_velocity * deltaTime))
self.quat = self.playerBase.getQuat()
self.forwardQuat = self.quat.getRight()[0]
self.rightQuat = self.quat.getForward()[0]
# ,self.z_velocity*-10*deltaTime * self.forwardQuat
self.character.setHpr(self.character,0,self.z_velocity*-10*deltaTime * self.forwardQuat,self.z_velocity*10*deltaTime * self.rightQuat)
GitHub also updated.
[EDIT]
The code above is essentially the same as the original one, so I am in doubt whether the way Iâve coded it matches what you had in mind.
Ah, not quite. I was thinking that you could construct a rotation-quaternion based on the cameraâs vectors (via âsetFromAxisAngleâ method of the âQuatâ class), and then apply that to the sphereâs quaternion in order that the rotation take effect.
(I think that this is done by multiplying the quaternions, but I forget exactly how this works offhand. Quaternions were never something that I really got into! ^^; )
1 Like
Oh that makes sense, thanks a lot!
Iâve been looking at the documentation and old forum posts, it seems like there is a minimal amount explanation to what goes into the two parameters (especially in my case). So do you mind clarifying what âangleâ and âaxisâ I should feed into setFromAxisAngle?
As I understand it, a quaternion can be thought of as a rotation around an axis-vectorâlike turning something around a central rod.
So, in âsetFromAxisAngleâ, the âaxisâ is this axis-vectorâthe vector around which the thing will be rotatedâand the angle is the amount by which to rotate it.
1 Like
Iâve got this:
axis = camera.getHpr()
axis.normalize()
angle = (self.z_velocity*deltaTime*-5)
quat = Quat()
quat.setFromAxisAngle(angle,axis)
newVec = quat.xform(self.character.getHpr())
self.character.setHpr(newVec)
and Iâm getting
line 252, in playerUpdate
quat.setFromAxisAngle(angle,axis)
AssertionError: IS_THRESHOLD_EQUAL(axis.length(), 1.0f, 0.001f) at line 302 of built1.10/include/lquaternion_src.I
HPR values donât form an axisâtheyâre a set of angles. (And if all said angles are zero, using them as a vector produces a zero-length vector, which may be the source of your problem.)
Iâd suggest instead getting the cameraâs ârightâ-vector, like so:
vec = camera.getQuat().getRight()
That is to say, getting the quaternion representation of the cameraâs orientation, and then requesting the ârightâ vector from that representation.
Similarly, I donât think that using the characterâs HPR values will workâyouâd likely want to get the characterâs quaternion, apply your quaternion to that one, and then set the characterâs orientation to be the result of that operation.
1 Like
Okay, worked on this and I got this so far, wanted to make sure I got this right before implementing it onto the actual character
axis = camera.getQuat().getRight()
axis.normalize()
angle = (self.z_velocity*deltaTime*-5)
quat = Quat()
quat.setFromAxisAngle(angle,axis)
newVec = quat*self.playerBase.getQuat()
Any changes needed? self.playerBase
is the parent (or grandparent) of all the nodes in the player scene graph that consists of the model and the camera, so I felt it would be more necessary to take the quad of that rather than self.character
which is the 3D model node.
Honestly, this is the point at which Iâd likely be experimenting myself to find a working form. ^^;
That said, Iâd likely work with âself.characterâ rather than the parent-nodeâthat way one can just update the new rotation from the current. (Presuming that itâs âself.characterâ that you intend to rotate.)
Indeed, I think that at the moment it wonât produce quite the right result, as it would presumably always be starting from the same base value, and thus not continue from its orientation as of the previous frame.
As Iâm not all that familiar with quaternions myself, I donât know whether that last line has the two quaternions the right way around, offhand. Swapping their order is something that I might have in mind if the result doesnât look right.
(By the way, Iâm not sure that you need to normalize the right-vectorâI think that itâs provided already unit-length. But as long as itâs not a performance issue, itâs likely pretty much harmless.)
1 Like
I have this so far (and I have tried another approach)
axis = camera.getQuat().getRight()
axis.normalize()
angle = (self.z_velocity*deltaTime*-5)
quat = Quat()
quat.setFromAxisAngle(angle,axis)
newVec = self.character.getQuat() * quat
print(newVec.getHpr())
if self.z_velocity > 0:
self.character.setHpr(newVec.getHpr())
It moves correctly but only in one direction, plus I wasnât sure where I can set the pitch rotation.
I am going experiment/play around with the code above more to see if I finally get a satisfactory result. If you see something above that needs fixing please let me know.
Hmm⌠Iâm not sure of whatâs going wrong, but I can suggest a few experiments to try:
- When you create ânewVecâ, perhaps try swapping âquatâ and âself.character.getQuat()â.
- I honestly donât remember which way around quaternion composition goes, and thus whether what you have is correct or not.
- Since âself.characterâ isnât attached directly to the root of the scene-graph, perhaps try setting its orientation relative to that root.
- In this case, when constructing your final rotation you would presumably want to get âself.characterâ's current rotation-quaternion relative to the root of the scene-graph, too.
By the way, you donât need to convert to HPR in order to apply your quaternionâyou should be able to just directly set it. Like so:
self.character.setQuat(newQuat)
Or to set it relative to another node (just as with âsetHprâ, âsetScaleâ, âsetPosâ, etc):
self.character.setQuat(otherNode, newQuat)
1 Like
The day has finally come where I think Iâve (or letâs say weâve) solved it!
axis = self.playerBase.getQuat().getRight()
angle = (self.z_velocity*deltaTime*-5)
quat = Quat()
quat.setFromAxisAngle(angle, axis)
newVec = self.character.getQuat()*quat
#print(newVec.getHpr())
if self.z_velocity > 0:
self.character.setQuat(newVec)
Thanks a lot for your help @Thaumaturge 
1 Like
If welcomed, I could actually take a short amount of time during the next 2 weeks creating a sample program based on this.
1 Like
Ah, congratulations and well done on getting it working! Iâm glad for you! 
1 Like