Exemplo n.º 1
0
    public async void Setup(SyncObject obj)
    {
        // TODO: dynamic model change handling
        if (!obj.HasField("model") || !(obj.GetField("model") is BlobHandle))
        {
            // TODO:
            obj.WriteErrorLog("Model", $"This object has no model field or not a blob handle. Ignoring.");
            return;
        }

        BlobHandle handle = (BlobHandle)obj.GetField("model");

        Blob blob = await obj.Node.ReadBlob(handle);

        obj.WriteDebugLog("Model", $"Blob {handle} loaded");

        // Because UniGLTF.ImporterContext is the parent class of VRMImporterContext,
        //  ( https://github.com/vrm-c/UniVRM/blob/3b68eb7f99bfe78ea9c83ea75511282ef1782f1a/Assets/VRM/UniVRM/Scripts/Format/VRMImporterContext.cs#L11 )
        // loading procedure is probably almost same (See PlyayerAvatar.cs for VRM loading).
        //  https://github.com/vrm-c/UniVRM/blob/3b68eb7f99bfe78ea9c83ea75511282ef1782f1a/Assets/VRM/UniGLTF/Editor/Tests/UniGLTFTests.cs#L46
        ctx = new UniGLTF.ImporterContext();
        // ParseGlb parses GLB file.
        //  https://github.com/vrm-c/UniVRM/blob/3b68eb7f99bfe78ea9c83ea75511282ef1782f1a/Assets/VRM/UniGLTF/Scripts/IO/ImporterContext.cs#L239
        // Currently, only GLB (glTF binary format) is supported because it is self-contained
        ctx.ParseGlb(blob.Data);
        ctx.Root = gameObject;
        await ctx.LoadAsyncTask();

        // UniGLTF also has ShowMeshes https://github.com/ousttrue/UniGLTF/wiki/Rutime-API#import
        ctx.ShowMeshes();

        obj.WriteDebugLog("Model", "Model load completed");

        LoadComplete?.Invoke(this);
    }
Exemplo n.º 2
0
    void HandleUpdate()
    {
        if (beforeSync)
        {
            return;
        }

        var rb = GetComponent <Rigidbody>();

        if (obj.HasField("velocity") && obj.GetField("velocity") is Vec velocity)
        {
            rb.velocity = transform.TransformVector(UnityUtil.FromVec(velocity));
        }
        if (obj.HasField("angularVelocity") && obj.GetField("angularVelocity") is Vec angularVelocity)
        {
            rb.angularVelocity = transform.TransformVector(UnityUtil.FromVec(angularVelocity));
        }
    }
Exemplo n.º 3
0
    void OnAfterSync(SyncObject obj, float dt)
    {
        if (GetComponent <ObjectSync>().IsOriginal)
        {
            return;
        }

        if (obj.HasField("forward") && obj.HasField("sideways") && obj.HasField("turn"))
        {
            forward  = (obj.GetField("forward") as Primitive <float>)?.Value ?? 0.0f;
            sideways = (obj.GetField("sideways") as Primitive <float>)?.Value ?? 0.0f;
            turn     = (obj.GetField("turn") as Primitive <float>)?.Value ?? 0.0f;
        }

        if (obj.TryGetField("lookAt", out Vec lookAtVec))
        {
            lookAt = UnityUtil.FromVec(lookAtVec);
        }
    }
Exemplo n.º 4
0
    public void EulerTest()
    {
        var node   = new DummyNode();
        var loader = new SceneLoader(node);

        loader.Load(new StringReader(eulerYaml)).Wait();

        SyncObject obj = node.Objects[0];

        TestUtils.AssertQuat(obj.GetField("rotation"), 1, 0, 0, 0);
    }
Exemplo n.º 5
0
    public void ObjectRefTest()
    {
        var node   = new DummyNode();
        var loader = new SceneLoader(node);

        loader.Load(new StringReader(objectRefYaml)).Wait();

        SyncObject theCube   = node.Objects[0];
        SyncObject secondObj = node.Objects[1];

        Assert.That(((ObjectRef)secondObj.GetField("reftest")).Id, Is.EqualTo(theCube.Id));
    }
