示例#1
0
        // returns frame at ray-intersection point, with normal pointing *outwards*
        public static Frame3f GetSphereFrame(float fHUDRadius, float fHorzAngleDeg, float fVertAngleDeg)
        {
            Ray   r     = VRUtil.MakeRayFromSphereCenter(fHorzAngleDeg, fVertAngleDeg);
            float fRayT = 0.0f;

            RayIntersection.Sphere(r.origin, r.direction, Vector3.zero, fHUDRadius, out fRayT);
            Vector3 v = r.origin + fRayT * r.direction;

            return(new Frame3f(v, v.normalized));
        }
示例#2
0
        // returns frame at ray-intersection point, with normal pointing *outwards*
        public static Frame3f GetCylinderFrameFromAngles(float fHUDRadius, float fHorzAngleDeg, float fVertAngleDeg)
        {
            Ray3f r     = VRUtil.MakeRayFromSphereCenter(fHorzAngleDeg, fVertAngleDeg);
            float fRayT = 0.0f;

            RayIntersection.InfiniteCylinder(r.Origin, r.Direction, Vector3f.Zero, Vector3f.AxisY, fHUDRadius, out fRayT);
            Vector3f v = r.Origin + fRayT * r.Direction;
            Vector3f n = new Vector3f(v[0], 0, v[2]).Normalized;

            return(new Frame3f(v, n));
        }
        virtual public Frame3f From2DCoords(Vector2f pos, float fNormalOffset)
        {
            // todo simplify this, use radians only
            float    circ    = 2 * MathUtil.PIf * Radius;
            float    fAngleX = (pos.x / circ) * 360.0f;
            float    fAngleY = (pos.y / circ) * 360.0f;
            Vector3f normal  = VRUtil.DirectionFromSphereCenter(fAngleX, fAngleY);
            Vector3f pos3    = (Radius + fNormalOffset) * normal + Origin;

            return(new Frame3f(pos3, normal));
        }
示例#4
0
 public override void PreRender()
 {
     if (MaintainConsistentViewSize)
     {
         float fScaling = VRUtil.GetVRRadiusForVisualAngle(
             pivotGO.GetPosition(),
             parentScene.ActiveCamera.GetPosition(),
             SceneGraphConfig.DefaultPivotVisualDegrees);
         fScaling /= parentScene.GetSceneScale();
         pivotGO.SetLocalScale(new Vector3f(fScaling, fScaling, fScaling));
     }
 }
示例#5
0
        public static Frame3f GetCylinderFrameFromAngleHeight(float fHUDRadius, float fHorzAngleDeg, float fVertHeight)
        {
            Ray r = VRUtil.MakeRayFromSphereCenter(fHorzAngleDeg, 0);

            r.direction = fHUDRadius * r.direction + fVertHeight * Vector3.up;
            r.direction.Normalize();
            float fRayT = 0.0f;

            RayIntersection.InfiniteCylinder(r.origin, r.direction, Vector3f.Zero, Vector3f.AxisY, fHUDRadius, out fRayT);
            Vector3 v = r.origin + fRayT * r.direction;
            Vector3 n = new Vector3(v[0], 0, v[2]).normalized;

            return(new Frame3f(v, n));
        }
        // called on per-frame Update()
        override public void PreRender()
        {
            gizmo.Show();

            foreach (var v in Widgets)
            {
                float fScaling = VRUtil.GetVRRadiusForVisualAngle(
                    v.Key.GetPosition(),
                    parentScene.ActiveCamera.GetPosition(),
                    SceneGraphConfig.DefaultPivotVisualDegrees);
                fScaling /= parentScene.GetSceneScale();
                v.Key.SetLocalScale(fScaling * WidgetScale);
            }
        }
        // called on per-frame Update()
        virtual public void PreRender()
        {
            gizmo.Show();

            float fScaling = VRUtil.GetVRRadiusForVisualAngle(
                gizmo.transform.position,
                parentScene.ActiveCamera.GetPosition(),
                SceneGraphConfig.DefaultAxisGizmoVisualDegrees);

            fScaling /= parentScene.GetSceneScale();
            float fGeomDim = gizmoGeomBounds.size.magnitude;

            fScaling /= fGeomDim;
            gizmo.transform.localScale = new Vector3(fScaling, fScaling, fScaling);
        }
示例#8
0
            public void UpdateSetWorldScale(Ray3f left, Ray3f right)
            {
                Vector3f hit1  = hitFrame.RayPlaneIntersection(left.Origin, left.Direction, 2);
                Vector3f hit2  = hitFrame.RayPlaneIntersection(right.Origin, right.Direction, 2);
                Vector3f avg   = (hit1 + hit2) * 0.5f;
                float    r0    = (hit1 - (Vector3f)go.transform.position).Length;
                float    r1    = (hit2 - (Vector3f)go.transform.position).Length;
                float    r     = (r0 + r1) * 0.5f;
                float    min_r = VRUtil.GetVRRadiusForVisualAngle(avg, camState.camPosition, 2.0f);

                r = (float)Math.Max(r, min_r);
                go.transform.localScale = r * Vector3f.One;
                go.GetComponent <Renderer>().material =
                    (r > deadzone_r) ? mYes : mNo;
            }
