Beispiel #1
0
        static Animation LoadAnimation(string name, Bvh.Bvh bvh, Model model, float scalingFactor)
        {
            var animation = new Animation(name);

            Dictionary <string, BvhNodeCurves> pathMap = new Dictionary <string, BvhNodeCurves>();

            for (int i = 0; i < bvh.Channels.Length; ++i)
            {
                var channel = bvh.Channels[i];

                if (!bvh.TryGetPathWithPropertyFromChannel(channel, out Bvh.Bvh.PathWithProperty prop))
                {
                    throw new Exception();
                }

                if (!pathMap.TryGetValue(prop.Path, out BvhNodeCurves curves))
                {
                    curves = new BvhNodeCurves();
                    pathMap.Add(prop.Path, curves);
                }

                curves.Set(prop.Property, channel);
            }

            // setup time
            var timeBytes = new byte[Marshal.SizeOf(typeof(float)) * bvh.FrameCount];
            var timeSpan  = SpanLike.Wrap <Single>(new ArraySegment <byte>(timeBytes));
            var now       = 0.0;

            for (int i = 0; i < timeSpan.Length; ++i, now += bvh.FrameTime.TotalSeconds)
            {
                timeSpan[i] = (float)now;
            }
            var times = new BufferAccessor(new ArraySegment <byte>(timeBytes), AccessorValueType.FLOAT, AccessorVectorType.SCALAR, bvh.FrameCount);

            foreach (var(key, nodeCurve) in pathMap)
            {
                var node    = Model.GetNode(model.Root, key);
                var bvhNode = GetNode(bvh.Root, key);
                var curve   = new NodeAnimation();

                if (nodeCurve.LocalPositionX != null)
                {
                    var values = new byte[Marshal.SizeOf(typeof(Vector3))
                                          * nodeCurve.LocalPositionX.Keys.Length];
                    var span = SpanLike.Wrap <Vector3>(new ArraySegment <byte>(values));
                    for (int i = 0; i < nodeCurve.LocalPositionX.Keys.Length; ++i)
                    {
                        span[i] = new Vector3
                        {
                            X = nodeCurve.LocalPositionX.Keys[i] * scalingFactor,
                            Y = nodeCurve.LocalPositionY.Keys[i] * scalingFactor,
                            Z = nodeCurve.LocalPositionZ.Keys[i] * scalingFactor,
                        };
                    }
                    var sampler = new CurveSampler
                    {
                        In  = times,
                        Out = new BufferAccessor(new ArraySegment <byte>(values),
                                                 AccessorValueType.FLOAT, AccessorVectorType.VEC3, span.Length)
                    };
                    curve.Curves.Add(AnimationPathType.Translation, sampler);
                }

                if (nodeCurve.EulerX != null)
                {
                    var values = new byte[Marshal.SizeOf(typeof(Quaternion))
                                          * nodeCurve.EulerX.Keys.Length];
                    var span = SpanLike.Wrap <Quaternion>(new ArraySegment <byte>(values));

                    Func <Quaternion, BvhNodeCurves, int, Quaternion> getRot = (q, c, i) => q;

                    foreach (var ch in bvhNode.Channels)
                    {
                        var tmp = getRot;
                        switch (ch)
                        {
                        case Channel.Xrotation:
                            getRot = (_, c, i) =>
                            {
                                return(tmp(_, c, i) *
                                       Quaternion.CreateFromAxisAngle(Vector3.UnitX, ToRad(c.EulerX.Keys[i])));
                            };
                            break;

                        case Channel.Yrotation:
                            getRot = (_, c, i) =>
                            {
                                return(tmp(_, c, i) *
                                       Quaternion.CreateFromAxisAngle(Vector3.UnitY, ToRad(c.EulerY.Keys[i])));
                            };
                            break;

                        case Channel.Zrotation:
                            getRot = (_, c, i) =>
                            {
                                return(tmp(_, c, i) *
                                       Quaternion.CreateFromAxisAngle(Vector3.UnitZ, ToRad(c.EulerZ.Keys[i])));
                            };
                            break;

                        default:
                            // throw new NotImplementedException();
                            break;
                        }
                    }

                    for (int i = 0; i < nodeCurve.EulerX.Keys.Length; ++i)
                    {
                        span[i] = getRot(Quaternion.Identity, nodeCurve, i);
                    }
                    var sampler = new CurveSampler
                    {
                        In  = times,
                        Out = new BufferAccessor(new ArraySegment <byte>(values),
                                                 AccessorValueType.FLOAT, AccessorVectorType.VEC4, span.Length)
                    };
                    curve.Curves.Add(AnimationPathType.Rotation, sampler);
                }

                animation.AddCurve(node, curve);
            }

            return(animation);
        }