Ejemplo n.º 1
0
    ///////////////////////////////////////////

    static Vec3 CalcPedestalUIDir()
    {
        // Get the angle from the center of the pedestal to the user's head,
        // flatten it on the Y axis, and normalize it for angle calculations.
        Vec3 dir = Input.Head.position - terrainPose.position;

        dir = dir.XZ.Normalized.X0Y;

        // Use a 'sticky' algorithm for updating the angle of the UI. We snap
        // to increments of 60 degrees, but only do it after we've traveled
        // 20 degrees into the next increment. This prevents the UI from
        // moving back and forth when the user is wiggling around at the edge
        // of a snap increment.
        const float snapAngle    = 60;
        const float stickyAmount = 20;
        float       angle        = dir.XZ.Angle();

        if (SKMath.AngleDist(angle, uiAngle) > snapAngle / 2 + stickyAmount)
        {
            uiAngle = (int)(angle / snapAngle) * snapAngle + snapAngle / 2;
        }

        // Turn the angle back into a direction we can use to position the
        // pedestal
        return(Vec3.AngleXZ(uiAngle));
    }
Ejemplo n.º 2
0
        public void Initialize()
        {
            /// :CodeSample: Sound Sound.FromFile Sound.Play
            /// ### Basic usage
            Sound sound = Sound.FromFile("BlipNoise.wav");

            sound.Play(Vec3.Zero);
            /// :End:

            /// :CodeSample: Sound Sound.Generate
            /// ### Generating a sound
            /// Making a procedural sound is pretty straightforward! Here's
            /// an example of building a sound from two frequencies of sin
            /// wave.
            Sound genSound = Sound.Generate((t) =>
            {
                float band1        = SKMath.Sin(t * 523.25f * SKMath.Tau);          // a 'C' tone
                float band2        = SKMath.Sin(t * 659.25f * SKMath.Tau);          // an 'E' tone
                const float volume = 0.1f;
                return((band1 * 0.6f + band2 * 0.4f) * volume);
            }, 0.5f);

            genSound.Play(Vec3.Zero);
            /// :End:
        }
Ejemplo n.º 3
0
        void StepWand()
        {
            if (wandStream == null)
            {
                wandStream = Sound.CreateStream(5f); wandStreamInst = wandStream.Play(wandTipPrev);
            }
            if (wandModel == null)
            {
                wandModel = Model.FromFile("Wand.glb", Shader.UI);
            }
            if (wandFollow == null)
            {
                wandFollow = new LinePoint[10]; for (int i = 0; i < wandFollow.Length; i += 1)
                {
                    wandFollow[i] = new LinePoint(Vec3.Zero, new Color(1, 1, 1, i / (float)wandFollow.Length), (i / (float)wandFollow.Length) * 0.01f + 0.001f);
                }
            }

            UI.HandleBegin("wand", ref wandPose, wandModel.Bounds);
            wandModel.Draw(Matrix.Identity);
            UI.HandleEnd();

            Vec3  wandTip   = wandPose.ToMatrix() * (wandModel.Bounds.center + wandModel.Bounds.dimensions.y * 0.5f * Vec3.Up);
            Vec3  wandVel   = (wandTip - wandTipPrev) * Time.Elapsedf;
            float wandSpeed = wandVel.Magnitude * 100;

            int count = Math.Max(0, (int)(0.1f * 48000) - (wandStream.TotalSamples - wandStream.CursorSamples));

            if (wandSamples.Length < count)
            {
                wandSamples = new float[count];
            }
            for (int i = 0; i < count; i++)
            {
                wandIntensity  = Math.Min(1, SKMath.Lerp(wandIntensity, wandSpeed, 0.001f));
                wandTime      += (1 / 48000.0) * (30000 * wandIntensity + 2000);
                wandSamples[i] = (float)Math.Sin(wandTime) * wandIntensity;
            }

            wandStreamInst.Position = wandTip;
            wandStream.WriteSamples(wandSamples, count);

            for (int i = 0; i < wandFollow.Length - 1; i++)
            {
                wandFollow[i].pt = wandFollow[i + 1].pt;
            }
            wandFollow[wandFollow.Length - 1].pt = wandTip;
            Lines.Add(wandFollow);
            wandTipPrev = wandTip;
        }
