ASF / AMC import to skeleton.xml

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
Post Reply
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

So, for my own purposes, I wanted to draw upon Carnegie Mellon's extensive motion capture database which is in ASF/AMC format for compatibility. I could find no extant utilities for importing these files, and I could only find one reference to importing them on the forums (and the fellow in question decided to instead switch to BVH). Right now, I have a Perl script to import an ASF and an AMC file and export a .skeleton.xml file. I'm looking at enhancing it to pull in additional animations and information off of the mocap pages like the names of the animations.

Would anybody be interested in this if I posted it?
User avatar
sparkprime
Ogre Magi
Posts: 1137
Joined: Mon May 07, 2007 3:43 am
Location: Ossining, New York
x 13
Contact:

Re: ASF / AMC import to skeleton.xml

Post by sparkprime »

What kind of data are we looking at here? Meshes would have to be made-to-fit for these animations, right?
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

:) Yeah, that's the first problem. I'm fiddling with the Pinnochio implementation to be able to fit skeletons to meshes automatically, but of course, then one gets into retargetting issues. *shrug* It's a first step in the process, same as most import of motion capture data. Mainly, I wound up with the Perl script and wondered whether it was worth cleaning it up and posting it, or if either no one particularly cared to import AMC files and/or the problem's considered so trivial that people just code it on the fly.
User avatar
sparkprime
Ogre Magi
Posts: 1137
Joined: Mon May 07, 2007 3:43 am
Location: Ossining, New York
x 13
Contact:

Re: ASF / AMC import to skeleton.xml

Post by sparkprime »

I would at least post it, if you clean it up and post it all the better. It's nice for someone to be able to find it if they're searching for something to do that even years after you've moved on.
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: ASF / AMC import to skeleton.xml

Post by jacmoe »

That would be awesome! :)

People have been asking for this for some time.
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

It's cruder than I would like, and I've only tested it on CMU's input, but it seems to work so far:

Code: Select all

#!/usr/bin/perl -w
#
# Convert 'amc' and 'asf' to '.skeleton.xml' -- OGRE3D Skeleton format.
#

use XML::Writer;
use IO::File;
use Math::Quaternion;

my $frameInterval = 1.0/60.0;		# This constant measures the number of seconds between frames, here 60 frames per second

my $skel;
my $motion;

if (@ARGV == 2) {
	($skel, $motion) = @ARGV;
} elsif (@ARGV == 1) {
	$skel = $ARGV[0];
	$motion = "";
} else {
	print "Please pass the name of an asf file and, optionally, the name of an amc file.\n";
	exit;
}

my $outfile = $skel;
$outfile =~ s/\.asf$/.skeleton.xml/;

if (!(-e $skel)) {
	print "Skeleton file '$skel' doesn't exist.\n";
	exit;
}

if ("" ne $motion && !(-e $motion)) {
	print "Motion file '$motion' doesn't exist.\n";
	exit;
}

my $output = new IO::File(">$outfile");

my $writer = new XML::Writer(OUTPUT => $output, DATA_MODE => 1, DATA_INDENT => 2);

$writer->startTag('skeleton');

open SKEL, "<", $skel;

my %dof; #degree-of-freedom count for each bone
my %direction; #direction vector for each bone
my %length; #length vector for each bone
my %children; #children array for each bone.

my @bones;	#An array of references to each bone's name in the original order

# We really should check the root object for its possible DOF.
# tx, ty, tz, rx, ry, rz, and l

my @dof;
my $line;

while (defined($line = <SKEL>) && !($line =~ /^:bonedata/)) {
	chomp($line);
	
	$line =~ s/\r$//;
	if ($line =~ s/^\s*order\s+//) {
		while ($line =~ s/^([rt][xyz]|l)\s*//i) {
			push @dof, uc($1);
		}
	} 
	elsif ($line =~ s/^\s*axis\s+//) {
		# Do nothing. We have nothing to do with this information.
	} 
	elsif ($line =~ s/^\s*position\s+//) {
		$position = $line;
	}
	elsif ($line =~ s/^\s*orientation\s+//) {
		$orientation = $line;
	}
	else {
		#ignore.
	}
}


