Beispiel #1
0
        private void SnapToObjectHitPoint(GameObjectRayHit objectHit, SnapToPointMode snapMode)
        {
            if (snapMode == SnapToPointMode.Exact)
            {
                float distToPlane = new Plane(Normal, Vector3.zero).GetDistanceToPoint(objectHit.HitPoint);
                YOffset = distToPlane;
            }
            else
            {
                ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
                boundsQConfig.ObjectTypes = GameObjectType.Mesh;

                OBB worldOBB = ObjectBounds.CalcWorldOBB(objectHit.HitObject, boundsQConfig);
                if (worldOBB.IsValid)
                {
                    Plane          slicePlane = new Plane(Normal, worldOBB.Center);
                    Vector3        destPt     = worldOBB.Center;
                    List <Vector3> obbCorners = BoxMath.CalcBoxCornerPoints(worldOBB.Center, worldOBB.Size, worldOBB.Rotation);

                    float sign = Mathf.Sign(slicePlane.GetDistanceToPoint(objectHit.HitPoint));
                    if (sign > 0.0f)
                    {
                        int furthestPtInFront = slicePlane.GetFurthestPtInFront(obbCorners);
                        if (furthestPtInFront >= 0)
                        {
                            destPt = obbCorners[furthestPtInFront];
                        }
                    }
                    else
                    {
                        int furthestPtBehind = slicePlane.GetFurthestPtBehind(obbCorners);
                        if (furthestPtBehind >= 0)
                        {
                            destPt = obbCorners[furthestPtBehind];
                        }
                    }

                    float distToPlane = new Plane(Normal, Vector3.zero).GetDistanceToPoint(destPt);
                    YOffset = distToPlane;
                }
            }
        }
Beispiel #2
0
        public void RegisterObject(GameObject gameObject)
        {
            if (!CanRegisterObject(gameObject))
            {
                return;
            }

            ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
            boundsQConfig.ObjectTypes  = GameObjectTypeHelper.AllCombined;
            boundsQConfig.NoVolumeSize = Vector3Ex.FromValue(RTScene.Get.Settings.NonMeshObjectSize);

            AABB   worldAABB   = ObjectBounds.CalcWorldAABB(gameObject, boundsQConfig);
            Sphere worldSphere = new Sphere(worldAABB);

            SphereTreeNode <GameObject> objectNode = _objectTree.AddNode(gameObject, worldSphere);

            _objectToNode.Add(gameObject, objectNode);

            RTFocusCamera.Get.SetObjectVisibilityDirty();
        }
Beispiel #3
0
        private void GatherDestinationObjects()
        {
            Camera focusCamera = RTFocusCamera.Get.TargetCamera;

            _destinationObjects.Clear();

            IInputDevice inputDevice = RTInputDevice.Get.Device;

            if (!inputDevice.HasPointer())
            {
                return;
            }
            Vector2 inputDevicePos = inputDevice.GetPositionYAxisUp();

            var boundsQConfig = new ObjectBounds.QueryConfig();

            boundsQConfig.ObjectTypes  = GameObjectTypeHelper.AllCombined;
            boundsQConfig.NoVolumeSize = Vector3Ex.FromValue(1e-5f);

            List <GameObject> visibleObjects = RTFocusCamera.Get.GetVisibleObjects();
            List <GameObject> targetObjects  = new List <GameObject>(_targetObjects);

            visibleObjects.RemoveAll(a => targetObjects.Contains(a) ||
                                     !ObjectBounds.CalcScreenRect(a, focusCamera, boundsQConfig).Contains(inputDevicePos) ||
                                     targetObjects.FindAll(b => a.transform.IsChildOf(b.transform)).Count != 0);

            foreach (var visibleObject in visibleObjects)
            {
                if (!CanUseObjectAsSnapDestination(visibleObject))
                {
                    continue;
                }

                GameObjectType objectType = visibleObject.GetGameObjectType();
                if (objectType == GameObjectType.Mesh || objectType == GameObjectType.Sprite)
                {
                    _destinationObjects.Add(visibleObject);
                }
            }
        }
        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);
            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;
        }
        private void SelectPivot()
        {
            if (!RTInputDevice.Get.Device.HasPointer())
            {
                return;
            }

            var boundsQConfig = GetObjectBoundsQConfig();

            Vector2 inputDevicePos    = RTInputDevice.Get.Device.GetPositionYAxisUp();
            float   minDistFromDevice = float.MaxValue;

            foreach (var targetObject in _targetObjects)
            {
                if (targetObject == null)
                {
                    continue;
                }

                OBB worldOBB = ObjectBounds.CalcWorldOBB(targetObject, boundsQConfig);
                if (worldOBB.IsValid)
                {
                    Camera         camera                 = RTFocusCamera.Get.TargetCamera;
                    List <Vector3> centerAndCorners       = worldOBB.GetCenterAndCornerPoints();
                    List <Vector2> screenCenterAndCorners = camera.ConvertWorldToScreenPoints(centerAndCorners);
                    for (int ptIndex = 0; ptIndex < screenCenterAndCorners.Count; ++ptIndex)
                    {
                        float distance = (inputDevicePos - screenCenterAndCorners[ptIndex]).magnitude;
                        if (distance < minDistFromDevice)
                        {
                            minDistFromDevice = distance;
                            _snapPivotPoint   = centerAndCorners[ptIndex];
                        }
                    }
                }
            }
        }
        private List <AABB> BuildVertOverlapAABBs(GameObject gameObject, Sprite sprite, RTMesh rtMesh)
        {
            if (sprite == null && rtMesh == null)
            {
                return(new List <AABB>());
            }

            const float overlapAmount     = 0.2f;
            float       halfOverlapAmount = overlapAmount * 0.5f;
            AABB        modelAABB         = sprite != null?ObjectBounds.CalcSpriteModelAABB(gameObject) : rtMesh.AABB;

            Vector3        modelAABBSize  = modelAABB.Size;
            List <BoxFace> modelAABBFaces = BoxMath.AllBoxFaces;

            const float sizeEps = 0.001f;

            Vector3[] overlapAABBSizes = new Vector3[modelAABBFaces.Count];
            overlapAABBSizes[(int)BoxFace.Left]   = new Vector3(overlapAmount, modelAABBSize.y + sizeEps, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Right]  = new Vector3(overlapAmount, modelAABBSize.y + sizeEps, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Bottom] = new Vector3(modelAABBSize.x + sizeEps, overlapAmount, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Top]    = new Vector3(modelAABBSize.x + sizeEps, overlapAmount, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Back]   = new Vector3(modelAABBSize.x + sizeEps, modelAABBSize.y + sizeEps, overlapAmount);
            overlapAABBSizes[(int)BoxFace.Front]  = new Vector3(modelAABBSize.x + sizeEps, modelAABBSize.y + sizeEps, overlapAmount);

            var overlapAABBs = new List <AABB>();

            for (int boxFaceIndex = 0; boxFaceIndex < modelAABBFaces.Count; ++boxFaceIndex)
            {
                BoxFace modelAABBFace = modelAABBFaces[boxFaceIndex];
                Vector3 faceCenter    = BoxMath.CalcBoxFaceCenter(modelAABB.Center, modelAABB.Size, Quaternion.identity, modelAABBFace);
                Vector3 faceNormal    = BoxMath.CalcBoxFaceNormal(modelAABB.Center, modelAABB.Size, Quaternion.identity, modelAABBFace);
                Vector3 overlapCenter = faceCenter - faceNormal * halfOverlapAmount;
                overlapAABBs.Add(new AABB(overlapCenter, overlapAABBSizes[boxFaceIndex]));
            }

            return(overlapAABBs);
        }