示例#9
0
        public void PreRender(Vector3f cameraPosW)
        {
            float fSceneScale = parentSO.GetScene().GetSceneScale();

            foreach (var i in vObjects)
            {
                Vector3f vPos = i.go.transform.position;
                float    fR   = VRUtil.GetVRRadiusForVisualAngle(vPos, cameraPosW, i.fVisualRadiusDeg);

                // have to compensate for scaling of parent SO
                float fParentSOScale = parentSO.GetLocalScale()[0];
                fR = fR / fParentSOScale / fSceneScale;

                i.go.transform.localScale = fR * Vector3f.One;
            }
        }
示例#10
0
        void update_geometry(FScene s)
        {
            if (bUpdatePending == false && curve_timestamp == curve.Timestamp)
            {
                return;
            }
            if (curve.VertexCount < 2)
            {
                return;
            }

            update_vertices(s);

            verticesf.Clear();
            buffer.Clear();

            for (int i = 0; i < curve.VertexCount; ++i)
            {
                buffer.Add(curve[i % curve.VertexCount]);
            }
            if (CurveProcessorF != null)
            {
                CurveProcessorF(buffer);
            }

            int Nmod = buffer.Count;
            int N    = (curve.Closed) ? buffer.Count + 1 : buffer.Count;

            for (int i = 0; i < N; ++i)
            {
                verticesf.Add((Vector3f)buffer[i % Nmod]);
            }
            curveObject.SetVertices(verticesf);

            float fWidth = VRUtil.EstimateStableCurveWidth(s, Frame3f.Identity, curve,
                                                           SceneGraphConfig.DefaultSceneCurveVisualDegrees);

            if (fWidth > 0)
            {
                curveObject.SetLineWidth(fWidth);
            }

            bUpdatePending  = false;
            curve_timestamp = curve.Timestamp;
        }
示例#11
0
        // called on per-frame Update()
        virtual public void PreRender()
        {
            root.Show();

            if (MaintainConsistentViewSize)
            {
                float useDegrees = (GizmoVisualDegrees > 0) ? GizmoVisualDegrees : SceneGraphConfig.DefaultAxisGizmoVisualDegrees;
                float fWorldSize = VRUtil.GetRadiusForVisualAngle(
                    root.GetPosition(),
                    parentScene.ActiveCamera.GetPosition(),
                    useDegrees);
                float fSceneSize = fWorldSize / parentScene.GetSceneScale();
                float fGeomScale = fSceneSize / initialGizmoRadius;
                root.SetLocalScale(new Vector3f(fGeomScale));
                foreach (var widget in Widgets)
                {
                    widget.Value.UpdateGizmoWorldSize(fWorldSize);
                }
            }
            else if (DynamicScaleFactor > 0)
            {
                float fWorldSize = DynamicScaleFactor;
                float fSceneSize = fWorldSize / parentScene.GetSceneScale();
                float fGeomScale = fSceneSize / initialGizmoRadius;
                root.SetLocalScale(new Vector3f(fGeomScale));
                foreach (var widget in Widgets)
                {
                    widget.Value.UpdateGizmoWorldSize(fWorldSize);
                }
            }


            if (DynamicVisibilityFiltering && targetWrapper != null)
            {
                Frame3f  frameW  = targetWrapper.GetLocalFrame(CoordSpace.WorldCoords);
                Vector3d camPosW = parentScene.ActiveCamera.GetPosition();
                foreach (var go in enabledWidgetGOs)
                {
                    Standard3DTransformWidget widget = Widgets[go];
                    bool visible = widget.CheckVisibility(ref frameW, ref camPosW);
                    go.SetVisible(visible);
                }
            }
        }
示例#12
0
        public override Capture BeginCapture(InputState input, CaptureSide eSide)
        {
            HandInfo hi = new HandInfo();

            hi.eMode = ActionMode.TransformCamera;

            Frame3f camFrame = cockpit.ActiveCamera.GetWorldFrame();

            // if both rays hit scene and are within a few visual degrees, then we
            // we pull out a sphere and use it to re-scale the world.
            // Otherwise do normal hand-transform actions
            AnyRayHit hit1, hit2;
            bool      bHit1 = cockpit.Scene.FindSceneRayIntersection(input.vLeftSpatialWorldRay, out hit1);
            bool      bHit2 = cockpit.Scene.FindSceneRayIntersection(input.vRightSpatialWorldRay, out hit2);

            if (bHit1 && bHit2)
            {
                Vector3 avg = (hit1.hitPos + hit2.hitPos) * 0.5f;
                float   d   = VRUtil.GetVRRadiusForVisualAngle(avg, camFrame.Origin, 2.0f);
                if ((hit1.hitPos - hit2.hitPos).Length < d)
                {
                    hi.eMode = ActionMode.SetWorldScale;
                    Frame3f centerF = cockpit.Scene.SceneFrame;
                    centerF.Origin = avg;
                    Frame3f planeF = new Frame3f(centerF.Origin, camFrame.Z);
                    hi.BeginSetWorldScale(centerF, planeF, 2 * d);
                    hi.UpdateSetWorldScale(input.vLeftSpatialWorldRay, input.vRightSpatialWorldRay);
                }
            }

            hi.leftStartF  = input.LeftHandFrame;
            hi.rightStartF = input.RightHandFrame;
            hi.camState    = cockpit.ActiveCamera.Manipulator().GetCurrentState(cockpit.Scene);
            hi.camRight    = camFrame.X;
            hi.camForward  = camFrame.Z;

            cockpit.ActiveCamera.SetTargetVisible(true);

            return(Capture.Begin(this, CaptureSide.Both, hi));
        }
