public static Object2ObjectBoxSnapData Create(GameObject meshObject)
        {
            if (meshObject == null)
            {
                return(null);
            }

            Mesh objectMesh = meshObject.GetMeshFromFilterOrSkinnedMeshRenderer();

            if (objectMesh == null)
            {
                return(null);
            }

            Renderer renderer = meshObject.GetRenderer();

            if (renderer == null || !renderer.enabled)
            {
                return(null);
            }

            Octave3DMesh octaveMesh = Octave3DMeshDatabase.Get().GetOctave3DMesh(objectMesh);

            if (octaveMesh == null)
            {
                return(null);
            }

            List <Box> modelVertOverlapBoxes = BuildModelVertOverlapBoxes(octaveMesh);
            var        snapBoxIDs            = Object2ObjectBoxSnapData.GetAllSnapBoxIDs();
            var        modelSnapBoxes        = new List <Box>(snapBoxIDs.Length);
            Box        modelMeshBox          = octaveMesh.ModelAABB;

            BoxFace[] meshBoxFaces = Object2ObjectBoxSnapData.GetBoxFaceToSnapBoxIDMap();
            foreach (var snapBox in snapBoxIDs)
            {
                Box            overlapBox      = modelVertOverlapBoxes[(int)snapBox];
                List <Vector3> overlappedVerts = octaveMesh.GetOverlappedModelVerts(overlapBox);
                Plane          meshFacePlane   = modelMeshBox.GetBoxFacePlane(meshBoxFaces[(int)snapBox]);
                overlappedVerts = meshFacePlane.ProjectAllPoints(overlappedVerts);

                modelSnapBoxes.Add(Box.FromPoints(overlappedVerts));
            }

            return(new Object2ObjectBoxSnapData(meshObject, modelSnapBoxes));
        }
        private static List <Box> BuildModelVertOverlapBoxes(Octave3DMesh octaveMesh)
        {
            const float overlapAmount     = 0.2f;
            float       halfOverlapAmount = overlapAmount * 0.5f;
            Box         modelMeshBox      = octaveMesh.ModelAABB;
            Vector3     meshBoxSize       = modelMeshBox.Size;

            BoxFace[] meshBoxFaces = Object2ObjectBoxSnapData.GetBoxFaceToSnapBoxIDMap();

            // Must have 1 to 1 mapping with Object2ObjectBoxSnapData.SnapBox enum
            const float sizeEps = 0.001f;

            Vector3[] overlapBoxSizes = new Vector3[]
            {
                // Left and right
                new Vector3(overlapAmount, meshBoxSize.y + sizeEps, meshBoxSize.z + sizeEps),
                new Vector3(overlapAmount, meshBoxSize.y + sizeEps, meshBoxSize.z + sizeEps),

                // Bottom and top
                new Vector3(meshBoxSize.x + sizeEps, overlapAmount, meshBoxSize.z + sizeEps),
                new Vector3(meshBoxSize.x + sizeEps, overlapAmount, meshBoxSize.z + sizeEps),

                // Back and front
                new Vector3(meshBoxSize.x + sizeEps, meshBoxSize.y + sizeEps, overlapAmount),
                new Vector3(meshBoxSize.x + sizeEps, meshBoxSize.y + sizeEps, overlapAmount),
            };

            var overlapBoxes = new List <Box>();

            for (int boxFaceIndex = 0; boxFaceIndex < meshBoxFaces.Length; ++boxFaceIndex)
            {
                BoxFace meshBoxFace   = meshBoxFaces[boxFaceIndex];
                Vector3 faceCenter    = modelMeshBox.GetBoxFaceCenter(meshBoxFace);
                Vector3 faceNormal    = modelMeshBox.GetBoxFacePlane(meshBoxFace).normal;
                Vector3 overlapCenter = faceCenter - faceNormal * halfOverlapAmount;
                overlapBoxes.Add(new Box(overlapCenter, overlapBoxSizes[boxFaceIndex]));
            }

            return(overlapBoxes);
        }
