} // Bake private KdTree CreateKdTree(List <FlowPath.Sample> _samples) { KdTree.Entry[] _kdEnt = new KdTree.Entry[_samples.Count]; for (int _it = 0; _it < _samples.Count; ++_it) { _kdEnt[_it] = new KdTree.Entry(_samples[_it].position, _it); } KdTree _kdTree = new KdTree(); _kdTree.build(_kdEnt); return(_kdTree); }
private void InterpolateSamples(FlowMap _inst, List <FlowPath.Sample> _samples, Vector2 _delta, FlowPath.Sample[,] _outputs) { var _transform = _inst.transform; var _offset = _inst.size * -0.5f + _delta * 0.5f; int _w = _outputs.GetUpperBound(0) + 1; int _h = _outputs.GetUpperBound(1) + 1; KdTree _kdTree = CreateKdTree(_samples); KdTree.KQueue _kqueue = new KdTree.KQueue(3); for (int _y = 0; _y < _h; ++_y) { for (int _x = 0; _x < _w; ++_x) { Vector2 _pos = _offset + Vector2.Scale(_delta, new Vector2(_x, _y)); Vector3 _worldPos = _transform.TransformPoint(new Vector3(_pos.x, 0, _pos.y)); FlowPath.Sample _outSamp = new FlowPath.Sample() { position = _worldPos, direction = Vector3.zero, }; int[] _knn = _kdTree.knearest(_kqueue, _worldPos, 3); if (_knn.Length == 3) { var _sampA = _samples[_knn[0]]; var _sampB = _samples[_knn[1]]; var _sampC = _samples[_knn[2]]; Vector3 _weights; Vector3 _dir = _sampA.direction; if (Geometry.GetBarycentricCoords(out _weights, _sampA.position, _sampB.position, _sampC.position, _worldPos)) { _dir = (_sampA.direction * _weights.x) + (_sampB.direction * _weights.y) + (_sampC.direction * _weights.z); } _outSamp.direction = _dir; } _outputs[_x, _y] = _outSamp; } } }
public List <FlowPath.Sample> GatherSamples(Vector2 _sampleSize) { var _flowPaths = GetComponentsInChildren <FlowPath>(); var _rawSamples = new List <FlowPath.Sample>(); foreach (var _flow in _flowPaths) { if (null == _flow || !_flow) { continue; } (_flow as FlowPath).GatherSamples(_rawSamples, _sampleSize); } KdTree.Entry[] _kdEnt = new KdTree.Entry[_rawSamples.Count]; for (int _it = 0; _it < _rawSamples.Count; ++_it) { _kdEnt[_it] = new KdTree.Entry(_rawSamples[_it].position, _it); } KdTree _kdTree = new KdTree(); _kdTree.build(_kdEnt); KdTree.RQueue _rqueue = new KdTree.RQueue(); var _processed = new System.Collections.Generic.HashSet <int>(); float _range = Mathf.Min(_sampleSize.x, _sampleSize.y); var _filteredSamples = new List <FlowPath.Sample>(); for (int _it = 0; _it < _rawSamples.Count; ++_it) { if (_processed.Contains(_it)) { continue; } int[] _neighbours = _kdTree.rquery(_rqueue, _rawSamples[_it].position, _range); if (_neighbours.Length == 1) { _filteredSamples.Add(_rawSamples[_it]); _processed.Add(_it); } else { Vector3 _pos = Vector3.zero; Vector3 _dir = Vector3.zero; foreach (int _id in _neighbours) { _pos += _rawSamples[_id].position; _dir += _rawSamples[_id].direction; _processed.Add(_id); } FlowPath.Sample _samp = new FlowPath.Sample(); _samp.position = _pos * (1.0f / _neighbours.Length); _samp.direction = _dir * (1.0f / _neighbours.Length); _filteredSamples.Add(_samp); } } return(_filteredSamples); }
public void PlaceProbes() { if (probeObject != null) { probeObject.transform.position = Vector3.zero; UnityEngine.AI.NavMeshTriangulation navMesh = UnityEngine.AI.NavMesh.CalculateTriangulation(); Vector3[] _pos = navMesh.vertices; // construct kd tree KdTree _kd = new KdTree(); KdTree.Entry[] _kdents = new KdTree.Entry[_pos.Length]; for (int i = 0; i < _kdents.Length; ++i) { _kdents[i] = new KdTree.Entry(_pos[i], i); } _kd.build(_kdents); List <ProbeGenPoint> probeGen = new List <ProbeGenPoint>(); foreach (Vector3 _pt in _pos) { probeGen.Add(new ProbeGenPoint(_pt, false)); } List <Vector3> mergedProbes = new List <Vector3>(); var _watch = new System.Diagnostics.Stopwatch(); _watch.Start(); var _queue = new KdTree.RQueue(); for (int i = 0; i < probeGen.Count; ++i) { ProbeGenPoint _pro = probeGen[i]; if (_pro.used) { continue; } float _mergedCnt = 1.0f; Vector3 _mergedPos = _pro.pos; var _neighbor = _kd.rquery(_queue, _pro.pos, mergeDistance); for (int n = 0; n < _neighbor.Length; ++n) { if (_neighbor[n] == i) { continue; } ProbeGenPoint _subject = probeGen[_neighbor[n]]; _subject.used = true; } if (_mergedCnt > 1.0f) { _mergedPos *= 1.0f / _mergedCnt; } for (int l = 0; l < layers; ++l) { mergedProbes.Add(_mergedPos + Vector3.up * (layerHeight * l)); } _pro.used = true; } _watch.Stop(); Log.I("merging completed in {0} ms", _watch.ElapsedMilliseconds); probeObject.probePositions = mergedProbes.ToArray(); } }