Beispiel #7
0
        public AABB CalculateBounds()
        {
            var activeScene = SceneManager.GetActiveScene();
            var roots       = new List <GameObject>(Mathf.Max(10, activeScene.rootCount));

            SceneManager.GetActiveScene().GetRootGameObjects(roots);

            var boundsQConfig = new ObjectBounds.QueryConfig();

            boundsQConfig.NoVolumeSize = Vector3.zero;
            boundsQConfig.ObjectTypes  = GameObjectType.Mesh | GameObjectType.Sprite;

            AABB sceneAABB = new AABB();

            foreach (var root in roots)
            {
                var allChildrenAndSelf = root.GetAllChildrenAndSelf();
                foreach (var sceneObject in allChildrenAndSelf)
                {
                    AABB aabb = ObjectBounds.CalcWorldAABB(sceneObject, boundsQConfig);
                    if (aabb.IsValid)
                    {
                        if (sceneAABB.IsValid)
                        {
                            sceneAABB.Encapsulate(aabb);
                        }
                        else
                        {
                            sceneAABB = aabb;
                        }
                    }
                }
            }

            return(sceneAABB);
        }
        public void Render()
        {
            if (_sharedLookAndFeel == null)
            {
                return;
            }

            if (IsActive)
            {
                Material material = MaterialPool.Get.SimpleColor;

                if (_sharedLookAndFeel.DrawBoxes)
                {
                    material.SetColor(_sharedLookAndFeel.BoxLineColor);
                    material.SetZTestEnabled(true);
                    material.SetPass(0);

                    var boundsQConfig = GetObjectBoundsQConfig();
                    foreach (var targetObject in _targetObjects)
                    {
                        if (targetObject == null)
                        {
                            continue;
                        }

                        OBB worldOBB = ObjectBounds.CalcWorldOBB(targetObject, boundsQConfig);
                        if (worldOBB.IsValid)
                        {
                            GraphicsEx.DrawWireBox(worldOBB);
                        }
                    }
                }

                Camera  camera          = Camera.current;
                Vector2 screenSnapPivot = camera.WorldToScreenPoint(_snapPivotPoint);
                if (_sharedLookAndFeel.PivotShapeType == PivotPointShapeType.Circle)
                {
                    material.SetZTestEnabled(false);
                    material.SetColor(_sharedLookAndFeel.PivotPointFillColor);
                    material.SetPass(0);

                    const int      numCirclePoints   = 100;
                    List <Vector2> pivotCirclePoints = PrimitiveFactory.Generate2DCircleBorderPointsCW(screenSnapPivot, _sharedLookAndFeel.PivotCircleRadius, numCirclePoints);
                    GLRenderer.DrawTriangleFan2D(screenSnapPivot, pivotCirclePoints, camera);

                    if (_sharedLookAndFeel.DrawPivotBorder)
                    {
                        material.SetColor(_sharedLookAndFeel.PivotPointBorderColor);
                        material.SetPass(0);
                        GLRenderer.DrawLineLoop2D(pivotCirclePoints, camera);
                    }
                }
                else
                if (_sharedLookAndFeel.PivotShapeType == PivotPointShapeType.Square)
                {
                    material.SetZTestEnabled(false);
                    material.SetColor(_sharedLookAndFeel.PivotPointFillColor);
                    material.SetPass(0);

                    Rect pivotRect = RectEx.FromCenterAndSize(screenSnapPivot, Vector2Ex.FromValue(_sharedLookAndFeel.PivotSquareSideLength));
                    GLRenderer.DrawRect2D(pivotRect, camera);

                    if (_sharedLookAndFeel.DrawPivotBorder)
                    {
                        material.SetColor(_sharedLookAndFeel.PivotPointBorderColor);
                        material.SetPass(0);
                        GLRenderer.DrawRectBorder2D(pivotRect, camera);
                    }
                }
            }
        }
        public void Render()
        {
            if (SharedLookAndFeel == null)
            {
                return;
            }

            if (IsActive && _grabSurfaceInfo.SurfaceType != GrabSurfaceType.Invalid)
            {
                Material material = MaterialPool.Get.SimpleColor;
                if (SharedLookAndFeel.DrawAnchorLines)
                {
                    List <Vector3> linePoints = new List <Vector3>(_grabTargets.Count * 2);
                    foreach (GrabTarget grabTarget in _grabTargets)
                    {
                        linePoints.Add(grabTarget.Transform.position);
                        linePoints.Add(_grabSurfaceInfo.AnchorPoint);
                    }

                    material.SetZTestAlways();
                    material.SetColor(_sharedLookAndFeel.AnchorLineColor);
                    material.SetPass(0);
                    GLRenderer.DrawLines3D(linePoints);
                }

                if (SharedLookAndFeel.DrawObjectBoxes)
                {
                    material.SetZTestLess();
                    material.SetColor(SharedLookAndFeel.ObjectBoxWireColor);
                    material.SetPass(0);

                    ObjectBounds.QueryConfig boundsQConfig = GetObjectBoundsQConfig();
                    foreach (GrabTarget grabTarget in _grabTargets)
                    {
                        OBB obb = ObjectBounds.CalcHierarchyWorldOBB(grabTarget.GameObject, boundsQConfig);
                        if (obb.IsValid)
                        {
                            GraphicsEx.DrawWireBox(obb);
                        }
                    }
                }

                if (SharedLookAndFeel.DrawObjectPosTicks)
                {
                    material.SetColor(SharedLookAndFeel.ObjectPosTickColor);
                    material.SetPass(0);

                    foreach (GrabTarget grabTarget in _grabTargets)
                    {
                        Vector2 screenPos = Camera.current.WorldToScreenPoint(grabTarget.Transform.position);
                        GLRenderer.DrawRect2D(RectEx.FromCenterAndSize(screenPos, Vector2Ex.FromValue(SharedLookAndFeel.ObjectPosTickSize)), Camera.current);
                    }
                }

                if (SharedLookAndFeel.DrawAnchorPosTick)
                {
                    material.SetColor(SharedLookAndFeel.AnchorPosTickColor);
                    material.SetPass(0);

                    Vector2 anchorScreenPos = Camera.current.WorldToScreenPoint(_grabSurfaceInfo.AnchorPoint);
                    GLRenderer.DrawRect2D(RectEx.FromCenterAndSize(anchorScreenPos, Vector2Ex.FromValue(SharedLookAndFeel.AnchorPosTickSize)), Camera.current);
                }
            }
        }
