Exemple #1
0
        public List <Triangle3DIntersectInfo> GetIntersectingTriangles(TransformMatrix thisTransform, Octave3DMesh otherMesh, TransformMatrix otherTransform)
        {
            OrientedBox thisOOBB = new OrientedBox(ModelAABB);

            thisOOBB.Transform(thisTransform);
            OrientedBox otherOOBB = new OrientedBox(otherMesh.ModelAABB);

            otherOOBB.Transform(otherTransform);

            if (thisOOBB.Intersects(otherOOBB))
            {
                List <Triangle3D> thisTriangles = GetOverlappedTriangles(otherOOBB, thisTransform);

                var output = new List <Triangle3DIntersectInfo>(50);
                Triangle3DIntersectInfo intersectInfo;
                for (int thisTriIndex = 0; thisTriIndex < thisTriangles.Count; ++thisTriIndex)
                {
                    Triangle3D thisTri = thisTriangles[thisTriIndex];

                    OrientedBox       thisTriOOBB    = new OrientedBox(thisTri.GetEncapsulatingBox());
                    List <Triangle3D> otherTriangles = otherMesh.GetOverlappedTriangles(thisTriOOBB, otherTransform);

                    for (int otherTriIndex = 0; otherTriIndex < otherTriangles.Count; ++otherTriIndex)
                    {
                        Triangle3D otherTri = otherTriangles[otherTriIndex];
                        if (thisTri.IntersectsTriangle(otherTri, out intersectInfo))
                        {
                            output.Add(intersectInfo);
                        }
                    }
                }

                return(output);
            }
            else
            {
                return(new List <Triangle3DIntersectInfo>());
            }
        }
Exemple #2
0
        /// <summary>
        /// Returns a list of all objects which are overlapped by the specified box.
        /// </summary>
        /// <param name="box">
        /// The box involved in the overlap query.
        /// </param>
        public List <GameObject> OverlapBox(OrientedBox box)
        {
            // Retrieve all the sphere tree nodes which are overlapped by the box. If no nodes are overlapped,
            // we can return an empty list because it means that no objects could possibly be overlapped either.
            List <SphereTreeNode <GameObject> > allOverlappedNodes = _sphereTree.OverlapBox(box);

            if (allOverlappedNodes.Count == 0)
            {
                return(new List <GameObject>());
            }

            // Loop through all overlapped nodes
            var overlappedObjects = new List <GameObject>();

            foreach (SphereTreeNode <GameObject> node in allOverlappedNodes)
            {
                // Store the node's object for easy access
                GameObject gameObject = node.Data;
                if (gameObject == null)
                {
                    continue;
                }
                if (!gameObject.activeSelf)
                {
                    continue;
                }

                // We need to perform an additional check. Even though the box overlaps the object's node (which is
                // a sphere), we must also check if the box overlaps the object's world oriented box. This allows
                // for better precision.
                OrientedBox objectWorldOrientedBox = gameObject.GetWorldOrientedBox();
                if (box.Intersects(objectWorldOrientedBox))
                {
                    overlappedObjects.Add(gameObject);
                }
            }

            return(overlappedObjects);
        }
Exemple #3
0
        public List <Triangle3D> GetOverlappedWorldTriangles(OrientedBox box, TransformMatrix meshTransformMatrix)
        {
            // If the tree was not yet build, we need to build it because we need
            // the triangle information in order to perform the raycast.
            if (!_wasBuilt)
            {
                Build();
            }

            // Work in mesh model space because the tree data exists in model space
            OrientedBox meshSpaceBox     = new OrientedBox(box);
            Matrix4x4   inverseTransform = meshTransformMatrix.ToMatrix4x4x.inverse;

            meshSpaceBox.Transform(inverseTransform);

            List <SphereTreeNode <MeshSphereTreeTriangle> > overlappedNodes = _sphereTree.OverlapBox(meshSpaceBox);

            if (overlappedNodes.Count == 0)
            {
                return(new List <Triangle3D>());
            }

            Box queryBox = Box.FromPoints(meshSpaceBox.GetCenterAndCornerPoints());
            var overlappedWorldTriangles = new List <Triangle3D>(50);

            foreach (var node in overlappedNodes)
            {
                int triangleIndex             = node.Data.TriangleIndex;
                MeshTriangleInfo triangleInfo = _octave3DMesh.GetMeshTriangleInfo(triangleIndex);

                if (triangleInfo.ModelSpaceTriangle.IntersectsBox(queryBox))
                {
                    triangleInfo.ModelSpaceTriangle.TransformPoints(meshTransformMatrix);
                    overlappedWorldTriangles.Add(triangleInfo.ModelSpaceTriangle);
                }
            }

            return(overlappedWorldTriangles);
        }
        public void FromOrientedBoxAndDecorStrokeSurface(OrientedBox orientedBox, DecorPaintStrokeSurface decorPaintStrokeSurface)
        {
            if (!decorPaintStrokeSurface.IsValid)
            {
                return;
            }

            Vector3 surfacePlaneNormal = decorPaintStrokeSurface.Plane.normal;

            if (AllShortcutCombos.Instance.PlaceGuideBehindSurfacePlane.IsActive())
            {
                surfacePlaneNormal *= -1.0f;
            }

            BoxFace        boxFaceMostAlignedWithSurface            = orientedBox.GetBoxFaceWhichFacesNormal(surfacePlaneNormal);
            List <Vector3> cornerPointsOfFaceMostAlignedWithSurface = orientedBox.GetBoxFaceCornerPoints(boxFaceMostAlignedWithSurface);

            CalculatePointsPlane(orientedBox, decorPaintStrokeSurface);

            StoreObjectPivotPoints(_pointsPlane.ProjectAllPoints(cornerPointsOfFaceMostAlignedWithSurface));
            StoreUnprojectedPivotPoints(cornerPointsOfFaceMostAlignedWithSurface);
            CalculateArea();
        }
Exemple #5
0
        public void SetData(ObjectPlacementPathManualConstructionSessionData sessionData)
        {
            if (!_isActive)
            {
                _path                    = sessionData.Path;
                _pathSegments            = sessionData.PathSegments;
                _pathExtensionPlane      = sessionData.PathExtensionPlane;
                _tileConnectionGridCells = sessionData.TileConnectionGridCells;

                _startObject = sessionData.StartObject;
                _startObjectHierarchyWorldOrientedBox = _startObject.GetHierarchyWorldOrientedBox();

                _pathSettings               = _path.Settings;
                _tileConnectionSettings     = _pathSettings.TileConnectionSettings;
                _manualConstructionSettings = _pathSettings.ManualConstructionSettings;
                _heightAdjustmentSettings   = _manualConstructionSettings.HeightAdjustmentSettings;
                _paddingSettings            = _manualConstructionSettings.PaddingSettings;
                _borderSettings             = _manualConstructionSettings.BorderSettings;

                _pathNoTileConnectionsObjectPlacementDataCalculator.Path   = _path;
                _pathWithTileConnectionsObjectPlacementDataCalculator.Path = _path;
            }
        }
Exemple #6
0
        public void UpdateProjectedBoxFacePivotPoints(GameObject hierarchyRoot, ProjectedBoxFacePivotPoints projectedBoxFacePivotPoints, bool keepCurrentSnapSurface)
        {
            OrientedBox hierarchyWorldOrientedBox = hierarchyRoot.GetHierarchyWorldOrientedBox();

            if (!hierarchyWorldOrientedBox.IsValid())
            {
                return;
            }

            if (keepCurrentSnapSurface)
            {
                if (!_objectSnapSurface.IsValid)
                {
                    return;
                }
                projectedBoxFacePivotPoints.FromOrientedBoxAndSnapSurface(hierarchyWorldOrientedBox, _objectSnapSurface);
            }
            else
            {
                _objectSnapSurface.FromMouseCursorRayHit(GetCursorRayHit());
                projectedBoxFacePivotPoints.FromOrientedBoxAndSnapSurface(hierarchyWorldOrientedBox, _objectSnapSurface);
            }
        }