$dof{"root"} = [@dof];
$children{"root"} = [];
push @bones, "root";
$direction{"root"} = "0 1 0";
$length{"root"} = "0";

if ($line !~ /^:bonedata/)
{
	while (defined($line = <SKEL>) && !($line =~ /^:bonedata/)) {
		#get to bone data.
	}
}

while (defined($line = <SKEL>) && ($line =~ /begin/)) {
	my $name = "";
	my @dof = ();
	my $axis = "";
	my $direction = "";
	my $length = "";
	while (defined($line = <SKEL>) && !($line =~ /end/)) {
		chomp($line);
		$line =~ s/\r$//;
		if ($line =~ /^\s*name\s+([^\s]+)/) {
			$name = $1;
		} 
		elsif ($line =~ s/^\s*dof\s+//) {
			while ($line =~ s/^([r][xyz])\s*//) {
				push @dof, uc($1);
			}
		} 
		elsif ($line =~ s/^\s*axis\s+//) {
			$axis = $line;
		} 
		elsif ($line =~ s/^\s*direction\s+//) {
			$direction = $line;
		}
		elsif ($line =~ s/^\s*length\s+//) {
			$length = $line;
		}
		else {
			#ignore.
		}
	}
	$name ne "" || die "Bone with no name!";
	$direction ne "" || die "Bone with no direction!";
	$length ne "" || die "Bone with no length!";
	!(exists $dof{$name}) || die "Bone $name with duplicate name!";
	
	$children{$name} = [];
	$dof{$name} = [@dof];
	$direction{$name} = $direction;
	$length{$name} = $length;
	
	push @bones, $name;
}

if (!($line =~ /^:hierarchy/)) {
	while (defined($line = <SKEL>) && !($line =~ /^:hierarchy/)) {
		#get to hierarchy.
	}
}

