public GameObjectRayHit RaycastMeshObject(Ray ray, GameObject gameObject)
        {
            Mesh   objectMesh = gameObject.GetMesh();
            RTMesh rtMesh     = RTMeshDb.Get.GetRTMesh(objectMesh);

            if (rtMesh != null)
            {
                MeshRayHit meshRayHit = rtMesh.Raycast(ray, gameObject.transform.localToWorldMatrix);
                if (meshRayHit != null)
                {
                    return(new GameObjectRayHit(ray, gameObject, meshRayHit));
                }
            }
            else
            {
                // If no RTMesh instance is available, we will cast a ray against
                // the object's MeshCollider as a last resort. This is actually useful
                // when dealing with static mesh objects. These objects' meshes have
                // their 'isReadable' flag set to false and can not be used to create
                // an RTMesh instance. Thus a mesh collider is the next best choice.
                MeshCollider meshCollider = gameObject.GetComponent <MeshCollider>();
                if (meshCollider != null)
                {
                    RaycastHit rayHit;
                    if (meshCollider.Raycast(ray, out rayHit, float.MaxValue))
                    {
                        return(new GameObjectRayHit(ray, rayHit));
                    }
                }
            }

            return(null);
        }
Exemple #2
0
 public bool Contains(RTMesh rtMesh)
 {
     if (rtMesh == null)
     {
         return(false);
     }
     return(_meshes.ContainsKey(rtMesh.UnityMesh));
 }
Exemple #3
0
        public void SetMeshDirty(Mesh unityMesh)
        {
            RTMesh rtMesh = null;

            if (_meshes.TryGetValue(unityMesh, out rtMesh))
            {
                rtMesh.SetDirty();
            }
        }
Exemple #4
0
        /// <summary>
        /// Creates an RTMesh from the passed Unity mesh. The method returns the
        /// RTMesh instance or null if the mesh can not be created.
        /// </summary>
        /// <remarks>
        /// The client code is responsible for calling 'BuildTree' for the returned
        /// mesh.
        /// </remarks>
        private RTMesh CreateRTMesh(Mesh unityMesh)
        {
            RTMesh rtMesh = RTMesh.Create(unityMesh);

            if (rtMesh != null)
            {
                _meshes.Add(unityMesh, rtMesh);
                return(rtMesh);
            }
            else
            {
                return(null);
            }
        }
        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;
                }

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

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

            return(collectedVerts);
        }