Exemple #7
0
        public void UpdateForMouseMovement()
        {
            if (_state == State.Inactive)
            {
                return;
            }

            if (MouseButtonStates.Instance.IsMouseButtonDown(MouseButton.Left))
            {
                _state = State.Snap;
            }
            else
            {
                _state = State.SelectPivot;
            }

            if (_state == State.SelectPivot && _selectedParents.Count != 0)
            {
                Camera  camera   = SceneViewCamera.Camera;
                Vector2 mousePos = Event.current.InvMousePos(camera);

                _isPivotAvailable = false;
                float minDistanceSq = float.MaxValue;
                foreach (var parent in _selectedParents)
                {
                    if (parent == null)
                    {
                        continue;
                    }

                    OrientedBox worldOOBB = parent.GetHierarchyWorldOrientedBox();
                    if (worldOOBB.IsValid())
                    {
                        List <Vector3> centerAndCorners = worldOOBB.GetCenterAndCornerPoints();
                        List <Vector2> oobbScreenPts    = Vector2Extensions.GetScreenPoints(centerAndCorners, camera);

                        for (int ptIndex = 0; ptIndex < centerAndCorners.Count; ++ptIndex)
                        {
                            Vector3 worldPt  = centerAndCorners[ptIndex];
                            Vector2 screenPt = oobbScreenPts[ptIndex];
                            float   distSq   = (mousePos - screenPt).sqrMagnitude;
                            if (distSq < minDistanceSq)
                            {
                                minDistanceSq     = distSq;
                                _pivot            = worldPt;
                                _isPivotAvailable = true;
                            }
                        }
                    }
                }
            }
            else
            if (_state == State.Snap && _isPivotAvailable)
            {
                GameObjectExtensions.RecordObjectTransformsForUndo(_selectedParents);
                MouseCursorRayHit cursorHit = MouseCursor.Instance.GetCursorRayHitForGridCell();
                if (cursorHit.WasACellHit)
                {
                    Camera         camera          = SceneViewCamera.Camera;
                    Vector2        mousePos        = Event.current.InvMousePos(camera);
                    GridCellRayHit cellRayHit      = cursorHit.GridCellRayHit;
                    Vector3        snapDestination = Vector3Extensions.GetClosestPointToPoint(cellRayHit.HitCell.Quad.GetCenterAndCornerPoints(), cellRayHit.HitPoint);

                    Vector3 moveVector = snapDestination - _pivot;
                    foreach (var parent in _selectedParents)
                    {
                        if (parent != null)
                        {
                            parent.transform.position += moveVector;
                        }
                    }

                    _pivot = snapDestination;

                    ObjectSelection.Get().ObjectSelectionTransformGizmoSystem.OnObjectSelectionUpdated();
                }
            }
        }
Exemple #8
0
 public void RenderMirroredEntityOrientedBox(OrientedBox entityBox)
 {
     _mirroredEntityRenderer.RenderMirroredEntityOrientedBox(_mirror.WorldPlane, entityBox, _mirrorRotation, RenderSettings.MirroredBoxColor, RenderSettings.MirroredBoxBorderLineColor);
 }
Exemple #9
0
        private bool DoesGuideIntersectPreviuslyPlacedObjectHierarchy()
        {
            OrientedBox guideWorldOrientedBox = ObjectPlacementGuide.SceneObject.GetHierarchyWorldOrientedBox();

            return(guideWorldOrientedBox.Intersects(_orientedBoxOfLastPlacedHierarchy));
        }