Exemplo n.º 6
0
    public void SimpleLoadTest()
    {
        var node   = new DummyNode();
        var loader = new SceneLoader(node);

        loader.Load(new StringReader(simpleYaml)).Wait();

        SyncObject obj = node.Objects[0];

        TestUtils.AssertVec(obj.GetField("position"), 0, 0, 0);
        TestUtils.AssertQuat(obj.GetField("rotation"), 1, 0, 0, 0);
        Assert.That(((Sequence)obj.GetField("tags")).Elements, Is.EqualTo(new IValue[] {
            new Primitive <string> {
                Value = "plane"
            },
            new Primitive <string> {
                Value = "foo_bar"
            }
        }));
        Assert.AreEqual(obj.GetField("test"), new Primitive <string> {
            Value = "testtest"
        });
        TestUtils.AssertPrimitive <int>(obj.GetField("foo"), 123);
        TestUtils.AssertPrimitive(obj.GetField("bar"), 3.14f);
    }
Exemplo n.º 7
0
    public void BlobTest()
    {
        var node   = new DummyNode();
        var loader = new SceneLoader(node);

        loader.Load(new StringReader(blobYaml), "blobtest.yml").Wait();

        SyncObject obj  = node.Objects[0];
        var        task = node.ReadBlob((BlobHandle)obj.GetField("blobtest"));

        task.Wait();
        Blob blob = task.Result;

        byte[] data = File.ReadAllBytes(loadedFile);

        Assert.That(blob.Data.SequenceEqual(data));
    }
