Exemplo n.º 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);
            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;
        }
Exemplo n.º 2
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);
                }
            }
        }
Exemplo n.º 3
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();
            }
        }
Exemplo n.º 4
0
        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);
                }
            }
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
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());
        }
Exemplo n.º 7
0
 private OBB CalcTargetRootOBB(GameObject targetRoot)
 {
     ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig();
     boundsQConfig.ObjectTypes = GameObjectType.Mesh | GameObjectType.Sprite;
     return(ObjectBounds.CalcHierarchyWorldOBB(targetRoot, boundsQConfig));
 }