Ejemplo n.º 4
0
        public void Initialize()
        {
            /// :CodeSample: Sound Sound.FromFile Sound.Play
            /// ### Basic usage
            Sound sound = Sound.FromFile("BlipNoise.wav");

            sound.Play(Vec3.Zero);
            /// :End:

            /// :CodeSample: Sound Sound.Generate
            /// ### Generating a sound via generator
            /// Making a procedural sound is pretty straightforward! Here's
            /// an example of building a 500ms sound from two frequencies of
            /// sin wave.
            Sound genSound = Sound.Generate((t) =>
            {
                float band1        = SKMath.Sin(t * 523.25f * SKMath.Tau);          // a 'C' tone
                float band2        = SKMath.Sin(t * 659.25f * SKMath.Tau);          // an 'E' tone
                const float volume = 0.1f;
                return((band1 * 0.6f + band2 * 0.4f) * volume);
            }, 0.5f);

            genSound.Play(Vec3.Zero);
            /// :End:

            /// :CodeSample: Sound Sound.FromSamples
            /// ### Generating a sound via samples
            /// Making a procedural sound is pretty straightforward! Here's
            /// an example of building a 500ms sound from two frequencies of
            /// sin wave.
            float[] samples = new float[(int)(48000 * 0.5f)];
            for (int i = 0; i < samples.Length; i++)
            {
                float       t      = i / 48000.0f;
                float       band1  = SKMath.Sin(t * 523.25f * SKMath.Tau);          // a 'C' tone
                float       band2  = SKMath.Sin(t * 659.25f * SKMath.Tau);          // an 'E' tone
                const float volume = 0.1f;
                samples[i] = (band1 * 0.6f + band2 * 0.4f) * volume;
            }
            Sound sampleSound = Sound.FromSamples(samples);

            sampleSound.Play(Vec3.Zero);
            /// :End:
        }
Ejemplo n.º 5
0
    public void Update()
    {
        UI.PushSurface(_modelPose);
        _model.Draw(Matrix.Identity, new Color(0.5f, 0.5f, 0.5f));
        UI.PushSurface(
            _surfaceNode.ModelTransform.Pose,
            _surfaceNode.ModelTransform.Scale.XY0 / 2,
            _surfaceNode.ModelTransform.Scale.XY);
        Vec3 center = Hierarchy.ToWorld(Vec3.Zero);

        UI.Label("UI on a Model node!");
        UI.HSeparator();
        UI.Button("Do Thing");
        UI.PopSurface();
        UI.PopSurface();

        if (_model.Intersect(new Ray(V.XYZ(SKMath.Cos(Time.Totalf) * 0.15f, 1, 0), -Vec3.Up), out Ray at))
        {
            Lines.Add(at, 0.3f, new Color32(0, 255, 0, 255), 0.005f);
        }

        Tests.Screenshot("Tests/NodeUI.jpg", 400, 400, center + Vec3.One * 0.15f, center);
    }
Ejemplo n.º 6
0
    bool TestAngleDist()
    {
        float angleDistA = SKMath.AngleDist(0, 359);
        float angleDistB = SKMath.AngleDist(359, 0);
        float angleDistC = SKMath.AngleDist(359, 720);
        float angleDistD = SKMath.AngleDist(-60, 70);
        float angleDistE = SKMath.AngleDist(-60, 140);

        Log.Info($"AngleDist 0 to 359: {angleDistA}");
        Log.Info($"AngleDist 359 to 0: {angleDistB}");
        Log.Info($"AngleDist 359 to 720: {angleDistC}");
        Log.Info($"AngleDist -60 to 70: {angleDistD}");
        Log.Info($"AngleDist -60 to 140: {angleDistE}");

        if (MathF.Abs(angleDistA - angleDistB) > tolerance)
        {
            return(false);
        }
        if (MathF.Abs(angleDistA - angleDistC) > tolerance)
        {
            return(false);
        }
        if (MathF.Abs(angleDistA - 1) > tolerance)
        {
            return(false);
        }
        if (MathF.Abs(angleDistD - 130) > tolerance)
        {
            return(false);
        }
        if (MathF.Abs(angleDistE - 160) > tolerance)
        {
            return(false);
        }
        return(true);
    }
