Author Topic: Questions about triggered animation  (Read 15566 times)

0 Members and 1 Guest are viewing this topic.

Re: Questions about triggered animation
Hmmm I've just learned something, makes things a bit more difficult.

Let's say the subobject has world orientation of (0,0,0) [for simplisitic sake]
Now let's rotate it (-90,0,0).  It looks good. but now let's look at the p/h/b and this is what we get: p=88 h~=180 b~=180

So now let's derotate it (90,0,0).  Things get all goofed up

edit: Hmmm.. think I might have to have SetupAnimation to include the starting orientation and destination orientation to work right.
« Last Edit: December 14, 2012, 02:56:36 am by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
if you have a starting orientation that is good (door looks closed), and an ending orientation that is good (door looks open), you should just be able to interpolate between them in theory (and assuming the interpolation algorithm is singularity free and fully linear, such as with slerp).
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Partly because of this:
88,0,0
89,0,0
90.1,180,180
91,180,180

if you want to move from (89,0,0) to (0,0,0) [(89,0,0)-(0,0,0) = (89,0,0)]
but:  (91,180,180) to (0,0,0) [(91,180,180)]  breaks rotation, and i can't tell if it's just because of the rotation that's caused or if it's a legit 180 rotation

but anyways the start orientation and end orientation works pretty good.  But I have noticed something a bit odd.... if you rotate on more than one axis, sometimes one axis will get ahead of the other then the other will quickly catch up.  Not really sure what's causing that, the delta's do not change
Code: [Select]
local newP = animation.originalOrientation.p + animation.deltaP * animation.loop
Outside of that, I don't see any other bugs so far.  :yes:
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Ugh one massive bug  just bit me....  when the local axis != world axis and you try to rotate on certain axises you get rotations that are broken.

For example, let's say you have an object rotate world axis:(-45,0,0) local:(0,0,0)  then you rotate by local:(0,-90,0) to make it appear as if it was opening (like a bay door).  Except it pivots on the world axis so instead of opening like it's on hinges it swing around.  What makes it really weird is local angle (0,0,0) is still on the subsystems local origin, which is completely confusing.

edit: Hmm, one possible if not ugly solution is to force all animated subobjects to be oriented (0,0,0) [world], then use an "init" function to rotate them to the correct starting positions

double edit: ok after two code rewrites I threw away my attempt and started using your code.  So far world=local axis rotation works good, but when they don't match things get messed up.  It keeps on rotating on the world axis.  I'll have to look at it better latter.
« Last Edit: December 14, 2012, 06:36:42 pm by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Ha ha... I kinda got something working.  It's a bit awkward, but it works. 
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
good to here you got it working, i was running out of ideas. only other thing was to delve into quaternions, which im not too good with thus far. a slerp interpolation, which only works with quats, would give better interpolation. its kind of like walking across the surface of a 4 dimensional sphere, and im kinda worried that my head would explode if i go there. heres some code for slerp (at least i hope this is, i based this off some c code i found on the internet).

Code: [Select]
--slerp interpolare between qa* and qb* by interpolation value int
function slerp(qaW, qaX, qaY, qaZ, qbW, qbX, qbY, qbZ, int)
local cosHalfTheta = qaW * qbW + qaX * qbX + qaY * qbY + qaZ * qbZ
--handle inverted quats
if cosHalfTheta < 0 end
qbW = -qbW
qbX = -qbX
qbY = -qbY
qbZ = qbZ
cosHalfTheta = -cosHalfTheta
end
--if qa=qb or qa=-qb then theta = 0 and we can return qa
if math.abs(cosHalfTheta) >= 1.0 then
return qaW, qaX, qaY, qaZ
end
--Calculate temporary values.
local halfTheta = math.acos(cosHalfTheta)
local sinHalfTheta = math.sqrt(1.0 - cosHalfTheta*cosHalfTheta)
--if theta = 180 degrees then result is not fully defined
--we could rotate around any axis normal to qa or qb
local w,x,y,z
if math.abs(sinHalfTheta) < 0.001 then
w = (qaW * 0.5 + qbW * 0.5)
x = (qaX * 0.5 + qbX * 0.5)
y = (qaY * 0.5 + qbY * 0.5)
z = (qaZ * 0.5 + qbZ * 0.5)
return w,x,y,z
end
local ratioA = math.sin((1 - int) * halfTheta) / sinHalfTheta
local ratioB = math.sin(int * halfTheta) / sinHalfTheta
--calculate Quaternion.
w = (qaW * ratioA + qbW * ratioB)
x = (qaX * ratioA + qbX * ratioB)
y = (qaY * ratioA + qbY * ratioB)
z = (qaZ * ratioA + qbZ * ratioB)
return w,x,y,z
end

