API Question Animationstates, Mesh instances and mesh modifications[SOLVED]

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,882
Reaction score
2,133
Points
203
Location
between the planets
Ok, next problem... I'm probably going to have a few of those before these animations behave they way they're supposed to.

Item1: I can create an animation from config file at runtime, and it works. I can save the animation state to scenario and load it, and it works (i.e. the animation picks up where it left off).

Item2: I can add meshes dynamically at runtime to a vessel, rotate, align and position them correctly, including any docking ports they might have, with proper direction and up vectors... the whole thing is tested pretty well by now, and errors in the rotation are a thing long past. So this works.
Of note for the problem might be that I am not using mgroup_transform for rotating the meshes, because graphics client compatibility. Instead, I'm physically moving the vertices of the mesh instance in question.

Item3: I can add a mesh with an animation dynamically at runtime to a vessel, properly rotate the mesh and the animation, and it all works splendidly.

Problem: I can not do item3, then save the state of the animation and reload it. [scratch]The animation breaks appart in that case.[/scratch] The animation starts and runs however much is left of it, but visually, it always starts at zero. So if the initial state is, for example, 0.5, the animation will execute the animation steps from 0.5 through 1, but will apply it to the 0.0 configuration of the mesh. So that can look a bit weird...

Question 1: From what I can tell, all data for an animation (like center of rotation, translation, axis, that stuff) is mesh relative, not vessel relative. I.E. the animation should always be added to the vessel with these things relative to the mesh, no matter where on the vessel that mesh is loccated. Is that observation correct?

Question 2: When creating a new animation with CreateAnimation, I have to supply a state which is the animation state of the unmodified mesh. Presumably orbiter then calculates the positions of the vertices in an animation group from the mesh template using the animation state... but in my case, the mesh template would not actually have the same alignement as the rotated mesh, because the mesh was rotated by moving the vertices without telling orbiter. As far as I can see, this should make the animation fail entirely when the mesh is rotated. Also, while the animation is messed up when loaded with an initial state <> 0, it is still evident that it goes in the right direction and along the right plane. so I'm understanding something wrong. Does orbiter never modify the mesh instance and instead just moves the vertices when rendering them?

Question 3: While the answer to above questions might give me a pointer as to where my problems lie, that still doesn't quite explain why an animation can work perfectly fine when it starts at zero, but not if it starts at, say, 0.5. As I figure it, Orbiter should be capable to derive any state of the animation without relying on incremental steps. CreateAnimation() only declares the state that conforms to the mesh as it is on file, when you create an animation. There's an undocumented SetAnimState() function of which I don't know what it does, though. So do I have to set the initial state of the animation in some way if the animation doesn't start at zero?

---------- Post added 10-25-15 at 12:41 PM ---------- Previous post was 10-24-15 at 06:53 PM ----------

A little update, on the above, as I can now see very clearly what the animation is doing:

The animation starts at the initial state loaaded from config and runs however much is left of it, but visually, it always starts at zero. So if the initial state is, for example, 0.5, the animation will execute the animation steps from 0.5 through 1, but will apply it to the 0.0 configuration of the mesh. So that can look a bit weird.

What I seem to be missing is a way to tell orbiter from which initial position to calculate the state positions of the vertices. Whatever I tried, the animation always takes the 0.0 state as origin. Changing the argument of CreateAnimation() seems to have no effect whatsoever, by the way.

Here's the code that creates the animation (it currently only does rotations, the rest will come once I have those working properly):


Create a rotation component:

Code:
MGROUP_ROTATE *IMS_Animation_Base::createRotationComponent(ANIMCOMPONENTDATA *comp, VECTOR3 modulelocalpos, MATRIX3 moduleorientation)
{
	//create an array for the groups and copy them over
	UINT *groups = new UINT[comp->groups.size()];
	for (UINT j = 0; j < comp->groups.size(); ++j)
	{
		groups[j] = comp->groups[j];
	}

	//get the rotation reference and transform it to the modules alignement within the vessel
	VECTOR3 rotreference = comp->reference;
	rotreference = mul(moduleorientation, rotreference);
	Calc::RoundVector(rotreference, 1000);
//	rotreference += modulelocalpos;

	//doing the same with the rotation axis
	VECTOR3 rotaxis = comp->axis;
	rotaxis = mul(moduleorientation, rotaxis);
	normalise(rotaxis);


	//bunch it all together into an MGROUP_ROTATE object
	return new MGROUP_ROTATE(
		meshindex,
		groups, comp->groups.size(),
		rotreference,
		rotaxis,
		(float)RAD_PER_DEGREE * comp->range);
}




Create the animation on the vessel:
Code:
void IMS_Animation_Base::AddAnimationToVessel(IMS2 *_vessel, int _meshindex, MATRIX3 moduleorientation, VECTOR3 modulelocalpos)
{
	vessel = _vessel;
	meshindex = _meshindex;

	//create animation on vessel and remember the orbiter ID 
	orbiterid = vessel->CreateAnimation(0.0);

	//create the animation on the vessel. We need to temporarily store the handles
	//for parent-child relations
	vector<ANIMATIONCOMPONENT_HANDLE> animcomponents;
	for (UINT i = 0; i < data->components.size(); ++i)
	{
		ANIMATIONCOMPONENT_HANDLE parent = NULL;
		int parentidx = data->components[i].parent;

		//check if the component has a parent
		if (parentidx > -1)
		{
			//sanity check in case the writer of the config file screwed up and declared a wrong order
			if (parentidx >= (int)animcomponents.size())
			{
				Helpers::writeToLog(string("ERROR: parent-child animations must be declared in order!"));
				return;
			}
			parent = animcomponents[parentidx];
		}

		if (data->components[i].type == "rotate")
		{
			animcomponents.push_back(vessel->AddAnimationComponent(orbiterid, data->components[i].duration[0], data->components[i].duration[1],
				createRotationComponent(&data->components[i], modulelocalpos, moduleorientation),
				parent));
		}
	}
	vessel->SetAnimation(orbiterid, state);

}



And here's the function that updates the animation:

Code:
Event_Base *IMS_Animation_Sequential::PropagateAnimation(double simdt)
{

	//check if the animation is running at all
	if (speed != 0)
	{
		//calculate how much the state propagates in the passed time and update it
		//this is where the abstract speed value becomes an actual speed in combination with the animation's default duration
		//if speed is 1 or -1, the animation will need duration seconds to complete. 
		state += simdt / data->duration * speed;

		//check if the animation has finished or not, in both directions
		if (state <= 0 || state >= 1)
		{
			//set the state to its boundaries and stop the animation
			state = max(state, 0);
			state = min(state, 1);
			speed = 0;
		}
		//set the state of the animation in orbiter
		vessel->SetAnimation(orbiterid, state);
		
		//if the animation has finished, return the event.
		if (speed == 0)
		{
			return new AnimationFinishedEvent(data->id);
		}
	}
	
	return NULL;
}


---------- Post added at 10:08 PM ---------- Previous post was at 12:41 PM ----------

Ok, got it figured out. The problem was that the meshes were rotated after the animations were created on the vessel. I wasn't aware of this anymore, because I wrote that code some time ago and didn't remember that I had to put off the rotation of the meshes until after the visuals were created, which only happens after the first clbkPreStep, while I thought that I was rotating them at the same time I added them to the vessel, which would have been in clbkPostStep.

Now, I'll have to see what that means when the visual gets destroyed... :shifty:
 
Last edited:
Top