Exemple #10
0
        public List <ObjectPlacementData> Calculate(Quaternion rotationToApplyForStrokeAlignment)
        {
            if (!ValidateCalculationRequirements())
            {
                return(new List <ObjectPlacementData>());
            }

            _objectNodeNetwork.Clear();
            _rotationToApplyForStrokeAlignment = rotationToApplyForStrokeAlignment;
            CreateSurfaceColliderProjector();
            _elementToNewPrefabRotation.Clear();
            _allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForDecorPaintBrushModeDrag;

            int currentObjectIndex           = 0;
            var objectPlacementDataInstances = new List <ObjectPlacementData>(_workingBrush.MaxNumberOfObjects);

            while (currentObjectIndex < _workingBrush.MaxNumberOfObjects)
            {
                DecorPaintObjectPlacementBrushElement brushElement = _brushElementSpawnChanceTable.PickEntity(UnityEngine.Random.Range(0.0f, 1.0f));
                int brushElementIndex = _allValidBrushElements.FindIndex(item => item == brushElement);
                ++currentObjectIndex;

                // No object nodes were created yet?
                if (_objectNodeNetwork.NumberOfNodes == 0)
                {
                    // Create the first node at a random position inside the brush circle
                    Vector3             randomPositionInsideCircle = _workingBrushCircle.GetRandomPointInside();
                    ObjectSurfaceData   objectSurfaceData          = CalculateObjectSurfaceData(randomPositionInsideCircle);
                    MatrixObjectBoxPair matrixObjectBoxPair        = CalculateMatrixObjectBoxPair(brushElementIndex, objectSurfaceData);

                    // We need to know if the normal of the surface on which the object resides lies within the desired slope range
                    bool passesSlopeTest = DoesObjectSurfacePassSlopeTest(objectSurfaceData, brushElement);

                    // Note: Even if the slope test is not passed, we will still create an object node. The reason for this is that
                    //       we want to have some kind of continuity in the algorithm. Imagine that the brush circle is large and is
                    //       divided by a large terrain mountain which sits in the middle. If the object generation starts on one side
                    //       of the mountain, the algorithm might never get a chance to go over the other side if the slope condition
                    //       is not satisifed. We want to spread objects as much as possible so even though this object will not be
                    //       placed in the scene, we will still add it to the node network.
                    _objectNodeNetwork.AddNodeToEnd(matrixObjectBoxPair.ObjectBox, objectSurfaceData);
                    if (passesSlopeTest && DoesBoxPassObjectIntersectionTest(matrixObjectBoxPair.ObjectBox, brushElement.Prefab.UnityPrefab, matrixObjectBoxPair.ObjectMatrix))
                    {
                        objectPlacementDataInstances.Add(new ObjectPlacementData(matrixObjectBoxPair.ObjectMatrix, brushElement.Prefab, brushElement.MustEmbedInSurface));
                    }
                }
                else
                {
                    // Are there any node segments available?
                    if (_objectNodeNetwork.NumberOfSegments != 0)
                    {
                        // The first step is to generate a random node index and store references to that node and its immediate neighbour
                        _objectNodeNetwork.RemoveAllNodesWhichGenerateConcavities(_workingBrushCircle.Plane);
                        int        randomNodeIndex = _objectNodeNetwork.GetRandomNodeIndex();
                        ObjectNode firstNode       = _objectNodeNetwork.GetNodeByIndex(randomNodeIndex);
                        ObjectNode secondNode      = _objectNodeNetwork.GetNodeByIndex(randomNodeIndex + 1);

                        // Calculate the plane of the segment which unites the 2 nodes. We will also store the
                        // actual segment and the middle point on the segment. We will use this middle point to
                        // generate the initial object position.
                        Segment3D   nodeSegment     = ObjectNodeNetwork.CalculateSegmentBetweenNodes(firstNode, secondNode);
                        Vector3     segmentMidPoint = nodeSegment.GetPoint(0.5f);
                        Plane       segmentPlane    = ObjectNodeNetwork.CalculateSegmentPlaneNormal(firstNode, secondNode);
                        OrientedBox firstNodeBox    = firstNode.ObjectBox;
                        OrientedBox secondNodeBox   = secondNode.ObjectBox;

                        // Calculate the furthest point in front of the plane using the corner points of the
                        // 2 nodes. The idea is to move the new object as much as possible from the bulk of
                        // objects that have already been generated.
                        Vector3        furthestPointFromPlane;
                        List <Vector3> nodeCornerPoints = firstNodeBox.GetCornerPoints();
                        nodeCornerPoints.AddRange(secondNodeBox.GetCornerPoints());
                        if (!segmentPlane.GetFurthestPointInFront(nodeCornerPoints, out furthestPointFromPlane))
                        {
                            continue;
                        }

                        // Use the calculated furthest point from plane and the the existing plane normal to calculate the
                        // pivot plane. The new object will reside at some distance away from this plane.
                        Plane pivotPlane = new Plane(segmentPlane.normal, furthestPointFromPlane);

                        // Calculate the new object transform data. We will use the segment's mid point to generate the
                        // initial object position.
                        ObjectSurfaceData   objectSurfaceData   = CalculateObjectSurfaceData(segmentMidPoint);
                        MatrixObjectBoxPair matrixObjectBoxPair = CalculateMatrixObjectBoxPair(brushElementIndex, objectSurfaceData);
                        OrientedBox         objectBox           = matrixObjectBoxPair.ObjectBox;

                        // Identify the objects's furthest point behind the plane
                        Vector3        objectBoxPivotPoint;
                        List <Vector3> objectBoxCornerPoints = objectBox.GetCornerPoints();
                        if (!pivotPlane.GetFurthestPointBehind(objectBoxCornerPoints, out objectBoxPivotPoint))
                        {
                            continue;
                        }

                        // Use the furthest point to move the object in front of the plane and take the distance between objects into account
                        Vector3 fromPivotPointToCenter = objectBox.Center - objectBoxPivotPoint;
                        Vector3 projectedPivotPoint    = pivotPlane.ProjectPoint(objectBoxPivotPoint);
                        objectBox.Center = projectedPivotPoint + fromPivotPointToCenter + pivotPlane.normal * _workingBrush.DistanceBetweenObjects;

                        // Generate the object surface data
                        objectSurfaceData = CalculateObjectSurfaceData(objectBox.Center);
                        bool passesSlopeTest = DoesObjectSurfacePassSlopeTest(objectSurfaceData, brushElement);

                        // Now we need to adjust the orientation and center of the box. If the calculated center
                        // lies outside the brush circle, we will ignore this node.
                        AdjustObjectBoxRotationOnSurface(objectBox, objectSurfaceData, brushElement);
                        AdjustObjectBoxCenterToSitOnSurface(objectBox, objectSurfaceData, brushElement);
                        if (!_workingBrushCircle.ContainsPoint(_workingBrushCircle.Plane.ProjectPoint(objectBox.Center)))
                        {
                            continue;
                        }

                        // Recalculate the object matrix using the new box data
                        TransformMatrix objectMatrix = matrixObjectBoxPair.ObjectMatrix;
                        objectMatrix.Rotation    = objectBox.Rotation;
                        objectMatrix.Translation = ObjectPositionCalculator.CalculateObjectHierarchyPosition(brushElement.Prefab, objectBox.Center, objectMatrix.Scale, objectBox.Rotation);

                        // We have been modifying the matrix and box data independently so we will ensure that the box uses the latest data
                        OrientedBox finalBox = new OrientedBox(objectBox);
                        finalBox.SetTransformMatrix(objectMatrix);

                        // If the slope test passed, we will calculate an object placement data instance. Otherwise, we will just insert a new node.
                        if (passesSlopeTest && DoesBoxPassObjectIntersectionTest(finalBox, brushElement.Prefab.UnityPrefab, objectMatrix))
                        {
                            objectPlacementDataInstances.Add(new ObjectPlacementData(objectMatrix, brushElement.Prefab, brushElement.MustEmbedInSurface));
                        }
                        _objectNodeNetwork.InsertAfterNode(objectBox, objectSurfaceData, randomNodeIndex);
                    }
                    else
                    {
                        // When there are no segments available it means we have only one node. We will use this node to generate
                        // a new one at some distance away from it. First we will store some data that we will need during the entire
                        // procedure.
                        ObjectNode  pivotNode = _objectNodeNetwork.GetFirstNode();
                        Vector3     pivotNodeSurfaceTangent = pivotNode.ObjectSurfaceData.GetSurfaceTangentVector();
                        OrientedBox pivotNodeObjectBox      = pivotNode.ObjectBox;

                        // We will place the new node at some distance away from the first node's face which points
                        // along the calculated tangent vector. We will call this the pivot face.
                        BoxFace pivotBoxFace   = pivotNodeObjectBox.GetBoxFaceMostAlignedWithNormal(pivotNodeSurfaceTangent);
                        Plane   pivotFacePlane = pivotNodeObjectBox.GetBoxFacePlane(pivotBoxFace);

                        // Generate the data for the new node in the same position as the first node.
                        // Note: Although the same position is used, the rotation and scale will differ and they will
                        //       be established by 'CalculateMatrixObjectBoxPair'.
                        MatrixObjectBoxPair matrixObjectBoxPair = CalculateMatrixObjectBoxPair(brushElementIndex, pivotNode.ObjectSurfaceData);
                        OrientedBox         objectBox           = matrixObjectBoxPair.ObjectBox;

                        // At this point we have to start moving the generated object box to its new positino along the
                        // tangent vector. We will do this by calculating the furthest box point which lies behind the
                        // pivot plane and then move the box so that this point resides on that plane. We will call this
                        // the pivot point.
                        // Note: We will perform a safety check to see if this point could not be calculated and use the
                        //       closest point in front if necessary. However, this check should not be necessary. Because
                        //       we are placing te object box in the center of the previous box, we can be usre that there
                        //       will always be a point which lies behind the pivot plane.
                        Vector3        objectBoxPivotPoint;
                        List <Vector3> objectBoxCornerPoints = objectBox.GetCornerPoints();
                        if (!pivotFacePlane.GetFurthestPointBehind(objectBoxCornerPoints, out objectBoxPivotPoint) &&
                            !pivotFacePlane.GetClosestPointInFront(objectBoxCornerPoints, out objectBoxPivotPoint))
                        {
                            continue;
                        }

                        // Project the pivot point onto the pivot plane. We will also store a vector which goes from the
                        // original pivot point to the box center. This will allow us to maintain the relationship between
                        // the projected pivot point and the box center so that the center can be adjusted accordingly.
                        Vector3 fromPivotPointToCenter = objectBox.Center - objectBoxPivotPoint;
                        Vector3 projectedPivotPoint    = pivotFacePlane.ProjectPoint(objectBoxPivotPoint);

                        // Adjust the center using the projected pivot point and also take the distance between objects into account
                        objectBox.Center = projectedPivotPoint + fromPivotPointToCenter + pivotNodeSurfaceTangent * _workingBrush.DistanceBetweenObjects;

                        // Generate the object surface data at the current box position.
                        // Note: This is the step which can actually cause objects to intersect a little bit. The surface data is
                        //       calculated by projecting along the brush circle plane normal. If we are placing objects on a terrain
                        //       and the center of the circle lies somewhere at the base of the terrain where the normal points straight
                        //       up, but the center of the box resides somewhere on a clif, the new center might move the box closer
                        //       or even further away from the pivot node. This however, should not be a problem especially if the distance
                        //       between objects is not 0.
                        ObjectSurfaceData objectSurfaceData = CalculateObjectSurfaceData(objectBox.Center);
                        bool passesSlopeTest = DoesObjectSurfacePassSlopeTest(objectSurfaceData, brushElement);

                        // Now we need to adjust the orientation and center of the box. If the calculated center
                        // lies outside the brush circle, we will ignore this node.
                        AdjustObjectBoxRotationOnSurface(objectBox, objectSurfaceData, brushElement);
                        AdjustObjectBoxCenterToSitOnSurface(objectBox, objectSurfaceData, brushElement);
                        if (!_workingBrushCircle.ContainsPoint(_workingBrushCircle.Plane.ProjectPoint(objectBox.Center)))
                        {
                            continue;
                        }

                        // Recalculate the object matrix using the new box data
                        TransformMatrix objectMatrix = matrixObjectBoxPair.ObjectMatrix;
                        objectMatrix.Rotation    = objectBox.Rotation;
                        objectMatrix.Translation = ObjectPositionCalculator.CalculateObjectHierarchyPosition(brushElement.Prefab, objectBox.Center, objectMatrix.Scale, objectBox.Rotation);

                        // We have been modifying the matrix and box data independently so we will ensure that the box uses the latest data
                        OrientedBox finalBox = new OrientedBox(objectBox);
                        finalBox.SetTransformMatrix(objectMatrix);

                        // If the slope test passed, we will calculate an object placement data instance. Otherwise, we will just insert a new node.
                        if (passesSlopeTest && DoesBoxPassObjectIntersectionTest(finalBox, brushElement.Prefab.UnityPrefab, objectMatrix))
                        {
                            objectPlacementDataInstances.Add(new ObjectPlacementData(objectMatrix, brushElement.Prefab, brushElement.MustEmbedInSurface));
                        }
                        _objectNodeNetwork.InsertAfterNode(objectBox, objectSurfaceData, 0);
                    }
                }
            }

            // Adjust the prefab rotations for the next time the function is called
            if (_elementToNewPrefabRotation.Count != 0)
            {
                foreach (var prefabRotationPair in _elementToNewPrefabRotation)
                {
                    DecorPaintObjectPlacementBrushElement brushElement = prefabRotationPair.Key;
                    if (_elementToCurrentPrefabRotation.ContainsKey(brushElement))
                    {
                        _elementToCurrentPrefabRotation[brushElement] = prefabRotationPair.Value;
                    }
                }
            }

            return(objectPlacementDataInstances);
        }
