示例#1
0
        public static Model Load(string name, Bvh.Bvh bvh)
        {
            var model = CreateFromBvh(bvh.Root);

            // estimate skeleton
            var skeleton = SkeletonEstimator.Detect(model.Root);

            if (skeleton == null)
            {
                throw new Exception("fail to estimate skeleton");
            }

            // foot to zero
            var minY = model.Nodes.Min(x => x.Translation.Y);
            var hips = model.Nodes.First(x => x.HumanoidBone == HumanoidBones.hips);

            if (model.Root.Children.Count != 1)
            {
                throw new Exception();
            }
            if (model.Root.Children[0] != hips)
            {
                throw new Exception();
            }
            hips.Translation -= new Vector3(0, minY, 0);

            // normalize scale
            var pos    = hips.Translation;
            var factor = 1.0f;

            if (pos.Y != 0)
            {
                factor = 1.0f / pos.Y;
                foreach (var x in hips.Traverse())
                {
                    x.LocalTranslation *= factor;
                }
                hips.Translation = new Vector3(pos.X, 1.0f, pos.Z);
            }

            // animation
            model.Animations.Add(LoadAnimation(name, bvh, model, factor));

            // add origin
            var origin = new Node("origin");

            origin.Add(model.Root.Children[0]);
            model.Nodes.Add(origin);
            model.Root.Add(origin);

            return(model);
        }
示例#2
0
        public static Bvh Parse(string src)
        {
            using (var r = new StringReader(src))
            {
                if (r.ReadLine() != "HIERARCHY")
                {
                    throw new BvhException("not start with HIERARCHY");
                }

                var root = ParseNode(r);
                if (root == null)
                {
                    return(null);
                }

                var frames    = 0;
                var frameTime = 0.0f;
                if (r.ReadLine() == "MOTION")
                {
                    var frameSplitted = r.ReadLine().Split(':');
                    if (frameSplitted[0] != "Frames")
                    {
                        throw new BvhException("Frames is not found");
                    }
                    frames = int.Parse(frameSplitted[1]);

                    var frameTimeSplitted = r.ReadLine().Split(':');
                    if (frameTimeSplitted[0] != "Frame Time")
                    {
                        throw new BvhException("Frame Time is not found");
                    }
                    frameTime = float.Parse(frameTimeSplitted[1]);
                }

                var bvh = new Bvh(root, frames, frameTime);

                for (int i = 0; i < frames; ++i)
                {
                    var line = r.ReadLine();
                    bvh.ParseFrame(i, line);
                }

                bvh.Root.UpdatePosition(Vector3.Zero);

                return(bvh);
            }
        }
示例#3
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);
        }