示例#13
0
        public void Update()
        {
            targetGO.transform.position = TargetPoint;
            float fScaling = VRUtil.GetVRRadiusForVisualAngle(TargetPoint, gameObject.transform.position, 1.0f);

            targetGO.transform.localScale = new Vector3(fScaling, fScaling, fScaling);

            if (ShowTarget)
            {
                Material setMaterial = hiddenMaterial;

                // raycast into scene and if we hit ball before we hit anything else, render
                // it darker red, to give some sense of inside/outside
                if (this.context != null)
                {
                    Vector3   camPos   = this.context.ActiveCamera.GetPosition();
                    float     fDistSqr = (TargetPoint - camPos).sqrMagnitude;
                    Ray       ray_t    = new Ray(camPos, (TargetPoint - camPos).normalized);
                    AnyRayHit hit;
                    if (this.context.Scene.FindSceneRayIntersection(ray_t, out hit) == false)
                    {
                        setMaterial = visibleMaterial;
                    }
                    else if (hit.fHitDist * hit.fHitDist * 1.005f > fDistSqr)
                    {
                        setMaterial = visibleMaterial;
                    }
                }

                MaterialUtil.SetMaterial(targetGO, setMaterial);
                targetGO.Show();
            }
            else
            {
                targetGO.Hide();
            }
        }