Ejemplo n.º 7
0
    public void Initialize()
    {
        /// :CodeSample: Mesh.GenerateCube
        /// ![Procedural Geometry Demo]({{site.url}}/img/screenshots/ProceduralGeometry.jpg)
        /// Here's a quick example of generating a mesh! You can store it in just a
        /// Mesh, or you can attach it to a Model for easier rendering later on.
        Mesh  cubeMesh  = Mesh.GenerateCube(Vec3.One * 0.4f);
        Model cubeModel = Model.FromMesh(cubeMesh, Default.Material);

        /// :End:
        demoCubeMesh  = cubeMesh;
        demoCubeModel = cubeModel;

        /// :CodeSample: Mesh.GenerateRoundedCube
        /// ![Procedural Geometry Demo]({{site.url}}/img/screenshots/ProceduralGeometry.jpg)
        /// Here's a quick example of generating a mesh! You can store it in just a
        /// Mesh, or you can attach it to a Model for easier rendering later on.
        Mesh  roundedCubeMesh  = Mesh.GenerateRoundedCube(Vec3.One * 0.4f, 0.05f);
        Model roundedCubeModel = Model.FromMesh(roundedCubeMesh, Default.Material);

        /// :End:
        demoRoundedCubeMesh  = roundedCubeMesh;
        demoRoundedCubeModel = roundedCubeModel;

        /// :CodeSample: Mesh.GenerateSphere
        /// ![Procedural Geometry Demo]({{site.url}}/img/screenshots/ProceduralGeometry.jpg)
        /// Here's a quick example of generating a mesh! You can store it in just a
        /// Mesh, or you can attach it to a Model for easier rendering later on.
        Mesh  sphereMesh  = Mesh.GenerateSphere(0.4f);
        Model sphereModel = Model.FromMesh(sphereMesh, Default.Material);

        /// :End:
        demoSphereMesh  = sphereMesh;
        demoSphereModel = sphereModel;

        /// :CodeSample: Mesh.GenerateCylinder
        /// ![Procedural Geometry Demo]({{site.url}}/img/screenshots/ProceduralGeometry.jpg)
        /// Here's a quick example of generating a mesh! You can store it in just a
        /// Mesh, or you can attach it to a Model for easier rendering later on.
        Mesh  cylinderMesh  = Mesh.GenerateCylinder(0.4f, 0.4f, Vec3.Up);
        Model cylinderModel = Model.FromMesh(cylinderMesh, Default.Material);

        /// :End:
        demoCylinderMesh  = cylinderMesh;
        demoCylinderModel = cylinderModel;

        /// :CodeSample: Mesh.GeneratePlane
        /// ![Procedural Geometry Demo]({{site.url}}/img/screenshots/ProceduralGeometry.jpg)
        /// Here's a quick example of generating a mesh! You can store it in just a
        /// Mesh, or you can attach it to a Model for easier rendering later on.
        Mesh  planeMesh  = Mesh.GeneratePlane(Vec2.One * 0.4f);
        Model planeModel = Model.FromMesh(planeMesh, Default.Material);

        /// :End:
        demoPlaneMesh  = planeMesh;
        demoPlaneModel = planeModel;

        /// :CodeSample: Mesh.SetVerts Mesh.SetInds
        /// ## Procedurally generating a wavy grid
        /// ![Wavy Grid]({{site.url}}/img/screenshots/ProceduralGrid.jpg)
        /// Here, we'll generate a grid mesh using Mesh.SetVerts and Mesh.SetInds! This
        /// is a common example of creating a grid using code, we're using a sin wave
        /// to make it more visually interesting, but you could also substitute this for
        /// something like sampling a heightmap, or a more interesting mathematical
        /// formula!
        ///
        /// Note: x+y*gridSize is the formula for 2D (x,y) access of a 1D array that represents
        /// a grid.
        const int gridSize = 8;

        Vertex[] verts = new Vertex[gridSize * gridSize];
        uint  [] inds  = new uint  [gridSize * gridSize * 6];

        for (int y = 0; y < gridSize; y++)
        {
            for (int x = 0; x < gridSize; x++)
            {
                // Create a vertex on a grid, centered about the origin. The dimensions extends
                // from -0.5 to +0.5 on the X and Z axes. The Y value is then sampled from
                // a sin wave using the x and y values.
                //
                // The normal of the vertex is then calculated from the derivative of the Y
                // value!
                verts[x + y * gridSize] = new Vertex(
                    new Vec3(
                        x / (float)gridSize - 0.5f,
                        SKMath.Sin((x + y) * 0.7f) * 0.1f,
                        y / (float)gridSize - 0.5f),
                    new Vec3(
                        -SKMath.Cos((x + y) * 0.7f),
                        1,
                        -SKMath.Cos((x + y) * 0.7f)).Normalized);

                // Create triangle face indices from the current vertex, and the vertices
                // on the next row and column! Since there is no 'next' row and column on
                // the last row and column, we guard this with a check for size-1.
                if (x < gridSize - 1 && y < gridSize - 1)
                {
                    int ind = (x + y * gridSize) * 6;
                    inds[ind]     = (uint)((x + 1) + (y + 1) * gridSize);
                    inds[ind + 1] = (uint)((x + 1) + (y) * gridSize);
                    inds[ind + 2] = (uint)((x) + (y + 1) * gridSize);

                    inds[ind + 3] = (uint)((x) + (y + 1) * gridSize);
                    inds[ind + 4] = (uint)((x + 1) + (y) * gridSize);
                    inds[ind + 5] = (uint)((x) + (y) * gridSize);
                }
            }
        }
        demoProcMesh = new Mesh();
        demoProcMesh.SetVerts(verts);
        demoProcMesh.SetInds(inds);
        /// :End:
    }