Exemplo n.º 8
0
    // Called by ObjectSync when become ready
    async void OnSyncReady()
    {
        Debug.Log("OnSyncReady");

        SyncObject obj  = GetComponent <ObjectSync>().SyncObject;
        SyncNode   node = GetComponent <ObjectSync>().Node;

        obj.BeforeSync += OnBeforeSync;
        obj.AfterSync  += OnAfterSync;
        obj.RegisterFieldUpdateHandler("leftHand", OnLeftHandUpdated);
        obj.RegisterFieldUpdateHandler("rightHand", OnRightHandUpdated);
        obj.RegisterFieldUpdateHandler("mouseGrabber", OnMouseGrabberUpdated);

        OnLeftHandUpdated();
        OnRightHandUpdated();
        OnMouseGrabberUpdated();

        Blob vrmBlob;

        if (GetComponent <ObjectSync>().IsOriginal)
        {
            byte[] vrmData = File.ReadAllBytes(Settings.Instance.AvatarPath);
            // Use MIME type for GLTF binary https://www.iana.org/assignments/media-types/model/gltf-binary
            vrmBlob = new Blob(vrmData, "model/gltf-binary");
            BlobHandle vrmHandle = vrmBlob.GenerateHandle();
            node.WriteBlob(vrmHandle, vrmBlob);
            obj.SetField("vrm", vrmHandle);
        }
        else
        {
            while (!obj.HasField("vrm") || !(obj.GetField("vrm") is BlobHandle))
            {
                obj.WriteDebugLog("PlayerAvatar", "Field vrm not ready");
                await UniTask.WaitForFixedUpdate();
            }
            BlobHandle blobHandle = (BlobHandle)obj.GetField("vrm");
            vrmBlob = await node.ReadBlob(blobHandle);
        }

        // Disable collision detection (and character control) during VRM load
        // When the avatar collides with something during creation,
        // it goes to wrong position (e.g. floating).
        // Note: CharacterController inherits Collider.
        //  (See https://docs.unity3d.com/2019.3/Documentation/ScriptReference/CharacterController.html )
        GetComponent <CharacterController>().enabled = false;

        // Load VRM from byte array
        // https://github.com/vrm-c/UniVRM/wiki/Runtime-import
        // https://qiita.com/sh_akira/items/8155e4b69107c2a7ede6
        ctx      = new VRMImporterContext();
        ctx.Root = new GameObject();    // VRM is loaded as a separate object
        ctx.ParseGlb(vrmBlob.Data);

        var meta = ctx.ReadMeta();

        obj.WriteLog("PlayerAvatar", $"Loading VRM {meta.Title} created by {meta.Author} ({meta.ContactInformation})");
        obj.WriteLog("PlayerAvatar", $"AllowedUser={meta.AllowedUser}, ViolentUsage={meta.ViolentUssage}");
        obj.WriteLog("PlayerAvatar", $"SexualUsage={meta.SexualUssage}, CommercialUsage={meta.CommercialUssage}");
        obj.WriteLog("PlayerAvatar", $"OtherPermissionUrl={meta.OtherPermissionUrl}");
        obj.WriteLog("PlayerAvatar", $"LicenseType={meta.LicenseType}");
        obj.WriteLog("PlayerAvatar", $"OtherLicenseUrl={meta.OtherLicenseUrl}");

        await ctx.LoadAsyncTask();

        ctx.EnableUpdateWhenOffscreen();
        ctx.ShowMeshes();

        // Enable collision (and character controller) again (see the disabling line above)
        GetComponent <CharacterController>().enabled = true;

        // Move VRM avatar inside this gameObject
        ctx.Root.transform.SetParent(transform);
        ctx.Root.transform.localPosition = Vector3.zero;
        ctx.Root.transform.localRotation = Quaternion.identity;

        GetComponent <Animator>().avatar = ctx.Root.GetComponent <Animator>().avatar;

        obj.WriteLog("PlayerAvatar", $"VRM loaded");

        if (GetComponent <ObjectSync>().IsOriginal)
        {
            // Set up first person view (do not display avatar of the player)
            //  https://vrm.dev/en/univrm/components/univrm_firstperson/
            //  https://vrm.dev/en/dev/univrm-0.xx/programming/univrm_use_firstperson/
            var fp = GetComponentInChildren <VRMFirstPerson>();
            fp.Setup();
            if (XRRig != null)
            {
                XRRig.transform.position = fp.FirstPersonBone.position + fp.FirstPersonBone.rotation * fp.FirstPersonOffset;
                XRRig.transform.rotation = transform.rotation;  // face forward
                // Do not render layer "VRMThirdPersonOnly" on first person camera
                xrCamera.cullingMask &= ~LayerMask.GetMask("VRMThirdPersonOnly");
                SetHeadShadow();
            }
            if (ThirdPersonCamera != null)
            {
                // Do not render layer "VRMFirstPersonOnly" on third person camera
                ThirdPersonCamera.cullingMask &= ~LayerMask.GetMask("VRMFirstPersonOnly");
            }

            // Left hand
            if (leftController.HasValue)
            {
                // If left hand device is present
                var leftId = await node.CreateObject();

                leftHandObj = node.Objects[leftId];
                leftHandObj.SetField("parent", obj.GetObjectRef());
                leftHandObj.SetField("tags", new Sequence(new IValue[] {
                    new Primitive <string>("constantVelocity"),
                    new Primitive <string>("collider")
                }));
                obj.SetField("leftHand", leftHandObj.GetObjectRef());
            }
            // Right hand
            if (rightController.HasValue)
            {
                // If right hand device is present
                var rightId = await node.CreateObject();

                rightHandObj = node.Objects[rightId];
                rightHandObj.SetField("parent", obj.GetObjectRef());
                rightHandObj.SetField("tags", new Sequence(new IValue[] {
                    new Primitive <string>("constantVelocity"),
                    new Primitive <string>("collider")
                }));
                obj.SetField("rightHand", rightHandObj.GetObjectRef());
            }
            // Mouse
            var mouseGrabberId = await node.CreateObject();

            mouseGrabberObj = node.Objects[mouseGrabberId];
            mouseGrabberObj.SetField("parent", obj.GetObjectRef());
            mouseGrabberObj.SetField("tags", new Sequence(new IValue[] {
                new Primitive <string>("constantVelocity"),
                new Primitive <string>("collider")
            }));
            obj.SetField("mouseGrabber", mouseGrabberObj.GetObjectRef());
        }
    }