<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      泊松盤采樣(Poisson Disk Sampling)生成均勻隨機點

      當需要生成隨機點且要求隨機點自然均勻的分布時,使用泊松盤采樣就較為適合。

      但該方法與統計學上的概念關聯不大,這個只相當于點在面積上服從泊松分布,

      而實現這個結果有很多做法。

       

      最終效果:

       圓形為含半徑的點,圓形的中心代表生成點

       

      B站有一個不錯的搬運教程(Bridson方法):

      https://www.bilibili.com/video/BV1KV411x7LM

       

      另外Bridson文章里說藍噪聲(BlueNoise)也基于此方法生成

       

      我做了些修改,代碼如下:

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      
      public static class PoissonDiscSampling
      {
          public static List<Vector3> GeneratePoints(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection = 32)
          {
              bool IsValid(Vector3 candidate, Vector2 sampleRegionSize, float cellSize, float radius, List<Vector3> points, int[,] grid)
              {
                  if (candidate.x - radius >= 0f && candidate.x + radius < sampleRegionSize.x && candidate.z - radius >= 0f && candidate.z + radius < sampleRegionSize.y)
                  {
                      int cellX = Mathf.RoundToInt(candidate.x / cellSize);
                      int cellZ = Mathf.RoundToInt(candidate.z / cellSize);
                      int searchStartX = Mathf.Max(0, cellX - 3);
                      int searchEndX = Mathf.Min(cellX + 3, grid.GetLength(0) - 1);
                      int searchStartZ = Mathf.Max(0, cellZ - 3);
                      int searchEndZ = Mathf.Min(cellZ + 3, grid.GetLength(1) - 1);
                      //如果要檢測其它格子內的球,需要遍歷周圍6個格子
      
                      for (int x = searchStartX; x <= searchEndX; x++)
                      {
                          for (int z = searchStartZ; z <= searchEndZ; z++)
                          {
                              int pointIndex = grid[x, z] - 1;//存長度不存索引,取時減1,0就變成了-1,不需要初始化數組了
                              if (pointIndex != -1)
                              {
                                  float dst = (candidate - points[pointIndex]).magnitude;
                                  if (dst < radius * 2f)
                                  {
                                      return false;
                                  }
                              }
                          }
                      }
      
                      return true;
                  }
      
                  return false;
              }
      
              float cellSize = radius / Mathf.Sqrt(2);
      
              int[,] grid = new int[Mathf.CeilToInt(sampleRegionSize.x / cellSize), Mathf.CeilToInt(sampleRegionSize.y / cellSize)];
              List<Vector3> points = new List<Vector3>();
              List<Vector3> spawnPoints = new List<Vector3>();
      
              spawnPoints.Add(new Vector3(sampleRegionSize.x / 2f, 0f, sampleRegionSize.y / 2f));
              while (spawnPoints.Count > 0)
              {
                  int spawnIndex = Random.Range(0, spawnPoints.Count);
                  Vector3 spawnCenter = spawnPoints[spawnIndex];
      
                  bool candidateAccepted = false;
                  for (int i = 0; i < numSamplesBeforeRejection; i++)
                  {
                      float angle = Random.value * Mathf.PI * 2f;
                      Vector3 dir = new Vector3(Mathf.Sin(angle), 0f, Mathf.Cos(angle));
                      Vector3 candidate = spawnCenter + dir * Random.Range(2f, 3f) * radius;
      
                      if (IsValid(candidate, sampleRegionSize, cellSize, radius, points, grid))
                      {
                          points.Add(candidate);
                          spawnPoints.Add(candidate);
                          grid[Mathf.RoundToInt(candidate.x / cellSize), Mathf.RoundToInt(candidate.z / cellSize)] = points.Count;
                          candidateAccepted = true;
                          break;
                      }
                  }
                  if (!candidateAccepted)
                  {
                      spawnPoints.RemoveAt(spawnIndex);
                  }
              }
      
              return points;
          }
      }

       

       

      測試代碼如下:

      using System.Collections.Generic;
      using UnityEngine;
      
      public class Test : MonoBehaviour
      {
          public float radius = 0.3f;
          public Vector2 sampleRegionSize = new Vector2(3f, 3f);
          private List<Vector3> mPoints;
      
      
          private void OnEnable()
          {
              mPoints = PossonDiscSampling.GeneratePoints(radius, sampleRegionSize);
          }
      
          private void OnDrawGizmos()
          {
              if (mPoints == null) return;
      
              float cellSize = radius / Mathf.Sqrt(2);
      
              Color cacheColor = Gizmos.color;
              Gizmos.color = new Color(0.5f, 0.5f, 0.5f, 0.5f);
              for (float x = 0; x < sampleRegionSize.x; x += cellSize)
              {
                  for (float z = 0; z < sampleRegionSize.y; z += cellSize)
                      Gizmos.DrawWireCube(new Vector3(x, 0f, z), new Vector3(cellSize, 0f, cellSize));
              }//生成對應采樣點的調試方格
              Gizmos.color = cacheColor;
      
              for (int i = 0; i < mPoints.Count; i++)
              {
                  Vector3 vector = mPoints[i];
      
                  Gizmos.DrawWireSphere(vector, radius);
      
                  int x = Mathf.FloorToInt(vector.x / cellSize);
                  int z = Mathf.FloorToInt(vector.z / cellSize);
      
                  Gizmos.DrawWireCube(new Vector3(x, 0f, z) * cellSize, new Vector3(cellSize, 0f, cellSize));
                  //生成當前點所屬方格
              }
          }
      }

       

      對于該做法還可以做如下應用層面的擴展:

      1.擴展到3D空間,一些鳥的移動軌跡可以直接用這個做路點尋路

      2.可以嘗試在UV上分布,然后映射到3D空間

      3.可以基于這個做三角剖分(http://www.rzrgm.cn/hont/p/15310157.html)

       

      posted @ 2022-06-25 20:31  HONT  閱讀(2889)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 人妻少妇精品视频二区| 99久久99久久精品免费看蜜桃| 桐庐县| 人妻一区二区三区人妻黄色| 亚洲最大成人免费av| 沂南县| 日日猛噜噜狠狠扒开双腿小说| 欧美丰满妇大ass| 亚洲色大成网站WWW永久麻豆| 蜜臀av一区二区三区精品| 成年午夜免费韩国做受视频| 日韩av一区二区不卡在线| 1000部拍拍拍18勿入免费视频| 麻豆国产va免费精品高清在线| 激情综合网激情五月伊人| 亚洲欧美人成人综合在线播放| 成人免费无码av| 人妻少妇精品中文字幕| 国产午夜精品福利视频| 国产欧美日韩精品第二区| 亚洲精品久久久久久下一站| 五月婷婷久久中文字幕| 无套内谢少妇一二三四| 日韩精品有码中文字幕| 欧洲免费一区二区三区视频 | 亚洲一区二区三午夜福利| 疯狂做受xxxx高潮欧美日本| 噜噜综合亚洲av中文无码| 毛片无遮挡高清免费| 在线一区二区中文字幕| 视频一区视频二区中文字幕| 国产精品无码一区二区桃花视频| 国产精品老熟女乱一区二区| 国产好大好硬好爽免费不卡| 亚洲人成小说网站色在线| 亚洲国产在一区二区三区| 中文字幕av高清片| а∨天堂一区中文字幕 | 丁香色婷婷国产精品视频| 国产成人啪精品午夜网站| 欧美做受视频播放|