Ejemplo n.º 8
0
    public void Update()
    {
        Hierarchy.Push(Matrix.T(0, 0, -0.3f));

        UI.WindowBegin("Alignment", ref alignWindow, new Vec2(20, 0) * Units.cm2m);
        Vec2 size = new Vec2(5 * Units.cm2m, UI.LineHeight);

        if (UI.Radio("Left", alignX == TextAlign.XLeft, size))
        {
            alignX = TextAlign.XLeft;
        }
        UI.SameLine();
        if (UI.Radio("CenterX", alignX == TextAlign.XCenter, size))
        {
            alignX = TextAlign.XCenter;
        }
        UI.SameLine();
        if (UI.Radio("Right", alignX == TextAlign.XRight, size))
        {
            alignX = TextAlign.XRight;
        }
        if (UI.Radio("Top", alignY == TextAlign.YTop, size))
        {
            alignY = TextAlign.YTop;
        }
        UI.SameLine();
        if (UI.Radio("CenterY", alignY == TextAlign.YCenter, size))
        {
            alignY = TextAlign.YCenter;
        }
        UI.SameLine();
        if (UI.Radio("Bottom", alignY == TextAlign.YBottom, size))
        {
            alignY = TextAlign.YBottom;
        }
        UI.WindowEnd();

        Hierarchy.Push(Matrix.T(0.1f, 0, 0));
        Text.Add("X Center", Matrix.TRS(new Vec3(0, .1f, 0), Quat.LookDir(0, 0, 1)), TextAlign.XCenter | TextAlign.YCenter, alignX | alignY);
        Text.Add("X Left", Matrix.TRS(new Vec3(0, .15f, 0), Quat.LookDir(0, 0, 1)), TextAlign.XLeft | TextAlign.YCenter, alignX | alignY);
        Text.Add("X Right", Matrix.TRS(new Vec3(0, .2f, 0), Quat.LookDir(0, 0, 1)), TextAlign.XRight | TextAlign.YCenter, alignX | alignY);
        Lines.Add(new Vec3(0, .05f, 0), new Vec3(0, .25f, 0), Color32.White, 0.001f);
        Hierarchy.Pop();

        Hierarchy.Push(Matrix.T(-0.1f, 0, 0));
        Text.Add("Y Center", Matrix.TRS(new Vec3(0, .1f, 0), Quat.LookDir(0, 0, 1)), TextAlign.YCenter | TextAlign.XCenter, alignX | alignY);
        Lines.Add(new Vec3(-0.05f, .1f, 0), new Vec3(.05f, .1f, 0), Color32.White, 0.001f);

        Text.Add("Y Top", Matrix.TRS(new Vec3(0, .15f, 0), Quat.LookDir(0, 0, 1)), TextAlign.YTop | TextAlign.XCenter, alignX | alignY);
        Lines.Add(new Vec3(-0.05f, .15f, 0), new Vec3(.05f, .15f, 0), Color32.White, 0.001f);

        Text.Add("Y Bottom", Matrix.TRS(new Vec3(0, .2f, 0), Quat.LookDir(0, 0, 1)), TextAlign.YBottom | TextAlign.XCenter, alignX | alignY);
        Lines.Add(new Vec3(-0.05f, .2f, 0), new Vec3(.05f, .2f, 0), Color32.White, 0.001f);
        Hierarchy.Pop();

        Hierarchy.Push(Matrix.T(0, -0.1f, 0));
        if (Tests.IsTesting)
        {
            Renderer.Screenshot(Hierarchy.ToWorld(new Vec3(0, 0, 0.09f)), Hierarchy.ToWorld(Vec3.Zero), 600, 300, "../../../docs/img/screenshots/BasicText.jpg");
        }
        /// :CodeSample: Text.MakeStyle Font.FromFile Text.Add
        /// Then it's pretty trivial to just draw some text on the screen! Just call
        /// Text.Add on update. If you don't have a TextStyle available, calling it
        /// without one will just fall back on the default style.
        // Text with an explicit text style
        Text.Add(
            "Here's\nSome\nMulti-line\nText!!",
            Matrix.TRS(new Vec3(0.1f, 0, 0), Quat.LookDir(0, 0, 1)),
            style);
        // Text using the default text style
        Text.Add(
            "Here's\nSome\nMulti-line\nText!!",
            Matrix.TRS(new Vec3(-0.1f, 0, 0), Quat.LookDir(0, 0, 1)));
        /// :End:

        Hierarchy.Push(Matrix.T(0, -0.2f, 0));
        Text.Add(
            "Here's Some Multi-line Text!!",
            Matrix.TRS(new Vec3(0, 0.0f, 0), Quat.LookDir(0, 0, 1)),
            new Vec2(SKMath.Cos(Time.Totalf) * 10 + 11, 20) * Units.cm2m,
            TextFit.Clip,
            style, TextAlign.Center, alignX | alignY);
        Hierarchy.Pop();

        Hierarchy.Pop();

        Hierarchy.Pop();
    }