Beispiel #10
0
        protected bool GetWorldPointClosestToInputDevice(Camera focusCamera, IEnumerable <GameObject> gameObjects, out Vector3 point)
        {
            point = Vector3.zero;
            if (gameObjects == null)
            {
                return(false);
            }
            if (!RTInputDevice.Get.Device.HasPointer())
            {
                return(false);
            }

            Vector2 inputDeviceScreenPt = RTInputDevice.Get.Device.GetPositionYAxisUp();
            float   minDistSqr          = float.MaxValue;

            bool foundPoint = false;

            foreach (GameObject srcObject in gameObjects)
            {
                Mesh mesh = srcObject.GetMesh();
                if (mesh != null)
                {
                    MeshVertexChunkCollection meshVChunkCollection = MeshVertexChunkCollectionDb.Get[mesh];
                    if (meshVChunkCollection == null)
                    {
                        continue;
                    }

                    Matrix4x4 worldMtx = srcObject.transform.localToWorldMatrix;
                    List <MeshVertexChunk> testChunks = meshVChunkCollection.GetWorldChunksHoveredByPoint(inputDeviceScreenPt, worldMtx, focusCamera);
                    if (testChunks.Count == 0)
                    {
                        MeshVertexChunk closestChunk = meshVChunkCollection.GetWorldVertChunkClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera);
                        if (closestChunk != null && closestChunk.VertexCount != 0)
                        {
                            testChunks.Add(closestChunk);
                        }
                    }

                    foreach (MeshVertexChunk chunk in testChunks)
                    {
                        Vector3 worldVert  = chunk.GetWorldVertClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera);
                        Vector2 screenVert = focusCamera.WorldToScreenPoint(worldVert);
                        float   distSqr    = (inputDeviceScreenPt - screenVert).sqrMagnitude;
                        if (distSqr < minDistSqr)
                        {
                            minDistSqr = distSqr;
                            point      = worldVert;
                            foundPoint = true;
                        }
                    }
                }
                else
                {
                    OBB spriteWorldOBB = ObjectBounds.CalcSpriteWorldOBB(srcObject);
                    if (spriteWorldOBB.IsValid)
                    {
                        List <Vector3> obbPoints      = spriteWorldOBB.GetCenterAndCornerPoints();
                        List <Vector2> screenPoints   = focusCamera.ConvertWorldToScreenPoints(obbPoints);
                        int            closestPtIndex = Vector2Ex.GetPointClosestToPoint(screenPoints, inputDeviceScreenPt);
                        if (closestPtIndex >= 0)
                        {
                            Vector2 closestPt = screenPoints[closestPtIndex];
                            float   distSqr   = (inputDeviceScreenPt - closestPt).sqrMagnitude;
                            if (distSqr < minDistSqr)
                            {
                                minDistSqr = distSqr;
                                point      = obbPoints[closestPtIndex];
                                foundPoint = true;
                            }
                        }
                    }
                }
            }

            return(foundPoint);
        }
        public Texture2D Generate(GameObject unityPrefab)
        {
            if (!_isGenSessionActive || _renderCamera.targetTexture == null)
            {
                return(null);
            }

            RenderTexture oldRenderTexture = UnityEngine.RenderTexture.active;

            RenderTexture.active = _renderCamera.targetTexture;
            GL.Clear(true, true, _previewLookAndFeel.BkColor);

            bool hasMesh   = unityPrefab.HierarchyHasMesh();
            bool hasSprite = unityPrefab.HierarchyHasSprite();

            PreviewObjectType previewObjectType = PreviewObjectType.Mesh;

            if (!hasMesh && hasSprite)
            {
                previewObjectType = PreviewObjectType.Sprite;
            }
            else if (!hasMesh && !hasSprite)
            {
                if (unityPrefab.HierarchyHasObjectsOfType(GameObjectType.Light))
                {
                    previewObjectType = PreviewObjectType.Light;
                }
                else if (unityPrefab.HierarchyHasObjectsOfType(GameObjectType.ParticleSystem))
                {
                    previewObjectType = PreviewObjectType.ParticleSystem;
                }
                else
                {
                    previewObjectType = PreviewObjectType.Other;
                }
            }

            GameObject previewObject = null;

            if (previewObjectType == PreviewObjectType.Mesh || previewObjectType == PreviewObjectType.Sprite)
            {
                previewObject = GameObject.Instantiate(unityPrefab);
            }
            else
            {
                previewObject = _nonMeshPreviewObject;
            }

            Transform previewObjectTransform = previewObject.transform;

            previewObjectTransform.position   = Vector3.zero;
            previewObjectTransform.rotation   = Quaternion.identity;
            previewObjectTransform.localScale = unityPrefab.transform.lossyScale;

            AABB   sceneAABB   = RTScene.Get.CalculateBounds();
            Sphere sceneSphere = new Sphere(sceneAABB);
            AABB   previewAABB = new AABB();

            previewAABB = ObjectBounds.CalcHierarchyWorldAABB(previewObject, _boundsQConfig);
            Sphere previewSphere = new Sphere(previewAABB);

            Vector3 previewSphereCenter = sceneSphere.Center - Vector3.right * (sceneSphere.Radius + previewSphere.Radius + 90.0f);

            previewObjectTransform.position += (previewSphereCenter - previewSphere.Center);
            previewAABB          = ObjectBounds.CalcHierarchyWorldAABB(previewObject, _boundsQConfig);
            previewSphere.Center = previewSphereCenter;

            Transform camTransform = _renderCamera.transform;

            if (previewObjectType == PreviewObjectType.Mesh || previewObjectType == PreviewObjectType.Sprite)
            {
                camTransform.rotation = Quaternion.identity;
                if (previewObjectType != PreviewObjectType.Sprite)
                {
                    camTransform.rotation = Quaternion.AngleAxis(-45.0f, Vector3.up) * Quaternion.AngleAxis(35.0f, camTransform.right);
                }
                camTransform.position = previewSphere.Center - camTransform.forward * (previewSphere.Radius * 2.0f + _renderCamera.nearClipPlane);
            }
            else
            {
                camTransform.rotation = previewObjectTransform.rotation;
                camTransform.position = previewSphere.Center - camTransform.forward * (previewSphere.Radius * 2.0f + _renderCamera.nearClipPlane);

                Texture2D previewIcon = previewObjectType == PreviewObjectType.Light ? RTScene.Get.LookAndFeel.LightIcon : RTScene.Get.LookAndFeel.ParticleSystemIcon;
                _nonMeshPreviewObject.GetComponent <MeshRenderer>().sharedMaterial.SetTexture("_MainTex", previewIcon);
            }

            _previewLight.transform.forward = camTransform.forward;
            _renderCamera.Render();
            if (previewObject != _nonMeshPreviewObject)
            {
                GameObject.DestroyImmediate(previewObject);
            }

            Texture2D previewTexture = new Texture2D(_previewLookAndFeel.PreviewWidth, _previewLookAndFeel.PreviewHeight, TextureFormat.ARGB32, true, true);

            previewTexture.ReadPixels(new Rect(0, 0, _previewLookAndFeel.PreviewWidth, _previewLookAndFeel.PreviewHeight), 0, 0);
            previewTexture.Apply();
            UnityEngine.RenderTexture.active = oldRenderTexture;

            return(previewTexture);
        }
