private void RenderKDTree() { #if UNITY_EDITOR grassRenderingCount = 0; //Debug.LogError ("RenderKDTree"); #endif //Clear all queue for (int i = 0; i < queue.Count; i++) { chunkState [queue [i]] = ChunkState.queueCache; } kdResults.Clear(); kdQuery.Radius(kdTree, playerPos, settings.RealDisVisible, kdResults); int listCount = kdResults.Count; for (int i = 0; i < listCount; i++) { int index = kdResults [i]; bool canSee = false; var pos = data.chunkPos [index]; float dis = Vector3.Distance(pos, playerPos); //if (dis < settings.DisSurround || (dis < settings.RealDisVisible && Vector3.Dot (pos - playerPos, playerForward) >= -settings.backView)) if (dis < settings.DisSurround || (dis < settings.RealDisVisible && Vector3.Angle(pos - playerPos, playerForward) <= settings.visibleAngle)) { canSee = true; } if (!canSee) { continue; } if (chunkState [index] == ChunkState.idle) { Enqueue(index, ChunkState.queueView); } else if (chunkState [index] == ChunkState.queueView || chunkState [index] == ChunkState.queueCache) { chunkState [index] = ChunkState.queueView; } else if (chunkState [index] == ChunkState.done) { RendChunk(index); } } #if UNITY_EDITOR //Debug.LogError ("Render grass in one frame:"+grassRenderingCount); #endif }
private void ClusterExtraction() { // KDTree int maxPointsPerLeafNode = 32; KDTree tree = new KDTree(PointClouds.ToArray(), maxPointsPerLeafNode); KDQuery query = new KDQuery(); List <int> results = new List <int>(); List <int> temp = new List <int>(); int clusterCounts = 0; for (int i = 0; i < newPointCloudsNum; i++) { bool next = false; for (int j = 0; j < Clusters.Count; j++) { if (Clusters[j].Contains(i)) { next = true; break; } } if (next) { continue; } results.Clear(); temp.Clear(); query.Radius(tree, PointClouds[i], Radius, temp); results.AddRange(temp); for (int j = 1; j < results.Count; j++) { if (results[j] < newPointCloudsNum) { temp.Clear(); query.Radius(tree, PointClouds[results[j]], Radius, temp); for (int k = 0; k < temp.Count; k++) { if (!results.Contains(temp[k])) { results.Add(temp[k]); } } } } Clusters.Add(new List <int>()); Clusters[clusterCounts].AddRange(results); clusterCounts += 1; } }
public List <List <int> > ExtractClusters(List <DetectedLocation> locations) { var points = new Vector3[locations.Count]; var nodes = new int[locations.Count]; for (int i = 0; i < locations.Count; i++) { var loc = locations[i]; points[i] = loc.ToPosition(); nodes[i] = i; } var tree = new KDTree(points, 32); List <List <int> > clusters = new List <List <int> >(); var processed = new bool[locations.Count]; for (int i = 0; i < locations.Count; i++) { if (processed[i]) { continue; } var loc = locations[i]; var p = loc.ToPosition2D(); var q = new Queue <int>(); q.Enqueue(i); processed[i] = true; int index = 0; while (index < q.Count) { var targetIndex = q.ElementAt <int>(index); var tp = locations[targetIndex].ToPosition(); List <int> resultIndices = new List <int>(); query.Radius(tree, tp, distanceThreshold, resultIndices); foreach (var neighbor in resultIndices) { if (processed[neighbor]) { continue; } q.Enqueue(neighbor); processed[neighbor] = true; } index++; } var l = q.ToList <int>(); //Debug.LogFormat("cluster size={0}", l.Count); clusters.Add(l); } return(clusters); }
long QueryRadius() { stopwatch.Reset(); stopwatch.Start(); float3 position = float3One() * 0.5f + RandomInsideUnitSphere(); float radius = 0.25f; results.Clear(); query.Radius(tree, position, radius, results); stopwatch.Stop(); return(stopwatch.ElapsedMilliseconds); }
// Update is called once per frame void Update() { //VPL.Clear(); //VPLPoints.Clear(); //VPLVector.Clear(); if (type == "Point Light") { Vector3 org = this.transform.position; RaycastHit hit; for (int i = 0; i < InitVPLCount; i++) { Vector3 checkdir = (VPLPoints[i] - org).normalized; float checkdistance = (VPLPoints[i] - org).magnitude; if (Physics.Raycast(org, checkdir, out hit, checkdistance)) { float Rx = Random48.Get(); float Ry = Random48.Get(); float Rz = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount, 3); Rz = halton(seedCount++, 4); seedCount = seedCount % (maxSeed * 3); Vector3 tempDir = new Vector3(Rx * 2.0f - 1.0f, Ry * 2.0f - 1.0f, Rz * 2.0f - 1.0f); tempDir.Normalize(); //tempDir -= new Vector3(0.5f, 0.5f, 0.5f); VPLVector[i] = tempDir; Vector3 B = VPLVector[i]; Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * B.z; if (Physics.Raycast(org, dir, out hit, 1000)) { VPLPoints[i] = (hit.point); VPL[i].GetComponent <Transform>().LookAt(hit.normal); } VPL[i].transform.position = VPLPoints[i]; Vector3 CubeUV = convert_xyz_to_cube_uv(B); if (CubeUV.x == 0.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 1.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 2.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 3.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 4.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 5.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } } } } else { Vector3 org = this.transform.position; RaycastHit hit; Texture2D tempTex = new Texture2D(1024, 1024); RenderTexture.active = rendertexture; tempTex.ReadPixels(new UnityEngine.Rect(0, 0, 1024, 1024), 0, 0); Vector3 temp = (this.transform.right + this.transform.up + this.transform.forward); Debug.DrawLine(transform.position + transform.forward * 10, this.transform.position); for (int i = 0; i < InitVPLCount; i++) { Vector3 checkdir = (VPL[i].transform.position - org).normalized; float checkdistance = (VPL[i].transform.position - org).magnitude; float checkAngle = Vector3.Angle(checkdir, transform.forward); if (Physics.Raycast(org, checkdir, out hit, checkdistance) || checkAngle > (SpotAngle / 2.0f)) { float Rx = Random48.Get(); float Ry = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount++, 3); seedCount = seedCount % (maxSeed * 2); if (Mathf.Sqrt((Rx - 0.5f) * (Rx - 0.5f) + (Ry - 0.5f) * (Ry - 0.5f)) <= radius) { Vector3 B = new Vector3(Rx, Ry, 0); B.x -= 0.5f; B.y -= 0.5f; // float l = Vector3.Dot(B, B); VPLVector[i] = B; float z; z = -Mathf.Tan((Fov / 2.0f) / 180.0f * 3.1415926f); Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * z; if (Physics.Raycast(org, dir, out hit, 1000)) { Vector3 p; p.x = B.x * 1024.0f; p.y = B.y * 1024.0f; VPL[i].transform.position = hit.point; tree.Points[i] = hit.point; VPL[i].GetComponent <Transform>().LookAt(hit.normal); VPL[i].GetComponent <Light>().color = (tempTex.GetPixel((int)p.x, (int)p.y)); } } } } tree.Rebuild(); int count = 0; Dictionary <int, bool> lightflag = new Dictionary <int, bool>(); for (int i = 0; i < InitVPLCount; i++) { if (!lightflag.ContainsKey(i)) { count++; VPL[i].GetComponent <Light>().enabled = true; lightflag[i] = true; var resultIndices = new List <int>(); query.Radius(tree, tree.Points[i], Radius, resultIndices); for (int j = 0; j < resultIndices.Count; j++) { if (resultIndices[j] != i) { VPL[resultIndices[j]].GetComponent <Light>().enabled = false; lightflag[resultIndices[j]] = true; } } } } VPL_Num = count.ToString(); Destroy(tempTex); } if (Input.GetKeyDown(KeyCode.D)) { DEB = !DEB; CANV.SetActive(DEB); } if (Input.GetKeyDown(KeyCode.E)) { SDEB = !SDEB; CANV2.SetActive(SDEB); } if (DEB == true) { Vector3 TP = this.GetComponent <Transform>().position; for (int i = 0; i < InitVPLCount; i++) { Debug.DrawLine(TP, VPL[i].GetComponent <Transform>().position); } if (Input.GetKeyDown(KeyCode.W)) { NowSeeLight++; NowSeeLight = NowSeeLight % InitVPLCount; MainCam.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; MainCam.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; //C.transform.parent = VPL[NowSeeLight].transform; C.transform.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; C.transform.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; } if (Input.GetKeyDown(KeyCode.S)) { NowSeeLight--; if (NowSeeLight < 0) { NowSeeLight += InitVPLCount; } NowSeeLight = NowSeeLight % InitVPLCount; MainCam.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; MainCam.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; //C.transform.parent = VPL[NowSeeLight].transform; C.transform.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; C.transform.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; } } }
private void OnDrawGizmos() { if (query == null) { return; } Vector3 size = 0.2f * Vector3.one; for (int i = 0; i < pointCloud.Length; i++) { Gizmos.DrawCube(pointCloud[i], size); } var resultIndices = new List <int>(); Color markColor = Color.red; markColor.a = 0.5f; Gizmos.color = markColor; switch (QueryType) { case QType.ClosestPoint: { query.ClosestPoint(tree, transform.position, resultIndices); } break; case QType.KNearest: { query.KNearest(tree, transform.position, K, resultIndices); } break; case QType.Radius: { query.Radius(tree, transform.position, Radius, resultIndices); Gizmos.DrawWireSphere(transform.position, Radius); } break; case QType.Interval: { query.Interval(tree, transform.position - IntervalSize / 2f, transform.position + IntervalSize / 2f, resultIndices); Gizmos.DrawWireCube(transform.position, IntervalSize); } break; default: break; } for (int i = 0; i < resultIndices.Count; i++) { Gizmos.DrawCube(pointCloud[resultIndices[i]], 2f * size); } Gizmos.color = Color.green; Gizmos.DrawCube(transform.position, 4f * size); if (DrawQueryNodes) { query.DrawLastQuery(); } }
void Update() { Debug.Log(checkObject.transform.position); for (int i = 0; i < tree.Count; i++) { tree.Points[i].Position += LorenzStep(tree.Points[i].Position) * Time.deltaTime * 0.01f; var gobj = (GameObject)tree.Points[i].UserObject; gobj.GetComponent <Renderer>().material.color = Color.white; } tree.Rebuild(); if (query == null) { return; } Vector3 size = 0.2f * Vector3.one; var resultIndices = new List <int>(); Color markColor = Color.red; markColor.a = 0.5f; Gizmos.color = markColor; switch (QueryType) { case QType.ClosestPoint: { query.ClosestPoint(tree, checkObject.transform.position, resultIndices); } break; case QType.KNearest: { query.KNearest(tree, checkObject.transform.position, K, resultIndices); } break; case QType.Radius: { query.Radius(tree, checkObject.transform.position, Radius, resultIndices); } break; case QType.Interval: { query.Interval(tree, checkObject.transform.position - IntervalSize / 2f, checkObject.transform.position + IntervalSize / 2f, resultIndices); } break; default: break; } for (int i = 0; i < resultIndices.Count; i++) { var gobj = (GameObject)tree.Points[resultIndices[i]].UserObject; gobj.GetComponent <Renderer>().material.color = Color.red; } }
public void tick(KDTree tree, KDQuery query, int index, List <Particle> particles, Transform cursor, SettingsMenu settings, ParticleController.State state) { switch (state) { case ParticleController.State.Boid: tree.Points[index] = position; List <int> neighbors = new List <int>(); query.Radius(tree, position, 1f, neighbors); if (neighbors.Count() == 0) { break; } Vector3 avgPosition = Vector3.zero, avgHeading = Vector3.zero, awayHeading = Vector3.zero; foreach (int idx in neighbors) { if (idx == index) { continue; } Particle neighbor = particles[idx]; avgPosition += neighbor.position; avgHeading += neighbor.velocity; awayHeading += (position - neighbor.position).normalized / ((position - neighbor.position).magnitude + 0.01f); } Vector3 desiredVelocity = Vector3.zero; // separation: steer to avoid crowding local flockmates desiredVelocity += awayHeading * settings.separation.value; //0.01 // alignment : steer towards the average heading of local flockmates desiredVelocity += avgHeading.normalized * settings.alignment.value; //0.05 // cohesion : steer to move towards the average position(center of mass) of local flockmates desiredVelocity += ((avgPosition / (neighbors.Count() - 1)) - position).normalized * settings.cohesion.value; //0.01 // boundry : steer towards player if outside boundary sphere // TODO : make radius a param Vector3 boundaryBearing = cursor.position - position; int radius = 15; if (boundaryBearing.magnitude > radius) { desiredVelocity += boundaryBearing.normalized * 0.1f; // position = position.normalized * -radius; } // acceleration += desiredVelocity - velocity; acceleration += desiredVelocity * 0.01f; if (acceleration.magnitude > settings.agility.value) { acceleration = acceleration.normalized * settings.agility.value; } if (velocity.magnitude > settings.speed.value) { velocity = velocity.normalized * settings.speed.value; } break; default: case ParticleController.State.FreeFly: velocity -= 0.005f * velocity; //todo make this a param break; } velocity += acceleration; position += velocity; acceleration = Vector3.zero; }
// This is the method that performs weighted sample elimination. static void DoEliminate( float2[] inputPoints, float2[] outputPoints, float d_max, Func <float2, float2, float, float, float, float> weightFunction, Func <float2, float> density ) { // Build a k-d tree for samples var kdtree = new KDTree(inputPoints); var query = new KDQuery(); var dmax2 = d_max * d_max; // Assign weights to each sample float[] weights = new float[inputPoints.Length]; float[] densities = new float[inputPoints.Length]; for (int i = 0; i < inputPoints.Length; i++) { var point = inputPoints[i]; densities[i] += density(point); foreach (var(qi, d2) in query.Radius(kdtree, inputPoints[i], d_max)) { var otherPoint = inputPoints[qi]; weights[i] += weightFunction(point, otherPoint, d2, d_max, densities[i]); } } // Build a heap for the samples using their weights MaxHeap <int> heap = new MaxHeap <int>(inputPoints.Length); for (int i = 0; i < inputPoints.Length; i++) { heap.PushObj(i, weights[i]); } // While the number of samples is greater than desired int sampleCount = inputPoints.Length; while (sampleCount > outputPoints.Length) { // Pull the top sample from heap var elim = heap.PopObj(); var pElim = inputPoints[elim]; // For each sample around it, remove its weight contribution and update the heap foreach (var(qi, d2) in query.Radius(kdtree, pElim, d_max)) { var point = inputPoints[qi]; weights[qi] -= weightFunction(point, pElim, d2, d_max, densities[qi]); heap.SetValue(qi, weights[qi]); } sampleCount--; } var outputIndex = 0; foreach (var i in heap.FlushResult()) { outputPoints[outputIndex++] = inputPoints[i]; } }