SDK Question Defining animations in a Array

Ok I know this is a bit of a necro-post but I've encountered a new issue.

I was working on animating my landing gear and it seems that my prior solution for defining a animation in an array does not tolerate multiple mesh groups. I did not encounter this before simply because each switch is comprise of only a single group (in the case of the needles a single triangle)

My landing gear are a bit more complex, here is the function...

Code:
	static UINT LegGroups[4][3] = {
		{DS_GRP_LandingFoot_FWD, DS_GRP_ShockStrut_FWD, DS_GRP_PrimaryStrut_FWD}, {DS_GRP_LandingFoot_AFT, DS_GRP_ShockStrut_AFT, DS_GRP_PrimaryStrut_AFT},
		{DS_GRP_LandingFoot_PORT, DS_GRP_ShockStrut_PORT, DS_GRP_PrimaryStrut_PORT}, {DS_GRP_LandingFoot_STBD, DS_GRP_ShockStrut_STBD, DS_GRP_PrimaryStrut_STBD} };
	static UINT StrutGroup[4], DownlockGroup[4];

	anim_Gear = CreateAnimation (1.0);
	for (int i = 0; i < 4; i++)
	{
		StrutGroup[i] = DS_GRP_SecondaryStruts_AFT + i;
		DownlockGroup[i] = DS_GRP_Downlock_AFT + i;

		Leg[i] = new MGROUP_ROTATE ( 2, &LegGroups[i][3], 3, LEM_LegPivot[i],LEM_LG_Axis[i], (float) 45*RAD);
		Strut[i] = new MGROUP_ROTATE ( 2, &StrutGroup[i], 1, LEM_StrutPivot[i], LEM_LG_Axis[i], (float)-63*RAD); 
		Downlock[i]	 = new MGROUP_ROTATE ( 2, &DownlockGroup[i], 1, LEM_DownlockPivot[i], LEM_LG_Axis[i], (float) 150*RAD);

		ah_Leg[i] = AddAnimationComponent (anim_Gear, 0, 1, Leg[i]);
		ah_Strut[i] = AddAnimationComponent (anim_Gear, 0, 1, Strut[i], ah_Leg[i]);
		AddAnimationComponent (anim_Gear, 0, 1, Downlock[i], ah_Strut[i]);
	}

Running the animation in Orbiter causes a CTD.

I'm pretty sure it's the "LegGroups" array that is the culprit as when I replace it with a fixed value I don't get the CTD.

My as it stands I''ve managed to get the whole animation sequence to work simply by dropping the "for (int i = 0; i < 4; i++)" manually defining each block of animations in turn but I'd like to why that works and my initial approach didn't.

The latter approach is also rather messy to look at.
 
This cannot be right.

It is a multi dimensional array. 4 sets of mesh groups containing three groups apiece.

The fact that it works when I replace "i" with a constant value (i.e "1") is the source of my confusion. Why would it work outside the "for (int i = 0; i < 4; i++)" statement but not within?
 
To elaborate why this cannot be right:

Code:
	static UINT LegGroups[4][[highlight]3[/highlight]] = {
		{DS_GRP_LandingFoot_FWD, DS_GRP_ShockStrut_FWD, DS_GRP_PrimaryStrut_FWD}, {DS_GRP_LandingFoot_AFT, DS_GRP_ShockStrut_AFT, DS_GRP_PrimaryStrut_AFT},
		{DS_GRP_LandingFoot_PORT, DS_GRP_ShockStrut_PORT, DS_GRP_PrimaryStrut_PORT}, {DS_GRP_LandingFoot_STBD, DS_GRP_ShockStrut_STBD, DS_GRP_PrimaryStrut_STBD} };

{...}

Code:
		Leg[i] = new MGROUP_ROTATE ( 2, &LegGroups[i][[highlight]3[/highlight]], 3, LEM_LegPivot[i],LEM_LG_Axis[i], (float) 45*RAD);

The index is 0 based and you are addressing 4th element of 3-element array.
 
Are you saying that the 3 and 4 should be transposed?