note that this takes quaternions (w,x,y,z) and not eulers. and just plug the return values into the arbitrary axis function to create a matrix that you can actually use from the result. you may need this to convert eulers to quaternions as well:
Code: [Select]
function eulerToQuat(p,y,r)
    local c2 = math.cos(p/2)
    local s2 = math.sin(p/2)
local c1 = math.cos(y/2)
    local s1 = math.sin(y/2)
    local c3 = math.cos(r/2)
    local s3 = math.sin(r/2)
    local c1c2 = c1*c2
    local s1s2 = s1*s2
local W = c1c2*c3 - s1s2*s3
local X = c1c2*s3 + s1s2*c3
local Y = s1*c2*c3 + c1*s2*s3
local Z = c1*s2*c3 - s1*c2*s3
return W,X,Y,Z
end

ive never tested either of these so dont know if they are right. p,y,r is pitch, yaw and roll (which may be different order from freespace, im not sure). so essentially create two quaternions from your euler angles, then interpolate between them with slerp, and finally convert them to matrix with arbitraryAxisMatrix(). but this is kind of unfamiliar territory for me and none of the code has been tested.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Yikes.. looks nasty lol

basically right now, the subobject's axis must match the worlds.  Just call an Initialize function that'll rotate it to the desired location.  Then you can call the rotate animations whenever you want. It still needs some work and lot of testing...
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Ugh... for lua being a nice dynamic language.. it's taking longer to do stuff than C#  :ick:
Where the heck is variable declarations and classes?  :hopping:
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
i kinda wrote a tutorial for that:

http://www.hard-light.net/forums/index.php/topic,45303.0.html

granted im a lot better with this stuff now than when i wrote it. but really when it comes right down to it is to use tables as your object, and assign a metatable which lets you overload operators and the like. tutorial should cover the basics of operator overloading and member functions.

e:
i guess i hadn't figured out member functions yet when i wrote it. i may give the tutorial a part 2. but essentially you create a table which contains member functions (i call it a metamethods table) and then in your metatable you just set __index = metamethodstable. i usually have it set up like:

Code: [Select]
--metamethods
aclass_me = {}
aclass_me:getX()
 return self.x
end
aclass_me:setX(newX) --lol
 self.x = newX
end
--metatable (bare minimum to make member funcs work)
aclass_mt = {
--this makes member funcs work
__index = aclass_me
}
--constructor
aclass(X)
 a = {}
 if X then
  a.x = X
 else
  a.x = 0
 end
 return setmetatable(a, aclass_mt)
end
--example
foo = aclass()
bar = foo:getX()
foo:setX(bar^2)

should point out that this isnt as strict as classes in language like c# or c++, there are countless variations.
« Last Edit: December 16, 2012, 06:56:52 am by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
I've kinda gotten back into the ole' C style object's being passed as params to function style.
Oh and Polish notation for naming variables :P
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Demo example!  ignore the stuttering at the beginning, that's fraps.
https://www.youtube.com/watch?v=B_SnBfShjT4&feature=youtu.be
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
 
Re: Questions about triggered animation
For now the subsystem's axis must match that of the ships.  In the F3 viewer they will look off, but ingame it automatically sets them up properly.  I'm making it easy enough to code the subsystems in though:

Code: [Select]
local Closed = CreateOrientation (0,0,0)
local ZeroOffset = Closed
local OpenPort = CreateOrientation (0, math.rad (-90), 0)
local OpenStar = CreateOrientation (0, math.rad ( 90), 0)

RegisterLandingGearSubsystem (p_subsystemList, "FrontLandingGear", ZeroOffset, Closed, CreateOrientation (math.rad(-90), 0, 0), 1.5, 1.5 )
RegisterLandingGearSubsystem (p_subsystemList, "PortMainLandingGear", ZeroOffset, Closed, OpenPort, 1.5, 1.5)
RegisterLandingGearSubsystem (p_subsystemList, "StarMainLandingGear", ZeroOffset, Closed, OpenStar, 1.5, 1.5)
RegisterLandingGearSubsystem (p_subsystemList, "PortDoor01", ZeroOffset, Closed, OpenPort, .5, 2.5)
RegisterLandingGearSubsystem (p_subsystemList, "PortDoor02", ZeroOffset, Closed, OpenPort, .5, 2.5)
RegisterLandingGearSubsystem (p_subsystemList, "PortDoor03", ZeroOffset, Closed, OpenPort, .5, 4.5)
RegisterLandingGearSubsystem (p_subsystemList, "StarDoor01", ZeroOffset, Closed, OpenStar, .5, 2.5)
RegisterLandingGearSubsystem (p_subsystemList, "StarDoor02", ZeroOffset, Closed, OpenStar, .5, 2.5)
RegisterLandingGearSubsystem (p_subsystemList, "StarDoor03", ZeroOffset, Closed, OpenStar, .5, 4.5)

