BACK

TRACKING AN ENEMY BY POINTING AT IT.

Bones transformations with lingo - the transform() object

transform() by definition....
the code thingamy that contains rotation, position and scale

If I want to make the head or guns of my character look or point at an enemy whilst in range, the only code I can use in lingo to rotate a bone is;

member("3d").model[1].bonesPlayer.bone[7].transform = ................

This is great because only the bone that im manipulating stops animating!
Hmmm a catch. My vector math skills will need an upheaval to solve one slightly larger than little problem problem...

Most but not all transform rotations are inverted. All bones on my model are at transform.position.y zero.

What I have been doing:
I have been using a camera (not rendered!) which will serve as null goal object for the head bone. If all goes well, if the camera faces north then the head faces north too.

IDEAL edge would be: model[1].bonesPlayer.bone[7].transform = camera[1].transform

see example movie no#1 here

The next point.- a useful bit of code to be called when in range of enemy....

tP = model("enemy").transform.position
camera[1].pointAt(tP ,vector(0,1,0))          -- ( tP , world up vector)

Abra Cadabra - The camera rotates to face the enemy. Hmmm if only the head did too!

What actually happens is... when I turn the camera null left the head faces right. When I turn the camera null upward the head faces downward. if I inverse() the transform I get other anomalies. Which made we wonder about editing the transform() object directly

-- Welcome to Director --
t = transform() --create new transform object
put t
-- transform(1.00000,0.00000,0.00000,0.00000, 0.00000,1.00000,0.00000,0.00000, 0.00000,0.00000,1.00000,0.00000, 0.00000,0.00000,0.00000,1.00000)

put t[1] , t[16] --report the 1st and 16th items in the list
-- 1.0000 1.0000

As I found, it is easy to target the different values in the transform() object

I know that "transform.position's" always inhabit item no's. 13,14,15 in the list; X, Y, Z respectively. What I need to know is, where are the rotations in this list ?

I did the following test...

Created a new transform() object;

LIST POSITION 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

t = transform()

1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0

Rotated 3 different versions of this object on either the X, Y, or Z axis and tracked the changes.

LIST POSITION 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
X axis rotation 1.0 0.0 0.0 0.0 0.0 0.2 0.9 0.0 0.0 -0.9 0.2 0.0 0.0 0.0 0.0 1.0
 Y axis rotation  0.2  0.0  -0.9  0.0  0.0  1.0  0.0  0.0  0.9  0.0  0.2  0.0  0.0  0.0  0.0  1.0
  Z axis rotation  0.2  0.9  0.0  0.0  -0.9  0.2  0.0  0.0  0.0  0.0  1.0  0.0  0.0  0.0  0.0  1.0

Ok ! so that left 6 values untouched..... and each some overlapped with 2 others !

Lets look at scaling an object using another new transform()

t = transform()
t.scale(11,12,13)

LIST POSITION 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

t.scale = (11,12,13)

11.0 0.0 0.0 0.0 0.0 12.0 0.0 0.0 0.0 0.0 13.0 0.0 0.0 0.0 0.0 1.0

Hmmm.... these values also overlap the previous. I guess I cant change

these values by extracting and replacing the list values.

 

I'll have to try this....

-- Welcome to Director --

t = transform() -- create a new transform
put t
-- transform(1.00000,0.00000,0.00000,0.00000, 0.00000,1.00000,0.00000,0.00000, 0.00000,0.00000,1.00000,0.00000, 0.00000,0.00000,0.00000,1.00000)
put t.rotation -- vector( 0.0, 0.0, 0.0 )
put t.position -- vector( 0.0, 0.0, 0.0 )
put t.scale -- vector( 1.0, 1.0, 1.0 )

put t.rotation.x -- 0.0

Ok so I can target the Y transform.rotation this way. What I need to do next is

invert() only that information and pass it on to a transform which I can use to rotate the head correctly.

-- Welcome to Director --

t = transform() --create new transform object
t.rotate(7,9,8) -- rotate it
put t -- report it
-- transform(0.97808,0.13746,-0.15643,0.00000, -0.11926,0.98554,0.12037,0.00000, 0.17072,-0.09907,0.98033,0.00000, 0.00000,0.00000,0.00000,1.00000)
t2 = t -- duplicate it
t2.invert() -- invert() the duplicate
t.rotation = t2.rotation -- change the original rotation to an inverted rotation
put t -- report it ( notice the change ! )
-- transform(0.97808,-0.11926,0.17072,0.00000, 0.13746,0.98554,-0.09907,0.00000, -0.15643,0.12037,0.98033,0.00000, 0.00000,0.00000,0.00000,1.00000)

I could do this -->
t.rotation.y = t2.rotation.y
!

I could also do this -->
t.rotation.y = t2.rotation.z !

In a word I thought - WHA-LAH ! Finally an answer - but it went deeper. the head now rotated side to side diagonally

Im not going to explain why, but multiplying the results by pi (3.1416) returned results twice the amount wanted
so it needed to be divided by 2, and the other result needed to be inverted so I multiplied it by minus 1.


t.rotation.z = (( tx.rotation.x * pi ) * -1 ) / 2
t.rotation.x = ( tx.rotation.y * pi ) / 2
w.model[1].bonesPlayer.bone[14].transform = t

To save some frame rate for something more important ill find out that amount myself

-- Welcome to Director --
put (pi * - 1 ) / 2
-- -1.5708

The finished version;

on handler (me)
t = w.camera("head null").getworldtransform() -- get the transform() of the camera null
tx = t -- duplicate it
t.rotation.z = tx.rotation.x * -1.5708 -- change thecurrent values to the desired values
t.rotation.x = tx.rotation.y * 1.5708 -------------------------------------------------
w.model[1].bonesPlayer.bone[14].transform = t -- then apply them
end

The next step was to make the Camera Null pointat() the enemy,

NB: I will have to set some limits so that if within a
certain distance the head will only track a certain degree relative to itself
otherwise it will look straight ahead as normal.

See the finished example here