That doesn't seem right either because in a 2-dimenstional array the first initializer is columns and the second rows.

Ordinary animation groups containing multiple meshes are quantified as a single row array. Why would an array with multiple rows be less valid?

ETA:

Likewise this still does not explain why the animation would work as planned when i is replaced with a constant value.
 
Last edited:
I'm just saying that 3rd element of the array has index 2 and not 3.
 
Are you saying that the 3 and 4 should be transposed?

That doesn't seem right either because in a 2-dimenstional array the first initializer is columns and the second rows.

Ordinary animation groups containing multiple meshes are quantified as a single row array. Why would an array with multiple rows be less valid?

Orbiter's API function there takes a pointer to an array of UINTs. Just make your structure flat like so:
Code:
static UINT LegGroups[12] = { 		DS_GRP_LandingFoot_FWD, DS_GRP_ShockStrut_FWD, DS_GRP_PrimaryStrut_FWD, DS_GRP_LandingFoot_AFT, DS_GRP_ShockStrut_AFT, DS_GRP_PrimaryStrut_AFT, 		DS_GRP_LandingFoot_PORT, DS_GRP_ShockStrut_PORT, DS_GRP_PrimaryStrut_PORT, DS_GRP_LandingFoot_STBD, DS_GRP_ShockStrut_STBD, DS_GRP_PrimaryStrut_STBD };

Then you can reference it with simple pointer arithmetic inside your loop like so:
Code:
Leg[i] = new MGROUP_ROTATE ( 2, LegGroups+(i*3), 3, LEM_LegPivot[i],LEM_LG_Axis[i], (float) 45*RAD);
 
I'm just saying that 3rd element of the array has index 2 and not 3.

I know, but I'm not trying to call the 3rd element, I'm calling the entirety of row "i" in which case the "[3]" is appropriate.

---------- Post added at 06:33 PM ---------- Previous post was at 06:33 PM ----------

Orbiter's API function there takes a pointer to an array of UINTs. Just make your structure flat like so:
Code:
static UINT LegGroups[12] = { 		DS_GRP_LandingFoot_FWD, DS_GRP_ShockStrut_FWD, DS_GRP_PrimaryStrut_FWD, DS_GRP_LandingFoot_AFT, DS_GRP_ShockStrut_AFT, DS_GRP_PrimaryStrut_AFT, 		DS_GRP_LandingFoot_PORT, DS_GRP_ShockStrut_PORT, DS_GRP_PrimaryStrut_PORT, DS_GRP_LandingFoot_STBD, DS_GRP_ShockStrut_STBD, DS_GRP_PrimaryStrut_STBD };

Then you can reference it with simple pointer arithmetic inside your loop like so:
Code:
Leg[i] = new MGROUP_ROTATE ( 2, LegGroups+(i*3), 3, LEM_LegPivot[i],LEM_LG_Axis[i], (float) 45*RAD);

Thank you, I'll try that.
 
I know, but I'm not trying to call the 3rd element, I'm calling the entirety of row "i" in which case the "[3]" is appropriate.

C++ doesn't work that way.

If you use the indexer, you'll get the (n+1)th element, that's it.
 
I know, but I'm not trying to call the 3rd element, I'm calling the entirety of row "i" in which case the "[3]" is appropriate.
For getting address of entire row more appropriate would be [0].
 
It is a multi dimensional array. 4 sets of mesh groups containing three groups apiece.

The fact that it works when I replace "i" with a constant value (i.e "1") is the source of my confusion. Why would it work outside the "for (int i = 0; i < 4; i++)" statement but not within?

If you say &LegGroups[1][3], what you actually get is &LegGroups[2][0], which is valid, although probably not what you want. If you try &LegGroups[3][3], you'll get problems, because this address points past the array.

Instead of "&LegGroups[3]", what you probably meant was "LegGroups" or "&LegGroups[0]" or "&LegGroups[i-1][3]" or "&LegGroups[i-248][744]", you get the idea ...
 
Thank you both Orb and Face, I think I've managed to isolate and solve my problem.

