Creating an animation using COLLADA format! PLEASE HELP!!!

I am writing a module to export 3D animations to COLLADA 1.4, so I can import it using 3D programs like Blender, for example:

I have a very simple animation I would like to export:

  • I have a cube at 0,0,0
  • the cube rotates JUST IN Z and has 5 keyframes with the following values:
KEYFRAMES
   frame    Z-angle
     1         0    
     66       100.8
    138       -75.96 
    214        75.783
    250      -157.808

just that. I would like to create a COLLADA 1.4 file that once imported on a 3D package could recreate this animation.

I have done the inverse operation. I created this animation on Blender and exported it to a COLLADA 1.4 file. The problem is that the generated file deals with “bezier interpolation” and gives me the following values at some point…

   <float_array count="5" id="Cube-rotateZ-input-array">0.04000 2.64000 5.52000 8.56000 11.60000</float_array>
    
    .... bla bla
    
    <Name_array count="5" id="Cube-rotateY-interpolation-array">BEZIER BEZIER BEZIER BEZIER BEZIER</Name_array>

The question is, given my initial values, how do I calculate these “input-array” values and what do they mean?

My math is a little rusted, so, please answer this as simple as possible, if possible with practical examples and codes instead of theoretical stuff.

THANKS.

Hello

I used the blender importer/exporter from illusoft [1] in the past. The loader only supported a subset of the norm and made invalid assumption about the xml structure and thus was only able to load very specific collada files. With this limited importer claiming “collada support” in Blender is abusive IMHO.

I know there is ongoing (finished?) work in order to make a new importer for blender based on opencollada, so the collada support in Blender should improve.

[1] http://colladablender.illusoft.com/cms/

That’s a good idea, doing so, you’re more likely to get files that the importer will accept.

Bézier curves are very common, and documented at many places on the web. See the wikipedia article for instance. You can also play with them in inkscape and look at the control points in the resulting svg file.

Alternatively, you can use linear interpolation. With linear interpolation, you only need the keyframes, no control point. To do so, you should replace “BEZIER” with “LINEAR” and adjust the input and output arrays.

I don’t know if blender and its loader support linear interpolation though. (They probably do.)

Cheers

Hi,

Thanks for your answer, but as I said before, I need this to use in applications LIKE Blender, not just Blender.

Sorry, but I still need to do it bezier and as I said before, my math is a little rusted. So, wikipedia pages won’t help, as they are theoretical. I need code examples on how to obtain the interpolation points based on keyframe pairs (time, value).

thanks.

May I ask you why?

I think this is not simple. An infinity of Bézier curves would pass through (or near?) your keyframe pairs, so you’ll need to choose one. Search for “bezier curve fitting”.

If you use LINEAR of BSPLINE instead of BEZIER, you won’t have this problem.

I think my question is not clear.

This code you see is generated by Blender. The only thing blender has is 5 keyframe pairs (value, time).

If Blender calculated these points, it is not impossible to do.

I just need to know how Blender did that.

I have analyzed Blender code but it is very complex to glance, because I have to understand how Blender work in general, before understand how it calculates the values.

I never said it was impossible. I said there is an infinity of possible bézier curves passing through your 5 keyframes. Blender just chose one.

Blender seems to define an animation curve by a set of keyframes and their handles, as shown there
http://www.blender.org/development/rele … e-handles/
The handles correspond to the bézier curve control points.

Blender generated the handles automatically from the keyframes thus effectively choosing one of the many possible bézier curves.
But it lets you move the handle, which allows you to tune the animation curve without changing the keyframes.

So at the end, it has more than just the keyframes.

I still see no reason why you want to get the exact same curve than blender. You haven’t explained why you want bézier curves. If your keyframes are near enough, you won’t see the difference between bezier and linear interpolation.

I have a software and I am writing a module to export the animation of an object to several formats. Collada is one of them.

Other formats use the sane way of representing an animation by defining time and value of an item.

Collada choses the difficult way. Instead of creating a bezier representation of a curve and put that on the exported file, it should export just the time/values pair and let to the 3D application the task of creating the bezier curve for that animation.

The keyframes I have are not near enough, so I need it bezier.

What I have now is N values of time values (where the keyframes are) and N values for a given variable.

Now I need to export this and generate a Collada file. Forget Blender. I need a Collada file that can be read in any 3D package and reproduce the same animation.

So again, what I have is: N keyframes (each keyframe is a value plot on a time scale). In my example, the animation goes in a bezier way thru these N keyframes.

I just need a way to convert N (time/value) pairs in X bezier points that COLLADA requires.

This is how Blender wrote a camera animation I did

		<animation id="Camera-rotateZ" name="Camera-rotateZ">
			<source id="Camera-rotateZ-input">
				<float_array count="5" id="Camera-rotateZ-input-array">0.04000 2.64000 5.52000 8.56000 11.60000</float_array>
				<technique_common>
					<accessor count="5" source="#Camera-rotateZ-input-array" stride="1">
						<param type="float" name="TIME"></param>
					</accessor>
				</technique_common>
			</source>
			<source id="Camera-rotateZ-output">
				<float_array count="5" id="Camera-rotateZ-output-array">0.00000 100.80463 -75.96180 75.78278 -157.80836</float_array>
				<technique_common>
					<accessor count="5" source="#Camera-rotateZ-output-array" stride="1">
						<param type="float" name="ANGLE"></param>
					</accessor>
				</technique_common>
			</source>
			<source id="Camera-rotateZ-interpolation">
				<Name_array count="5" id="Camera-rotateZ-interpolation-array">BEZIER BEZIER BEZIER BEZIER BEZIER</Name_array>
				<technique_common>
					<accessor count="5" source="#Camera-rotateZ-interpolation-array" stride="1">
						<param type="Name" name="ANGLE"></param>
					</accessor>
				</technique_common>
			</source>