Beispiel #12
0
        public static List <Vector3> CollectHierarchyVerts(GameObject root, BoxFace collectFace, float collectBoxScale, float collectEps)
        {
            List <GameObject> meshObjects   = root.GetMeshObjectsInHierarchy();
            List <GameObject> spriteObjects = root.GetSpriteObjectsInHierarchy();

            if (meshObjects.Count == 0 && spriteObjects.Count == 0)
            {
                return(new List <Vector3>());
            }

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

            OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig);

            if (!hierarchyOBB.IsValid)
            {
                return(new List <Vector3>());
            }

            int     faceAxisIndex = BoxMath.GetFaceAxisIndex(collectFace);
            Vector3 faceCenter    = BoxMath.CalcBoxFaceCenter(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, collectFace);
            Vector3 faceNormal    = BoxMath.CalcBoxFaceNormal(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, collectFace);

            float   sizeEps         = collectEps * 2.0f;
            Vector3 collectAABBSize = hierarchyOBB.Size;

            collectAABBSize[faceAxisIndex]            = (hierarchyOBB.Size[faceAxisIndex] * collectBoxScale) + sizeEps;
            collectAABBSize[(faceAxisIndex + 1) % 3] += sizeEps;
            collectAABBSize[(faceAxisIndex + 2) % 3] += sizeEps;

            OBB collectOBB = new OBB(faceCenter + faceNormal * (-collectAABBSize[faceAxisIndex] * 0.5f + collectEps), collectAABBSize);

            collectOBB.Rotation = hierarchyOBB.Rotation;

            List <Vector3> collectedVerts = new List <Vector3>(80);

            foreach (GameObject meshObject in meshObjects)
            {
                Mesh   mesh   = meshObject.GetMesh();
                RTMesh rtMesh = RTMeshDb.Get.GetRTMesh(mesh);
                if (rtMesh == null)
                {
                    continue;
                }

                List <Vector3> verts = rtMesh.OverlapVerts(collectOBB, meshObject.transform);
                if (verts.Count != 0)
                {
                    collectedVerts.AddRange(verts);
                }
            }

            foreach (GameObject spriteObject in spriteObjects)
            {
                List <Vector3> verts = CollectWorldSpriteVerts(spriteObject.GetSprite(), spriteObject.transform, collectOBB);
                if (verts.Count != 0)
                {
                    collectedVerts.AddRange(verts);
                }
            }

            return(collectedVerts);
        }