After some experimentation it appears that I misinterpreted/didn't account for how the MGROUP_TRANSLATE class interpretted the "UINT _ngrp" component.

_ngrp, tells the animation class to asses each component of an array in turn, in the absense of valid array values it appears to revert to counting through the mesh index.

By starting the count at 3 (an invalid term in this case) the animation reverted to the base meshindex and it seems that my CTDs were being caused by Orbiter trying to animate mesh groups that did not actually exist. (ei "Meshgroup 26" in a mesh that only had 24 groups to begin with)

After shifting LegGroups from [3] to [0] and adjusting the formats of StrutGroup and DownlockGroup to match I have an animation that works.

Here is the working code...
Code:
// Landing gear animations
static MGROUP_ROTATE *Leg[4];
ANIMATIONCOMPONENT_HANDLE ah_Leg[4], ah_Strut[4];
	
static UINT LegGroups[4][3] = {
  { DS_GRP_LandingFoot_FWD, DS_GRP_ShockStrut_FWD, DS_GRP_PrimaryStrut_FWD}, {DS_GRP_LandingFoot_AFT, DS_GRP_ShockStrut_AFT, DS_GRP_PrimaryStrut_AFT},
  { DS_GRP_LandingFoot_PORT, DS_GRP_ShockStrut_PORT, DS_GRP_PrimaryStrut_PORT}, {DS_GRP_LandingFoot_STBD, DS_GRP_ShockStrut_STBD, DS_GRP_PrimaryStrut_STBD}
  };

static UINT StrutGroup[4] = { DS_GRP_SecondaryStruts_FWD, DS_GRP_SecondaryStruts_AFT, DS_GRP_SecondaryStruts_PORT, DS_GRP_SecondaryStruts_STBD};

static UINT DownlockGroup[4] = { DS_GRP_Downlock_FWD, DS_GRP_Downlock_AFT, DS_GRP_Downlock_PORT, DS_GRP_Downlock_STBD};

static UINT LadderGroup = DS_GRP_Ladder;

anim_Gear = CreateAnimation (1.0);
for (int i = 0; i < 4; i++) // Animate legs and gear fold components
{
  Leg[i] = new MGROUP_ROTATE ( 2, &LegGroups[i][0], 3, LEM_LegPivot[i], LEM_LG_Axis[i], (float) 45*RAD); // Landing legs

  Strut[i] = new MGROUP_ROTATE ( 2, &StrutGroup[i], 1, LEM_StrutPivot[i], LEM_LG_Axis[i], (float)-63*RAD); // Support Struts (attatched to legs)

  Downlock[i] = new MGROUP_ROTATE ( 2, &DownlockGroup[i], 1, LEM_DownlockPivot[i], LEM_LG_Axis[i], (float) 150*RAD); // Locking mechanism (joins support struts to body)

  ah_Leg[i] = AddAnimationComponent (anim_Gear, 0, 1, Leg[i]);
  ah_Strut[i] = AddAnimationComponent (anim_Gear, 0, 1, Strut[i], ah_Leg[i]);
  AddAnimationComponent (anim_Gear, 0, 1, Downlock[i], ah_Strut[i]);
}

static MGROUP_ROTATE Ladder ( 2, & LadderGroup, 1, LEM_LegPivot[0], LEM_LG_Axis[0], (float) 45*RAD); // Match ladder's position to front leg.
AddAnimationComponent (anim_Gear, 0, 1, &Ladder);


---------- Post added at 08:00 PM ---------- Previous post was at 07:56 PM ----------

If you say &LegGroups[1][3], what you actually get is &LegGroups[2][0], which is valid, although probably not what you want. If you try &LegGroups[3][3], you'll get problems, because this address points past the array.

Thank you, After some experimentation I figured out that this was what was happeneing as well as what was causing the CTDs. The Landing Gear groups are at the end of the mesh index and "LegGroups[3][3]" was causing the animation to call for meshgroups that did not exist.

---------- Post added at 08:19 PM ---------- Previous post was at 08:00 PM ----------

Ok, new problem.

