/// <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); }
//--------------------------------------------------------------- #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)); } }