Beispiel #13
0
        public List <GameObjectRayHit> RaycastAll(Ray ray, SceneRaycastPrecision raycastPresicion)
        {
            List <SphereTreeNodeRayHit <GameObject> > nodeHits = _objectTree.RaycastAll(ray);

            if (nodeHits.Count == 0)
            {
                return(new List <GameObjectRayHit>());
            }

            ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
            boundsQConfig.ObjectTypes  = GameObjectTypeHelper.AllCombined;
            boundsQConfig.NoVolumeSize = Vector3Ex.FromValue(RTScene.Get.Settings.NonMeshObjectSize);

            Vector3 camLook = RTFocusCamera.Get.Look;

            if (raycastPresicion == SceneRaycastPrecision.BestFit)
            {
                List <GameObjectRayHit> hitList = new List <GameObjectRayHit>(10);
                foreach (SphereTreeNodeRayHit <GameObject> nodeHit in nodeHits)
                {
                    GameObject sceneObject = nodeHit.HitNode.Data;
                    if (sceneObject == null || !sceneObject.activeInHierarchy)
                    {
                        continue;
                    }

                    Renderer renderer = sceneObject.GetComponent <Renderer>();
                    if (renderer != null && !renderer.isVisible)
                    {
                        continue;
                    }

                    GameObjectType objectType = sceneObject.GetGameObjectType();
                    if (objectType == GameObjectType.Mesh)
                    {
                        GameObjectRayHit objectHit = RaycastMeshObject(ray, sceneObject);
                        if (objectHit != null)
                        {
                            hitList.Add(objectHit);
                        }
                    }
                    else
                    if (objectType == GameObjectType.Terrain)
                    {
                        TerrainCollider terrainCollider = sceneObject.GetComponent <TerrainCollider>();
                        if (terrainCollider != null)
                        {
                            RaycastHit hitInfo;
                            if (terrainCollider.Raycast(ray, out hitInfo, float.MaxValue))
                            {
                                hitList.Add(new GameObjectRayHit(ray, hitInfo));
                            }
                        }
                    }
                    else
                    if (objectType == GameObjectType.Sprite)
                    {
                        GameObjectRayHit objectHit = RaycastSpriteObject(ray, sceneObject);
                        if (objectHit != null)
                        {
                            hitList.Add(objectHit);
                        }
                    }
                    else
                    {
                        OBB worldOBB = ObjectBounds.CalcWorldOBB(sceneObject, boundsQConfig);
                        if (worldOBB.IsValid)
                        {
                            float t;
                            if (BoxMath.Raycast(ray, out t, worldOBB.Center, worldOBB.Size, worldOBB.Rotation))
                            {
                                BoxFaceDesc      faceDesc = BoxMath.GetFaceClosestToPoint(ray.GetPoint(t), worldOBB.Center, worldOBB.Size, worldOBB.Rotation, camLook);
                                GameObjectRayHit hit      = new GameObjectRayHit(ray, sceneObject, faceDesc.Plane.normal, t);
                                hitList.Add(hit);
                            }
                        }
                    }
                }

                return(hitList);
            }
            else
            if (raycastPresicion == SceneRaycastPrecision.Box)
            {
                List <GameObjectRayHit> hitList = new List <GameObjectRayHit>(10);
                foreach (SphereTreeNodeRayHit <GameObject> nodeHit in nodeHits)
                {
                    GameObject sceneObject = nodeHit.HitNode.Data;
                    if (sceneObject == null || !sceneObject.activeInHierarchy)
                    {
                        continue;
                    }

                    Renderer renderer = sceneObject.GetComponent <Renderer>();
                    if (renderer != null && !renderer.isVisible)
                    {
                        continue;
                    }

                    OBB worldOBB = ObjectBounds.CalcWorldOBB(sceneObject, boundsQConfig);
                    if (worldOBB.IsValid)
                    {
                        float t;
                        if (BoxMath.Raycast(ray, out t, worldOBB.Center, worldOBB.Size, worldOBB.Rotation))
                        {
                            BoxFaceDesc      faceDesc = BoxMath.GetFaceClosestToPoint(ray.GetPoint(t), worldOBB.Center, worldOBB.Size, worldOBB.Rotation, camLook);
                            GameObjectRayHit hit      = new GameObjectRayHit(ray, sceneObject, faceDesc.Plane.normal, t);
                            hitList.Add(hit);
                        }
                    }
                }

                return(hitList);
            }

            return(new List <GameObjectRayHit>());
        }