Exemple #11
0
 public ObjectNode(OrientedBox objectBox, ObjectSurfaceData objectSurfaceData)
 {
     _objectBox         = new OrientedBox(objectBox);
     _objectSurfaceData = new ObjectSurfaceData(objectSurfaceData);
 }
Exemple #12
0
        public static List <OrientedBox> GetTileConnectionExtrusionOrientedBoxes(ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell)
        {
            ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack;
            ObjectPlacementPathTileConnectionTypeSettings tileConnectionTypeSettings = tileConnectionGridCell.TileConnectionPath.Settings.TileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType);

            if (tileConnectionStack != null)
            {
                if (tileConnectionStack.NumberOfBoxes == 0)
                {
                    return(new List <OrientedBox>());
                }
                if (tileConnectionTypeSettings.IsAnyExtrusionNecessary())
                {
                    // Handle upwards extrusion
                    Vector3 nextTilePositionForUpwardsExtrusion;
                    Vector3 extrudeOffset;
                    Vector3 pathExtensionPlaneNormal = tileConnectionGridCell.TileConnectionPath.ExtensionPlane.normal;

                    var     tileConnectionYOffsetVectorCalculator = new ObjectPlacementPathTileConnectionYOffsetVectorCalculator();
                    Vector3 yOffsetVector = tileConnectionYOffsetVectorCalculator.Calculate(tileConnectionTypeSettings, tileConnectionGridCell.TileConnectionPath);

                    extrudeOffset = pathExtensionPlaneNormal * tileConnectionStack.GetBoxSizeAlongNormalizedDirection(pathExtensionPlaneNormal);
                    if (tileConnectionStack.IsGrowingUpwards)
                    {
                        nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(tileConnectionStack.NumberOfBoxes - 1).Center + extrudeOffset;
                    }
                    else
                    {
                        nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(0).Center + extrudeOffset;
                    }

                    var extrudedBox = new OrientedBox();
                    extrudedBox.Rotation       = tileConnectionStack.Rotation;
                    extrudedBox.ModelSpaceSize = tileConnectionStack.BoxSize;

                    var extrusionOrientedBoxes = new List <OrientedBox>();
                    for (int extrudeIndex = 0; extrudeIndex < tileConnectionTypeSettings.UpwardsExtrusionAmount; ++extrudeIndex)
                    {
                        extrudedBox.Center = nextTilePositionForUpwardsExtrusion + yOffsetVector;
                        extrusionOrientedBoxes.Add(new OrientedBox(extrudedBox));

                        nextTilePositionForUpwardsExtrusion += extrudeOffset;
                    }

                    // Handle downwards extrusion
                    extrudeOffset = -pathExtensionPlaneNormal *tileConnectionStack.GetBoxSizeAlongNormalizedDirection(pathExtensionPlaneNormal);

                    if (tileConnectionStack.IsGrowingDownwards)
                    {
                        nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(tileConnectionStack.NumberOfBoxes - 1).Center + extrudeOffset;
                    }
                    else
                    {
                        nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(0).Center + extrudeOffset;
                    }

                    for (int extrudeIndex = 0; extrudeIndex < tileConnectionTypeSettings.DownwardsExtrusionAmount; ++extrudeIndex)
                    {
                        extrudedBox.Center = nextTilePositionForUpwardsExtrusion + yOffsetVector;
                        extrusionOrientedBoxes.Add(new OrientedBox(extrudedBox));

                        nextTilePositionForUpwardsExtrusion += extrudeOffset;
                    }

                    return(extrusionOrientedBoxes);
                }
                else
                {
                    return(new List <OrientedBox>());
                }
            }
            else
            {
                return(new List <OrientedBox>());
            }
        }
        public void Update()
        {
            if (IsActive)
            {
                if (AllShortcutCombos.Instance.GrabRotateSelection.IsActive())
                {
                    _state = State.Rotating;
                }
                else if (AllShortcutCombos.Instance.GrabScaleSelection.IsActive())
                {
                    if (_state != State.Scaling)
                    {
                        _objectToWorldScale.Clear();
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject != null)
                            {
                                _objectToWorldScale.Add(grabbedObject, grabbedObject.transform.lossyScale);
                            }
                        }
                        _cursorPosAtScaleBegin = MouseCursor.Instance.Position;
                        _state = State.Scaling;
                    }
                }
                else
                {
                    // Need to reset the anchor relationships because the cursor was moved without
                    // the objects following it.
                    if (_state == State.Rotating || _state == State.Scaling)
                    {
                        _objectToPivotDir.Clear();
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject != null)
                            {
                                _objectToPivotDir.Add(grabbedObject, grabbedObject.transform.position - _surfaceHitPoint);
                            }
                        }
                    }
                    _state = State.Moving;
                }

                _currentCursorRayHit = GetCursorRayHit();
                if (!_currentCursorRayHit.WasAnythingHit)
                {
                    return;
                }

                if (_currentCursorRayHit.WasAnythingHit)
                {
                    if (_currentCursorRayHit.WasAnObjectHit)
                    {
                        _surfaceHitPoint = _currentCursorRayHit.ClosestObjectRayHit.HitPoint;
                    }
                    else
                    {
                        _surfaceHitPoint = _currentCursorRayHit.GridCellRayHit.HitPoint;
                    }
                }

                if (_state == State.Moving || _objectToSurfaceInfo.Count == 0)
                {
                    if (_currentCursorRayHit.WasAnObjectHit)
                    {
                        GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                        GameObjectRayHit objectRayHit = _currentCursorRayHit.ClosestObjectRayHit;
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject == null)
                            {
                                continue;
                            }

                            Transform objectTransform = grabbedObject.transform;
                            objectTransform.position = objectRayHit.HitPoint + _objectToPivotDir[grabbedObject];
                            if (objectRayHit.WasTerrainHit)
                            {
                                Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + Vector3.up, -Vector3.up);
                                GameObjectRayHit sitPointHit = null;
                                if (objectRayHit.HitObject.RaycastTerrainReverseIfFail(ray, out sitPointHit))
                                {
                                    Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint);
                                    if (_grabSettings.AlignAxis)
                                    {
                                        AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal);
                                    }
                                    grabbedObject.PlaceHierarchyOnPlane(surfacePlane);
                                    if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                                    {
                                        objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal;
                                    }
                                    if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis)
                                    {
                                        grabbedObject.EmbedInSurfaceByVertex(-Vector3.up, objectRayHit.HitObject);
                                    }

                                    ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo();
                                    surfaceInfo.SurfacePlane = surfacePlane;
                                    surfaceInfo.SitPoint     = sitPointHit.HitPoint;
                                    SetObjectSurfaceInfo(grabbedObject, surfaceInfo);
                                }
                            }
                            else
                            if (objectRayHit.WasMeshHit)
                            {
                                Ray ray = new Ray(grabbedObject.GetHierarchyWorldOrientedBox().Center + objectRayHit.HitNormal * 2.0f, -objectRayHit.HitNormal);
                                GameObjectRayHit sitPointHit = null;
                                if (objectRayHit.HitObject.RaycastMeshReverseIfFail(ray, out sitPointHit))
                                {
                                    Plane surfacePlane = new Plane(sitPointHit.HitNormal, sitPointHit.HitPoint);
                                    if (_grabSettings.AlignAxis)
                                    {
                                        AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, sitPointHit.HitNormal);
                                    }
                                    grabbedObject.PlaceHierarchyOnPlane(surfacePlane);
                                    if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                                    {
                                        objectTransform.position += _grabSettings.OffsetFromSurface * sitPointHit.HitNormal;
                                    }
                                    if (_grabSettings.EmbedInSurfaceWhenNoAlign && !_grabSettings.AlignAxis)
                                    {
                                        grabbedObject.EmbedInSurfaceByVertex(-sitPointHit.HitNormal, objectRayHit.HitObject);
                                    }

                                    ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo();
                                    surfaceInfo.SurfacePlane = surfacePlane;
                                    surfaceInfo.SitPoint     = sitPointHit.HitPoint;
                                    SetObjectSurfaceInfo(grabbedObject, surfaceInfo);
                                }
                            }
                        }
                    }
                    else
                    if (_currentCursorRayHit.WasACellHit)
                    {
                        GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                        GridCellRayHit cellRayHit = _currentCursorRayHit.GridCellRayHit;
                        foreach (var grabbedObject in _grabbedObjects)
                        {
                            if (grabbedObject == null)
                            {
                                continue;
                            }

                            Transform objectTransform = grabbedObject.transform;
                            objectTransform.position = cellRayHit.HitPoint + _objectToPivotDir[grabbedObject];

                            Plane   surfacePlane = new Plane(cellRayHit.HitNormal, cellRayHit.HitPoint);
                            Vector3 sitPoint     = surfacePlane.ProjectPoint(grabbedObject.GetWorldOrientedBox().Center);

                            if (_grabSettings.AlignAxis)
                            {
                                AxisAlignment.AlignObjectAxis(grabbedObject, _grabSettings.AlignmentAxis, cellRayHit.HitNormal);
                            }
                            grabbedObject.PlaceHierarchyOnPlane(surfacePlane);
                            if (!_grabSettings.EmbedInSurfaceWhenNoAlign || _grabSettings.AlignAxis)
                            {
                                objectTransform.position += _grabSettings.OffsetFromSurface * cellRayHit.HitNormal;
                            }

                            ObjectSurfaceInfo surfaceInfo = new ObjectSurfaceInfo();
                            surfaceInfo.SurfacePlane = surfacePlane;
                            surfaceInfo.SitPoint     = sitPoint;
                            SetObjectSurfaceInfo(grabbedObject, surfaceInfo);
                        }
                    }
                }
                else
                if (_state == State.Rotating)
                {
                    GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                    float rotationSensitivity = _grabSettings.RotationSensitivity;
                    foreach (var grabbedObject in _grabbedObjects)
                    {
                        if (!_objectToSurfaceInfo.ContainsKey(grabbedObject))
                        {
                            continue;
                        }

                        var         surfaceInfo = _objectToSurfaceInfo[grabbedObject];
                        OrientedBox worldOOBB   = grabbedObject.GetHierarchyWorldOrientedBox();
                        grabbedObject.RotateHierarchyBoxAroundPoint(MouseCursor.Instance.OffsetSinceLastMouseMove.x * rotationSensitivity, _grabSettings.AlignAxis ? surfaceInfo.SurfacePlane.normal : Vector3.up, worldOOBB.Center);
                    }
                }
                else
                if (_state == State.Scaling)
                {
                    GameObjectExtensions.RecordObjectTransformsForUndo(_grabbedObjects);
                    Vector2 currentCursorPos           = MouseCursor.Instance.Position;
                    Vector2 cursorOffsetFromScaleBegin = currentCursorPos - _cursorPosAtScaleBegin;

                    float scaleFactor = 1.0f + _grabSettings.ScaleSensitivity * cursorOffsetFromScaleBegin.x;
                    foreach (var grabbedObject in _grabbedObjects)
                    {
                        if (!_objectToSurfaceInfo.ContainsKey(grabbedObject) ||
                            !_objectToWorldScale.ContainsKey(grabbedObject))
                        {
                            continue;
                        }

                        var surfaceInfo = _objectToSurfaceInfo[grabbedObject];
                        grabbedObject.SetHierarchyWorldScaleByPivotPoint(_objectToWorldScale[grabbedObject] * scaleFactor, surfaceInfo.SitPoint);
                    }
                }
            }
        }
