/// <summary> /// GetPartition() takes a connected graph (in the form of a dataset or lightweight graph), /// and returns a partitioning of the graph created from applying the resilience measure. /// The minimum number of clusters in the partitioning is given by the instance variable _minK. /// </summary> /// <returns>A partition of the instance graph</returns> public Partition GetPartition() { DistanceMatrix mat = null; if (_data.Type == AbstractDataset.DataType.DistanceMatrix) { mat = (DistanceMatrix)_data; } else if (_data.Type == AbstractDataset.DataType.PointSet) { mat = ((PointSet)_data).GetDistanceMatrix(); } //Setup our partition with a single cluster, with all points List <Cluster> clusterList = new List <Cluster> { new Cluster(0, Enumerable.Range(0, _data.Count).ToList()) }; Partition partition = new Partition(clusterList, _data); //Dictionary to hold VAT var vatMap = new Dictionary <int, Scattering>(); //Dictionary to hold subset array var subsetMap = new Dictionary <int, int[]>(); while (clusterList.Count < _minK) { //Calculate the VAT for all values foreach (var c in partition.Clusters.Where(c => !vatMap.ContainsKey(c.ClusterId))) { //We must calculate a graph for this subset of data List <int> clusterSubset = c.Points.Select(p => p.Id).ToList(); //Now calculate Vat LightWeightGraph lwg; if (_data.Type == AbstractDataset.DataType.Graph) { bool[] exclusion = new bool[_data.Count]; for (int i = 0; i < _data.Count; i++) { exclusion[i] = true; } foreach (var p in c.Points) { exclusion[p.Id] = false; } lwg = new LightWeightGraph((LightWeightGraph)_data, exclusion); } else //Distance matrix or Pointset { Debug.Assert(mat != null, "mat != null"); var subMatrix = mat.GetReducedDataSet(clusterSubset); //Generate our graph lwg = _graphGen.GenerateGraph(subMatrix.Mat); } subsetMap.Add(c.ClusterId, clusterSubset.ToArray()); lwg.IsWeighted = _weighted; Scattering v = new Scattering(lwg, _reassignNodes, _alpha, _beta); _vatNodeRemovalOrder = v.NodeRemovalOrder; _vatNumNodesRemoved = v.NumNodesRemoved; if (_hillClimb) { v.HillClimb(); } ////VATClust v = new VATClust(subMatrix.Mat, _weighted, _useKnn, _kNNOffset, _alpha, _beta); vatMap.Add(c.ClusterId, v); } meta.AppendLine("All calculated Scatterings:"); //Now find the minimum vat value int minVatCluster = 0; double minVatValue = double.MaxValue; foreach (var c in vatMap) { meta.Append(String.Format("{0} ", c.Value.MinVat)); if (c.Value.MinVat < minVatValue) { minVatCluster = c.Key; minVatValue = c.Value.MinVat; } } meta.AppendLine(); //now merge the partition into the cluster var minVAT = vatMap[minVatCluster]; var subPartition = minVAT.GetPartition(); var nodeIndexMap = subsetMap[minVatCluster]; meta.AppendFormat("Scattering: MinScattering={0}\r\n", minVAT.MinVat); meta.AppendFormat("Removed Count:{0} \r\n", minVAT.NumNodesRemoved); meta.AppendLine(String.Join(",", minVAT.NodeRemovalOrder.GetRange(0, minVAT.NumNodesRemoved).Select(c => nodeIndexMap[c]))); partition.MergeSubPartition(subPartition, nodeIndexMap, minVatCluster); vatMap.Remove(minVatCluster); subsetMap.Remove(minVatCluster); } partition.MetaData = meta.ToString(); return(partition); }
public override void Inject(Scattering scattering, ComputeShader compute, Matrix4x4 viewProj) { if (HasShadow) { if (GetShadowMapResolution() != m_shadowMap.width) { DestroyImmediate(m_shadowMap); CreateShadowTex(); } } //TODO: This doesn't really need to run every frame UpdateCommandBuffer(); //Setup basic params Vector4 posRange = transform.position; posRange.w = 1.0f / (m_light.range * m_light.range); compute.SetVector("_LightPosRange", posRange); Vector4 lightStrength = m_light.color * m_light.intensity * FogScatterIntensity; lightStrength *= 10; compute.SetVector("_LightColor", lightStrength); //Per light type things switch (LightType) { case LightType.Directional: int dirKernel; if (HasShadow) { if (QualitySettings.shadowCascades > 1) { dirKernel = scattering.LightDirKernel.GetKernel(ScatterKernel.EShadowMode.Cascaded); } else { dirKernel = scattering.LightDirKernel.GetKernel(ScatterKernel.EShadowMode.Shadowed); } } else { dirKernel = scattering.LightDirKernel.GetKernel(ScatterKernel.EShadowMode.None); } compute.SetVector("_LightPosRange", m_light.transform.forward); if (HasShadow) { compute.SetBuffer(dirKernel, "_MatrixBuf", MatrixBuffer); compute.SetTexture(dirKernel, "_ShadowMapTexture", m_shadowMap); } else { compute.SetTexture(dirKernel, "_ShadowMapTexture", Texture2D.whiteTexture); } scattering.SetLightAccum(dirKernel, false); Profiler.BeginSample("Dir Light pass"); var tex = scattering.GetDensityTex(); compute.DispatchScaled(dirKernel, tex.width, tex.height, tex.volumeDepth); Profiler.EndSample(); break; case LightType.Point: scattering.SetLightAccum(scattering.LightPointKernel, false); scattering.InjectObject(viewProj, scattering.LightPointKernel, this); break; case LightType.Spot: int spotKernel = scattering.LightSpotKernel.GetKernel(HasShadow ? ScatterKernel.EShadowMode.Shadowed : ScatterKernel.EShadowMode.None); if (HasShadow) { Matrix4x4 v = transform.worldToLocalMatrix; Matrix4x4 p = GL.GetGPUProjectionMatrix(Matrix4x4.Perspective(m_light.spotAngle, 1.0f, m_light.shadowNearPlane, m_light.range), true); //For some reason z is flipped :( p *= Matrix4x4.Scale(new Vector3(1.0f, 1.0f, -1.0f)); compute.SetMatrix("_SpotShadowMatrix", p * v); compute.SetTexture(spotKernel, "_SpotShadow", m_shadowMap); } var lightProjMatrix = Matrix4x4.identity; float d = Mathf.Deg2Rad * m_light.spotAngle * 0.5f; d = Mathf.Cos(d) / Mathf.Sin(d); lightProjMatrix[3, 2] = 2f / d; lightProjMatrix[3, 3] = SpotBaseSize; var mat = lightProjMatrix * transform.worldToLocalMatrix; compute.SetMatrix("_SpotMatrix", mat); if (m_light.cookie != null) { compute.SetTexture(spotKernel, "_SpotCookie", m_light.cookie); } else { compute.SetTexture(spotKernel, "_SpotCookie", scattering.SpotCookie); } scattering.SetLightAccum(spotKernel, false); scattering.InjectObject(viewProj, spotKernel, this); break; } }
public abstract void Inject(Scattering scat, ComputeShader comp, Matrix4x4 viewProj);