示例#14
0
        public void Update()
        {
            targetGO.transform.position = TargetPoint;
            float fScaling = VRUtil.GetVRRadiusForVisualAngle(TargetPoint, gameObject.transform.position, SceneGraphConfig.CameraPivotVisualDegrees);

            targetGO.transform.localScale = fScaling * Vector3f.One;

            if (ShowTarget && SceneGraphConfig.EnableVisibleCameraPivot)
            {
                Material setMaterial = hiddenMaterial;

                // raycast into scene and if we hit ball before we hit anything else, render
                // it darker red, to give some sense of inside/outside
                if (this.context != null)
                {
                    Vector3f  camPos   = this.context.ActiveCamera.GetPosition();
                    float     fDistSqr = TargetPoint.DistanceSquared(camPos);
                    Ray3f     ray_t    = new Ray3f(camPos, (TargetPoint - camPos).Normalized);
                    AnyRayHit hit;
                    if (this.context.Scene.FindSceneRayIntersection(ray_t, out hit) == false)
                    {
                        setMaterial = visibleMaterial;
                    }
                    else if (hit.fHitDist * hit.fHitDist * 1.005f > fDistSqr)
                    {
                        setMaterial = visibleMaterial;
                    }
                }

                MaterialUtil.SetMaterial(targetGO, setMaterial);
                targetGO.Show();
            }
            else
            {
                targetGO.Hide();
            }
        }
        // FixedUpdate is called before any Update
        public void Update()
        {
            if (bFreezeCursor)
            {
                return;
            }

            // if we are in capture we freeze the cursor plane
            if (context.InCaptureMouse == false)
            {
                Vector3 camPos  = camera.gameObject.transform.position;
                Vector3 forward = camera.gameObject.transform.forward;

                // orient Y-up plane so that it is in front of eye, perp to camera direction
                float fCursorDepth = 10.0f;
                fCursorSpeedNormalization = 1.0f;
                if (context.ActiveCockpit != null && context.ActiveCockpit.DefaultCursorDepth > 0)
                {
                    fCursorDepth = context.ActiveCockpit.DefaultCursorDepth;
                    // cursor speed will change depending on cursor plane distance, unless we normalize
                    fCursorSpeedNormalization *= (fCursorDepth / 10.0f);
                }
                xformObject.transform.position = camPos + fCursorDepth * forward;
                xformObject.transform.LookAt(camera.gameObject.transform);
                xformObject.transform.RotateAround(xformObject.transform.position, xformObject.transform.right, 90);

                // that plane is the plane the mouse cursor moves on
                this.vCursorPlaneOrigin = xformObject.transform.position;
                this.vCursorPlaneRight  = xformObject.transform.right;
                this.vCursorPlaneUp     = xformObject.transform.forward;                    // because we rotated? weird...
                this.vRaySourcePosition = camera.transform.position;

                // if we were capturing, then plane was frozen and when we stop capturing, if
                //  head moved, the cursor will pop to a new position (because it is stored in
                //  local plane coords). So raycast through old cursor to hit new plane and figure
                //  out new local coords (fCurPlaneX, fCurPlaneY)
                if (bWasInCaptureFreeze)
                {
                    Frame3f newF      = new Frame3f(vCursorPlaneOrigin, this.camera.transform.forward);
                    Vector3 vPlaneHit = newF.RayPlaneIntersection(this.vRaySourcePosition,
                                                                  (vPlaneCursorPos - vRaySourcePosition).normalized, 2);
                    fCurPlaneX          = Vector3.Dot((vPlaneHit - vCursorPlaneOrigin), vCursorPlaneRight);
                    fCurPlaneY          = Vector3.Dot((vPlaneHit - vCursorPlaneOrigin), vCursorPlaneUp);
                    bWasInCaptureFreeze = false;
                }
            }
            else
            {
                bWasInCaptureFreeze = true;
            }

            Vector2f mousePos  = InputExtension.Get.Mouse.PositionDelta;
            Vector2f leftStick = InputExtension.Get.GamepadLeftStick.Position;
            float    fX        = mousePos.x + leftStick.x;
            float    fY        = mousePos.y + leftStick.y;

            // auto-hide cursor if it doesn't move for a while
            if (fX == 0 && fY == 0 && SceneGraphConfig.MouseCursorHideTimeout > 0)
            {
                if ((FPlatform.RealTime() - lastMouseEventTime) > SceneGraphConfig.MouseCursorHideTimeout)
                {
                    Cursor.SetVisible(false);
                    mouseInactiveState = true;
                }
                if (mouseInactiveState)
                {
                    return;
                }
            }
            else
            {
                lastMouseEventTime = FPlatform.RealTime();
                if (mouseInactiveState)
                {
                    Cursor.SetVisible(true);
                }
                mouseInactiveState = false;
            }

            // update cursor location
            fCurPlaneX     -= 0.3f * fX * fCursorSpeedNormalization;
            fCurPlaneY     -= 0.3f * fY * fCursorSpeedNormalization;
            vPlaneCursorPos =
                vCursorPlaneOrigin + fCurPlaneX * vCursorPlaneRight + fCurPlaneY * vCursorPlaneUp;
            vSceneCursorPos = vPlaneCursorPos;

            // if cursor gets outside of viewpoint it is almost impossible to get it back.
            // So, if it goes too far out of view (45 deg here), we snap it back to the origin
            if (context.InCameraManipulation == false && context.InCaptureMouse == false)
            {
                float fAngle = Vector3.Angle((vPlaneCursorPos - camera.transform.position).normalized, camera.transform.forward);
                if (fAngle > 50.0f)
                {
                    fCurPlaneX      = fCurPlaneY = 0;
                    vPlaneCursorPos =
                        vCursorPlaneOrigin + fCurPlaneX * vCursorPlaneRight + fCurPlaneY * vCursorPlaneUp;
                    vSceneCursorPos = vPlaneCursorPos;
                }
            }


            bool bHit = false;

            // [RMS] boundsHit cursor orientation could be useful for things where you are picking a point
            //   on the ground plane (eg like drawing contours). Not sure how to toggle that though.
            //   Just disabling for now...
            //bool bIsBoundsHit = false;
            if (context != null)
            {
                Ray       r   = new Ray(camera.transform.position, (vPlaneCursorPos - camera.transform.position).normalized);
                AnyRayHit hit = null;
                if (context.FindAnyRayIntersection(r, out hit))
                {
                    vSceneCursorPos = hit.hitPos;
                    bHit            = true;
                }
                else
                {
                    GameObjectRayHit ghit = null;
                    if (context.GetScene().FindWorldBoundsHit(r, out ghit))
                    {
                        vSceneCursorPos = ghit.hitPos;
                        //bIsBoundsHit = true;
                    }
                }
            }

            this.CurrentCursorPosWorld       = vPlaneCursorPos;
            this.CurrentCursorRaySourceWorld = this.vRaySourcePosition;

            Vector3 vEyeToPos = (vPlaneCursorPos - camera.transform.position).normalized;
            //if (bIsBoundsHit) {
            //    Vector3 rotAxis = (vEyeToPos + camera.transform.right).normalized;
            //    Cursor.transform.localRotation = Quaternion.AngleAxis(180.0f-45.0f, rotAxis);
            //} else {
            Quaternion rotAlignUp = Quaternion.FromToRotation(Vector3.up, camera.transform.up);
            Vector3    rotAxis    = (vEyeToPos + camera.transform.right).normalized;

            Cursor.transform.localRotation = Quaternion.AngleAxis(45.0f, rotAxis) * rotAlignUp;
            //}

            Cursor.transform.position = vSceneCursorPos;
            if (context.InCaptureMouse)
            {
                Cursor.GetComponent <MeshRenderer> ().material = CursorCapturingMaterial;
            }
            else if (bHit)
            {
                Cursor.GetComponent <MeshRenderer> ().material = CursorHitMaterial;
            }
            else
            {
                Cursor.GetComponent <MeshRenderer> ().material = CursorDefaultMaterial;
            }

            Cursor.SetLayer(FPlatform.CursorLayer);

            // maintain a consistent visual size for 3D cursor sphere
            float fScaling = VRUtil.GetVRRadiusForVisualAngle(vSceneCursorPos, camera.transform.position, CursorVisualAngleInDegrees);

            Cursor.transform.localScale = new Vector3(fScaling, fScaling, fScaling);

            // update cursor
            Mesh useMesh = context.ToolManager.HasActiveTool(ToolSide.Right) ? activeToolCursorMesh : standardCursorMesh;

            if (Cursor.GetSharedMesh() != useMesh)
            {
                Cursor.SetSharedMesh(useMesh);
            }
        }
        public void Initialize(Cockpit cockpit, float fCockpitRadius)
        {
            activeCockpit = cockpit;
            activeCockpit.PositionMode = Cockpit.MovementMode.Static;
            activeCockpit.GrabFocus    = true;
            activeHUDRadius            = fCockpitRadius;

            string[] files, folders;
            try {
                files   = Source.GetFiles(FolderPath);
                folders = Source.GetFolders(FolderPath);
            } catch (Exception e) {
                Debug.Log("[CurrentFolderList.Initialize] exception! " + e.Message);
                return;
            }

            float fMinHorz = -45.0f, fMaxHorz = 45.0f;
            float fStartVert = 15.0f;
            float fTop       = HUDUtil.GetSphereFrame(fCockpitRadius, 0.0f, fStartVert).Origin.y;

            int folderi = 0, filei = 0;

            Mesh  folderMesh              = Resources.Load <Mesh>("icon_meshes/folder_v1");
            Color folderColor             = ColorUtil.make(241, 213, 146);
            Color inaccessibleFolderColor = ColorUtil.make(100, 100, 100);
            Mesh  fileMesh                = Resources.Load <Mesh>("icon_meshes/file_v1");
            Color fileColor               = ColorUtil.make(250, 250, 250);

            // [TODO] something wrong here, icons are loading backwards...??
            Quaternion meshRotation =
                Quaternion.AngleAxis(270.0f, Vector3.right) *
                Quaternion.AngleAxis(180.0f + 25.0f, Vector3.forward);
            float meshScale = IconSize * 0.9f;

            HUDCylinder hudSurf = new HUDCylinder()
            {
                Radius = fCockpitRadius, VerticalCoordIsAngle = false
            };
            float fStepH     = VRUtil.HorizontalStepAngle(fCockpitRadius, 0, IconSize + IconPadding);
            int   nStepsHorz = (int)((fMaxHorz - fMinHorz) / fStepH);

            fMinHorz = -(nStepsHorz * fStepH * 0.5f);
            fMaxHorz = (nStepsHorz * fStepH * 0.5f);
            float fStepV = IconSize + IconPadding;


            IconCollection = new HUDCollection();
            IconCollection.Create();

            bool bDone = false;
            int  yi    = 0;

            while (!bDone)
            {
                float fCurV = fTop - yi * fStepV;
                yi++;

                for (int xi = 0; xi < nStepsHorz && bDone == false; ++xi)
                {
                    float fCurH = fMinHorz + ((float)xi + 0.5f) * fStepH;

                    string name        = "x";
                    fMesh  useMesh     = null;
                    Color  useColor    = Color.white;
                    bool   bAccessible = true;
                    bool   bIsFile     = false;
                    if (folderi < folders.Length)
                    {
                        name     = folders[folderi++];
                        useMesh  = new fMesh(UnityEngine.Object.Instantiate <Mesh>(folderMesh));
                        useColor = folderColor;
                        if (Source.FilterInaccessibleFolders == false &&
                            FileSystemUtils.CanAccessFolder(Path.Combine(FolderPath, name)) == false)
                        {
                            bAccessible = false;
                            useColor    = inaccessibleFolderColor;
                        }
                    }
                    else if (filei < files.Length)
                    {
                        name     = files[filei++];
                        useMesh  = new fMesh(UnityEngine.Object.Instantiate <Mesh>(fileMesh));
                        useColor = fileColor;
                        bIsFile  = true;
                    }
                    else
                    {
                        bDone = true;
                        break;
                    }
                    //useColor.a = 0.999f;        // [RMS] can use this to force into alpha pass

                    string displayName = name;
                    if (displayName.Length > 12)
                    {
                        displayName = name.Substring(0, 12) + "...";
                    }

                    //float TextScale = 0.01f, ShiftX = -IconSize * 0.5f;
                    float TextScale = 0.005f, ShiftX = -IconSize * 0.5f;

                    HUDButton iconButton = HUDBuilder.CreateMeshClickButton(
                        useMesh, useColor, meshScale, meshRotation,
                        hudSurf, fCurH, fCurV,
                        new TextLabelGenerator()
                    {
                        Text = displayName, Scale = TextScale, Translate = new Vector3(ShiftX, 0.0f, 0.0f)
                    });
                    iconButton.Name = name;
                    //cockpit.AddUIElement(iconButton, true);
                    IconCollection.AddChild(iconButton);

                    if (bIsFile)
                    {
                        iconButton.OnClicked += (o, e) => {
                            if (this.OnFileClicked != null)
                            {
                                this.OnFileClicked(name);
                            }
                        };
                    }

                    if (bAccessible)
                    {
                        iconButton.OnDoubleClicked += IconButton_DoubleClick;
                    }
                }
            }

            cockpit.AddUIElement(IconCollection, true);
            fCurMaxScroll = Mathf.Max(0, (yi - 4) * fStepV);
        }