Exemple #14
0
        public List <ObjectPlacementData> Calculate()
        {
            if (_block == null || _block.NumberOfSegments == 0 || !ObjectPlacementGuide.ExistsInScene)
            {
                return(new List <ObjectPlacementData>());
            }

            Prefab     placementGuidePrefab        = ObjectPlacementGuide.Instance.SourcePrefab;
            Vector3    placementGuideWorldScale    = ObjectPlacementGuide.Instance.WorldScale;
            Quaternion placementGuideWorldRotation = ObjectPlacementGuide.Instance.WorldRotation;
            float      objectMissChance            = _block.Settings.ManualConstructionSettings.ObjectMissChance;
            ObjectRotationRandomizationSettings blockObjectRotationRandomizationSettings = _block.Settings.ManualConstructionSettings.ObjectRotationRandomizationSettings;
            bool           randomizeRotations = blockObjectRotationRandomizationSettings.RandomizeRotation;
            Vector3        objectOffsetAlongExtensionPlaneNormal = _block.Settings.ManualConstructionSettings.OffsetAlongGrowDirection * _block.ExtensionPlane.normal;
            bool           allowObjectIntersection = ObjectPlacementSettings.Get().ObjectIntersectionSettings.AllowIntersectionForBlockPlacement;
            bool           randomizePrefabs        = _block.Settings.ManualConstructionSettings.RandomizePrefabs;
            PrefabCategory activePrefabCategory    = PrefabCategoryDatabase.Get().ActivePrefabCategory;
            ObjectPlacementBlockProjectionSettings projectionSettings = _block.Settings.BlockProjectionSettings;
            bool canProject = projectionSettings.ProjectOnSurface &&
                              (projectionSettings.CanProjectOnMesh || projectionSettings.CanProjectOnTerrain);

            var objectPlacementDataInstances = new List <ObjectPlacementData>(_block.NumberOfSegments * 10);

            for (int segmentIndex = 0; segmentIndex < _block.NumberOfSegments; ++segmentIndex)
            {
                ObjectPlacementBoxStackSegment segment = _block.GetSegmentByIndex(segmentIndex);
                for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex)
                {
                    ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex);
                    if (stack.IsOverlappedByAnotherStack || stack.NumberOfBoxes == 0)
                    {
                        continue;
                    }

                    Vector3          projectionOffset     = Vector3.zero;
                    Vector3          projectionDirection  = Vector3.zero;
                    Quaternion       prjAlignRotation     = Quaternion.identity;
                    GameObjectRayHit projectionSurfaceHit = null;

                    if (canProject)
                    {
                        Vector3 rayOrigin = stack.GetBoxByIndex(0).Center;
                        Vector3 rayDir    = Vector3.zero;

                        if (projectionSettings.ProjectionDirection == ObjectBlockProjectionDir.BlockUp)
                        {
                            rayDir = _block.ExtensionPlane.normal;
                        }
                        else
                        {
                            rayDir = -_block.ExtensionPlane.normal;
                        }

                        projectionDirection = rayDir;

                        Ray ray = new Ray(rayOrigin, rayDir);
                        GameObjectRayHit closestMeshHit    = null;
                        GameObjectRayHit closestTerrainHit = null;

                        if (projectionSettings.CanProjectOnMesh)
                        {
                            closestMeshHit = Octave3DScene.Get().RaycastAllMeshClosest(ray);
                        }
                        if (projectionSettings.CanProjectOnTerrain)
                        {
                            closestTerrainHit = Octave3DScene.Get().RaycastAllTerainsClosest(ray);
                        }

                        // Ignore stack if no surface was found and non-projectables must be rejected
                        if (closestMeshHit == null && closestTerrainHit == null)
                        {
                            if (projectionSettings.RejectNonProjectables)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            projectionSurfaceHit = closestMeshHit;
                            if (closestMeshHit == null || (closestTerrainHit != null && closestMeshHit.HitEnter > closestTerrainHit.HitEnter))
                            {
                                projectionSurfaceHit = closestTerrainHit;
                            }
                        }

                        if (projectionSurfaceHit != null)
                        {
                            ObjectPlacementBox projectionBox = stack.GetBoxByIndex(0);
                            projectionOffset = projectionSurfaceHit.HitPoint - stack.GetBoxByIndex(0).Center;

                            if (projectionOffset.sqrMagnitude > (projectionSurfaceHit.HitPoint - stack.GetBoxByIndex(stack.NumberOfBoxes - 1).Center).sqrMagnitude)
                            {
                                projectionBox    = stack.GetBoxByIndex(stack.NumberOfBoxes - 1);
                                projectionOffset = projectionSurfaceHit.HitPoint - projectionBox.Center;
                            }

                            if (!projectionSettings.AlignToSurfaceNormal)
                            {
                                var     oobb      = projectionBox.OrientedBox;
                                Vector3 oldCenter = oobb.Center;
                                GameObjectExtensions.EmbedObjectBoxInSurface(oobb, projectionDirection, projectionSurfaceHit.HitObject);
                                projectionOffset = oobb.Center - oldCenter;
                            }
                        }
                    }

                    for (int stackBoxIndex = 0; stackBoxIndex < stack.NumberOfBoxes; ++stackBoxIndex)
                    {
                        ObjectPlacementBox box = stack.GetBoxByIndex(stackBoxIndex);
                        if (box.IsHidden)
                        {
                            continue;
                        }

                        if (ObjectPlacementMissChance.Missed(objectMissChance, ObjectPlacementBlockManualConstructionSettings.MinObjectMissChance,
                                                             ObjectPlacementBlockManualConstructionSettings.MaxObjectMissChance))
                        {
                            continue;
                        }

                        if (!allowObjectIntersection && ObjectQueries.IntersectsAnyObjectsInScene(box.OrientedBox, true))
                        {
                            continue;
                        }

                        Quaternion worldRotation = placementGuideWorldRotation;
                        if (randomizeRotations)
                        {
                            worldRotation = ObjectRotationRandomization.GenerateRandomRotationQuaternion(blockObjectRotationRandomizationSettings);
                        }

                        Vector3 worldScale = placementGuideWorldScale;
                        Prefab  prefab     = placementGuidePrefab;
                        if (randomizePrefabs && activePrefabCategory.NumberOfPrefabs != 0)
                        {
                            int    randomPrefabIndex = UnityEngine.Random.Range(0, activePrefabCategory.NumberOfPrefabs);
                            Prefab randomPrefab      = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex);
                            if (randomPrefab != null && randomPrefab.UnityPrefab != null)
                            {
                                prefab     = activePrefabCategory.GetPrefabByIndex(randomPrefabIndex);
                                worldScale = prefab.UnityPrefab.transform.lossyScale;
                            }
                        }

                        Vector3 boxCenter = box.Center + objectOffsetAlongExtensionPlaneNormal + projectionOffset;
                        if (projectionSurfaceHit != null)
                        {
                            if (projectionSettings.AlignToSurfaceNormal)
                            {
                                worldRotation = AxisAlignment.CalculateRotationQuaternionForAxisAlignment(worldRotation, projectionSettings.AlignmentAxis, projectionSurfaceHit.HitNormal);
                                OrientedBox prefabWorldOOBB = prefab.UnityPrefab.GetHierarchyWorldOrientedBox();
                                Vector3     oobbSize        = prefabWorldOOBB.ScaledSize;
                                int         axisIndex       = (int)((int)(projectionSettings.AlignmentAxis) * 0.5f);
                                boxCenter = projectionSurfaceHit.HitPoint + projectionSurfaceHit.HitNormal * oobbSize[axisIndex] * 0.5f + (oobbSize[axisIndex] * stackBoxIndex * projectionSurfaceHit.HitNormal);
                            }
                        }

                        var objectPlacementData = new ObjectPlacementData();
                        objectPlacementData.WorldPosition = ObjectPositionCalculator.CalculateObjectHierarchyPosition(prefab, boxCenter, worldScale, worldRotation);
                        objectPlacementData.WorldScale    = worldScale;
                        objectPlacementData.WorldRotation = worldRotation;
                        objectPlacementData.Prefab        = prefab;
                        objectPlacementDataInstances.Add(objectPlacementData);
                    }
                }
            }

            return(objectPlacementDataInstances);
        }
        private bool IsGameObjectFullyOverlappedByCircle(GameObject gameObject)
        {
            OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();

            return(IsWorldOrientedBoxFullyOverlappedByCircle(worldOrientedBox));
        }
