예제 #1
0
        /// <summary>
        /// Returns the mesh managers suitable for a shadow.
        /// </summary>
        /// <param name="shadow">
        /// The shadow to get mesh manager for.
        /// </param>
        /// <returns>
        /// The <see cref="ShadowMeshManager"/>.
        /// </returns>
        private ShadowMeshManager GetMeshManager(SwiftShadow shadow)
        {
            ShadowMeshManager meshManager;

            if (_meshManagers.TryGetValue(shadow.GetMeshManagerHashCode(), out meshManager))
            {
                return(meshManager);
            }

            if (shadow.Material == null)
            {
                throw new ArgumentNullException("shadow.material");
            }

            if (_meshManagersNew.TryGetValue(shadow.GetMeshManagerHashCode(), out meshManager))
            {
                return(meshManager);
            }

            meshManager = new ShadowMeshManager(shadow.Material, shadow.Layer, shadow.IsStatic);
            if (_isRecalculatingMesh)
            {
                _meshManagersNew.Add(meshManager.GetInstanceHashCode(), meshManager);
            }
            else
            {
                _meshManagers.Add(meshManager.GetInstanceHashCode(), meshManager);
            }

            return(meshManager);
        }
예제 #2
0
        /// <summary>
        /// Recalculates the geometry of every attached shadow and builds a batched mesh.
        /// </summary>
        /// <param name="frustumPlanes">
        /// The frustum planes of camera that renders the scene.
        /// Ignored when recalculating static shadows.
        /// </param>
        /// <param name="skipRecalculate">
        /// Whether to skip recalculation of shadow geometry.
        /// </param>
        private void RecalculateGeometry(Plane[] frustumPlanes, bool skipRecalculate)
        {
            // No need to rebuild static mesh when it hasn't changed
            bool mustRebuildMesh = !_isStatic || _isStaticDirty;

            int currentVisibleShadowsCount = 0;

            if (_isStatic)
            {
                frustumPlanes = null;
            }

            for (int i = 0, shadowCount = _shadowsList.Count; i < shadowCount; i++)
            {
                SwiftShadow shadow = _shadowsList.Items[i];
                if (!skipRecalculate)
                {
                    SwiftShadow.RecalculateShadowResult recalculateResult = shadow.RecalculateShadow(frustumPlanes, false);
                    switch (recalculateResult)
                    {
                    case SwiftShadow.RecalculateShadowResult.ChangedManager:
                        i--;
                        shadowCount = _shadowsList.Count;
                        continue;

                    case SwiftShadow.RecalculateShadowResult.Recalculated:
                        mustRebuildMesh = true;
                        break;
                    }
                }

                if (shadow.IsVisible)
                {
                    currentVisibleShadowsCount++;
                }
            }

            if (!mustRebuildMesh || (_visibleShadowsCount == 0 && currentVisibleShadowsCount == 0))
            {
                return;
            }

            _visibleShadowsCount = currentVisibleShadowsCount;

            if (_visibleShadowsCount != 0)
            {
                bool isMeshNull = _mesh == null;
                if (isMeshNull)
                {
                    CreateMesh();
                }

                RebuildMesh(isMeshNull || _isStatic || _isStaticDirty);
                _isStaticDirty = false;
            }

            _lastVisibleShadowsCount = _visibleShadowsCount;
        }
예제 #3
0
        /// <summary>
        /// Registers the shadow in this manager.
        /// </summary>
        /// <param name="shadow">
        /// The shadow to register.
        /// </param>
        public void RegisterShadow(SwiftShadow shadow)
        {
            if (_isStatic)
            {
                shadow.RecalculateShadow(null, true);
            }

            _shadowsList.Add(shadow);
            _isStaticDirty = true;
        }
예제 #4
0
        /// <summary>
        /// Unregisters the shadow.
        /// </summary>
        /// <param name="shadow">
        /// The shadow to unregister.
        /// </param>
        public void UnregisterShadow(SwiftShadow shadow)
        {
            ShadowMeshManager meshManager;
            int shadowHash = shadow.GetMeshManagerHashCode();

            if (_meshManagers.TryGetValue(shadowHash, out meshManager))
            {
                meshManager.UnregisterShadow(shadow);
            }
        }