Ejemplo n.º 9
0
    public void Update()
    {
        Color colIntersect = Color.HSV(0, 0.8f, 1);
        Color colTest      = Color.HSV(0, 0.6f, 1);
        Color colObj       = Color.HSV(0.05f, 0.7f, 1);
        Color active       = new Color(1, 1, 1, 0.7f);
        Color notActive    = new Color(1, 1, 1, 1);

        // Plane and Ray
        bool planeRayActive = UI.AffordanceBegin("PlaneRay", ref posePlaneRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), planeRayActive ? active:notActive);

        Plane ground    = new Plane(Vec3.Zero, new Vec3(1, 2, 0));
        Ray   groundRay = new Ray(Vec3.Zero + new Vec3(0, 0.2f, 0), Vec3.AngleXZ(Time.Totalf * 90, -2).Normalized());

        Lines.Add(groundRay.position, groundRay.position + groundRay.direction * 0.1f, new Color32(255, 0, 0, 255), 2 * Units.mm2m);
        planeMesh.Draw(material, Matrix.TRS(Vec3.Zero, Quat.LookDir(ground.normal), 0.25f), colObj);
        if (groundRay.Intersect(ground, out Vec3 groundAt))
        {
            sphereMesh.Draw(material, Matrix.TS(groundAt, 0.02f), colIntersect);
        }

        UI.AffordanceEnd();

        if (Demos.TestMode)
        {
            Renderer.Screenshot(posePlaneRay.position + new Vec3(0.0f, 0.3f, 0.15f), posePlaneRay.position + Vec3.Up * 0.1f, 400, 400, "../../../docs/img/screenshots/RayIntersectPlane.jpg");
        }

        // Line and Plane
        bool linePlaneActive = UI.AffordanceBegin("LinePlane", ref poseLinePlane, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), linePlaneActive ? active : notActive);

        Plane groundLinePlane = new Plane(Vec3.Zero, new Vec3(1, 2, 0));
        Ray   groundLineRay   = new Ray(Vec3.Zero + new Vec3(0, 0.25f, 0), Vec3.AngleXZ(Time.Totalf * 90, -2).Normalized());
        Vec3  groundLineP1    = groundLineRay.position + groundLineRay.direction * (SKMath.Cos(Time.Totalf * 3) + 1) * 0.2f;
        Vec3  groundLineP2    = groundLineRay.position + groundLineRay.direction * ((SKMath.Cos(Time.Totalf * 3) + 1) * 0.2f + 0.1f);

        Lines.Add(groundLineP1, groundLineP2, colTest, 2 * Units.mm2m);
        sphereMesh.Draw(material, Matrix.TS(groundLineP1, 0.01f), colTest);
        sphereMesh.Draw(material, Matrix.TS(groundLineP2, 0.01f), colTest);
        bool groundLineIntersects = groundLinePlane.Intersect(groundLineP1, groundLineP2, out Vec3 groundLineAt);

        planeMesh.Draw(material, Matrix.TRS(Vec3.Zero, Quat.LookDir(groundLinePlane.normal), 0.25f), groundLineIntersects? colIntersect : colObj);
        if (groundLineIntersects)
        {
            sphereMesh.Draw(material, Matrix.TS(groundLineAt, 0.02f), colIntersect);
        }

        UI.AffordanceEnd();

        if (Demos.TestMode)
        {
            Renderer.Screenshot(poseLinePlane.position + new Vec3(0.0f, 0.3f, 0.15f), poseLinePlane.position + Vec3.Up * 0.1f, 400, 400, "../../../docs/img/screenshots/LineIntersectPlane.jpg");
        }

        // Sphere and Ray
        bool sphereRayActive = UI.AffordanceBegin("SphereRay", ref poseSphereRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), sphereRayActive ? active : notActive);

        Sphere sphere    = new Sphere(Vec3.Zero, 0.25f);
        Vec3   sphereDir = Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 3) * 1.5f + 0.1f).Normalized();
        Ray    sphereRay = new Ray(sphere.center - sphereDir * 0.35f, sphereDir);

        Lines.Add(sphereRay.position, sphereRay.position + sphereRay.direction * 0.1f, colTest, 2 * Units.mm2m);
        if (sphereRay.Intersect(sphere, out Vec3 sphereAt))
        {
            sphereMesh.Draw(material, Matrix.TS(sphereAt, 0.02f), colIntersect);
        }
        sphereMesh.Draw(material, Matrix.TS(sphere.center, 0.25f), colObj);

        UI.AffordanceEnd();

        if (Demos.TestMode)
        {
            Renderer.Screenshot(poseSphereRay.position + new Vec3(0.0f, 0.3f, 0.15f), poseSphereRay.position, 400, 400, "../../../docs/img/screenshots/RayIntersectSphere.jpg");
        }

        // Bounds and Ray
        bool boundsRayActive = UI.AffordanceBegin("BoundsRay", ref poseBoundsRay, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), boundsRayActive ? active : notActive);

        Bounds bounds    = new Bounds(Vec3.Zero, Vec3.One * 0.25f);
        Vec3   boundsDir = Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 3) * 1.5f).Normalized();
        Ray    boundsRay = new Ray(bounds.center - boundsDir * 0.35f, boundsDir);

        Lines.Add(boundsRay.position, boundsRay.position + boundsRay.direction * 0.1f, colTest, 2 * Units.mm2m);
        if (boundsRay.Intersect(bounds, out Vec3 boundsAt))
        {
            sphereMesh.Draw(material, Matrix.TS(boundsAt, 0.02f), colIntersect);
        }
        cubeMesh.Draw(material, Matrix.TS(bounds.center, 0.25f), colObj);

        UI.AffordanceEnd();

        if (Demos.TestMode)
        {
            Renderer.Screenshot(poseBoundsRay.position + new Vec3(0.0f, 0.3f, 0.15f), poseBoundsRay.position, 400, 400, "../../../docs/img/screenshots/RayIntersectBounds.jpg");
        }

        // Bounds and Line
        bool boundsLineActive = UI.AffordanceBegin("BoundsLine", ref poseBoundsLine, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), boundsLineActive ? active : notActive);

        Bounds boundsLine   = new Bounds(Vec3.Zero, Vec3.One * 0.25f);
        Vec3   boundsLineP1 = boundsLine.center + Vec3.AngleXZ(Time.Totalf * 45, SKMath.Cos(Time.Totalf * 3)) * 0.35f;
        Vec3   boundsLineP2 = boundsLine.center + Vec3.AngleXZ(Time.Totalf * 90, SKMath.Cos(Time.Totalf * 6)) * SKMath.Cos(Time.Totalf) * 0.35f;

        Lines.Add(boundsLineP1, boundsLineP2, colTest, 2 * Units.mm2m);
        sphereMesh.Draw(material, Matrix.TS(boundsLineP1, 0.01f), colTest);
        sphereMesh.Draw(material, Matrix.TS(boundsLineP2, 0.01f), colTest);
        cubeMesh.Draw(material, Matrix.TS(boundsLine.center, 0.25f),
                      boundsLine.Contains(boundsLineP1, boundsLineP2) ? colIntersect : colObj);

        UI.AffordanceEnd();

        if (Demos.TestMode)
        {
            Renderer.Screenshot(poseBoundsLine.position + new Vec3(0.0f, 0.3f, 0.15f), poseBoundsLine.position, 400, 400, "../../../docs/img/screenshots/LineIntersectBounds.jpg");
        }

        // Cross product
        bool crossActive = UI.AffordanceBegin("Cross", ref poseCross, new Bounds(Vec3.One * 0.4f));

        boundsMesh.Draw(boundsMat, Matrix.TS(Vec3.Zero, 0.4f), crossActive ? active : notActive);

        Vec3 crossStart = Vec3.Zero;
        //Vec3 right      = Vec3.Cross(Vec3.Forward, Vec3.Up); // These are the same!
        Vec3 right = Vec3.PerpendicularRight(Vec3.Forward, Vec3.Up);

        Lines.Add(crossStart, crossStart + Vec3.Up * 0.1f, new Color32(255, 255, 255, 255), 2 * Units.mm2m);
        Lines.Add(crossStart, crossStart + Vec3.Forward * 0.1f, new Color32(255, 255, 255, 255), 2 * Units.mm2m);
        Lines.Add(crossStart, crossStart + right * 0.1f, new Color32(0, 255, 0, 255), 2 * Units.mm2m);
        Text.Add("Up", Matrix.TRS(crossStart + Vec3.Up * 0.1f, Quat.LookDir(-Vec3.Forward), 1), TextAlign.XCenter | TextAlign.YBottom);
        Text.Add("Fwd", Matrix.TRS(crossStart + Vec3.Forward * 0.1f, Quat.LookDir(-Vec3.Forward), 1), TextAlign.XCenter | TextAlign.YBottom);
        Text.Add("Vec3.Cross(Fwd,Up)", Matrix.TRS(crossStart + right * 0.1f, Quat.LookDir(-Vec3.Forward), 1), TextAlign.XCenter | TextAlign.YBottom);

        UI.AffordanceEnd();

        if (Demos.TestMode)
        {
            Renderer.Screenshot(poseCross.position + new Vec3(0.075f, 0.1f, 0.15f), poseCross.position + new Vec3(0.075f, 0, 0), 400, 400, "../../../docs/img/screenshots/CrossProduct.jpg");
        }
    }