示例#17
0
        public void UpdateDraw_Spatial(Ray3f ray, Frame3f handFrame, int nStep)
        {
            // scene xform may have changed during steps (eg view rotation), so we
            // need to reconstruct our local frame
            Frame3f primCurW = scene.ToWorldFrame(primStartS);

            // step 1: find radius in plane
            if (nStep == 0)
            {
                Vector3f forwardDir = ray.Direction;
                Vector3f plane_hit  = VRUtil.SafeRayPlaneIntersection(ray, forwardDir, primCurW.Origin, primCurW.Y);
                plane_hit_local = primCurW.ToFrameP(plane_hit);
            }
            float fX       = MathUtil.SignedClamp(plane_hit_local[0], MinDimension, MaxDimension);
            float fY       = MinDimension;
            float fZ       = MathUtil.SignedClamp(plane_hit_local[2], MinDimension, MaxDimension);
            float fR_plane = MathUtil.Clamp(plane_hit_local.Length, MinDimension / 2, MaxDimension / 2);

            // step 2: find height from plane
            if (nStep == 1)
            {
                Vector3f plane_hit = primCurW.FromFrameP(plane_hit_local);
                Line3d   l         = new Line3d(plane_hit, primCurW.Y);
                Vector3f handTip   = handFrame.Origin + SceneGraphConfig.HandTipOffset * handFrame.Z;
                float    fHandDist = (float)l.DistanceSquared(handTip);
                if (fHandDist < fR_plane * 1.5f)
                {
                    fY = (float)l.Project(handTip);
                }
                else
                {
                    fY = (float)DistLine3Ray3.MinDistanceLineParam(ray, l);
                }
            }

            // figure out possible dimensions, clamp to ranges
            fY = MathUtil.SignedClamp(fY, MinDimension, MaxDimension);

            // update frame
            primitive.Frame = primCurW;

            // update dimensions
            bool  bIsCorner = (primitive.Center == CenterModes.Corner);
            float fScale    = 1.0f;     // object is not in scene coordinates!

            if (primitive.Type == MeshPrimitivePreview.PrimType.Cylinder)
            {
                primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale;
                primitive.Depth = primitive.Width;
                //primitive.Depth = Mathf.Sign(fZ) * primitive.Width;
                //primitive.Width = Mathf.Sign(fX) * primitive.Width;
                primitive.Height = fY * fScale;
            }
            else if (primitive.Type == MeshPrimitivePreview.PrimType.Box)
            {
                primitive.Width  = (bIsCorner) ? fX : 2 * fX * fScale;
                primitive.Depth  = (bIsCorner) ? fZ : 2 * fZ * fScale;
                primitive.Height = fY * fScale;
            }
            else if (primitive.Type == MeshPrimitivePreview.PrimType.Sphere)
            {
                primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale;
                primitive.Depth = primitive.Height = primitive.Width;
                //primitive.Depth = Mathf.Sign(fZ) * primitive.Width;
                //primitive.Width = Mathf.Sign(fX) * primitive.Width;
                //primitive.Height = Mathf.Sign(fY) * primitive.Width;
            }
            else
            {
                throw new NotImplementedException("DrawPrimitivesTool.UpdateDraw_Ray - type not supported");
            }
        }