Something I did broke my switch animations.

I haven't touched anything else VC since I started working on the Landing Gear so I'm not sure hat it could be.

---------- Post added at 08:53 PM ---------- Previous post was at 08:19 PM ----------

Update.

Something has caused my definitions from cockpitmesh.h (my meshc index file for the VC) to be ignored

P3RotaryGroups = VC_GRP_RSwitch_P3_01 + i;

should be be read as P3RotaryGroups = 65 + i;

not

P3RotaryGroups = 0 + i;
 
Something I did broke my switch animations.

I haven't touched anything else VC since I started working on the Landing Gear so I'm not sure hat it could be.

After shifting LegGroups from [3] to [0] and adjusting the formats of StrutGroup and DownlockGroup to match I have an animation that works.


Well, you've changed the numbers there. Maybe one of your macros is wrong now? Before that refactoring, you've used programmatic assignment. Now you're using fixed defines for the numbers in those group arrays.

I have to admit that I find it a bit tiring to guess along code snippets, that's why I prefer open source. Do you have the code hosted anywhere by any chance? Having a bigger picture might help to spot problems faster...

regards,
Face
 
I have to admit that I find it a bit tiring to guess along code snippets, that's why I prefer open source. Do you have the code hosted anywhere by any chance?


While I make a point to include copies of my addons' source files as SDK samples as a matter of general principal.

I learned much of my orbiter-fu by tearing the stock atlantis apart line by line and asking questions on this very forums and it just seems rude to deny that kind of resourse to others.

I never really felt the need for online hosting as I kind run a one-man show. That said, you do raise a good point and maybe I should change that.

If you want I could Email you a zip-file or set up an account on source forge.

---------- Post added at 09:08 PM ---------- Previous post was at 09:05 PM ----------

Well, you've changed the numbers there. Maybe one of your macros is wrong now? Before that refactoring, you've used programmatic assignment. Now you're using fixed defines for the numbers in those group arrays.

The thing is that all I did was change StrutGroup and DownlockGroup to constants rather than being populated programmaticaly, I didn't touch any of the arrays associated with the VC so I don't know why that would make such a difference.
 
Last edited:
While I make a point to include copies of my addons' source files as SDK samples as a matter of general principal.

I learned much of my orbiter-fu by tearing the stock atlantis apart line by line and asking questions on this very forums and it just seems rude to deny that kind of resourse to others.

A very good reason to open up the source indeed. I'd wish for more developers to think the same way...

I never really felt the need for online hosting as I kind run a one-man show. That said, you do raise a good point and maybe I should change that.

If you want I could Email you a zip-file or set up an account on source forge.

While the ZIP-file certainly helps to see the status quo, it will not reflect your train of thoughts and your course of development. E.g. your changes there with the refactoring in contrast to the previous trials will not be clear enough to quickly find the point of breakage. A version controlled history always helps tremendously to find such errors.

This is why I always strongly suggest to use something like Mercurial - a new-fangled DVCS in contrast to dinosaurs like SVN on SourceForge - even as a "lonesome cowboy" developer, all right from start. Modern "social coding" infrastructures like BitBucket offer a zero-cost, low-barrier hosting of small code projects. So before you even start to code, do a "hg init" ;) .

Mailing the ZIP archive only to me would make you miss the opportunity to have other developers see your code and maybe spot the problem before I even have the chance to. So my suggestion would be to upload it here as an attachment, maybe leaving out meshes and textures to keep the size down. At this point - where you practically ask for a peer review of your code - this has the best chance IMHO.

regards,
Face
 
Last edited:
Well I'm currently trying to figure out how to upload to Sourceforge but in the mean time see the attatched zip.

NOTE: attref.h and attref.cpp are not mine, they were barrowed from the Shuttle A's OrbiterSDK sample. (I needed the functionality and didn't feel like reinventing the wheel sorry Martins, for what it's worth I've made a point to note this in the addon's docs)
 

Attachments

Well I'm currently trying to figure out how to upload to Sourceforge but in the mean time see the attatched zip.