Ejemplo n.º 10
0
    public void Update()
    {
        Tests.Screenshot("Tests/LineRenderer.jpg", 600, 600, V.XYZ(0, 0, 0.5f), Vec3.Zero);

        // A ring of lines that goes out past the edge of the screen
        Color32 c = Color32.White;

        for (int i = 0; i < 16; i++)
        {
            Vec3 at = Vec3.AngleXY((i / 16.0f) * 360.0f) * 0.5f;
            Lines.Add(at - V.XYZ(0, 0, 0.2f), at + V.XYZ(0, 0, 0.2f), c, 0.01f);
        }

        // A Circle
        c = new Color(1, .5f, .5f, 1).ToLinear();
        LinePoint[] points = new LinePoint[17];
        for (int i = 0; i < points.Length; i++)
        {
            points[i] = new LinePoint(
                Vec3.AngleXY((i / (float)(points.Length - 1)) * 360.0f) * 0.4f,
                c, 0.01f);
        }
        Lines.Add(points);

        // A square, worst case for this system
        c = new Color(.5f, 1, .5f, 1).ToLinear();
        Lines.Add(new LinePoint[] {
            new LinePoint(V.XY0(-0.25f, 0.25f), c, 0.01f),
            new LinePoint(V.XY0(0.25f, 0.25f), c, 0.01f),
            new LinePoint(V.XY0(0.25f, -0.25f), c, 0.01f),
            new LinePoint(V.XY0(-0.25f, -0.25f), c, 0.01f),
            new LinePoint(V.XY0(-0.25f, 0.25f), c, 0.01f),
        });

        // A beveled square
        c = new Color(.5f, .5f, 1, 1).ToLinear();
        Lines.Add(new LinePoint[] {
            new LinePoint(V.XY0(-0.2f, 0.19f), c, 0.01f),
            new LinePoint(V.XY0(-0.19f, 0.2f), c, 0.01f),
            new LinePoint(V.XY0(0.19f, 0.2f), c, 0.01f),
            new LinePoint(V.XY0(0.2f, 0.19f), c, 0.01f),
            new LinePoint(V.XY0(0.2f, -0.19f), c, 0.01f),
            new LinePoint(V.XY0(0.19f, -0.2f), c, 0.01f),
            new LinePoint(V.XY0(-0.19f, -0.2f), c, 0.01f),
            new LinePoint(V.XY0(-0.2f, -0.19f), c, 0.01f),
            new LinePoint(V.XY0(-0.2f, 0.19f), c, 0.01f),
        });

        // an Icosohedron
        float t  = (1.0f + SKMath.Sqrt(5.0f)) / 2.0f;
        float s  = 0.08f;
        float s2 = 0.3f;
        int   h  = 0;
        Vec3  v;

        Hierarchy.Push(Matrix.R(Quat.FromAngles(10, 10, 10)));
        v = V.XYZ(-1, t, 0) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(1, t, 0) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(-1, -t, 0) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(1, -t, 0) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(0, -1, t) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(0, 1, t) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(0, -1, -t) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(0, 1, -t) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(t, 0, -1) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(t, 0, 1) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(-t, 0, -1) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        v = V.XYZ(-t, 0, 1) * s; Lines.Add(v, v * s2, Color.HSV((h++) / 12.0f, 0.8f, 0.8f).ToLinear(), 0.01f);
        Hierarchy.Pop();
    }