Beispiel #14
0
        public void FitBoxToTargets()
        {
            if (NumTargetParents == 0)
            {
                _boxSize = Vector3.zero;
                return;
            }

            if (ExtrudeSpace == GizmoSpace.Global)
            {
                AABB worldAABB = AABB.GetInvalid();
                foreach (var parent in _targetParents)
                {
                    if (_ignoredParentObjects.Contains(parent))
                    {
                        continue;
                    }

                    AABB aabb = ObjectBounds.CalcHierarchyWorldAABB(parent, _boundsQConfig);
                    if (aabb.IsValid)
                    {
                        if (worldAABB.IsValid)
                        {
                            worldAABB.Encapsulate(aabb);
                        }
                        else
                        {
                            worldAABB = aabb;
                        }
                    }
                }

                SetAABB(worldAABB);
                UpdateSnapSteps();
            }
            else
            if (ExtrudeSpace == GizmoSpace.Local)
            {
                int firstParentIndex = 0;
                while (firstParentIndex < NumTargetParents)
                {
                    if (_ignoredParentObjects.Contains(_targetParents[firstParentIndex]))
                    {
                        ++firstParentIndex;
                    }
                    else
                    {
                        break;
                    }
                }

                if (firstParentIndex == NumTargetParents)
                {
                    SetOBB(OBB.GetInvalid());
                    UpdateSnapSteps();
                    return;
                }

                OBB worldOBB = ObjectBounds.CalcHierarchyWorldOBB(_targetParents[firstParentIndex], _boundsQConfig);
                for (int parentIndex = firstParentIndex; parentIndex < NumTargetParents; ++parentIndex)
                {
                    GameObject parent = _targetParents[parentIndex];
                    if (_ignoredParentObjects.Contains(parent))
                    {
                        continue;
                    }

                    OBB obb = ObjectBounds.CalcHierarchyWorldOBB(parent, _boundsQConfig);
                    if (obb.IsValid)
                    {
                        if (worldOBB.IsValid)
                        {
                            worldOBB.Encapsulate(obb);
                        }
                        else
                        {
                            worldOBB = obb;
                        }
                    }
                }

                SetOBB(worldOBB);
                UpdateSnapSteps();
            }
        }
        public bool Initialize(GameObject gameObject)
        {
            if (gameObject == null || _gameObject != null)
            {
                return(false);
            }

            Mesh   mesh   = gameObject.GetMesh();
            Sprite sprite = gameObject.GetSprite();

            if (mesh == null && sprite == null)
            {
                return(false);
            }

            bool useMesh = true;

            if (mesh == null)
            {
                useMesh = false;
            }

            RTMesh rtMesh = null;

            if (useMesh)
            {
                Renderer meshRenderer = gameObject.GetMeshRenderer();
                if (meshRenderer == null || !meshRenderer.enabled)
                {
                    useMesh = false;
                }

                rtMesh = RTMeshDb.Get.GetRTMesh(mesh);
                if (rtMesh == null)
                {
                    useMesh = false;
                }
            }
            if (rtMesh == null && sprite == null)
            {
                return(false);
            }

            List <AABB> vertOverlapAABBs = BuildVertOverlapAABBs(gameObject, useMesh ? null : sprite, useMesh ? rtMesh : null);

            if (vertOverlapAABBs.Count == 0)
            {
                return(false);
            }

            AABB modelAABB = useMesh ? rtMesh.AABB : ObjectBounds.CalcSpriteModelAABB(gameObject);
            var  aabbFaces = BoxMath.AllBoxFaces;

            _gameObject = gameObject;
            if (useMesh)
            {
                foreach (var aabbFace in aabbFaces)
                {
                    AABB           overlapAABB     = vertOverlapAABBs[(int)aabbFace];
                    List <Vector3> overlappedVerts = rtMesh.OverlapModelVerts(overlapAABB);
                    Plane          facePlane       = BoxMath.CalcBoxFacePlane(modelAABB.Center, modelAABB.Size, Quaternion.identity, aabbFace);
                    overlappedVerts = facePlane.ProjectAllPoints(overlappedVerts);
                    _snapAreaBounds[(int)aabbFace] = new AABB(overlappedVerts);
                    _snapAreaDesc[(int)aabbFace]   = BoxMath.GetBoxFaceAreaDesc(_snapAreaBounds[(int)aabbFace].Size, aabbFace);
                }
            }
            else
            {
                foreach (var aabbFace in aabbFaces)
                {
                    if (aabbFace != BoxFace.Front && aabbFace != BoxFace.Back)
                    {
                        AABB           overlapAABB     = vertOverlapAABBs[(int)aabbFace];
                        List <Vector3> overlappedVerts = ObjectVertexCollect.CollectModelSpriteVerts(sprite, overlapAABB);
                        Plane          facePlane       = BoxMath.CalcBoxFacePlane(modelAABB.Center, modelAABB.Size, Quaternion.identity, aabbFace);
                        overlappedVerts = facePlane.ProjectAllPoints(overlappedVerts);
                        _snapAreaBounds[(int)aabbFace] = new AABB(overlappedVerts);
                        _snapAreaDesc[(int)aabbFace]   = BoxMath.GetBoxFaceAreaDesc(_snapAreaBounds[(int)aabbFace].Size, aabbFace);
                    }
                    else
                    {
                        _snapAreaBounds[(int)aabbFace] = AABB.GetInvalid();
                        _snapAreaDesc[(int)aabbFace]   = BoxFaceAreaDesc.GetInvalid();
                    }
                }
            }

            return(true);
        }