예제 #5
0
        /// <summary>
        /// Rebuilds the batched mesh.
        /// </summary>
        /// <param name="forceRebuildTriangles">
        /// Whether to force the rebuild of vertex indices.
        /// </param>
        private void RebuildMesh(bool forceRebuildTriangles)
        {
            bool mustRebuildTriangles =
                forceRebuildTriangles ||
                _lastVisibleShadowsCount != _visibleShadowsCount;

            _meshData.EnsureCapacity(_visibleShadowsCount);

            Vector3 meshBoundsMin;

            meshBoundsMin.x = float.MaxValue;
            meshBoundsMin.y = float.MaxValue;
            meshBoundsMin.z = float.MaxValue;
            Vector3 meshBoundsMax;

            meshBoundsMax.x = float.MinValue;
            meshBoundsMax.y = float.MinValue;
            meshBoundsMax.z = float.MinValue;
            int index         = 1;
            int triangleIndex = 0;

            for (int i = 0, shadowsCount = _shadowsList.Count; i < shadowsCount; i++)
            {
                SwiftShadow shadow = _shadowsList.Items[i];
                if (!shadow.IsVisible)
                {
                    continue;
                }

                Vector3[] shadowVertices = shadow.ShadowVertices;
#if SET_MESH_NORMALS
                Vector3 normal = shadow.Normal;
#endif
                Vector2[] textureUV = shadow.TextureUV;
                Color32   color32   = shadow.CurrentColor;

                _meshData.Vertices[index]     = shadowVertices[0];
                _meshData.Vertices[index + 1] = shadowVertices[1];
                _meshData.Vertices[index + 2] = shadowVertices[2];
                _meshData.Vertices[index + 3] = shadowVertices[3];

                // Calculate min/max X
                if (shadowVertices[0].x < meshBoundsMin.x)
                {
                    meshBoundsMin.x = shadowVertices[0].x;
                }
                else if (shadowVertices[0].x > meshBoundsMax.x)
                {
                    meshBoundsMax.x = shadowVertices[0].x;
                }
                if (shadowVertices[1].x < meshBoundsMin.x)
                {
                    meshBoundsMin.x = shadowVertices[1].x;
                }
                else if (shadowVertices[1].x > meshBoundsMax.x)
                {
                    meshBoundsMax.x = shadowVertices[1].x;
                }
                if (shadowVertices[2].x < meshBoundsMin.x)
                {
                    meshBoundsMin.x = shadowVertices[2].x;
                }
                else if (shadowVertices[2].x > meshBoundsMax.x)
                {
                    meshBoundsMax.x = shadowVertices[2].x;
                }
                if (shadowVertices[3].x < meshBoundsMin.x)
                {
                    meshBoundsMin.x = shadowVertices[3].x;
                }
                else if (shadowVertices[3].x > meshBoundsMax.x)
                {
                    meshBoundsMax.x = shadowVertices[3].x;
                }

                // Calculate min/max Y
                if (shadowVertices[0].y < meshBoundsMin.y)
                {
                    meshBoundsMin.y = shadowVertices[0].y;
                }
                else if (shadowVertices[0].y > meshBoundsMax.y)
                {
                    meshBoundsMax.y = shadowVertices[0].y;
                }
                if (shadowVertices[1].y < meshBoundsMin.y)
                {
                    meshBoundsMin.y = shadowVertices[1].y;
                }
                else if (shadowVertices[1].y > meshBoundsMax.y)
                {
                    meshBoundsMax.y = shadowVertices[1].y;
                }
                if (shadowVertices[2].y < meshBoundsMin.y)
                {
                    meshBoundsMin.y = shadowVertices[2].y;
                }
                else if (shadowVertices[2].y > meshBoundsMax.y)
                {
                    meshBoundsMax.y = shadowVertices[2].y;
                }
                if (shadowVertices[3].y < meshBoundsMin.y)
                {
                    meshBoundsMin.y = shadowVertices[3].y;
                }
                else if (shadowVertices[3].y > meshBoundsMax.y)
                {
                    meshBoundsMax.y = shadowVertices[3].y;
                }

                // Calculate min/max Z
                if (shadowVertices[0].z < meshBoundsMin.z)
                {
                    meshBoundsMin.z = shadowVertices[0].z;
                }
                else if (shadowVertices[0].z > meshBoundsMax.z)
                {
                    meshBoundsMax.z = shadowVertices[0].z;
                }
                if (shadowVertices[1].z < meshBoundsMin.z)
                {
                    meshBoundsMin.z = shadowVertices[1].z;
                }
                else if (shadowVertices[1].z > meshBoundsMax.z)
                {
                    meshBoundsMax.z = shadowVertices[1].z;
                }
                if (shadowVertices[2].z < meshBoundsMin.z)
                {
                    meshBoundsMin.z = shadowVertices[2].z;
                }
                else if (shadowVertices[2].z > meshBoundsMax.z)
                {
                    meshBoundsMax.z = shadowVertices[2].z;
                }
                if (shadowVertices[3].z < meshBoundsMin.z)
                {
                    meshBoundsMin.z = shadowVertices[3].z;
                }
                else if (shadowVertices[3].z > meshBoundsMax.z)
                {
                    meshBoundsMax.z = shadowVertices[3].z;
                }

                _meshData.UV[index]     = textureUV[0];
                _meshData.UV[index + 1] = textureUV[1];
                _meshData.UV[index + 2] = textureUV[2];
                _meshData.UV[index + 3] = textureUV[3];

#if SET_MESH_NORMALS
                _meshData.Normals[index]     = normal;
                _meshData.Normals[index + 1] = normal;
                _meshData.Normals[index + 2] = normal;
                _meshData.Normals[index + 3] = normal;
#endif

                _meshData.Colors32[index]     = color32;
                _meshData.Colors32[index + 1] = color32;
                _meshData.Colors32[index + 2] = color32;
                _meshData.Colors32[index + 3] = color32;

                if (mustRebuildTriangles)
                {
                    _meshData.Indices[triangleIndex]     = index + 0;
                    _meshData.Indices[triangleIndex + 1] = index + 1;
                    _meshData.Indices[triangleIndex + 2] = index + 2;
                    _meshData.Indices[triangleIndex + 3] = index + 0;
                    _meshData.Indices[triangleIndex + 4] = index + 2;
                    _meshData.Indices[triangleIndex + 5] = index + 3;
                    triangleIndex += 6;
                }

                index += 4;
            }

            _mesh.vertices = _meshData.Vertices;
#if SET_MESH_NORMALS
            _mesh.normals = _meshData.Normals;
#endif
            _mesh.uv       = _meshData.UV;
            _mesh.colors32 = _meshData.Colors32;

            if (mustRebuildTriangles)
            {
                _mesh.triangles = _meshData.Indices;
            }

            if (meshBoundsMax.x == float.MinValue)
            {
                meshBoundsMax.x = meshBoundsMin.x;
            }
            if (meshBoundsMax.y == float.MinValue)
            {
                meshBoundsMax.y = meshBoundsMin.y;
            }
            if (meshBoundsMax.z == float.MinValue)
            {
                meshBoundsMax.z = meshBoundsMin.z;
            }

            Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
            Vector3 meshBoundsCenter  = meshBoundsMin + meshBoundsExtents * 0.5f;
            _mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);
        }
예제 #6
0
 /// <summary>
 /// Unregisters the shadow from this manager.
 /// </summary>
 /// <param name="shadow">
 /// The shadow to unregister.
 /// </param>
 public void UnregisterShadow(SwiftShadow shadow)
 {
     _shadowsList.Remove(shadow);
     _isStaticDirty = true;
 }
예제 #7
0
 /// <summary>
 /// Registers the shadow.
 /// </summary>
 /// <param name="shadow">
 /// The shadow to register.
 /// </param>
 public void RegisterShadow(SwiftShadow shadow)
 {
     GetMeshManager(shadow).RegisterShadow(shadow);
 }