Ejemplo n.º 11
0
        public void Step()
        {
            const float shoulderWidth = 0.16f;             // half the total shoulder width
            const float forearm       = 0.22f;             // length of the forearm
            const float uarm          = 0.25f;             // length of the upper arm
            const float headLength    = 0.1f;              // length from head point to neck
            const float neckLength    = 0.02f;             // length from neck to center shoulders
            const float shoulderDrop  = 0.05f;             // shoulder drop height from shoulder center
            const float elbowFlare    = 0.45f;             // Elbows point at a location 1m down, and elbowFlare out from the shoulder

            Pose head = Input.Head;

            // Head, neck, and shoulder center
            headLine[0].pt = head.position;
            headLine[1].pt = headLine[0].pt + head.orientation * V.XYZ(0, -headLength, 0);
            headLine[2].pt = headLine[1].pt - V.XYZ(0, neckLength, 0);
            headLine[0].pt = Vec3.Lerp(headLine[0].pt, headLine[1].pt, 0.1f);
            Lines.Add(headLine);

            // Shoulder forward facing direction is head direction weighted
            // equally with the direction of both hands.
            Vec3 forward =
                head.Forward.X0Z.Normalized * 2
                + (Input.Hand(Handed.Right).wrist.position - headLine[2].pt.X0Z).Normalized
                + (Input.Hand(Handed.Left).wrist.position - headLine[2].pt.X0Z).Normalized;

            forward = forward * 0.25f;
            Vec3 right = Vec3.PerpendicularRight(forward, Vec3.Up).Normalized;

            // Now for each arm
            for (int h = 0; h < 2; h++)
            {
                float handed  = h == 0 ? -1 : 1;
                Hand  hand    = Input.Hand((Handed)h);
                Vec3  handPos = hand.wrist.position;
                if (!hand.IsTracked)
                {
                    continue;
                }

                armLine[0].pt = headLine[2].pt;
                armLine[1].pt = armLine[0].pt + right * handed * shoulderWidth - Vec3.Up * shoulderDrop;
                armLine[3].pt = handPos;

                // Triangle represented by 3 edges, forearm, uarm, and armDist
                float armDist = Math.Min(forearm + uarm, Vec3.Distance(armLine[1].pt, handPos));

                // Heron's formula to find area
                float s    = (forearm + uarm + armDist) / 2;
                float area = SKMath.Sqrt(s * (s - forearm) * (s - uarm) * (s - armDist));
                // Height of triangle based on area
                float offsetH = (2 * area) / armDist;
                // Height can now be used to calculate how far off the elbow is
                float offsetD = SKMath.Sqrt(Math.Abs(offsetH * offsetH - uarm * uarm));

                // Elbow calculation begins somewhere along the line between the
                // shoulder and the wrist.
                Vec3 dir = (handPos - armLine[1].pt).Normalized;
                Vec3 at  = armLine[1].pt + dir * offsetD;
                // The elbow naturally flares out to the side, rather than
                // dropping straight down. Here, we find a point to flare out
                // towards.
                Vec3  flarePoint = headLine[2].pt + right * handed * elbowFlare - Vec3.Up;
                Plane flarePlane = new Plane(flarePoint, Ray.FromTo(headLine[2].pt, handPos).Closest(flarePoint) - flarePoint);
                Vec3  dirDown    = (flarePlane.Closest(at) - at).Normalized;
                armLine[2].pt = at + dirDown * offsetH;

                Lines.Add(armLine);
                for (int i = 1; i < 5; i++)
                {
                    Lines.Add(handPos, hand[(FingerId)i, JointId.KnuckleMajor].position, Color32.White, new Color32(255, 255, 255, 0), 0.01f);
                }
            }
        }