Beispiel #16
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());
        }
Beispiel #17
0
 private OBB CalcTargetRootOBB(GameObject targetRoot)
 {
     ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
     boundsQConfig.ObjectTypes = GameObjectType.Mesh | GameObjectType.Sprite;
     return(ObjectBounds.CalcHierarchyWorldOBB(targetRoot, boundsQConfig));
 }
Beispiel #18
0
        public override void OnGizmoDragUpdate(int handleId)
        {
            if (OwnsHandle(handleId) && Gizmo.RelativeDragOffset.magnitude != 0.0f)
            {
                float extrAmount = Gizmo.RelativeDragOffset.magnitude;
                float boxSize    = _boxSize[_handleDragExtrData.AxisIndex];
                float fNumClones = boxSize != 0.0f ? (extrAmount / boxSize) : 0.0f;
                int   iNumClones = (int)fNumClones;

                float absFractional = Mathf.Abs(fNumClones - (int)fNumClones);
                if (iNumClones == 0 && Mathf.Abs(absFractional - 1.0f) < 1e-5f)
                {
                    ++iNumClones;
                }

                var createdClones = new List <GameObject>(10);
                var cloneConfig   = ObjectCloning.DefaultConfig;
                var cloneOffset   = _handleDragExtrData.ExtrudeDir * boxSize;
                for (int cloneIndex = 0; cloneIndex < iNumClones; ++cloneIndex)
                {
                    foreach (var targetParent in _targetParents)
                    {
                        if (_ignoredParentObjects.Contains(targetParent))
                        {
                            continue;
                        }

                        if (!Hotkeys.EnableOverlapTest.IsActive())
                        {
                            cloneConfig.Parent = targetParent.transform.parent;
                            var clonedHierarchy = ObjectCloning.CloneHierarchy(targetParent, cloneConfig);
                            if (clonedHierarchy != null)
                            {
                                _sceneOverlapFilter.IgnoreObjects.AddRange(clonedHierarchy.GetAllChildrenAndSelf());
                                _dragEndAction.AddExtrudeClone(clonedHierarchy);
                                createdClones.Add(clonedHierarchy);
                            }
                            clonedHierarchy.transform.position += cloneIndex * cloneOffset;
                        }
                        else
                        {
                            OBB targetOBB = ObjectBounds.CalcHierarchyWorldOBB(targetParent, _boundsQConfig);
                            if (!targetOBB.IsValid)
                            {
                                continue;
                            }
                            targetOBB.Center += cloneIndex * cloneOffset;

                            // Bring the size down a tad. Otherwise, we can get false positives when objects are really close to
                            // each other even if they do not intersect.
                            targetOBB.Inflate(-1e-2f);
                            var overlappedObjects = RTScene.Get.OverlapBox(targetOBB, _sceneOverlapFilter);
                            if (overlappedObjects.Count != 0)
                            {
                                continue;
                            }

                            cloneConfig.Parent = targetParent.transform.parent;
                            var clonedHierarchy = ObjectCloning.CloneHierarchy(targetParent, cloneConfig);
                            if (clonedHierarchy != null)
                            {
                                _sceneOverlapFilter.IgnoreObjects.AddRange(clonedHierarchy.GetAllChildrenAndSelf());
                                _dragEndAction.AddExtrudeClone(clonedHierarchy);
                                createdClones.Add(clonedHierarchy);
                            }
                            clonedHierarchy.transform.position += cloneIndex * cloneOffset;
                        }
                    }
                }
                _handleDragExtrData.ExtrudeCenter += Gizmo.RelativeDragOffset;

                foreach (var targetParent in _targetParents)
                {
                    if (!_ignoredParentObjects.Contains(targetParent))
                    {
                        targetParent.transform.position += Gizmo.RelativeDragOffset;
                    }
                }

                if (ExtrudeUpdate != null)
                {
                    ExtrudeUpdate(createdClones);
                }
            }
        }
        public static SnapResult CalculateSnapResult(GameObject root, Config snapConfig)
        {
            if (snapConfig.IgnoreDestObjects == null)
            {
                snapConfig.IgnoreDestObjects = new List <GameObject>();
            }

            List <GameObject> sourceObjects = root.GetAllChildrenAndSelf();

            if (sourceObjects.Count > MaxSourceObjects)
            {
                return(new SnapResult(SnapFailReson.MaxObjectsExceeded));
            }

            List <GameObject> sourceMeshObjects   = root.GetMeshObjectsInHierarchy();
            List <GameObject> sourceSpriteObjects = root.GetSpriteObjectsInHierarchy();

            if (sourceMeshObjects.Count == 0 && sourceSpriteObjects.Count == 0)
            {
                return(new SnapResult(SnapFailReson.InvalidSourceObjects));
            }

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

            Vector3             overlapSizeAdd     = Vector3.one * snapConfig.SnapRadius * 2.0f;
            List <BoxFace>      allSnapFaces       = BoxMath.AllBoxFaces;
            bool                tryMatchAreas      = (snapConfig.Prefs & Prefs.TryMatchArea) != 0;
            bool                foundMatchingAreas = false;
            List <SnapSortData> sortedSnapData     = new List <SnapSortData>(10);
            SnapSortData        sortData           = new SnapSortData();

            foreach (GameObject sourceObject in sourceObjects)
            {
                OBB overlapOBB = ObjectBounds.CalcWorldOBB(sourceObject, boundsQConfig);
                overlapOBB.Size = overlapOBB.Size + overlapSizeAdd;

                List <GameObject> nearbyObjects = RTScene.Get.OverlapBox(overlapOBB);
                nearbyObjects.RemoveAll(item => item.transform.IsChildOf(root.transform) ||
                                        snapConfig.IgnoreDestObjects.Contains(item) || !LayerEx.IsLayerBitSet(snapConfig.DestinationLayers, item.layer));
                if (nearbyObjects.Count == 0)
                {
                    continue;
                }

                Object2ObjectSnapData sourceSnapData = Object2ObjectSnapDataDb.Get.GetObject2ObjectSnapData(sourceObject);
                if (sourceSnapData == null)
                {
                    continue;
                }

                sortData.SrcObject = sourceObject;
                foreach (BoxFace srcSnapFace in allSnapFaces)
                {
                    BoxFaceAreaDesc srcAreaDesc   = sourceSnapData.GetWorldSnapAreaDesc(srcSnapFace);
                    OBB             srcAreaBounds = sourceSnapData.GetWorldSnapAreaBounds(srcSnapFace);
                    List <Vector3>  srcAreaPts    = srcAreaBounds.GetCenterAndCornerPoints();
                    sortData.SrcSnapFace = srcSnapFace;

                    foreach (GameObject destObject in nearbyObjects)
                    {
                        Object2ObjectSnapData destSnapData = Object2ObjectSnapDataDb.Get.GetObject2ObjectSnapData(destObject);
                        if (destSnapData == null)
                        {
                            continue;
                        }

                        sortData.DestObject = destObject;
                        foreach (BoxFace destSnapFace in allSnapFaces)
                        {
                            sortData.DestSnapFace = destSnapFace;
                            BoxFaceAreaDesc destAreaDesc = destSnapData.GetWorldSnapAreaDesc(destSnapFace);

                            sortData.FaceAreasMatch = false;

                            if (tryMatchAreas && destAreaDesc.AreaType == srcAreaDesc.AreaType)
                            {
                                sortData.FaceAreaDiff = Mathf.Abs(destAreaDesc.Area - srcAreaDesc.Area);
                                if (sortData.FaceAreaDiff <= 1000.0f)
                                {
                                    sortData.FaceAreasMatch = true;
                                }
                            }

                            OBB            destAreaBounds = destSnapData.GetWorldSnapAreaBounds(destSnapFace);
                            List <Vector3> destAreaPts    = destAreaBounds.GetCenterAndCornerPoints();

                            foreach (Vector3 srcPt in srcAreaPts)
                            {
                                sortData.SnapPivot = srcPt;
                                foreach (Vector3 destPt in destAreaPts)
                                {
                                    sortData.SnapDistance = (destPt - srcPt).magnitude;
                                    if (sortData.SnapDistance < snapConfig.SnapRadius)
                                    {
                                        sortData.SnapDest = destPt;
                                        sortedSnapData.Add(sortData);

                                        if (sortData.FaceAreasMatch)
                                        {
                                            foundMatchingAreas = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (sortedSnapData.Count != 0)
            {
                if (!tryMatchAreas || !foundMatchingAreas)
                {
                    sortedSnapData.Sort(delegate(SnapSortData s0, SnapSortData s1)
                    {
                        return(s0.SnapDistance.CompareTo(s1.SnapDistance));
                    });
                }
                else
                {
                    while (true)
                    {
                        if (!sortedSnapData[0].FaceAreasMatch)
                        {
                            sortedSnapData.RemoveAt(0);
                        }
                        else
                        {
                            break;
                        }
                    }

                    sortedSnapData.Sort(delegate(SnapSortData s0, SnapSortData s1)
                    {
                        return(s0.FaceAreaDiff.CompareTo(s1.FaceAreaDiff));
                    });
                }

                return(new SnapResult(sortedSnapData[0].SnapPivot, sortedSnapData[0].SnapDest, sortedSnapData[0].SnapDistance));
            }
            return(new SnapResult(SnapFailReson.NoDestinationFound));
        }