Exemple #16
0
        public override void Render(List <GameObject> selectedObjects)
        {
            ObjectSelectionRenderSettings                   selectionRenderSettings                   = ObjectSelectionRenderSettings.Get();
            ObjectSelectionBoxRenderModeSettings            selectionBoxRenderModeSettings            = selectionRenderSettings.BoxRenderModeSettings;
            ObjectSelectionBoxCornerEdgesRenderModeSettings selectionBoxCornerEdgesRenderModeSettings = selectionBoxRenderModeSettings.CornerEdgesRenderModeSettings;

            Color boxColor  = selectionBoxRenderModeSettings.BoxColor;
            Color edgeColor = selectionBoxRenderModeSettings.EdgeColor;
            float boxScale  = selectionBoxRenderModeSettings.BoxScale;

            bool renderBoxes = boxColor.a != 0.0f;
            bool renderEdges = edgeColor.a != 0.0f;

            if (!renderBoxes && !renderEdges)
            {
                return;
            }

            // Note: Code duplication is intentional here in order to avoid further abstractions which may hinder performance.
            if (selectionBoxRenderModeSettings.EdgeRenderMode == ObjectSelectionBoxEdgeRenderMode.Wire)
            {
                if (renderBoxes && renderEdges)
                {
                    foreach (GameObject gameObject in selectedObjects)
                    {
                        if (!gameObject.activeInHierarchy)
                        {
                            continue;
                        }

                        OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();
                        if (worldOrientedBox.IsValid())
                        {
                            worldOrientedBox.Scale *= boxScale;
                            GizmosEx.RenderOrientedBox(worldOrientedBox, boxColor);
                            GizmosEx.RenderOrientedBoxEdges(worldOrientedBox, edgeColor);
                        }
                    }
                }
                else
                if (renderEdges && !renderBoxes)
                {
                    foreach (GameObject gameObject in selectedObjects)
                    {
                        if (!gameObject.activeInHierarchy)
                        {
                            continue;
                        }

                        OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();
                        if (worldOrientedBox.IsValid())
                        {
                            worldOrientedBox.Scale *= boxScale;
                            GizmosEx.RenderOrientedBoxEdges(worldOrientedBox, edgeColor);
                        }
                    }
                }
                else
                if (renderBoxes && !renderEdges)
                {
                    foreach (GameObject gameObject in selectedObjects)
                    {
                        if (!gameObject.activeInHierarchy)
                        {
                            continue;
                        }

                        OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();
                        if (worldOrientedBox.IsValid())
                        {
                            worldOrientedBox.Scale *= boxScale;
                            GizmosEx.RenderOrientedBox(worldOrientedBox, boxColor);
                        }
                    }
                }
            }
            else
            if (selectionBoxRenderModeSettings.EdgeRenderMode == ObjectSelectionBoxEdgeRenderMode.CornerEdges)
            {
                float cornerEdgeLengthPercentage = selectionBoxCornerEdgesRenderModeSettings.CornerEdgeLengthPercentage;
                if (renderBoxes && renderEdges)
                {
                    foreach (GameObject gameObject in selectedObjects)
                    {
                        if (!gameObject.activeInHierarchy)
                        {
                            continue;
                        }

                        OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();
                        if (worldOrientedBox.IsValid())
                        {
                            worldOrientedBox.Scale *= boxScale;
                            GizmosEx.RenderOrientedBox(worldOrientedBox, boxColor);
                            GizmosEx.RenderOrientedBoxCornerEdges(worldOrientedBox, cornerEdgeLengthPercentage, edgeColor);
                        }
                    }
                }
                else
                if (renderEdges && !renderBoxes)
                {
                    foreach (GameObject gameObject in selectedObjects)
                    {
                        if (!gameObject.activeInHierarchy)
                        {
                            continue;
                        }

                        OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();
                        if (worldOrientedBox.IsValid())
                        {
                            worldOrientedBox.Scale *= boxScale;
                            GizmosEx.RenderOrientedBoxCornerEdges(worldOrientedBox, cornerEdgeLengthPercentage, edgeColor);
                        }
                    }
                }
                else
                if (renderBoxes && !renderEdges)
                {
                    foreach (GameObject gameObject in selectedObjects)
                    {
                        if (!gameObject.activeInHierarchy)
                        {
                            continue;
                        }

                        OrientedBox worldOrientedBox = gameObject.GetWorldOrientedBox();
                        if (worldOrientedBox.IsValid())
                        {
                            worldOrientedBox.Scale *= boxScale;
                            GizmosEx.RenderOrientedBox(worldOrientedBox, boxColor);
                        }
                    }
                }
            }
        }