Ejemplo n.º 12
0
        void StepMenu(Hand hand)
        {
            // Animate the menu a bit
            float time = (Time.Elapsedf * 24);

            menuPose.position    = Vec3.Lerp(menuPose.position, destPose.position, time);
            menuPose.orientation = Quat.Slerp(menuPose.orientation, destPose.orientation, time);
            activation           = SKMath.Lerp(activation, 1, time);

            // Pre-calculate some circle traversal values
            HandRadialLayer layer    = layers[activeLayer];
            int             count    = layer.items.Length;
            float           step     = 360 / count;
            float           halfStep = step / 2;

            // Push the Menu's pose onto the stack, so we can draw, and work
            // in local space.
            Hierarchy.Push(menuPose.ToMatrix(activation));

            // Calculate the status of the menu!
            Vec3  tipWorld = hand[FingerId.Index, JointId.Tip].position;
            Vec3  tipLocal = Hierarchy.ToLocal(tipWorld);
            float magSq    = tipLocal.MagnitudeSq;
            bool  onMenu   = tipLocal.z > -0.02f && tipLocal.z < 0.02f;
            bool  focused  = onMenu && magSq > minDist * minDist;
            bool  selected = onMenu && magSq > midDist * midDist;
            bool  cancel   = magSq > maxDist * maxDist;

            // Find where our finger is pointing to, and draw that
            float fingerAngle = (float)Math.Atan2(tipLocal.y, tipLocal.x) * Units.rad2deg - (layer.startAngle + angleOffset);

            while (fingerAngle < 0)
            {
                fingerAngle += 360;
            }
            int angleId = (int)(fingerAngle / step);

            Lines.Add(Vec3.Zero, new Vec3(tipLocal.x, tipLocal.y, 0), Color.White * 0.5f, 0.001f);

            // Draw the menu inner and outer circles
            Lines.Add(circle);
            Lines.Add(innerCircle);

            // Now draw each of the menu items!
            for (int i = 0; i < count; i++)
            {
                float currAngle     = i * step + layer.startAngle + angleOffset;
                bool  highlightText = focused && angleId == i;
                bool  highlightLine = highlightText || (focused && (angleId + 1) % count == i);
                Vec3  dir           = Vec3.AngleXY(currAngle);
                Lines.Add(dir * minDist, dir * maxDist, highlightLine ? Color.White : Color.White * 0.5f, highlightLine?0.002f:0.001f);
                Text.Add(layer.items[i].name, Matrix.TRS(Vec3.AngleXY(currAngle + halfStep) * midDist, Quat.FromAngles(0, 0, currAngle + halfStep - 90), highlightText?1.2f:1), TextAlign.XCenter | TextAlign.YBottom);
            }

            // Done with local work
            Hierarchy.Pop();

            // Execute any actions that were discovered

            // But not if we're still in the process of animating, interaction values
            // could be pretty incorrect when we're still lerping around.
            if (activation < 0.95f)
            {
                return;
            }
            if (selected)
            {
                SelectItem(layer.items[angleId], tipWorld, (angleId + 0.5f) * step);
            }
            if (cancel)
            {
                Close();
            }
        }