Rotating A StaticShape to Orient Towards Another
by Michael Greene · in Torque 3D Beginner · 12/28/2012 (5:58 pm) · 14 replies
For a project I'm working on, I'm trying to get an "energy cable" static shape to correctly orient itself between two other objects. Getting it to be the correct length is of no consequence and is just a matter of scaling it by the distance. Getting it to point in the correct direction on the other hand is another matter entirely and is something I've been beating my head against the wall with for a while now. This is largely because I just don't have the knowledge of the math involved.
I have seen the following before (see reply #3) http://www.garagegames.com/community/forums/viewthread/129813
Unfortunately, when I've tried pointToPos(%posOne,%posTwo), the effect has been rather.. lackluster. Since in my searches, I've seen this several times, perhaps I just need to hook this in in a different way than I am?
The following is my current implementation:
Instead of orienting between the two objects, the cable is instead parallel with the y-axis of the world. Ideas for why this may be/suggestions for a fix?
I have seen the following before (see reply #3) http://www.garagegames.com/community/forums/viewthread/129813
Unfortunately, when I've tried pointToPos(%posOne,%posTwo), the effect has been rather.. lackluster. Since in my searches, I've seen this several times, perhaps I just need to hook this in in a different way than I am?
The following is my current implementation:
// Spawn Energy Cable
%start = %reactor.position;
%end = %obj.position;
%rot = pointToPos(%start,%end);
%cable = new StaticShape() {
canSaveDynamicFields = "1";
Enabled = "1";
position = %reactor.position;
rotation = %rot;
scale = "1.0" SPC VectorDist(%start,%end) SPC "1.0";
doDistanceFade = "0";
startFadeDistance = "10";
endFadeDistance = "500";
teamIndex = %reactor.Owner.teamIndex;
dataBlock = "EnergyCable";
receiveSunLight = "1";
receiveLMLighting = "0";
useCustomAmbientLighting = "0";
customAmbientLighting = "0 0 0 1";
usePolysoup = "1";
polysoupDL = "0";
};Instead of orienting between the two objects, the cable is instead parallel with the y-axis of the world. Ideas for why this may be/suggestions for a fix?
#2
And merely setting the rotation to the vector (normalized or not) didn't in my experience result in anything useful but rather an orientation that was always incorrect. The cable was always correct in one plane but completely wrong in another.
12/29/2012 (9:25 am)
pointToPos is a function given at the aforementioned location: reply 3 of http://www.garagegames.com/community/forums/viewthread/129813And merely setting the rotation to the vector (normalized or not) didn't in my experience result in anything useful but rather an orientation that was always incorrect. The cable was always correct in one plane but completely wrong in another.
#3
Not sure why that's not working. Indeed seems to do nothing
12/30/2012 (10:40 am)
// And this lil function generates the rotation required for an object at posOne
// to point at PosTwo for X, Y And Z axis.
function pointToPos(%posOne, %posTwo)
{
// sub the two positions so we get a vector pointing from the origin in the
// direction we want our object to face
%vec = VectorSub(%posTwo, %posOne);
// pull the values out of the vector
%x = firstWord(%vec);
%y = getWord(%vec, 1);
%z = getWord(%vec, 2);
// this finds the distance from origin to our point
%len = vectorLen(%vec);
//---------X-----------------
// given the rise and length of our vector this will give us the angle in radians
%rotAngleX = mATan(%z, %len);
//---------Z-----------------
// get the angle for the z axis
%rotAngleZ = mATan(%x, %y);
// create 2 matrices, one for the z rotation, the other for the x rotation
%matrix = MatrixCreateFromEuler("0 0" SPC %rotAngleZ * -1);
%matrix2 = MatrixCreateFromEuler(%rotAngleX SPC "0 0");
// now multiply them together so we end up with the rotation we want
%finalMat = MatrixMultiply(%matrix, %matrix2);
// we're done, send the proper numbers back
return getWords(%finalMat, 3, 6);
}Not sure why that's not working. Indeed seems to do nothing
#4
12/31/2012 (9:53 am)
Just to note, returning the numbers from that pointToPos() helper method doesn't actually make object A look at object B, you still have to use them in a call to setTransform() for the action to take place.
#5
12/31/2012 (10:09 am)
He is defining the rotation numbers from his function in the object creation however.
#6
That's what I get for posting without testing first.... lol
I suppose the better thing would be to create the object and immediately call setTransform() rather than trying to directly set the value. I've noticed that with some objects (or perhaps under certain circumstances) setting the parameters in the "constructor" fails to perform as expected, but setting them immediately following the object's creation works.
12/31/2012 (10:41 am)
Ah - see, that's where I was sort of curious. I knew that would get the vector but I wasn't sure if setTransform() takes a vector or if it expects a full rotation transform - obviously it's the second case reading the results.That's what I get for posting without testing first.... lol
I suppose the better thing would be to create the object and immediately call setTransform() rather than trying to directly set the value. I've noticed that with some objects (or perhaps under certain circumstances) setting the parameters in the "constructor" fails to perform as expected, but setting them immediately following the object's creation works.
#7
That worked , thanks a bunch : )
12/31/2012 (4:52 pm)
%p2p = pointToPos(%start,%end); %pos = getWords(%cable.getTransform(), 0, 2); %cable.setTransform(%pos SPC %p2p);
That worked , thanks a bunch : )
#8
12/31/2012 (11:55 pm)
Quote:I've noticed that with some objects (or perhaps under certain circumstances) setting the parameters in the "constructor" fails to perform as expected, but setting them immediately following the object's creation works.Sounds like bug report material! Though in initPersistFields, SceneObject's rotation member is defined as a TypeMatrixRotation. Does is mean it expects a full matrix? One way to check would be to echo someObj.rotation in the console and see what sort of data type you get back.
#9
01/01/2013 (9:51 am)
I see Matt already posted, but anyways, thanks again guys.
#10
01/01/2013 (12:22 pm)
Actually it works well if objects are with 10 or 15 meters or so within the same plane. As soon as the second object is way above the first . the beam misses under and when the second object is way below the first, the beam missed above. Anyone know what this is about ?
#11
Thanks,
Matt
01/31/2013 (3:37 pm)
I have been trying with the problem mentioned in my last post and cant really figure out how to test this math to fix it. I also verified the pivot point for the bounds and other objects are in the correct place on the 'beams' anyone have any insight as to why this might happen ? this math is so beyond me.Thanks,
Matt
#12
01/31/2013 (3:50 pm)
This last issue probably has to do with the center of the object.
#13
01/31/2013 (3:58 pm)
I have all the pivot points of the objects/bounds at one end direct center of two X planes. The idea being that it would scale and aim from that point , is that what you mean ?
#14
Also, if that is what is causing the problem you could add half the height of the object to the position to make it aim more at the center of the bounding box.
Maybe a picture or movie showing the problem would help.
01/31/2013 (9:11 pm)
That is sort of what I was thinking. Is it aiming for the pivot point? Is that what causes it to miss? Or does it look like some sort of distance error? Also, if that is what is causing the problem you could add half the height of the object to the position to make it aim more at the center of the bounding box.
Maybe a picture or movie showing the problem would help.
Torque Owner Richard Ranft
Roostertail Games
So, add a script function like so:
function pointToPos(%startPos, %targetPos) { return VectorSub(%targetPos, %startPos); }That'll get you a vector to the other object - and I think passing that in as your object's rotation should aim it at the target object. Give it a shot, and watch your game's console.log file for error messages - it helps.