Ejemplo n.º 3
0
        public static SnapResult Snap(List <GameObject> roots, float snapEpsilon, List <GameObject> ignoreDestSnapObjects)
        {
            if (ignoreDestSnapObjects == null)
            {
                ignoreDestSnapObjects = new List <GameObject>();
            }

            Vector3 snapDestPt = Vector3.zero, snapPivotPt = Vector3.zero;
            float   minSnapDistance = float.MaxValue;

            List <GameObject> allSourceObjects = new List <GameObject>();

            foreach (var root in roots)
            {
                allSourceObjects.AddRange(root.GetAllChildrenIncludingSelf());
            }

            foreach (var hierarchyRoot in roots)
            {
                List <GameObject> sourceObjects = hierarchyRoot.GetAllChildrenIncludingSelf();
                if (sourceObjects.Count > MaxSourceObjects)
                {
                    continue;
                }

                List <GameObject> meshObjectsInHierarchy   = hierarchyRoot.GetHierarchyObjectsWithMesh();
                List <GameObject> spriteObjectsInHierarchy = hierarchyRoot.GetHierarchyObjectsWithSprites();
                if (meshObjectsInHierarchy.Count == 0 && spriteObjectsInHierarchy.Count == 0)
                {
                    return(SnapResult.GetWasNotSnapped());
                }

                var object2ObjectSnapDatabase = Object2ObjectBoxSnapDatabase.Instance;
                if (sourceObjects.Count > 1 || spriteObjectsInHierarchy.Count == 0)
                {
                    foreach (var sourceObject in sourceObjects)
                    {
                        Box queryBox = sourceObject.GetWorldBox();
                        queryBox.Size = queryBox.Size + Vector3.one * snapEpsilon;

                        List <GameObject> nearbyObjects = Octave3DScene.Get().OverlapBox(queryBox);
                        if (nearbyObjects.Count == 0)
                        {
                            return(SnapResult.GetWasNotSnapped());
                        }
                        nearbyObjects.RemoveAll(item => allSourceObjects.Contains(item) ||
                                                ignoreDestSnapObjects.Contains(item));

                        Object2ObjectBoxSnapData sourceSnapData = object2ObjectSnapDatabase.GetObject2ObjectBoxSnapData(sourceObject);
                        if (sourceSnapData == null)
                        {
                            continue;
                        }

                        var sourceSnapBoxes = sourceSnapData.GetWorldSnapBoxes();
                        foreach (var destObject in nearbyObjects)
                        {
                            Object2ObjectBoxSnapData destSnapData = object2ObjectSnapDatabase.GetObject2ObjectBoxSnapData(destObject);
                            if (destSnapData == null)
                            {
                                continue;
                            }

                            var destSnapBoxes = destSnapData.GetWorldSnapBoxes();

                            foreach (var sourceSnapBox in sourceSnapBoxes)
                            {
                                var sourceBoxPoints = sourceSnapBox.GetCenterAndCornerPoints();
                                foreach (var destSnapBox in destSnapBoxes)
                                {
                                    var destBoxPoints = destSnapBox.GetCenterAndCornerPoints();
                                    foreach (var srcPt in sourceBoxPoints)
                                    {
                                        foreach (var destPt in destBoxPoints)
                                        {
                                            float distance = (destPt - srcPt).magnitude;
                                            if (distance < minSnapDistance)
                                            {
                                                minSnapDistance = distance;
                                                snapDestPt      = destPt;
                                                snapPivotPt     = srcPt;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    Box hierarchyWorldAABB = hierarchyRoot.GetHierarchyWorldBox();
                    Box hierarchyQueryBox  = hierarchyWorldAABB;
                    hierarchyQueryBox.Size = hierarchyQueryBox.Size + Vector3.one * snapEpsilon;

                    List <GameObject> nearbyObjects = Octave3DScene.Get().OverlapBox(hierarchyQueryBox);
                    if (nearbyObjects.Count == 0)
                    {
                        return(SnapResult.GetWasNotSnapped());
                    }
                    nearbyObjects.RemoveAll(item => allSourceObjects.Contains(item) ||
                                            ignoreDestSnapObjects.Contains(item));

                    List <Vector3> hierarchyBoxCornerPoints = hierarchyWorldAABB.GetCornerPoints();
                    foreach (GameObject gameObject in nearbyObjects)
                    {
                        Box objectWorldBox = Box.GetInvalid();

                        Mesh objectMesh = gameObject.GetMeshFromFilterOrSkinnedMeshRenderer();
                        if (objectMesh != null)
                        {
                            objectWorldBox = gameObject.GetMeshWorldBox();
                        }
                        if (objectWorldBox.IsInvalid() && gameObject.HasSpriteRendererWithSprite())
                        {
                            objectWorldBox = gameObject.GetNonMeshWorldBox();
                        }

                        if (objectWorldBox.IsInvalid())
                        {
                            continue;
                        }

                        List <Vector3> worldBoxCornerPoints = objectWorldBox.GetCornerPoints();
                        foreach (Vector3 hierarchyBoxPt in hierarchyBoxCornerPoints)
                        {
                            foreach (Vector3 objectMeshBoxPt in worldBoxCornerPoints)
                            {
                                float distance = (hierarchyBoxPt - objectMeshBoxPt).magnitude;
                                if (distance < minSnapDistance)
                                {
                                    minSnapDistance = distance;
                                    snapDestPt      = objectMeshBoxPt;
                                    snapPivotPt     = hierarchyBoxPt;
                                }
                            }
                        }
                    }
                }
            }

            if (minSnapDistance < snapEpsilon)
            {
                foreach (var root in roots)
                {
                    ObjectHierarchySnap.Snap(root, snapPivotPt, snapDestPt);
                }
                return(new SnapResult(true, snapPivotPt, snapDestPt));
            }

            return(SnapResult.GetWasNotSnapped());
        }