Exemple #6
0
 public MeshTree(RTMesh mesh)
 {
     _mesh = mesh;
 }
        private List <AABB> BuildVertOverlapAABBs(GameObject gameObject, Sprite sprite, RTMesh rtMesh)
        {
            if (sprite == null && rtMesh == null)
            {
                return(new List <AABB>());
            }

            const float overlapAmount     = 0.2f;
            float       halfOverlapAmount = overlapAmount * 0.5f;
            AABB        modelAABB         = sprite != null?ObjectBounds.CalcSpriteModelAABB(gameObject) : rtMesh.AABB;

            Vector3        modelAABBSize  = modelAABB.Size;
            List <BoxFace> modelAABBFaces = BoxMath.AllBoxFaces;

            const float sizeEps = 0.001f;

            Vector3[] overlapAABBSizes = new Vector3[modelAABBFaces.Count];
            overlapAABBSizes[(int)BoxFace.Left]   = new Vector3(overlapAmount, modelAABBSize.y + sizeEps, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Right]  = new Vector3(overlapAmount, modelAABBSize.y + sizeEps, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Bottom] = new Vector3(modelAABBSize.x + sizeEps, overlapAmount, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Top]    = new Vector3(modelAABBSize.x + sizeEps, overlapAmount, modelAABBSize.z + sizeEps);
            overlapAABBSizes[(int)BoxFace.Back]   = new Vector3(modelAABBSize.x + sizeEps, modelAABBSize.y + sizeEps, overlapAmount);
            overlapAABBSizes[(int)BoxFace.Front]  = new Vector3(modelAABBSize.x + sizeEps, modelAABBSize.y + sizeEps, overlapAmount);

            var overlapAABBs = new List <AABB>();

            for (int boxFaceIndex = 0; boxFaceIndex < modelAABBFaces.Count; ++boxFaceIndex)
            {
                BoxFace modelAABBFace = modelAABBFaces[boxFaceIndex];
                Vector3 faceCenter    = BoxMath.CalcBoxFaceCenter(modelAABB.Center, modelAABB.Size, Quaternion.identity, modelAABBFace);
                Vector3 faceNormal    = BoxMath.CalcBoxFaceNormal(modelAABB.Center, modelAABB.Size, Quaternion.identity, modelAABBFace);
                Vector3 overlapCenter = faceCenter - faceNormal * halfOverlapAmount;
                overlapAABBs.Add(new AABB(overlapCenter, overlapAABBSizes[boxFaceIndex]));
            }

            return(overlapAABBs);
        }
        public bool Initialize(GameObject gameObject)
        {
            if (gameObject == null || _gameObject != null)
            {
                return(false);
            }

            Mesh   mesh   = gameObject.GetMesh();
            Sprite sprite = gameObject.GetSprite();

            if (mesh == null && sprite == null)
            {
                return(false);
            }

            bool useMesh = true;

            if (mesh == null)
            {
                useMesh = false;
            }

            RTMesh rtMesh = null;

            if (useMesh)
            {
                Renderer meshRenderer = gameObject.GetMeshRenderer();
                if (meshRenderer == null || !meshRenderer.enabled)
                {
                    useMesh = false;
                }

                rtMesh = RTMeshDb.Get.GetRTMesh(mesh);
                if (rtMesh == null)
                {
                    useMesh = false;
                }
            }
            if (rtMesh == null && sprite == null)
            {
                return(false);
            }

            List <AABB> vertOverlapAABBs = BuildVertOverlapAABBs(gameObject, useMesh ? null : sprite, useMesh ? rtMesh : null);

            if (vertOverlapAABBs.Count == 0)
            {
                return(false);
            }

            AABB modelAABB = useMesh ? rtMesh.AABB : ObjectBounds.CalcSpriteModelAABB(gameObject);
            var  aabbFaces = BoxMath.AllBoxFaces;

            _gameObject = gameObject;
            if (useMesh)
            {
                foreach (var aabbFace in aabbFaces)
                {
                    AABB           overlapAABB     = vertOverlapAABBs[(int)aabbFace];
                    List <Vector3> overlappedVerts = rtMesh.OverlapModelVerts(overlapAABB);
                    Plane          facePlane       = BoxMath.CalcBoxFacePlane(modelAABB.Center, modelAABB.Size, Quaternion.identity, aabbFace);
                    overlappedVerts = facePlane.ProjectAllPoints(overlappedVerts);
                    _snapAreaBounds[(int)aabbFace] = new AABB(overlappedVerts);
                    _snapAreaDesc[(int)aabbFace]   = BoxMath.GetBoxFaceAreaDesc(_snapAreaBounds[(int)aabbFace].Size, aabbFace);
                }
            }
            else
            {
                foreach (var aabbFace in aabbFaces)
                {
                    if (aabbFace != BoxFace.Front && aabbFace != BoxFace.Back)
                    {
                        AABB           overlapAABB     = vertOverlapAABBs[(int)aabbFace];
                        List <Vector3> overlappedVerts = ObjectVertexCollect.CollectModelSpriteVerts(sprite, overlapAABB);
                        Plane          facePlane       = BoxMath.CalcBoxFacePlane(modelAABB.Center, modelAABB.Size, Quaternion.identity, aabbFace);
                        overlappedVerts = facePlane.ProjectAllPoints(overlappedVerts);
                        _snapAreaBounds[(int)aabbFace] = new AABB(overlappedVerts);
                        _snapAreaDesc[(int)aabbFace]   = BoxMath.GetBoxFaceAreaDesc(_snapAreaBounds[(int)aabbFace].Size, aabbFace);
                    }
                    else
                    {
                        _snapAreaBounds[(int)aabbFace] = AABB.GetInvalid();
                        _snapAreaDesc[(int)aabbFace]   = BoxFaceAreaDesc.GetInvalid();
                    }
                }
            }

            return(true);
        }