예제 #1
0
        public void Render()
        {
            if (SharedLookAndFeel == null)
            {
                return;
            }

            if (IsActive && _grabSurfaceInfo.SurfaceType != GrabSurfaceType.Invalid)
            {
                Material material = MaterialPool.Get.SimpleColor;
                if (SharedLookAndFeel.DrawAnchorLines)
                {
                    var linePoints = new List <Vector3>(_grabTargets.Count * 2);
                    foreach (var 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);

                    var boundsQConfig = GetObjectBoundsQConfig();
                    foreach (var 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 (var 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);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Renders a wire box with lines meeting at corners.
        /// </summary>
        /// <param name="wireCornerLinePercentage">
        /// Can have values in the [0, 1] interval and it controls the length of the
        /// corner lines. A value of 0 draws lines of length 0 and a value of 1
        /// draws lines of length equal to half the box length along a certain axis.
        /// </param>
        public static void DrawWireCornerBox(OBB box, float wireCornerLinePercentage)
        {
            // Store these for easy access
            Mesh           wireCornerLineMesh = MeshPool.Get.UnitCoordSystem;
            List <Vector3> boxCorners         = box.GetCornerPoints();

            // Clamp percentage
            wireCornerLinePercentage = Mathf.Clamp(wireCornerLinePercentage, 0.0f, 1.0f);

            // Front bottom left point
            Vector3   originalScale   = box.Extents * wireCornerLinePercentage;
            Vector3   scale           = originalScale;
            Vector3   position        = boxCorners[(int)BoxCorner.FrontBottomLeft];
            Matrix4x4 transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);

            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Front bottom right point
            position        = boxCorners[(int)BoxCorner.FrontBottomRight];
            scale.x        *= -1.0f;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Front top right point
            position        = boxCorners[(int)BoxCorner.FrontTopRight];
            scale.y        *= -1.0f;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Front top left point
            position        = boxCorners[(int)BoxCorner.FrontTopLeft];
            scale           = originalScale;
            scale.y        *= -1.0f;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Back bottom left point
            position        = boxCorners[(int)BoxCorner.BackBottomLeft];
            scale.y         = originalScale.y;
            scale.x        *= -1.0f;
            scale.z        *= -1.0f;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Back bottom right point
            position        = boxCorners[(int)BoxCorner.BackBottomRight];
            scale.x         = originalScale.x;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Back top right point
            position        = boxCorners[(int)BoxCorner.BackTopRight];
            scale.y        *= -1.0f;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);

            // Back top left point
            position        = boxCorners[(int)BoxCorner.BackTopLeft];
            scale.x        *= -1.0f;
            transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale);
            Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix);
        }
예제 #3
0
 public bool IntersectsOBB(OBB otherOBB)
 {
     return(BoxMath.BoxIntersectsBox(_center, _size, _rotation, otherOBB.Center, otherOBB.Size, otherOBB.Rotation));
 }
예제 #4
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);
        }
예제 #5
0
 public static void DrawWireBox(OBB box)
 {
     Graphics.DrawMeshNow(MeshPool.Get.UnitWireBox, box.GetUnitBoxTransform());
 }
예제 #6
0
        public static SnapResult CalculateSnapResult(GameObject root, Config snapConfig)
        {
            if (snapConfig.IgnoreDestObjects == null)
            {
                snapConfig.IgnoreDestObjects = new List <GameObject>();
            }

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

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

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

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

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

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

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

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

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

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

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

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

                            sortData.FaceAreasMatch = false;

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

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

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

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

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

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

                return(new SnapResult(sortedSnapData[0].SnapPivot, sortedSnapData[0].SnapDest, sortedSnapData[0].SnapDistance));
            }
            return(new SnapResult(SnapFailReson.NoDestinationFound));
        }
예제 #7
0
        public static List <Vector3> CollectWorldSpriteVerts(Sprite sprite, Transform spriteTransform, OBB collectOBB)
        {
            List <Vector3> spriteWorldVerts = sprite.GetWorldVerts(spriteTransform);
            List <Vector3> collectedVerts   = new List <Vector3>(7);

            foreach (Vector3 vertPos in spriteWorldVerts)
            {
                if (BoxMath.ContainsPoint(vertPos, collectOBB.Center, collectOBB.Size, collectOBB.Rotation))
                {
                    collectedVerts.Add(vertPos);
                }
            }

            return(collectedVerts);
        }
예제 #8
0
        protected bool GetWorldPointClosestToInputDevice(Camera focusCamera, IEnumerable <GameObject> gameObjects, out Vector3 point)
        {
            point = Vector3.zero;
            if (gameObjects == null)
            {
                return(false);
            }
            if (!RTInputDevice.Get.Device.HasPointer())
            {
                return(false);
            }

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

            bool foundPoint = false;

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

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

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

            return(foundPoint);
        }
예제 #9
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());
        }
예제 #10
0
        public List <GameObjectRayHit> RaycastAll(Ray ray, SceneRaycastPrecision raycastPresicion)
        {
            List <SphereTreeNodeRayHit <GameObject> > nodeHits = _objectTree.RaycastAll(ray);

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

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

            Vector3 camLook = RTFocusCamera.Get.Look;

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

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

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

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

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

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

                return(hitList);
            }

            return(new List <GameObjectRayHit>());
        }
예제 #11
0
 public void FromOBB(OBB obb)
 {
     Center   = obb.Center;
     Size     = obb.Size;
     Rotation = obb.Rotation;
 }
        public void Render()
        {
            if (_sharedLookAndFeel == null)
            {
                return;
            }

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

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

                    ObjectBounds.QueryConfig boundsQConfig = GetObjectBoundsQConfig();
                    foreach (GameObject targetObject in _targetObjects)
                    {
                        if (targetObject == null)
                        {
                            continue;
                        }

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

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

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

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

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

                    if (_sharedLookAndFeel.DrawPivotBorder)
                    {
                        material.SetColor(_sharedLookAndFeel.PivotPointBorderColor);
                        material.SetPass(0);
                        GLRenderer.DrawRectBorder2D(pivotRect, camera);
                    }
                }
            }
        }