Exemple #1
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);
        }
Exemple #2
0
 public bool OverlapModelVerts(OBB modelOBB, List <Vector3> verts)
 {
     return(_meshTree.OverlapModelVerts(modelOBB, verts));
 }
Exemple #3
0
 public static void DrawWireBox(OBB box)
 {
     Graphics.DrawMeshNow(MeshPool.Get.UnitWireBox, box.GetUnitBoxTransform());
 }
        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));
            }

            var 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;

            var 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);
                        var     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);
                            var     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);
                            var     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);
                                var     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);
                        var     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());
        }
Exemple #5
0
 public bool OverlapVerts(OBB obb, Transform meshObjectTransform, List <Vector3> verts)
 {
     return(_meshTree.OverlapVerts(obb, new MeshTransform(meshObjectTransform), verts));
 }
 public bool IntersectsOBB(OBB otherOBB)
 {
     return(BoxMath.BoxIntersectsBox(_center, _size, _rotation, otherOBB.Center, otherOBB.Size, otherOBB.Rotation));
 }
Exemple #7
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);
        }
 public List <Vector3> OverlapModelVerts(OBB modelOBB)
 {
     return(_meshTree.OverlapModelVerts(modelOBB));
 }
 public List <Vector3> OverlapVerts(OBB obb, Transform meshObjectTransform)
 {
     return(_meshTree.OverlapVerts(obb, new MeshTransform(meshObjectTransform)));
 }
Exemple #10
0
 public void FromOBB(OBB obb)
 {
     Center   = obb.Center;
     Size     = obb.Size;
     Rotation = obb.Rotation;
 }
        public static List <Vector3> CollectHierarchyVerts(GameObject root, BoxFace collectFace, float collectBoxScale, float collectEps)
        {
            var meshObjects   = root.GetMeshObjectsInHierarchy();
            var spriteObjects = root.GetSpriteObjectsInHierarchy();

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

            var 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;

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

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

                rtMesh.OverlapVerts(collectOBB, meshObject.transform, _hierarchyVertsCollectBuffer);
                if (_hierarchyVertsCollectBuffer.Count != 0)
                {
                    collectedVerts.AddRange(_hierarchyVertsCollectBuffer);
                }
            }

            foreach (var spriteObject in spriteObjects)
            {
                var verts = CollectWorldSpriteVerts(spriteObject.GetSprite(), spriteObject.transform, collectOBB);
                if (verts.Count != 0)
                {
                    collectedVerts.AddRange(verts);
                }
            }

            return(collectedVerts);
        }
        public static List <Vector3> CollectWorldSpriteVerts(Sprite sprite, Transform spriteTransform, OBB collectOBB)
        {
            var spriteWorldVerts = sprite.GetWorldVerts(spriteTransform);
            var collectedVerts   = new List <Vector3>(7);

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

            return(collectedVerts);
        }