{"id":13676317,"url":"https://github.com/ArthurBrussee/KNN","last_synced_at":"2025-04-29T06:31:36.430Z","repository":{"id":41388842,"uuid":"191354810","full_name":"ArthurBrussee/KNN","owner":"ArthurBrussee","description":"Fast K-Nearest Neighbour Library for Unity DOTS","archived":false,"fork":false,"pushed_at":"2023-01-18T13:31:23.000Z","size":705,"stargazers_count":441,"open_issues_count":5,"forks_count":51,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-11-11T18:40:56.760Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArthurBrussee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-11T11:08:59.000Z","updated_at":"2024-11-08T00:11:37.000Z","dependencies_parsed_at":"2023-02-10T15:16:26.385Z","dependency_job_id":null,"html_url":"https://github.com/ArthurBrussee/KNN","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurBrussee%2FKNN","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurBrussee%2FKNN/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurBrussee%2FKNN/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArthurBrussee%2FKNN/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArthurBrussee","download_url":"https://codeload.github.com/ArthurBrussee/KNN/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251450656,"owners_count":21591407,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T13:00:22.682Z","updated_at":"2025-04-29T06:31:33.046Z","avatar_url":"https://github.com/ArthurBrussee.png","language":"C#","funding_links":[],"categories":["GamePlay","Open Source Repositories","C#","Open Source Packages"],"sub_categories":["HUD","DOTS"],"readme":"![Demo Image](http://g2f.nl/0jx82rw)\n\n# KNN\n\nSimple K-Nearest Neighbour library for Unity, using the 'Dots' technology stack (the Burst compiler and Unity's job system). It uses K-D trees to speed up queries.\n\nIt is totally free from managed allocations and can run multi-threaded. The Burst compiler heavily vectorizes the searching code.\n\nThe implementation is a heavily modified version of a KD-Tree by viliwonka: https://github.com/viliwonka/KDTree . It only includes a sub-set of functionality however.\n\nAs a rough benchmark, here are perf numbers on a i7-770hq, querying the k=10 nearest neighbours, 100.000 times, in 100.000 points\n\n![Performance comparison](http://g2f.nl/04y9z7g)\n\nThis shows an approximately ~130x speedup over the original implementation! Note that this is very much apples to oranges though (eg. this is multi-threaded, the original implementation was not); I don't mean to pick on the original at all, but does hopefully it shows this implementation is really fast!\n\n# API Overview\n\n```C#\t\n// First let's create a random point cloud\nvar points = new NativeArray\u003cfloat3\u003e(100000, Allocator.Persistent);\nvar rand = new Random(123456);\nfor (int i = 0; i \u003c points.Length; ++i) {\n    points[i] = rand.NextFloat3();\n}\n\n// Number of neighbours we want to query\nconst int kNeighbours = 10;\nfloat3 queryPosition = float3.zero;\n\n// Create a container that accelerates querying for neighbours.\n// The 2nd argument indicates whether we want to build the tree straight away or not\n// Let's hold off on building it a little bit\nvar knnContainer = new KnnContainer(points, false, Allocator.TempJob);\n\n// Whenever your point cloud changes, you can make a job to rebuild the container:\nvar rebuildJob = new KnnRebuildJob(knnContainer);\nrebuildJob.Schedule().Complete();\n\n// Most basic usage:\n// Get 10 nearest neighbours as indices into our points array!\n// This is NOT burst accelerated yet! Unity need to implement compiling delegates with Burst\nvar result = new NativeArray\u003cint\u003e(kNeighbours, Allocator.TempJob);\nknnContainer.QueryKNearest(queryPosition, result);\n\n// The result array at this point contains indices into the points array with the nearest neighbours!\nProfiler.BeginSample(\"Simple Query\");\n// Get a job to do the query.\nvar queryJob = new QueryKNearestJob(knnContainer, queryPosition, result);\n\n// And just run immediately on the main thread for now. This uses Burst!\nqueryJob.Schedule().Complete();\nProfiler.EndSample();\n\n// Or maybe we want to query neighbours for multiple points.\nconst int queryPoints = 100000;\n\n// Keep an array of neighbour indices of all points\nvar results = new NativeArray\u003cint\u003e(queryPoints * kNeighbours, Allocator.TempJob);\n\n// Query at a few random points\nvar queryPositions = new NativeArray\u003cfloat3\u003e(queryPoints, Allocator.TempJob);\nfor (int i = 0; i \u003c queryPoints; ++i) {\n    queryPositions[i] = rand.NextFloat3() * 0.1f;\n}\t\n\n// Fire up job to get results for all points\nvar batchQueryJob = new QueryKNearestBatchJob(knnContainer, queryPositions, results);\n\n// And just run immediately now. This will run on multiple threads!\nbatchQueryJob.ScheduleBatch(queryPositions.Length, queryPositions.Length / 32).Complete();\n\n// Or maybe we're interested in a range around eacht query point\nvar queryRangeResult = new NativeList\u003cint\u003e(Allocator.TempJob);\nvar rangeQueryJob = new QueryRangeJob(knnContainer, queryPosition, 2.0f, queryRangeResult);\n\n// Store a list of particles in range\nvar rangeResults = new NativeArray\u003cRangeQueryResult\u003e(queryPoints, Allocator.TempJob);\n\n// And just run immediately on the main thread for now. This uses Burst!\nrangeQueryJob.Schedule().Complete();\n\n// Unfortunately, for batch range queries we do need to decide upfront the maximum nr. of neighbours we allow\n// This is due to limitation on allocations within a job.\nfor (int i = 0; i \u003c rangeResults.Length; ++i) {\n    rangeResults[i] = new RangeQueryResult(128, Allocator.TempJob);\n}\n\n// Fire up job to get results for all points\nvar batchRange = new QueryRangeBatchJob(knnContainer, queryPositions, 2.0f, rangeResults);\n\n// And just run immediately now. This will run on multiple threads!\nbatchRange.ScheduleBatch(queryPositions.Length, queryPositions.Length / 32).Complete();\n\n// Now the results array contains all the neighbours!\nqueryRangeResult.Dispose();\nforeach (var r in rangeResults) {\n    r.Dispose();\n}\nrangeResults.Dispose();\nknnContainer.Dispose();\nqueryPositions.Dispose();\nresults.Dispose();\npoints.Dispose();\nresult.Dispose();\n```\n\n# Demo\n\nThe demo folder contains 2 demos:\n\n- KnnApiDemo.cs, Illustrates various API usages from a basic to advanced level\n- KnnVisualizationDemo.cs: Illustrates a real scene where particles are colored based on their neighbourhood information. Shows how to dynamically rebuild your container and other advanced API usages\n\n\n## Installation\n\nThe project was made as a Unity Package. Just add the git URL to your package manifest and Unity should install it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FArthurBrussee%2FKNN","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FArthurBrussee%2FKNN","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FArthurBrussee%2FKNN/lists"}