I don’t see any indication here, of the time values I mentioned on my original question. What I see is these strange numbers 0.04, 2.64, etc… How these numbers were calculated

Why I need my script to work like Blender? Simple: because I tested importing this script in other 3D packages and all packages imported my original animation perfectly. So, Blender is doing a fine representation of the animation.

EDIT: there’s an error on my original post. The time for the last keyframe is 290, not 250.

… complementing my last reply… please read it

this is the curve that blender shows for the animation…

Hi, I figured out the problem. Thanks anyway.

<animation id="back_root_translate">
            <source id="back_root_translate_back_root_translate-input">
                <float_array id="back_root_translate_back_root_translate-input-array" count="3">0.041667 0.666667 1.125</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_translate_back_root_translate-input-array">
                        <param name="TIME" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_translate_back_root_translate-output">
                <float_array id="back_root_translate_back_root_translate-output-array" count="9">6.79721 1.90855 0.854563 6.71314 1.90855 0.854563 6.79721 1.90855 0.854563</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_translate_back_root_translate-output-array" stride="3">
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="Z" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_translate_back_root_translate-intangents">
                <float_array id="back_root_translate_back_root_translate-intangents-array" count="18">-0.291667 6.84205 -0.291667 1.90855 -0.291667 0.854563 0.458333 6.71314 0.458333 1.90855 0.458333 0.854563 0.972222 6.83393 0.972222 1.90855 0.972222 0.854563</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_translate_back_root_translate-intangents-array" stride="6">
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_translate_back_root_translate-outtangents">
                <float_array id="back_root_translate_back_root_translate-outtangents-array" count="18">0.25 6.76919 0.25 1.90855 0.25 0.854563 0.819444 6.71314 0.819444 1.90855 0.819444 0.854563 1.45833 6.7171 1.45833 1.90855 1.45833 0.854563</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_translate_back_root_translate-outtangents-array" stride="6">
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_translate_back_root_translate-interpolations">
                <Name_array id="back_root_translate_back_root_translate-interpolations-array" count="3">BEZIER BEZIER BEZIER</Name_array>
                <technique_common>
                    <accessor count="3" source="#back_root_translate_back_root_translate-interpolations-array">
                        <param name="INTERPOLATION" type="Name"/>
                    </accessor>
                </technique_common>
            </source>
            <sampler id="back_root_translate_back_root_translate-sampler">
                <input semantic="INPUT" source="#back_root_translate_back_root_translate-input"/>
                <input semantic="OUTPUT" source="#back_root_translate_back_root_translate-output"/>
                <input semantic="IN_TANGENT" source="#back_root_translate_back_root_translate-intangents"/>
                <input semantic="OUT_TANGENT" source="#back_root_translate_back_root_translate-outtangents"/>
                <input semantic="INTERPOLATION" source="#back_root_translate_back_root_translate-interpolations"/>
            </sampler>
            <channel source="#back_root_translate_back_root_translate-sampler" target="back_root/translate"/>
        </animation>
        <animation id="back_root_scale">
            <source id="back_root_scale_back_root_scale-input">
                <float_array id="back_root_scale_back_root_scale-input-array" count="3">0.041667 0.666667 1.125</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_scale_back_root_scale-input-array">
                        <param name="TIME" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_scale_back_root_scale-output">
                <float_array id="back_root_scale_back_root_scale-output-array" count="9">1 1 1 1 1 1 1 1 1</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_scale_back_root_scale-output-array" stride="3">
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="Z" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_scale_back_root_scale-intangents">
                <float_array id="back_root_scale_back_root_scale-intangents-array" count="18">-0.291667 1 -0.291667 1 -0.291667 1 0.458333 1 0.458333 1 0.458333 1 0.972222 1 0.972222 1 0.972222 1</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_scale_back_root_scale-intangents-array" stride="6">
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_scale_back_root_scale-outtangents">
                <float_array id="back_root_scale_back_root_scale-outtangents-array" count="18">0.25 1 0.25 1 0.25 1 0.819444 1 0.819444 1 0.819444 1 1.45833 1 1.45833 1 1.45833 1</float_array>
                <technique_common>
                    <accessor count="3" source="#back_root_scale_back_root_scale-outtangents-array" stride="6">
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                        <param name="X" type="float"/>
                        <param name="Y" type="float"/>
                    </accessor>
                </technique_common>
            </source>
            <source id="back_root_scale_back_root_scale-interpolations">
                <Name_array id="back_root_scale_back_root_scale-interpolations-array" count="3">BEZIER BEZIER BEZIER</Name_array>
                <technique_common>
                    <accessor count="3" source="#back_root_scale_back_root_scale-interpolations-array">
                        <param name="INTERPOLATION" type="Name"/>
                    </accessor>
                </technique_common>
            </source>
            <sampler id="back_root_scale_back_root_scale-sampler">
                <input semantic="INPUT" source="#back_root_scale_back_root_scale-input"/>
                <input semantic="OUTPUT" source="#back_root_scale_back_root_scale-output"/>
                <input semantic="IN_TANGENT" source="#back_root_scale_back_root_scale-intangents"/>
                <input semantic="OUT_TANGENT" source="#back_root_scale_back_root_scale-outtangents"/>
                <input semantic="INTERPOLATION" source="#back_root_scale_back_root_scale-interpolations"/>
            </sampler>
            <channel source="#back_root_scale_back_root_scale-sampler" target="back_root/scale"/>
        </animation>

There is a translation here in 3 direction and there are 3 output float and there are 6 IN_TANGENT points and 6 OUT_TANGENT points.
Could you explain me how I must use the second component in the tangent points in the spec equation? I suppose that tangent point is (time, value). If so then the question is how to use time values of tangents points?