That's pretty much all you have to do, just register the subsystems with the script and when you have FRED call "OpenLandGear" it'll know which subsystems to rotate and do it all by itself.  Same with closing them.  Right now I'm working on the thrust vector part.  Working pretty good except for one small part, when you rotate from a little less than 359 to a little more than 1, it gets messed up.  Thinks it's delta changed 300+ degrees in a frame.  I also want to do a sweeping motion (like on real jet radio systems) and thrust nozzle sizing.


Ugh... ship pitch rotation goes as follows:
{0.0001......89.99999, -89.99999....-0.0001,.0001......89.99999, -89.99999....-0.0001}  for a complete 360 loop.  Not sure how to handle this.   89 - (-89) != 2
« Last Edit: December 18, 2012, 05:16:15 am by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
transform a 0'0'1 vector by the matrix, then use atan2 on its components (the two that are not the axis you want the rotation for). theres probibly a better way to do this but idk.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
I'm going to do some if-then around the 90 degree point.  I'll post it when I get it working.

edit: i was wrong, probably why my methods were failing big time
it's:
0,10,20,30.....70,80,89,89,80,70,......30,20,10,0,-10,-20,-30.....-80,-89,-89,-80,-70....-20,-10,0

back to scratchpaper to find the solution
« Last Edit: December 19, 2012, 01:04:43 am by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

  

Offline Aardwolf

  • 211
  • Posts: 16,384
Re: Questions about triggered animation
What are those numbers supposed to mean? Are they angles?

Nuke, what are you doing  :ick: The beauty of quaternions is that you can slerp just by lerping each component separately.

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
What are those numbers supposed to mean? Are they angles?

Nuke, what are you doing  :ick: The beauty of quaternions is that you can slerp just by lerping each component separately.

i said it was untested and probibly didnt work :D, care to show me something that does?
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Ya that's the pitch of the craft as it does a loop-de-loop.  For some reason I'm getting sudden negative flips on the delta pitches between two frames.  i.e.  1.2, 1.2,1.1,1.2,1.2,1.1,1.2,-2,-2.1,-1,9....

edit: i suppose I could watch for neg/pos change on an angle that's too large for normal use.
something like:
Code: [Select]
if (sign(delta) != sign (previousDelta)
   changeDelta = delta - previousDelta
   if (changeDelta > TOO_BIG)
« Last Edit: December 19, 2012, 01:47:04 am by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
I think I see the problem, just can't seem to see a solution

source - dest = delta
75 - 80 = -5
80 - 85 = -5
85 - 90 = -5
90 - 85 = 5
even though your still rotating at the same degrees per second in the same direction.
I can't check H or B because the ship might actually be banking, rotating in those directions too.
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Aardwolf

  • 211
  • Posts: 16,384
Re: Questions about triggered animation
We need more people giving him conflicting suggestions!

subsystem.Orientation is relative to the ship, right? Maybe try this:

Code: [Select]
function AddAnimationToQueue(ship, subsystem, destOrientation, ttl)

local now = mn.getMissionTime()

local animation =
{
ship = ship,
subsystem = subsystem,
startOri = EulerToQuaternion(subsystem.Orientation), -- idk the implementation for this (never used euler angles)
endOri = EulerToQuaternion(destOrientation),
startTime = now,
endTime = now + ttl
}

table.insert(animationQueue, animation)

end

function ProcessAnimation(animation)

-- calculate lerp coefficients
local b = (mn.getMissionTime() - animation.startTime) / (animation.endTime - animation.startTime)
local a = 1.0 - b

local slerped =
{
w = animation.startOri.w * a + animation.endOri.w * b,
x = animation.startOri.x * a + animation.endOri.x * b,
y = animation.startOri.y * a + animation.endOri.y * b,
z = animation.startOri.x * a + animation.endOri.z * b
}

animation.subsystem.Orientation = QuaternionToEuler(slerped) -- idk this one either

end

Big differences: instead of storing a TTL and deltas, it stores a start and end time and orientation. And orientations are converted to quaternions to make slerp nicer. Er... do you have quat-to-euler and euler-to-quat? If not you can probably find those online somewhere.