Exemple #17
0
 public MatrixObjectBoxPair(TransformMatrix objectMatrix, OrientedBox objectBox)
 {
     _objectMatrix = objectMatrix;
     _objectBox    = new OrientedBox(objectBox);
 }
Exemple #18
0
 public static bool IntersectsAnyObjectsInScene(OrientedBox orientedBox, List <GameObject> ignoreObjects, bool ignoreFaceTouch)
 {
     return(GetIntersectingObjects(orientedBox, ignoreObjects, ignoreFaceTouch).Count != 0);
 }
Exemple #19
0
 public void AddNodeToEnd(OrientedBox orientedBox, ObjectSurfaceData objectSurfaceData)
 {
     _nodes.Add(new ObjectNode(orientedBox, objectSurfaceData));
 }
Exemple #20
0
 public List <GameObject> OverlapBox(OrientedBox box)
 {
     return(_gameObjectSphereTree.OverlapBox(box));
 }
Exemple #21
0
        private MatrixObjectBoxPair CalculateMatrixObjectBoxPair(int brushElementIndex, ObjectSurfaceData objectSurfaceData)
        {
            // Store the needed data for easy access
            DecorPaintObjectPlacementBrushElement brushElement = _allValidBrushElements[brushElementIndex];
            OrientedBox objectBox = new OrientedBox(_brushElementsPrefabOrientedBoxes[brushElementIndex]);

            // Establish the object's scale. Randomize the scale if necessary. Otherwise, just use the brush element's scale.
            Vector3 xyzObjectBoxScale = _brushElementsPrefabWorldScaleValues[brushElementIndex];

            if (brushElement.ScaleRandomizationSettings.RandomizeScale)
            {
                // Generate a random scale factor and apply it to the current scale
                ObjectUniformScaleRandomizationSettings uniformScaleRandomizationSettings = brushElement.ScaleRandomizationSettings.UniformScaleRandomizationSettings;
                xyzObjectBoxScale *= UnityEngine.Random.Range(uniformScaleRandomizationSettings.MinScale, uniformScaleRandomizationSettings.MaxScale);;
            }
            else
            {
                xyzObjectBoxScale *= brushElement.Scale;
            }

            // Apply the scale that we have calculated
            objectBox.Scale = xyzObjectBoxScale;

            // Now we will calculate the rotation. First we will calculate a quaternion which allow us to take the
            // specified rotation offset into account. The quaternion rotates around the surface normal by an angle
            // of 'RotationOffset' degrees.
            Quaternion rotationOffset = brushElement.AlignToSurface ? Quaternion.AngleAxis(brushElement.RotationOffsetInDegrees, objectSurfaceData.SurfaceNormal) : Quaternion.identity;

            // If we need to align to stroke, we have some more work to do. Otherwise, we will just set the
            // rotation to be the same as the prefab's rotation, but offset by 'rotationOffset'.
            if (brushElement.AlignToStroke)
            {
                // First calculate the rotation without any offset. This is the rotation of the prefab plus the rotation which
                // must be applied for alignment.
                Quaternion rotationWithoutOffset = _rotationToApplyForStrokeAlignment * _elementToCurrentPrefabRotation[brushElement];

                // The rotation of the box must be set to the rotation which we just calculated (which ensures proper alingment) plus
                // the rotation offset.
                objectBox.Rotation = rotationOffset * rotationWithoutOffset;

                // Store the rotation inside the dictionary if an entry doesn't already exist
                if (!_elementToNewPrefabRotation.ContainsKey(brushElement))
                {
                    _elementToNewPrefabRotation.Add(brushElement, rotationWithoutOffset);
                }
            }
            else
            {
                objectBox.Rotation = rotationOffset * brushElement.Prefab.UnityPrefab.transform.rotation;
            }

            // Adjust the rotation of the object so that its axis is aligned with the placement surface if necessary
            if (brushElement.AlignToSurface)
            {
                AdjustObjectBoxRotationOnSurface(objectBox, objectSurfaceData, brushElement);
            }

            // The final step is to rotate the object by a random amount around the placement surface
            if (brushElement.RotationRandomizationMode != BrushElementRotationRandomizationMode.None)
            {
                Vector3 rotationAxis = objectSurfaceData.SurfaceNormal;
                if (brushElement.RotationRandomizationMode == BrushElementRotationRandomizationMode.X)
                {
                    rotationAxis = Vector3.right;
                }
                else if (brushElement.RotationRandomizationMode == BrushElementRotationRandomizationMode.Y)
                {
                    rotationAxis = Vector3.up;
                }
                else if (brushElement.RotationRandomizationMode == BrushElementRotationRandomizationMode.Z)
                {
                    rotationAxis = Vector3.forward;
                }

                if (!brushElement.AlignToStroke)
                {
                    // When stroke alignment is not required, we will generate a random rotation angle and apply it
                    // to the current box rotation.
                    float      randomRotationAngle = UnityEngine.Random.Range(0.0f, 360.0f);
                    Quaternion additionalRotation  = Quaternion.AngleAxis(randomRotationAngle, rotationAxis);
                    objectBox.Rotation = additionalRotation * objectBox.Rotation;
                }
                else
                {
                    // When both rotation randomization and stroke alingment are turned on, we will proudce a small
                    // random rotation offset to randomize the alingmnet a little bit.
                    float      randomRotationAngle = UnityEngine.Random.Range(0.0f, 25.0f);
                    Quaternion additionalRotation  = Quaternion.AngleAxis(randomRotationAngle, rotationAxis);
                    objectBox.Rotation = additionalRotation * objectBox.Rotation;
                }
            }

            // Place the object on the surface
            AdjustObjectBoxCenterToSitOnSurface(objectBox, objectSurfaceData, brushElement);

            // Construct the object matrix and return the object/marix pair
            TransformMatrix objectMatrix = new TransformMatrix(ObjectPositionCalculator.CalculateObjectHierarchyPosition(brushElement.Prefab,
                                                                                                                         objectBox.Center, xyzObjectBoxScale, objectBox.Rotation), objectBox.Rotation, xyzObjectBoxScale);

            return(new MatrixObjectBoxPair(objectMatrix, objectBox));
        }
