コード例 #1
0
        public static GameObject SpawnInFrontOfCamera(GameObject sourceObject, Camera camera, Config config)
        {
            float halfSize = config.ObjectSize * 0.5f;

            var boundsQConfig = new ObjectBounds.QueryConfig();

            boundsQConfig.ObjectTypes  = GameObjectTypeHelper.AllCombined;
            boundsQConfig.NoVolumeSize = Vector3Ex.FromValue(1.0f);

            Transform cameraTransform = camera.transform;
            AABB      aabb            = ObjectBounds.CalcHierarchyWorldAABB(sourceObject, boundsQConfig);

            if (!aabb.IsValid)
            {
                return(null);
            }

            Sphere  sphere          = new Sphere(aabb);
            Vector3 fromCenterToPos = sourceObject.transform.position - sphere.Center;
            float   zOffset         = Mathf.Max(camera.nearClipPlane + sphere.Radius, sphere.Radius / halfSize);
            Vector3 spherePos       = cameraTransform.position + cameraTransform.forward * zOffset;

            GameObject spawned = GameObject.Instantiate(sourceObject, spherePos + fromCenterToPos, sourceObject.transform.rotation) as GameObject;

            spawned.SetActive(true);

            //VRCTS
            spawned.name = sourceObject.name;

            OBB spawnedOBB    = ObjectBounds.CalcHierarchyWorldOBB(spawned, boundsQConfig);
            Ray ray           = new Ray(camera.transform.position, (spawnedOBB.Center - camera.transform.position).normalized);
            var raycastFilter = new SceneRaycastFilter();

            raycastFilter.AllowedObjectTypes.Add(GameObjectType.Mesh);
            raycastFilter.AllowedObjectTypes.Add(GameObjectType.Terrain);
            raycastFilter.AllowedObjectTypes.Add(GameObjectType.Sprite);

            var rayHit = RTScene.Get.Raycast(ray, SceneRaycastPrecision.BestFit, raycastFilter);

            if (rayHit.WasAnObjectHit)
            {
                Vector3 oldCenter = spawnedOBB.Center;
                spawnedOBB.Center = rayHit.ObjectHit.HitPoint;
                Vector3 offsetVector = spawnedOBB.Center - oldCenter;
                offsetVector += ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(spawnedOBB, rayHit.ObjectHit.HitPlane, 0.0f);

                spawned.transform.position += offsetVector;
            }

            return(spawned);
        }
コード例 #2
0
        private void SnapTargets()
        {
            if (!CalculateTargetAABB())
            {
                return;
            }

            Vector3 oldCenter = _targetAABB.Center;

            _targetAABB.Center = _sitSurface.SitPoint;

            Plane sitSurfacePlane = _sitSurface.SitPlane;

            if (_sitBelowSurface)
            {
                sitSurfacePlane = sitSurfacePlane.InvertNormal();
            }

            Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(_targetAABB, sitSurfacePlane, 0.0f);

            _targetAABB.Center += sitOnPlaneOffset;

            Vector3 parentMove = _targetAABB.Center - oldCenter;

            foreach (var parent in _targetParents)
            {
                parent.transform.position += parentMove;
            }

            if (!SharedHotkeys.EnableFlexiSnap.IsActive())
            {
                var snapConfig = new Object2ObjectSnap.Config();
                snapConfig.Prefs             = SharedHotkeys.EnableMoreControl.IsActive() ? Object2ObjectSnap.Prefs.None : Object2ObjectSnap.Prefs.TryMatchArea;
                snapConfig.AreaMatchEps      = 1e-2f;
                snapConfig.SnapRadius        = SharedSettings.SnapRadius;
                snapConfig.DestinationLayers = SharedSettings.SnapDestinationLayers;
                snapConfig.IgnoreDestObjects = new List <GameObject>();
                snapConfig.IgnoreDestObjects.AddRange(_targetParents);
                foreach (var parent in _targetParents)
                {
                    snapConfig.IgnoreDestObjects.AddRange(parent.GetAllChildren());
                }

                Object2ObjectSnap.Snap(_targetParents, snapConfig);
            }
        }