while (defined($line = <SKEL>) && !($line =~ /^\s*begin/)) {
	#get to hierarchy begin.
}
while (defined($line = <SKEL>) && !($line =~ /^\s*end/)) {
	chomp($line);
	($line =~ s/^\s*([^\s]+)//) || die "can't get first name in '$line'!";
	my $name = $1;
	(exists $children{$name}) || die "bone '$name' doesn't seem to exist!";
	while ($line =~ s/^\s*([^\s]+)//) {
		push @{$children{$name}}, $1;
	}
}

close SKEL;

$writer->startTag('bones');

my %boneFrames;

$count = 0;
foreach (@bones)
{
	$name = $_;
	$writer->startTag('bone', 'name' => $name, 'id' => "$count");
	
	@directions = split(/ /, $direction{$name});
	# We need to verify that there are 3 and then normalize the vector.
	scalar(@directions) == 3 || die "Not 3 values in $name direction";
	$directionlength = sqrt($directions[0] ** 2 + $directions[1] ** 2 + $directions[2] ** 2);
	if (abs($directionlength - 1) > 0.0001)
	{
		# Not a unit vector, so we normalize it.
		$directions[0] /= $directionlength;
		$directions[1] /= $directionlength;
		$directions[2] /= $directionlength;
	}
	
	$directions[0] *= $length{$name};
	$directions[1] *= $length{$name};
	$directions[2] *= $length{$name};
	
	$writer->emptyTag('position', 'x' => "$directions[0]"
								, 'y' => "$directions[1]"
								, 'z' => "$directions[2]");
								
	# Check if valid DOF? Currently checked later in motion.
	
	# We're adding a boilerplate rotation since it requires one
	$writer->startTag('rotation', 'angle' => '0');
	$writer->emptyTag('axis', 'x' => '0', 'y' => '1', 'z' => '0');
	$writer->endTag('rotation');
	
	$writer->endTag('bone');
	$count++;
	
	my @frames;
	
	# Add an array for the frames of animation for this bone.
	$boneFrames{$name} = [@frames]; 
}

$writer->endTag('bones');

# Generate the hierarchy
$writer->startTag('bonehierarchy');

foreach(@bones)
{
	my $parent = $_;
	foreach(@{$children{$parent}})
	{
		$writer->emptyTag('boneparent', 'bone' => "$_",
		   'parent' => "$parent");
	}
}

$writer->endTag('bonehierarchy');

$writer->startTag('animations');

if ("" ne $motion)
{
	open MOTION, "<", $motion;

	my @frames;	#Empty array to push the frames into.
	my $frame = 1;
	my $anglecorrection = 1;	# If radians, there's no correction.

	while (defined($line = <MOTION>) && !($line =~ /^$frame/)) {
		if ($line =~ /:DEG/)	# If the line :DEGREES or something similar shows up.
		{
			$pi = 3.14159;
			$anglecorrection =  1 * $pi / 180.0;
		}
		else
		{
			#Otherwise, we're just eating down to the frame
		}
	}
	while (1) {
		++$frame;
		my %value_arrays;	# This array  holds the offsets of each of the frames.
		while (defined($line = <MOTION>) && !($line =~ /^$frame/)) {
			($line =~ s/^([^\s]+)\s+//) || die "Expecting a bone name in '$line'.\n";
			my $name = $1;
			my @values = ();
			while ($line =~ s/^([^\s]+)\s+//) {
				push @values, ($1 + 0);
			}
			scalar(@values) == scalar @{$dof{$name}} || die "Frame " . ($frame - 1) . ": got the wrong number of values (" . scalar(@values) . ", expecting " . scalar @{$dof{$name}} . ") for $name.";
			
			push @{$boneFrames{$name}}, [$frame - 1, @values];
		}

		if (!(defined($line))) {
			last;
		}
	}

	close MOTION;

	$writer->startTag('animation', 'name' => 'anim1', 'length' => ($frame - 1) * $frameInterval);

	$writer->startTag('tracks');

	foreach (@bones)
	{
		my $name = $_;
		
		if (scalar (@{$boneFrames{$name}}) > 0)
		{
			$writer->startTag('track', 'bone' => $_);
			$writer->startTag('keyframes');
			
			foreach (@{$boneFrames{$name}})
			{
				my $frame = (shift @{$_}) - 1;
				$writer->startTag('keyframe', 'time' => $frame * $frameInterval);
				
				my @movementValues = @{$_};
				my $tempCounter = 0;
				
				my $tx = 0; my $ty = 0; my $tz = 0; my $rx = 0; my $ry = 0; my $rz = 0; my $l = 1;
				
				foreach(@{$dof{$name}})
				{			
					if(lc($_) eq "tx")
					{
						$tx = $movementValues[$tempCounter];
					}
					elsif(lc($_) eq "ty")
					{
						$ty = $movementValues[$tempCounter];
					}
					elsif(lc($_) eq "tz")
					{
						$tz = $movementValues[$tempCounter];
					}
					elsif(lc($_) eq "rx")
					{
						$rx = $movementValues[$tempCounter];
					}
					elsif(lc($_) eq "ry")
					{
						$ry = $movementValues[$tempCounter];
					}
					elsif(lc($_) eq "rz")
					{
						$rz = $movementValues[$tempCounter];
					}
					elsif(lc($_) eq "l")
					{
						$l = $movementValues[$tempCounter];
					}
					else
					{
						die "Unexpected DOF $_";
					}
					
					$tempCounter++;
				}
				
				if($tx != 0 or $ty != 0 or $tz != 0)
				{
					$writer->emptyTag('translate', 'x' => $tx, 'y' => $ty, 'z' => $tz);
				}
				
				if($rx != 0 or $ry != 0 or $rz != 0)
				{
					#Calculate the rotation angle.
					my $q = Math::Quaternion->from_euler($rx * $anglecorrection, $ry * $anglecorrection, $rz * $anglecorrection);
					
					$writer->startTag('rotate', 'angle' => $q->rotation_angle);
					my @v = $q->rotation_axis; 
					
					$writer->emptyTag('axis', 'x' => $v[0], 'y' => $v[1], 'z' => $v[2]);
					$writer->endTag('rotate');
				}
				
				if($l != 1)
				{
					$writer->emptyTag('scale', 'factor' => $l);
				}
				$writer->endTag('keyframe');
			}
			$writer->endTag('keyframes');
			$writer->endTag('track');
		}
		
	}

	$writer->endTag('tracks');

	$writer->endTag('animation');
}

$writer->endTag('animations');

$writer->endTag('skeleton');

$writer->end();
There is one non-standard addition to the Math::Quaternion library. It lacked a function to create a quaternion from euler angles, so I added the following:

Code: Select all

sub from_euler {
	my $rx = $_[1];
	my $ry = $_[2];
	my $rz = $_[3];
	
	my $q0 = cos($rx / 2) * cos($ry / 2) * cos($rz / 2) + sin($rx / 2) * sin($ry / 2) * sin($rz / 2);
	my $q1 = sin($rx / 2) * cos($ry / 2) * cos($rz / 2) - cos($rx / 2) * sin($ry / 2) * sin($rz / 2);
	my $q2 = cos($rx / 2) * sin($ry / 2) * cos($rz / 2) + sin($rx / 2) * cos($ry / 2) * sin($rz / 2);
	my $q3 = cos($rx / 2) * cos($ry / 2) * sin($rz / 2) - sin($rx / 2) * sin($ry / 2) * cos($rz / 2);
	
	return Math::Quaternion->new($q0,$q1,$q2,$q3);
}
Last edited by FuzzyBoots on Thu Aug 19, 2010 2:18 am, edited 1 time in total.
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

I'm having issues with the HTML processing (looks like it has to do with versions of Perl, which I am not free to change on this computer), so my next step will be to clean up the output by eliminating values which do not change from frame to frame. After that, I plan to try to find a way to detect anomolous input since the CMU dataset, at least, is known for the occasional frame where the values spike because it confused the markers.
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

*grumble* *grumble* *grumble* *grumble* And right now, the converter is choking on my output. Segmentation fault due to one of the imported bone pointers being NULL when exporting. I don't suppose someone could check this for me? A sample file without animations:

Code: Select all

<skeleton>

  <bones>

    <bone name="root" id="1">

      <position x="0" y="0" z="0" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lhipjoint" id="2">

      <position x="1.58895320509306" y="-1.83664936737439" z="0.717526745318765" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lfemur" id="3">

      <position x="2.50528204926557" y="-6.88321152190079" z="0" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="ltibia" id="4">

      <position x="2.63243820578737" y="-7.23257047807424" z="0" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lfoot" id="5">

      <position x="0.236910276096276" y="-0.650902556991898" z="1.72750248115058" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="ltoes" id="6">

      <position x="1.42137290088e-011" y="-3.90480693312e-011" z="0.925608" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rhipjoint" id="7">

      <position x="-1.51435423813563" y="-1.83664809465656" z="0.717526553818794" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rfemur" id="8">

      <position x="-2.54551384950135" y="-6.99374757552035" z="0" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rtibia" id="9">

      <position x="-2.66026494443553" y="-7.30902387705824" z="0" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rfoot" id="10">

      <position x="-0.229805115254575" y="-0.631383729311456" z="2.03958669917795" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rtoes" id="11">

      <position x="-1.643338882e-011" y="-4.517118344e-011" z="1.0706" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lowerback" id="12">

      <position x="-0.0265133514841054" y="1.86274648941361" z="-0.111518031144467" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="upperback" id="13">

      <position x="0.0101945571182134" y="1.86224356773346" z="0.0408749781716846" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="thorax" id="14">

      <position x="0.0217257767437695" y="1.86787590925687" z="0.0926804631123265" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lowerneck" id="15">

      <position x="-0.01926218556391" y="1.80512094393698" z="0.088668517340593" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="upperneck" id="16">

      <position x="0.0551565105621222" y="1.76450785142108" z="-0.384749499955467" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="head" id="17">

      <position x="0.0159181220178988" y="1.82587072232342" z="-0.140008602427061" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lclavicle" id="18">

      <position x="3.47116170282302" y="1.51376496379479" z="0.144910971779894" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lhumerus" id="19">

      <position x="4.78095" y="-2.14648877865e-010" z="1.52657167785e-026" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lradius" id="20">

      <position x="3.58615" y="-1.61006300705e-010" z="-1.3554714601e-026" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lwrist" id="21">

      <position x="1.79307" y="-8.0495753589e-011" z="2.296384749e-027" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lhand" id="22">

      <position x="0.659812" y="-2.96279341232e-011" z="1.6900424568e-027" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lfingers" id="23">

      <position x="0.531957" y="-2.38876354764e-011" z="2.7251093196e-027" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="lthumb" id="24">

      <position x="0.54007896708213" y="-4.85013760357e-011" z="0.54007896708213" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rclavicle" id="25">

      <position x="-3.31724901441104" y="1.61216232503873" z="0.351559831344071" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rhumerus" id="26">

      <position x="-4.48913" y="-2.01548918523e-010" z="1.07265965698e-026" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rradius" id="27">

      <position x="-3.7051" y="-1.663404645e-010" z="1.6253088068e-026" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rwrist" id="28">

      <position x="-1.85255" y="-8.3180791785e-011" z="2.372560785e-027" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rhand" id="29">

      <position x="-0.449136" y="-2.01595142736e-011" z="1.1504169504e-027" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rfingers" id="30">

      <position x="-0.362105" y="-1.6263149444e-011" z="1.854991494e-027" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

    <bone name="rthumb" id="31">

      <position x="-0.36763330082026" y="-3.30066550973252e-011" z="0.36763330082026" />

      <rotation angle="0">

        <axis x="0" y="1" z="0" />

      </rotation>

    </bone>

  </bones>

  <bonehierarchy>

    <boneparent bone="lhipjoint" parent="root" />

    <boneparent bone="rhipjoint" parent="root" />

    <boneparent bone="lowerback" parent="root" />

    <boneparent bone="lfemur" parent="lhipjoint" />

    <boneparent bone="ltibia" parent="lfemur" />

    <boneparent bone="lfoot" parent="ltibia" />

    <boneparent bone="ltoes" parent="lfoot" />

    <boneparent bone="rfemur" parent="rhipjoint" />

    <boneparent bone="rtibia" parent="rfemur" />

    <boneparent bone="rfoot" parent="rtibia" />

    <boneparent bone="rtoes" parent="rfoot" />

    <boneparent bone="upperback" parent="lowerback" />

    <boneparent bone="thorax" parent="upperback" />

    <boneparent bone="lowerneck" parent="thorax" />

    <boneparent bone="lclavicle" parent="thorax" />

    <boneparent bone="rclavicle" parent="thorax" />

    <boneparent bone="upperneck" parent="lowerneck" />

    <boneparent bone="head" parent="upperneck" />

    <boneparent bone="lhumerus" parent="lclavicle" />

    <boneparent bone="lradius" parent="lhumerus" />

    <boneparent bone="lwrist" parent="lradius" />

    <boneparent bone="lhand" parent="lwrist" />

    <boneparent bone="lthumb" parent="lwrist" />

    <boneparent bone="lfingers" parent="lhand" />

    <boneparent bone="rhumerus" parent="rclavicle" />

    <boneparent bone="rradius" parent="rhumerus" />

    <boneparent bone="rwrist" parent="rradius" />

    <boneparent bone="rhand" parent="rwrist" />

    <boneparent bone="rthumb" parent="rwrist" />

    <boneparent bone="rfingers" parent="rhand" />

  </bonehierarchy>

  <animations>

    

  </animations>

</skeleton>
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

*facepalm* Alright, I'm not certain if this comes under bad implementation or me not understanding the spec. I was starting my IDs with 1. Apparently if you do that, you will never have "0" filled and therefore it fails immediately. Is the bones being in order from 0 to n-1 part of the specification or is it just so common of usage that no one thought to add a bounds check?
mr_mocap
Gnoblar
Posts: 6
Joined: Tue Apr 10, 2007 6:46 pm

Re: ASF / AMC import to skeleton.xml

Post by mr_mocap »

FuzzyBoots wrote:*facepalm* Alright, I'm not certain if this comes under bad implementation or me not understanding the spec. I was starting my IDs with 1. Apparently if you do that, you will never have "0" filled and therefore it fails immediately. Is the bones being in order from 0 to n-1 part of the specification or is it just so common of usage that no one thought to add a bounds check?
Actually, according to specification, the "id" is optional. Internally, it will be automatically generated, but really it's only for keeping things unique, whether no duplicate body names exist or duplicate "id"'s exist.

It wouldn't surprise me that over the years, so many people started their "id"'s at zero that everyone now just writes code assuming that.
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

mr_mocap wrote:Actually, according to specification, the "id" is optional. Internally, it will be automatically generated, but really it's only for keeping things unique, whether no duplicate body names exist or duplicate "id"'s exist.

It wouldn't surprise me that over the years, so many people started their "id"'s at zero that everyone now just writes code assuming that.
According to the DTD in Subversion, it's required:

Code: Select all

<!ATTLIST bone
	id		CDATA	#REQUIRED
	name	CDATA	#REQUIRED>
Still, the code should probably pull them in no matter what the IDs are and then just use those IDs for the Mesh attachment. ^_^ Yay! I have a project for a proposed code patch.
mr_mocap
Gnoblar
Posts: 6
Joined: Tue Apr 10, 2007 6:46 pm

Re: ASF / AMC import to skeleton.xml

Post by mr_mocap »

FuzzyBoots wrote:
mr_mocap wrote:Actually, according to specification, the "id" is optional. Internally, it will be automatically generated, but really it's only for keeping things unique, whether no duplicate body names exist or duplicate "id"'s exist.

It wouldn't surprise me that over the years, so many people started their "id"'s at zero that everyone now just writes code assuming that.
According to the DTD in Subversion, it's required:

Code: Select all

<!ATTLIST bone
	id		CDATA	#REQUIRED
	name	CDATA	#REQUIRED>
Still, the code should probably pull them in no matter what the IDs are and then just use those IDs for the Mesh attachment. ^_^ Yay! I have a project for a proposed code patch.
And the ORIGINAL spec is here: http://www.mocap.co.nz/downloads/ASF_spec_v1.html

I also have a copy from the early 90's. Use the location above for future reference.... also for anyone else that needs to connect OGRE and ASF/AMC.

I suppose I should probably use my expertise to improve things, but I just have no extra time to spare.

Good Luck and keep us posted on your progress! :-)
mr_mocap
Gnoblar
Posts: 6
Joined: Tue Apr 10, 2007 6:46 pm

Re: ASF / AMC import to skeleton.xml

Post by mr_mocap »

FuzzyBoots wrote:
mr_mocap wrote:Actually, according to specification, the "id" is optional. Internally, it will be automatically generated, but really it's only for keeping things unique, whether no duplicate body names exist or duplicate "id"'s exist.

It wouldn't surprise me that over the years, so many people started their "id"'s at zero that everyone now just writes code assuming that.
According to the DTD in Subversion, it's required:

Code: Select all

<!ATTLIST bone
	id		CDATA	#REQUIRED
	name	CDATA	#REQUIRED>
Still, the code should probably pull them in no matter what the IDs are and then just use those IDs for the Mesh attachment. ^_^ Yay! I have a project for a proposed code patch.
And the ORIGINAL spec is here: http://www.mocap.co.nz/downloads/ASF_spec_v1.html

I also have a copy from the early 90's. Use the location above for future reference.... also for anyone else that needs to connect OGRE and ASF/AMC.

I suppose I should probably use my expertise to improve things, but I just have no extra time to spare.

Good Luck and keep us posted on your progress! :-)
FuzzyBoots
Gnoblar
Posts: 23
Joined: Thu Aug 12, 2010 1:52 pm

Re: ASF / AMC import to skeleton.xml

Post by FuzzyBoots »

Ah! I was speaking of the Ogre Skeleton.xml spec. ^_^ The ASF and AMC I can parse just fine. It's when I outputted the Skeleton.xml and tried to send it into the conversion tool that it failed.
butigy
Gnoblar
Posts: 3
Joined: Thu Dec 19, 2019 2:22 pm

Re: ASF / AMC import to skeleton.xml

Post by butigy »

Are you able to reproduce the animations in Ogre after you load the skeleton? Doesn't look like you've processed all the required info.
Post Reply