Exemple #22
0
 public List <Vector3> GetOverlappedWorldVerts(OrientedBox box, TransformMatrix meshTransformMatrix)
 {
     return(_meshSphereTree.GetOverlappedWorldVerts(box, meshTransformMatrix));
 }
Exemple #23
0
        private void AdjustGuidePivotPoints()
        {
            OrientedBox guideHierarchyWorldOrientedBox = ObjectPlacementGuide.SceneObject.GetHierarchyWorldOrientedBox();

            ObjectPlacement.Get().ProjectedGuidePivotPoints.FromOrientedBoxAndDecorStrokeSurface(guideHierarchyWorldOrientedBox, _strokeSurface);
        }
Exemple #24
0
 public List <Triangle3D> GetOverlappedTriangles(OrientedBox box, TransformMatrix meshTransformMatrix)
 {
     return(_meshSphereTree.GetOverlappedWorldTriangles(box, meshTransformMatrix));
 }
Exemple #25
0
 public OrientedBox MirrorOrientedBox(OrientedBox orientedBox)
 {
     return(Mirroring.MirrorOrientedBox(_mirror.WorldPlane, orientedBox, _mirrorRotation));
 }
 public ObjectPlacementBox(ObjectPlacementBox source)
 {
     _orientedBox = source.OrientedBox;
 }
 public Octave3DBoxCollider(OrientedBox orientedBox)
 {
     _orientedBox = new OrientedBox(orientedBox);
 }
Exemple #28
0
        public bool OverlapsFullyOrPartially(OrientedBox orientedBox)
        {
            Vector3 closestPointToSphereCenter = orientedBox.GetClosestPointToPoint(_center);

            return((closestPointToSphereCenter - _center).sqrMagnitude <= _radius * _radius);
        }
Exemple #29
0
        /// <summary>
        /// Returns the world space vertices overlapped by the specified box.
        /// </summary>
        public List <Vector3> GetOverlappedWorldVerts(OrientedBox box, TransformMatrix meshTransformMatrix)
        {
            // If the tree was not yet build, we need to build it because we need
            // the triangle information in order to perform the raycast.
            if (!_wasBuilt)
            {
                Build();
            }

            // Work in mesh model space because the tree data exists in model space
            OrientedBox meshSpaceOOBB    = new OrientedBox(box);
            Matrix4x4   inverseTransform = meshTransformMatrix.ToMatrix4x4x.inverse;

            meshSpaceOOBB.Transform(inverseTransform);

            // Used to avoid duplicate indices since there can be triangles which share the same vertices
            // and we don't want to return the same vertex multiple times.
            HashSet <int> usedIndices = new HashSet <int>();

            // Retrieve the nodes overlapped by the specified box
            List <SphereTreeNode <MeshSphereTreeTriangle> > overlappedNodes = _sphereTree.OverlapBox(meshSpaceOOBB);

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

            // Loop through all nodes
            var overlappedWorldVerts = new List <Vector3>(50);

            foreach (var node in overlappedNodes)
            {
                // Get the triangle associated with the node
                int triangleIndex = node.Data.TriangleIndex;

                MeshTriangleInfo triangleInfo   = _octave3DMesh.GetMeshTriangleInfo(triangleIndex);
                List <Vector3>   trianglePoints = triangleInfo.ModelSpaceTriangle.GetPoints();

                for (int ptIndex = 0; ptIndex < trianglePoints.Count; ++ptIndex)
                {
                    if (usedIndices.Contains(triangleInfo.VertIndices[ptIndex]))
                    {
                        continue;
                    }

                    Vector3 point = trianglePoints[ptIndex];
                    if (meshSpaceOOBB.ContainsPoint(point))
                    {
                        overlappedWorldVerts.Add(meshTransformMatrix.MultiplyPoint(point));
                        usedIndices.Add(triangleInfo.VertIndices[ptIndex]);
                    }
                }

                /*Triangle3D modelSpaceTriangle = _octave3DMesh.GetTriangle(triangleIndex);
                 *
                 * // Now check which of the triangle points resides inside the box
                 * List<Vector3> trianglePoints = modelSpaceTriangle.GetPoints();
                 * foreach(var pt in trianglePoints)
                 * {
                 *  // When a point resides inside the box, we will transform it in world space and add it to the final point list
                 *  if (box.ContainsPoint(pt)) overlappedWorldVerts.Add(meshTransformMatrix.MultiplyPoint(pt));
                 * }*/
            }

            return(overlappedWorldVerts);
        }
Exemple #30
0
        public bool FullyContainsOrientedBoxCenterAndCornerPointsInScreenSpace(OrientedBox orientedBox, Camera camera)
        {
            List <Vector2> boxCenterAndCornerScreenPoints = orientedBox.GetScreenCenterAndCornerPoints(camera);

            return(ContainsAllPoints(boxCenterAndCornerScreenPoints));
        }