Quantcast
Channel: Community | MonoGame - Latest topics
Viewing all articles
Browse latest Browse all 6821

nuget assimp net model loading

$
0
0

@willmotil wrote:

Ok so i've been working on and off at getting the nuget version of assimp.net to load up a model into MonoGame correctly for the past month or so.

Im however having a problem which is making me scratch my head.
When i look at how other viewers loop animations it seems they know something i don't.
For example with the dude.fbx when i play the animation and just loop it.

I see a poping motion on the hand from the last frames to the first.

But other viewers like the internal vs studio don't seem to get that effect.

Though it seems to have a stutter itself.

Now i am interpolating rotations to build new frames in total for a set amount of frames determined by a fps value i pass to the loader. So the final frames are just look ups it all looks right in the debuging and i would think its the model but it seems other viewers are handling looping differently or i have a bug.

But i cannot see anything wrong with the interpolation this part has been bugging me for a few days now,

Here is the full runnable GL desktop project as it is now with everything to regenerate the above animation.
The nuget assimp.net is like 40 mb so this vs 2017 project is pretty fat but it should just work.
https://drive.google.com/file/d/1xbFXjd4wjyS9K9Y1dpGgMomd7XKMpCFX/view?usp=sharing

this is the interpolation im doing which looks ok to me.

        public void SetAnimationFpsCreateFrames(int animationFramesPerSecond, RiggedModel model)
        {
            fps = animationFramesPerSecond;
            TotalFrames = (int)(DurationInSeconds * (double)(animationFramesPerSecond));
            TicksPerFramePerSecond = TicksPerSecond / (double)(animationFramesPerSecond);
            SecondsPerFrame = (1d / (animationFramesPerSecond));
            CalculateNewInterpolatedAnimationFrames(model);
        }

        private void CalculateNewInterpolatedAnimationFrames(RiggedModel model)
        {
            // Loop nodes.
            for (int i = 0; i < animatedNodes.Count; i++)
            {
                // Make sure we have enough frame orientations alloted for the number of frames.
                animatedNodes[i].frameOrientations = new Matrix[TotalFrames];
                animatedNodes[i].frameOrientationTimes = new double[TotalFrames];
                
                // print name of node as we loop
                Console.WriteLine("name " + animatedNodes[i].nodeName);

                // Loop destination frames.
                for (int j = 0; j < TotalFrames; j++)
                {
                    // Find and set the interpolated value from the s r t elements based on time.
                    var frameTime = j * SecondsPerFrame + .0001d; 
                    animatedNodes[i].frameOrientations[j] = Interpolate(frameTime, animatedNodes[i]);
                    animatedNodes[i].frameOrientationTimes[j] = frameTime;
                }
                Console.WriteLine("");
            }
        }

        /// <summary>
        /// Hummm its just a little bit off it seems..
        /// </summary>
        public Matrix Interpolate(double animTime, RiggedAnimationNodes n)
        {
            var nodeAnim = n;
            // 
            Microsoft.Xna.Framework.Quaternion q1 = nodeAnim.qrot[0];
            Vector3 p1 = nodeAnim.position[0];
            Vector3 s1 = nodeAnim.scale[0];
            // 
            double tq1 = nodeAnim.qrotTime[0]; // =0;
            double tp1 = nodeAnim.positionTime[0]; ; // =0;
            double ts1 = nodeAnim.scaleTime[0]; //=0;
            // 
            int qindex1 = 0; int qindex2 = 0; // for output to console only
            int pindex1 = 0; int pindex2 = 0; // for output to console only
            // 
            int i2 = 0;
            if (nodeAnim.qrot.Count > 1)
            {
                i2 = 1;
            }
            Microsoft.Xna.Framework.Quaternion q2 = nodeAnim.qrot[i2];
            double tq2 = nodeAnim.qrotTime[i2];

            i2 = 0;
            if (nodeAnim.position.Count > 1)
            {
                i2 = 1;
            }
            Vector3 p2 = nodeAnim.position[i2];
            double tp2 = nodeAnim.positionTime[i2];

            i2 = 0;
            if (nodeAnim.scale.Count > 1)
            {
                i2 = 1;
            }
            Vector3 s2 = nodeAnim.scale[i2];
            double ts2 = nodeAnim.scaleTime[i2];

            //
            for (int frame = 0; frame < nodeAnim.qrot.Count; frame++)
            {
                var t = nodeAnim.qrotTime[frame];
                if (t <= animTime)
                {
                    //1___
                    q1 = nodeAnim.qrot[frame];
                    tq1 = t;
                    qindex1 = frame; // for output to console only
                    //2___
                    var frame2 = frame;
                    if (nodeAnim.qrot.Count > 1)
                    {
                        frame2 += 1;
                    }
                    if (frame2 >= nodeAnim.qrot.Count)
                    {
                        frame2 = 0;
                        q2 = nodeAnim.qrot[frame2];
                        tq2 = nodeAnim.qrotTime[frame2] + DurationInSeconds;
                        qindex2 = frame2; // for output to console only
                    }
                    else
                    {
                        q2 = nodeAnim.qrot[frame2];
                        tq2 = nodeAnim.qrotTime[frame2];
                        qindex2 = frame2; // for output to console only
                    }
                }
            }
            //
            for (int frame = 0; frame < nodeAnim.position.Count; frame++)
            {
                var t = nodeAnim.positionTime[frame];
                if (t <= animTime)
                {
                    //1___
                    p1 = nodeAnim.position[frame];
                    tp1 = t;
                    pindex1 = frame; // for output to console only
                    //2___
                    var frame2 = frame;
                    if (nodeAnim.position.Count > 1)
                    {
                        frame2 += 1;
                    }
                    if (frame2 >= nodeAnim.position.Count)
                    {
                        frame2 = 0;
                        p2 = nodeAnim.position[frame2];
                        tp2 = nodeAnim.positionTime[frame2] + DurationInSeconds;
                        pindex2 = frame2; // for output to console only
                    }
                    else
                    {
                        p2 = nodeAnim.position[frame2];
                        tp2 = nodeAnim.positionTime[frame2];
                        pindex2 = frame2; // for output to console only
                    }
                }
            }

            Microsoft.Xna.Framework.Quaternion q;
            if (tq1 != tq2)
                q = Microsoft.Xna.Framework.Quaternion.Slerp(q1, q2, (float)GetInterpolationTimeRatio(tq1, tq2, animTime));
            else
                q = q1;

            Vector3 p;
            if (tp1 != tp2)
                p = Vector3.Lerp(p1, p2, (float)GetInterpolationTimeRatio(tp1, tp2, animTime));
            else
                p = p1;

            Console.WriteLine("" + " animTime: " + animTime);
            Console.WriteLine(" q : " + " index1: " + qindex1 + " index2: " + qindex2 + " time1: " + tq1 + "  time2: " + tq2 + "  quaternion: " + q.ToString());
            Console.WriteLine(" p : " + " index1: " + pindex1 + " index2: " + pindex2 + " time1: " + tp1 + "  time2: " + tp2 + "  position: " + p.ToString());

            var r = Matrix.CreateFromQuaternion(q);
            r.Translation = p;

            return r; // * Matrix.CreateTranslation(p); //  * Matrix.CreateScale(s);
        }

        public double GetInterpolationTimeRatio(double s, double e, double val)
        {
            if (e < s)
                s = s + e;
            return (val - s) / (e - s);
        }

Id like to say i do have the basics flushed out and it does basically work for a rigged model.
this has 2 classes... a loader and a riggedmodel.
Then game1 uses the loader to load a model from the fbx to the riggedmodel

Ill accept any input or help on fixing it up or if you want to chip in.

It is somewhat sloppy as this is basically still a sort rough draft even after all this time
I guess im running out of steam on this and im really looking for some suggestions or direction as well.

I did quite a bit so far.
I think the overall model structural ideology is pretty solid it has both a tree node and a flat list linked to it.
I added the basic stuff so far , and a very basic shader to load it and show it as seen in the above pic.
I got the animations weights and meshes loading and the textures are added to the content pipeline for now.
I still can't see how the mesh transform is supposed to fit in and when either.

Posts: 1

Participants: 1

Read full topic


Viewing all articles
Browse latest Browse all 6821

Trending Articles