Exemplo n.º 1
0
        /// <summary>
        /// Calculates a the ShadowVolume for a certain lightPosition.
        /// </summary>
        /// <param name="light">The light that is used for casting the ShadowVolume.</param>
        /// <param name="world">The object to world space matrix.</param>
        /// <param name="recalcFaceNormals">Recalculates the face normals. This is just necessary if the vertices
        /// of the mesh are manipulated by the CPU like for SoftwareSkinning.</param>
        /// <returns>The ShadowVolume in form of an Mesh.</returns>
        public Mesh Calculate(Light light, Matrix4 world, bool recalcFaceNormals)
        {
            // Init variables
            int j = 0;

            // Calculate the object space light vector
            this.world = world;
            Vector4 osLight = light.Vector4 * Matrix4.Invert(world);

            // calc the method to use
            if (method == StencilMethod.Automatic)
            {
                currentMethod = CalcMethod(light, world);
            }
            else
            {
                currentMethod = method;
            }
            SetTechnique(currentMethod);

            // for all subsets of the mesh add the silohuette
            for (int iSubSet = 0; iSubSet < mesh.SubSets.Count; iSubSet++)
            {
                SubSet subset = mesh.SubSets[iSubSet];
                SubSet shadow = shadowVolume.SubSets[iSubSet];

                // get indices and positions
                PositionStream positionStream = (PositionStream)subset.VertexUnit[typeof(PositionStream)];

                // recalc face normals
                if (recalcFaceNormals)
                {
                    faceNormals[iSubSet] = subset.CalcFaceNormals();
                }

                shadow.IndexBufferStart = j;

                CalcVisibilityInfo(ref j, iSubSet, osLight);

                if (indexStream.ElementSize == 2)
                {
                    AddShadowVolume16(ref j, iSubSet, light, positionStream.Size / 2);
                }
                else
                {
                    AddShadowVolume32(ref j, iSubSet, light, positionStream.Size / 2);
                }
                shadow.PrimitiveCount = (j - shadow.IndexBufferStart) / 3;
            }

            indexStream.Upload();
            return(shadowVolume);
        }
Exemplo n.º 2
0
        //---------------------------------------------------------------
        #endregion
        //---------------------------------------------------------------

        //---------------------------------------------------------------
        #region Methods
        //---------------------------------------------------------------
        private void UpdateMetaInfo()
        {
            faceNormals       = new Vector3[mesh.SubSets.Count][];
            backface          = new bool[mesh.SubSets.Count][];
            edges             = new Edge[mesh.SubSets.Count][];
            this.shadowVolume = new Mesh();

            int maxIndex = 0;

            for (int iSubSet = 0; iSubSet < mesh.SubSets.Count; iSubSet++)
            {
                maxIndex = System.Math.Min(mesh.SubSets[iSubSet].VertexUnit.Size, maxIndex);
            }
            indexStream = IndexStream.Create(1024 * 16, maxIndex);

            for (int iSubSet = 0; iSubSet < mesh.SubSets.Count; iSubSet++)
            {
                SubSet subSet = mesh.SubSets[iSubSet];
                faceNormals[iSubSet] = subSet.CalcFaceNormals();
                backface[iSubSet]    = new bool[subSet.PrimitiveCount];
                edges[iSubSet]       = subSet.CalcEdges();
                shadowVolume.SubSets.Add(new SubSet(subSet.VertexUnit, indexStream));
            }
        }