I see 3 points for further investigation:

  1. There are many sections uncommented for debugging, especially in the SpiderLEM.cpp in the DefineAnimations(). Do those deactivated sections relate to the failing VC animations you see?
  2. All the VC animation declarations use your previous programmatic incremental group assignment. Could it be that your base macros used there changed values during the "Leg" refactoring?
  3. Sometimes mesh exporters re-order groups. We've had that effect twice now with AscensionUltra, so maybe you have the same problem here. Did you edit and perhaps re-export the appropriate mesh by any chance between your last working point and now?
regards,
Face

---------- Post added at 17:13 ---------- Previous post was at 17:00 ----------

Something has caused my definitions from cockpitmesh.h (my meshc index file for the VC) to be ignored

P3RotaryGroups = VC_GRP_RSwitch_P3_01 + i;

should be be read as P3RotaryGroups = 65 + i;

not

P3RotaryGroups = 0 + i;


I can see that VC_GRP_RSwitch_P3_01 is only used in SpiderLEM.cpp, and this is including SpiderLEM.h, with the later including cockpitmesh.h with the macro declaration.

So in principle, the macro should be expanded to 65 while compiling SpiderLEM.cpp. How do you come to the conclusion that it is not the case? Debugger?
 
[*]There are many sections uncommented for debugging, especially in the SpiderLEM.cpp in the DefineAnimations(). Do those deactivated sections relate to the failing VC animations you see?

That is correct.

[*]All the VC animation declarations use your previous programmatic incremental group assignment. Could it be that your base macros used there changed values during the "Leg" refactoring?

Possibly.

This actually sounds promising but to be honest I don't know how I would go about checking for it or fixing it.

[*]Sometimes mesh exporters re-order groups. We've had that effect twice now with AscensionUltra, so maybe you have the same problem here. Did you edit and perhaps re-export the appropriate mesh by any chance between your last working point and now?

This is what I thought it might be at first, so I re-generated cockpitmesh.h using meshc.exe and the most recent export but the problems persist.

I can see that VC_GRP_RSwitch_P3_01 is only used in SpiderLEM.cpp, and this is including SpiderLEM.h, with the later including cockpitmesh.h with the macro declaration.

So in principle, the macro should be expanded to 65 while compiling SpiderLEM.cpp. How do you come to the conclusion that it is not the case? Debugger?

Correct again.

Though I was tipped off when I found that clicking on the rirst rotary switch of Panel 3 would cause the ADIball to jump free of it's housing and hover in the middle of the cabin. :lol:

---------- Post added at 06:52 PM ---------- Previous post was at 06:09 PM ----------

Just a further note in favor of the base macros theory.

Commenting out the landing gear animations causes the VC switchs to revert to normal.

Specifically, the culprit lies within this statement...

Code:
	//for ( i = 0; i < 4; i++)
	//{
	//	Leg[i]		= new MGROUP_ROTATE ( 2, &LegGroups[i][0], 3, LEM_LegPivot[i],	LEM_LG_Axis[i], (float) 45*RAD);
	//	Strut[i]	= new MGROUP_ROTATE ( 2, &StrutGroup[i], 1, LEM_StrutPivot[i], LEM_LG_Axis[i], (float)-69*RAD); 
	//	Downlock[i]	= new MGROUP_ROTATE ( 2, &DownlockGroup[i], 1, LEM_DownlockPivot[i], LEM_LG_Axis[i], (float) 147*RAD);

	//	ah_Leg[i] = AddAnimationComponent (anim_Gear, 0, 1, Leg[i]);
	//	ah_Strut[i] = AddAnimationComponent (anim_Gear, 0, 1, Strut[i], ah_Leg[i]);
	//	AddAnimationComponent (anim_Gear, 0, 1, Downlock[i], ah_Strut[i]);
	//}


---------- Post added at 08:23 PM ---------- Previous post was at 06:52 PM ----------

On a unrelated note...

I've downloaded Tortoise Hg, whats the best way to go about setting it up?

Should I just open my projects/Spider folder and init?
 
Last edited:
Back
Top