示例#18
0
        public Capture Update_TransformCamera(InputState input, CaptureData data)
        {
            // need both controllers to have valid positions
            if (input.bLeftControllerActive == false || input.bRightControllerActive == false)
            {
                return(Capture.Continue);
            }

            float    fSceneScale = cockpit.Scene.GetSceneScale();
            HandInfo hi          = (HandInfo)data.custom_data;

            // deadzones and scaling factors
            const float fZoomDeadzoneInM       = 0.1f;
            const float fZoomScale             = 25.0f;
            const float fPanDeadzoneInM        = 0.05f;
            const float fPanScale              = 25.0f;
            const float fAzimuthDeadzoneInDeg  = 10.0f;
            const float fAltitudeDeadzoneInDeg = 15.0f;
            const float fTrackAlpha            = 0.1f; // larger == faster tracking

            // zoom is indicated by moving hands together/apart. But we want to get rid of
            // influence from other gestures (like rotate below) so we project to camera-right axis first.
            Frame3f camFrame  = cockpit.ActiveCamera.GetWorldFrame();
            Vector3 right     = camFrame.X;
            float   fOrig     = Vector3.Dot((hi.rightStartF.Origin - hi.leftStartF.Origin), hi.camRight);
            float   fCur      = Vector3.Dot((input.RightHandFrame.Origin - input.LeftHandFrame.Origin), right);
            float   deltaZAbs = fCur - fOrig;
            float   deltaZ    = (hi.bInZoomDeadzone) ? ApplyDeadzone(deltaZAbs, fZoomDeadzoneInM) : deltaZAbs - hi.fZoomShift;

            if (Math.Abs(deltaZ) > 0 && hi.bInZoomDeadzone)
            {
                hi.bInZoomDeadzone = false;
                hi.fZoomShift      = deltaZAbs - deltaZ;
            }
            hi.runningZ = Mathf.Lerp(hi.runningZ, deltaZ, fTrackAlpha);
            float tz = hi.runningZ * fZoomScale;

            if (tz != 0.0f && hi.activeXForm == TransformType.NoTransform)
            {
                hi.activeXForm = TransformType.Zoom;
            }


            // translation is done by moving both hands in unison. We find the midpoint
            // of the start and current pairs, delta is translate
            Vector3f cOrig      = 0.5f * (hi.leftStartF.Origin + hi.rightStartF.Origin);
            Vector3f cCur       = 0.5f * (input.LeftHandFrame.Origin + input.RightHandFrame.Origin);
            Vector3f translateO = cCur - cOrig;
            Vector3f translate  = (hi.bInPanDeadzone) ? ApplyDeadzone(translateO, fPanDeadzoneInM) : translateO - hi.vPanShift;

            if (translate.LengthSquared > 0 && hi.bInPanDeadzone)
            {
                hi.bInPanDeadzone = false;
                hi.vPanShift      = translateO - translate;
            }
            hi.runningT = Vector3.Lerp(hi.runningT, translate, fTrackAlpha);
            Vector3f tx = hi.runningT * fPanScale * fSceneScale;

            if (tx.Length != 0.0f && hi.activeXForm == TransformType.NoTransform)
            {
                hi.activeXForm = TransformType.Pan;
            }

            // azimuth (left/right rotate) is specified by making a spin-the-wheel gesture,
            //   where one hand slides forward and the other back. We guess a center-of-rotation
            //   as the midpoint of the start and current frames, and then average the two rotation
            //   angles in the XZ plane (by the vectors on the left and right sides).
            //   *But* if there is also a translation, this goes wonky, so we have to subtract
            //   of the translation first!
            //     (above only applies if we permit simultaneous rotate & translate, which is currently disabled...)
            //Vector3 rotTranslate = translate;
            Vector3f rotTranslate = Vector3.zero;
            Vector3f origCenterXY = new Vector3(cOrig[0], 0, cOrig[2]);
            Vector3f shiftLeftO   = input.LeftHandFrame.Origin - rotTranslate;
            Vector3f shiftRightO  = input.RightHandFrame.Origin - rotTranslate;
            Vector3f shiftCenter  = 0.5f * (shiftLeftO + shiftRightO);
            Vector3f curCenterXY  = new Vector3(shiftCenter[0], 0, shiftCenter[2]);
            Vector3f sharedC      = 0.5f * (origCenterXY + curCenterXY);
            float    aLeft        = VRUtil.PlaneAngleSigned(hi.leftStartF.Origin - sharedC, shiftLeftO - sharedC, 1);
            float    aRight       = VRUtil.PlaneAngleSigned(hi.rightStartF.Origin - sharedC, shiftRightO - sharedC, 1);
            float    azO          = -(aLeft + aRight) * 0.5f;
            float    az           = (hi.bInAzimuthDeadzone) ? ApplyDeadzone(azO, fAzimuthDeadzoneInDeg) : azO - hi.fAzimuthShift;

            if (Math.Abs(az) > 0 && hi.bInAzimuthDeadzone)
            {
                hi.bInAzimuthDeadzone = false;
                hi.fAzimuthShift      = azO - az;
            }
            hi.runningAz = Mathf.Lerp(hi.runningAz, az, fTrackAlpha);
            float fAzimuth = hi.runningAz;

            if (fAzimuth != 0.0f && hi.activeXForm == TransformType.NoTransform)
            {
                hi.activeXForm = TransformType.Rotate;
            }


            // altitude (up/down rotate) is specified by tilting controllers up or down.
            // This is the trickiest one as hands tend to tilt up/down during the other actions.
            // We compute an average tilt up/down angle at the start, and then the per-hand delta
            // each frame, as well as the average delta, and use the smallest of these.
            // mean hand-tilt at start frame
            float o1 = VRUtil.PlaneAngleSigned(hi.leftStartF.Rotation * Vector3.forward, hi.camForward, hi.camRight);
            float o2 = VRUtil.PlaneAngleSigned(hi.rightStartF.Rotation * Vector3.forward, hi.camForward, hi.camRight);
            float oa = (o1 + o2) * 0.5f;
            // per-frame hand tilt
            Vector3 camfw = camFrame.Z, camright = camFrame.X;
            float   c1 = VRUtil.PlaneAngleSigned(input.LeftHandFrame.Rotation * Vector3.forward, camfw, camright);
            float   c2 = VRUtil.PlaneAngleSigned(input.RightHandFrame.Rotation * Vector3.forward, camfw, camright);
            // use the smallest per-hand tilt delta, to prevent one-hand tilting from having an effect
            float d1 = oa - c1, d2 = oa - c2;

            float altO = (Mathf.Abs(d1) < Mathf.Abs(d2)) ? d1 : d2;
            // also consider the average, to reduce crazy popping from each hand tilting in opposite direction
            float dm = 0.5f * (d1 + d2);

            altO = (Mathf.Abs(altO) < Mathf.Abs(dm)) ? altO : dm;

            // deadzone and smoothing
            float alt = (hi.bInAltitudeDeadzone) ? ApplyDeadzone(altO, fAltitudeDeadzoneInDeg) : altO - hi.fAltitudeShift;

            if (Math.Abs(alt) > 0 && hi.bInAltitudeDeadzone)
            {
                hi.bInAltitudeDeadzone = false;
                hi.fAltitudeShift      = altO - alt;
            }
            hi.runningAlt = Mathf.Lerp(hi.runningAlt, alt, fTrackAlpha);
            float fAltitude = hi.runningAlt;

            if (fAltitude != 0.0f && hi.activeXForm == TransformType.NoTransform)
            {
                hi.activeXForm = TransformType.Rotate;
            }


            // reset view to state when we started, then apply the accumulated rotate/zoom/translate
            cockpit.ActiveCamera.Manipulator().SetCurrentSceneState(cockpit.Scene, hi.camState);
            if (hi.activeXForm == TransformType.Rotate)
            {
                cockpit.ActiveCamera.Manipulator().SceneOrbit(cockpit.Scene, cockpit.ActiveCamera, fAzimuth, fAltitude);
            }
            else if (hi.activeXForm == TransformType.Pan)
            {
                cockpit.ActiveCamera.Manipulator().SceneTranslate(cockpit.Scene, tx, false);
            }
            else if (hi.activeXForm == TransformType.Zoom)
            {
                cockpit.ActiveCamera.Manipulator().SceneZoom(cockpit.Scene, cockpit.ActiveCamera, tz);
            }

            return(Capture.Continue);
        }