コード例 #3
0
        public static SnapResult SnapHierarchy(GameObject root, SnapConfig snapConfig)
        {
            const float collectEps      = 1e-2f;
            const float collectBoxScale = 1e-3f;

            bool hierarchyHasMeshes  = root.HierarchyHasMesh();
            bool hierarchyHasSprites = root.HierarchyHasSprite();

            if (!hierarchyHasMeshes && !hierarchyHasSprites)
            {
                Transform rootTransform = root.transform;
                rootTransform.position = snapConfig.SurfaceHitPlane.ProjectPoint(rootTransform.position) + snapConfig.OffsetFromSurface * snapConfig.SurfaceHitNormal;
                return(new SnapResult(snapConfig.SurfaceHitPlane, rootTransform.position));
            }

            ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
            boundsQConfig.ObjectTypes = GameObjectType.Sprite | GameObjectType.Mesh;

            bool isSurfaceSpherical    = snapConfig.SurfaceType == Type.SphericalMesh;
            bool isSurfaceTerrain      = snapConfig.SurfaceType == Type.UnityTerrain || snapConfig.SurfaceType == Type.TerrainMesh;
            bool isSurfaceUnityTerrain = snapConfig.SurfaceType == Type.UnityTerrain;

            SurfaceRaycaster raycaster = CreateSurfaceRaycaster(snapConfig.SurfaceType, snapConfig.SurfaceObject, true);

            if (snapConfig.SurfaceType != Type.SceneGrid)
            {
                Transform rootTransform = root.transform;
                if (snapConfig.AlignAxis)
                {
                    if (isSurfaceTerrain)
                    {
                        rootTransform.Align(Vector3.up, snapConfig.AlignmentAxis);

                        OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                        if (!hierarchyOBB.IsValid)
                        {
                            return(new SnapResult());
                        }

                        BoxFace        pivotFace      = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -Vector3.up);
                        List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps);

                        if (collectedVerts.Count != 0)
                        {
                            Vector3          vertsCenter = Vector3Ex.GetPointCloudCenter(collectedVerts);
                            Ray              ray         = new Ray(vertsCenter + Vector3.up * 1e-3f, -Vector3.up);
                            GameObjectRayHit surfaceHit  = raycaster.Raycast(ray);

                            if (surfaceHit != null)
                            {
                                Vector3 alignmentAxis = surfaceHit.HitNormal;
                                if (isSurfaceUnityTerrain)
                                {
                                    Terrain terrain = snapConfig.SurfaceObject.GetComponent <Terrain>();
                                    alignmentAxis = terrain.GetInterpolatedNormal(surfaceHit.HitPoint);
                                }
                                Quaternion appliedRotation = rootTransform.Align(alignmentAxis, snapConfig.AlignmentAxis);

                                hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                                appliedRotation.RotatePoints(collectedVerts, rootTransform.position);

                                Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, new Plane(Vector3.up, surfaceHit.HitPoint), 0.1f);
                                rootTransform.position += sitOnPlaneOffset;
                                hierarchyOBB.Center    += sitOnPlaneOffset;
                                Vector3Ex.OffsetPoints(collectedVerts, sitOnPlaneOffset);

                                Vector3 embedVector = ObjectSurfaceSnap.CalculateEmbedVector(collectedVerts, snapConfig.SurfaceObject, -Vector3.up, snapConfig.SurfaceType);
                                rootTransform.position += (embedVector + alignmentAxis * snapConfig.OffsetFromSurface);
                                return(new SnapResult(new Plane(alignmentAxis, surfaceHit.HitPoint), surfaceHit.HitPoint));
                            }
                        }
                    }
                    else
                    {
                        if (!isSurfaceSpherical)
                        {
                            rootTransform.Align(snapConfig.SurfaceHitNormal, snapConfig.AlignmentAxis);
                            OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                            if (!hierarchyOBB.IsValid)
                            {
                                return(new SnapResult());
                            }

                            BoxFace        pivotFace      = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -snapConfig.SurfaceHitNormal);
                            List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps);

                            if (collectedVerts.Count != 0)
                            {
                                Vector3 vertsCenter = Vector3Ex.GetPointCloudCenter(collectedVerts);

                                // Note: Cast the ray from far away enough so that we don't cast from the interior of the mesh.
                                //       This can happen when the object is embedded inside the mesh surface.
                                AABB    surfaceAABB  = ObjectBounds.CalcMeshWorldAABB(snapConfig.SurfaceObject);
                                float   sphereRadius = surfaceAABB.Extents.magnitude;
                                Vector3 rayOrigin    = vertsCenter + snapConfig.SurfaceHitNormal * sphereRadius;

                                Ray ray = new Ray(rayOrigin, -snapConfig.SurfaceHitNormal);
                                GameObjectRayHit surfaceHit = raycaster.Raycast(ray);

                                if (surfaceHit != null)
                                {
                                    Vector3 alignmentAxis = surfaceHit.HitNormal;
                                    rootTransform.Align(alignmentAxis, snapConfig.AlignmentAxis);
                                    hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);

                                    Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, surfaceHit.HitPlane, 0.0f);
                                    rootTransform.position += sitOnPlaneOffset;
                                    rootTransform.position += alignmentAxis * snapConfig.OffsetFromSurface;
                                    return(new SnapResult(new Plane(alignmentAxis, surfaceHit.HitPoint), surfaceHit.HitPoint));
                                }
                                else
                                {
                                    Vector3 alignmentAxis = snapConfig.SurfaceHitNormal;
                                    rootTransform.Align(alignmentAxis, snapConfig.AlignmentAxis);
                                    hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);

                                    Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, snapConfig.SurfaceHitPlane, 0.0f);
                                    rootTransform.position += sitOnPlaneOffset;
                                    rootTransform.position += alignmentAxis * snapConfig.OffsetFromSurface;
                                    return(new SnapResult(snapConfig.SurfaceHitPlane, snapConfig.SurfaceHitPlane.ProjectPoint(vertsCenter)));
                                }
                            }
                        }
                        else
                        {
                            Transform surfaceObjectTransform = snapConfig.SurfaceObject.transform;
                            Vector3   sphereCenter           = surfaceObjectTransform.position;
                            Vector3   radiusDir    = (rootTransform.position - sphereCenter).normalized;
                            float     sphereRadius = surfaceObjectTransform.lossyScale.GetMaxAbsComp() * 0.5f;

                            rootTransform.Align(radiusDir, snapConfig.AlignmentAxis);
                            OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                            if (!hierarchyOBB.IsValid)
                            {
                                return(new SnapResult());
                            }

                            BoxFace        pivotFace      = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -radiusDir);
                            List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps);

                            Vector3 sitPoint         = sphereCenter + radiusDir * sphereRadius;
                            Plane   sitPlane         = new Plane(radiusDir, sitPoint);
                            Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, sitPlane, 0.0f);

                            rootTransform.position += sitOnPlaneOffset;
                            hierarchyOBB.Center    += sitOnPlaneOffset;
                            Vector3Ex.OffsetPoints(collectedVerts, sitOnPlaneOffset);

                            rootTransform.position += radiusDir * snapConfig.OffsetFromSurface;
                            return(new SnapResult(sitPlane, sitPoint));
                        }
                    }
                }
                else
                {
                    OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                    if (!hierarchyOBB.IsValid)
                    {
                        return(new SnapResult());
                    }

                    if (isSurfaceTerrain || (!isSurfaceSpherical && snapConfig.SurfaceType == Type.Mesh))
                    {
                        Ray ray = new Ray(hierarchyOBB.Center, isSurfaceTerrain ? -Vector3.up : -snapConfig.SurfaceHitNormal);
                        GameObjectRayHit surfaceHit = raycaster.Raycast(ray);
                        if (surfaceHit != null)
                        {
                            Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, surfaceHit.HitPlane, 0.0f);
                            rootTransform.position += sitOnPlaneOffset;

                            if (isSurfaceTerrain)
                            {
                                hierarchyOBB.Center += sitOnPlaneOffset;
                                BoxFace        pivotFace      = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -surfaceHit.HitNormal);
                                List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps);

                                Vector3 embedVector = ObjectSurfaceSnap.CalculateEmbedVector(collectedVerts, snapConfig.SurfaceObject, -Vector3.up, snapConfig.SurfaceType);
                                rootTransform.position += embedVector;
                            }

                            rootTransform.position += surfaceHit.HitNormal * snapConfig.OffsetFromSurface;
                            return(new SnapResult(surfaceHit.HitPlane, surfaceHit.HitPoint));
                        }
                        else
                        if (!isSurfaceSpherical && snapConfig.SurfaceType == Type.Mesh)
                        {
                            Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, snapConfig.SurfaceHitPlane, 0.0f);
                            rootTransform.position += sitOnPlaneOffset;
                            rootTransform.position += snapConfig.SurfaceHitNormal * snapConfig.OffsetFromSurface;
                            return(new SnapResult(snapConfig.SurfaceHitPlane, snapConfig.SurfaceHitPlane.ProjectPoint(hierarchyOBB.Center)));
                        }
                    }
                    else
                    if (isSurfaceSpherical)
                    {
                        Transform surfaceObjectTransform = snapConfig.SurfaceObject.transform;
                        Vector3   sphereCenter           = surfaceObjectTransform.position;
                        Vector3   radiusDir    = (rootTransform.position - sphereCenter).normalized;
                        float     sphereRadius = surfaceObjectTransform.lossyScale.GetMaxAbsComp() * 0.5f;

                        BoxFace        pivotFace      = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -radiusDir);
                        List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps);

                        Vector3 sitPoint         = sphereCenter + radiusDir * sphereRadius;
                        Plane   sitPlane         = new Plane(radiusDir, sitPoint);
                        Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, sitPlane, 0.0f);

                        rootTransform.position += sitOnPlaneOffset;
                        hierarchyOBB.Center    += sitOnPlaneOffset;
                        Vector3Ex.OffsetPoints(collectedVerts, sitOnPlaneOffset);

                        rootTransform.position += radiusDir * snapConfig.OffsetFromSurface;
                        return(new SnapResult(sitPlane, sitPoint));
                    }
                }
            }
            if (snapConfig.SurfaceType == Type.SceneGrid)
            {
                OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                if (!hierarchyOBB.IsValid)
                {
                    return(new SnapResult());
                }

                Transform rootTransform = root.transform;
                if (snapConfig.AlignAxis)
                {
                    rootTransform.Align(snapConfig.SurfaceHitNormal, snapConfig.AlignmentAxis);
                    hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);
                }

                rootTransform.position += ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, snapConfig.SurfaceHitPlane, snapConfig.OffsetFromSurface);
                return(new SnapResult(snapConfig.SurfaceHitPlane, snapConfig.SurfaceHitPlane.ProjectPoint(hierarchyOBB.Center)));
            }

            return(new SnapResult());
        }