示例#19
0
        // FixedUpdate is called before any Update
        public void Update()
        {
            if (CheckForSpatialInputActive() == false)
            {
                return;
            }

            Vector3 rootPos = spatialCamRig.transform.position;

            SpatialDevice[] hands = { Left, Right };
            for (int i = 0; i < 2; ++i)
            {
                SpatialDevice h = hands[i];

                h.CursorActive = VRPlatform.IsSpatialDeviceTracked(i);
                if (h.CursorActive)
                {
                    h.Hand.Show();
                    h.Cursor.Show();

                    Vector3    handPos = VRPlatform.GetLocalControllerPosition(i);
                    Quaternion handRot = VRPlatform.GetLocalControllerRotation(i);

                    h.AbsoluteHandFrame = new Frame3f(rootPos + handPos, handRot);

                    float fPositionT = 0.2f;
                    float fRotationT = 0.2f;
                    //float fPositionT = 1.0f;
                    //float fRotationT = 1.0f;

                    if (h.SmoothedHandFrame.Origin != Vector3f.Zero)
                    {
                        Vector3 new_origin =
                            Vector3.Lerp(h.SmoothedHandFrame.Origin, h.AbsoluteHandFrame.Origin, fPositionT);
                        Quaternion new_rotation =
                            Quaternion.Slerp(h.SmoothedHandFrame.Rotation, h.AbsoluteHandFrame.Rotation, fRotationT);
                        h.SmoothedHandFrame = new Frame3f(new_origin, new_rotation);
                    }
                    else
                    {
                        h.SmoothedHandFrame = h.AbsoluteHandFrame;
                    }

                    h.Hand.transform.position = h.SmoothedHandFrame.Origin;
                    h.Hand.transform.rotation = h.SmoothedHandFrame.Rotation * (Quaternionf)handGeomRotation;

                    h.CursorRay = new Ray(h.SmoothedHandFrame.Origin,
                                          (h.SmoothedHandFrame.Rotation * Vector3.forward).Normalized);

                    if (Mathf.Abs(h.CursorRay.direction.sqrMagnitude - 1.0f) > 0.001f)
                    {
                        DebugUtil.Log(2, "SpatialInputController.Update - invlaid cursor ray! rotation was {0}", h.SmoothedHandFrame.Rotation);
                        h.CursorRay = new Ray(h.SmoothedHandFrame.Origin, Vector3.up);
                    }

                    // raycast into scene to see if we hit object, UI, bounds, etc.
                    bool bHit = false;
                    if (context != null)
                    {
                        // want to hit-test active gizmo first, because that has hit-priority
                        if (context.TransformManager.HaveActiveGizmo)
                        {
                            UIRayHit uiHit = null;
                            if (context.TransformManager.ActiveGizmo.FindRayIntersection(h.CursorRay, out uiHit))
                            {
                                h.RayHitPos = uiHit.hitPos;
                                bHit        = true;
                            }
                        }
                        // next we tested scene
                        if (bHit == false)
                        {
                            AnyRayHit hit = null;
                            if (context.FindAnyRayIntersection(h.CursorRay, out hit))
                            {
                                h.RayHitPos = hit.hitPos;
                                bHit        = true;
                            }
                        }
                        // finally test worldbounds
                        if (bHit == false)
                        {
                            GameObjectRayHit ghit = null;
                            if (context.GetScene().FindWorldBoundsHit(h.CursorRay, out ghit))
                            {
                                h.RayHitPos = ghit.hitPos;
                            }
                        }
                    }

                    // if not, plane cursor on view-perp plane centered at last hit pos,
                    // otherwise it will be stuck/disappear
                    if (bHit == false)
                    {
                        Frame3f f = new Frame3f(h.RayHitPos, camera.transform.forward);
                        h.RayHitPos = f.RayPlaneIntersection(h.CursorRay.origin, h.CursorRay.direction, 2);
                    }

                    h.Cursor.transform.position = h.RayHitPos;
                    //if (scene.InCapture)
                    //    MaterialUtil.SetMaterial(h.Cursor, h.CursorCapturingMaterial);
                    //else
                    if (bHit)
                    {
                        MaterialUtil.SetMaterial(h.Cursor, h.CursorHitMaterial);
                    }
                    else
                    {
                        MaterialUtil.SetMaterial(h.Cursor, h.CursorDefaultMaterial);
                    }

                    // maintain a consistent visual size for 3D cursor sphere
                    float fScaling = VRUtil.GetVRRadiusForVisualAngle(h.RayHitPos, camera.transform.position, CursorVisualAngleInDegrees);
                    h.Cursor.transform.localScale = fScaling * Vector3.one;

                    // orient cursor so it is tilted like a 2D cursor, but per-hand
                    Vector3 cursor_right = Vector3.Cross(camera.transform.up, h.CursorRay.direction);
                    Vector3 cursor_fw    = Vector3.Cross(cursor_right, camera.transform.up);
                    float   rotSign      = (h == Right) ? 1.0f : -1.0f;
                    Vector3 pointDir     = (camera.transform.up + cursor_fw - 0.5f * rotSign * cursor_right).normalized;
                    h.Cursor.transform.localRotation = Quaternion.FromToRotation(Vector3.up, pointDir);

                    // update laser line
                    if (h.Laser != null)
                    {
                        float   hDist = (h.RayHitPos - h.CursorRay.origin).magnitude;
                        Vector3 p0    = h.RayHitPos - 0.9f * hDist * h.CursorRay.direction;
                        Vector3 p1    = h.RayHitPos + 100.0f * h.CursorRay.direction;
                        float   r0    = VRUtil.GetVRRadiusForVisualAngle(p0, camera.transform.position, 0.5f);
                        h.LaserRen.SetPosition(0, p0);
                        h.LaserRen.SetPosition(1, p1);
                        h.LaserRen.startWidth = h.LaserRen.endWidth = r0;
                    }

                    // udpate cursor
                    Mesh useMesh = context.ToolManager.HasActiveTool(i) ? activeToolCursorMesh : standardCursorMesh;
                    if (h.Cursor.GetSharedMesh() != useMesh)
                    {
                        h.Cursor.SetSharedMesh(useMesh);
                    }
                }
                else
                {
                    h.Hand.Hide();
                    h.Cursor.Hide();
                }
            }
        }