{"version":3,"file":"MeshSurfaceSampler.cjs","sources":["../../src/math/MeshSurfaceSampler.js"],"sourcesContent":["import { Triangle, Vector3 } from 'three'\n\n/**\n * Utility class for sampling weighted random points on the surface of a mesh.\n *\n * Building the sampler is a one-time O(n) operation. Once built, any number of\n * random samples may be selected in O(logn) time. Memory usage is O(n).\n *\n * References:\n * - http://www.joesfer.com/?p=84\n * - https://stackoverflow.com/a/4322940/1314762\n */\n\nconst _face = new Triangle()\nconst _color = new Vector3()\n\nclass MeshSurfaceSampler {\n  constructor(mesh) {\n    let geometry = mesh.geometry\n\n    if (geometry.index) {\n      console.warn('THREE.MeshSurfaceSampler: Converting geometry to non-indexed BufferGeometry.')\n\n      geometry = geometry.toNonIndexed()\n    }\n\n    this.geometry = geometry\n    this.randomFunction = Math.random\n\n    this.positionAttribute = this.geometry.getAttribute('position')\n    this.colorAttribute = this.geometry.getAttribute('color')\n    this.weightAttribute = null\n\n    this.distribution = null\n  }\n\n  setWeightAttribute(name) {\n    this.weightAttribute = name ? this.geometry.getAttribute(name) : null\n\n    return this\n  }\n\n  build() {\n    const positionAttribute = this.positionAttribute\n    const weightAttribute = this.weightAttribute\n\n    const faceWeights = new Float32Array(positionAttribute.count / 3)\n\n    // Accumulate weights for each mesh face.\n\n    for (let i = 0; i < positionAttribute.count; i += 3) {\n      let faceWeight = 1\n\n      if (weightAttribute) {\n        faceWeight = weightAttribute.getX(i) + weightAttribute.getX(i + 1) + weightAttribute.getX(i + 2)\n      }\n\n      _face.a.fromBufferAttribute(positionAttribute, i)\n      _face.b.fromBufferAttribute(positionAttribute, i + 1)\n      _face.c.fromBufferAttribute(positionAttribute, i + 2)\n      faceWeight *= _face.getArea()\n\n      faceWeights[i / 3] = faceWeight\n    }\n\n    // Store cumulative total face weights in an array, where weight index\n    // corresponds to face index.\n\n    this.distribution = new Float32Array(positionAttribute.count / 3)\n\n    let cumulativeTotal = 0\n\n    for (let i = 0; i < faceWeights.length; i++) {\n      cumulativeTotal += faceWeights[i]\n\n      this.distribution[i] = cumulativeTotal\n    }\n\n    return this\n  }\n\n  setRandomGenerator(randomFunction) {\n    this.randomFunction = randomFunction\n    return this\n  }\n\n  sample(targetPosition, targetNormal, targetColor) {\n    const faceIndex = this.sampleFaceIndex()\n    return this.sampleFace(faceIndex, targetPosition, targetNormal, targetColor)\n  }\n\n  sampleFaceIndex() {\n    const cumulativeTotal = this.distribution[this.distribution.length - 1]\n    return this.binarySearch(this.randomFunction() * cumulativeTotal)\n  }\n\n  binarySearch(x) {\n    const dist = this.distribution\n    let start = 0\n    let end = dist.length - 1\n\n    let index = -1\n\n    while (start <= end) {\n      const mid = Math.ceil((start + end) / 2)\n\n      if (mid === 0 || (dist[mid - 1] <= x && dist[mid] > x)) {\n        index = mid\n\n        break\n      } else if (x < dist[mid]) {\n        end = mid - 1\n      } else {\n        start = mid + 1\n      }\n    }\n\n    return index\n  }\n\n  sampleFace(faceIndex, targetPosition, targetNormal, targetColor) {\n    let u = this.randomFunction()\n    let v = this.randomFunction()\n\n    if (u + v > 1) {\n      u = 1 - u\n      v = 1 - v\n    }\n\n    _face.a.fromBufferAttribute(this.positionAttribute, faceIndex * 3)\n    _face.b.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 1)\n    _face.c.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 2)\n\n    targetPosition\n      .set(0, 0, 0)\n      .addScaledVector(_face.a, u)\n      .addScaledVector(_face.b, v)\n      .addScaledVector(_face.c, 1 - (u + v))\n\n    if (targetNormal !== undefined) {\n      _face.getNormal(targetNormal)\n    }\n\n    if (targetColor !== undefined && this.colorAttribute !== undefined) {\n      _face.a.fromBufferAttribute(this.colorAttribute, faceIndex * 3)\n      _face.b.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 1)\n      _face.c.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 2)\n\n      _color\n        .set(0, 0, 0)\n        .addScaledVector(_face.a, u)\n        .addScaledVector(_face.b, v)\n        .addScaledVector(_face.c, 1 - (u + v))\n\n      targetColor.r = _color.x\n      targetColor.g = _color.y\n      targetColor.b = _color.z\n    }\n\n    return this\n  }\n}\n\nexport { MeshSurfaceSampler }\n"],"names":["Triangle","Vector3"],"mappings":";;;AAaA,MAAM,QAAQ,IAAIA,MAAAA,SAAU;AAC5B,MAAM,SAAS,IAAIC,MAAAA,QAAS;AAE5B,MAAM,mBAAmB;AAAA,EACvB,YAAY,MAAM;AAChB,QAAI,WAAW,KAAK;AAEpB,QAAI,SAAS,OAAO;AAClB,cAAQ,KAAK,8EAA8E;AAE3F,iBAAW,SAAS,aAAc;AAAA,IACnC;AAED,SAAK,WAAW;AAChB,SAAK,iBAAiB,KAAK;AAE3B,SAAK,oBAAoB,KAAK,SAAS,aAAa,UAAU;AAC9D,SAAK,iBAAiB,KAAK,SAAS,aAAa,OAAO;AACxD,SAAK,kBAAkB;AAEvB,SAAK,eAAe;AAAA,EACrB;AAAA,EAED,mBAAmB,MAAM;AACvB,SAAK,kBAAkB,OAAO,KAAK,SAAS,aAAa,IAAI,IAAI;AAEjE,WAAO;AAAA,EACR;AAAA,EAED,QAAQ;AACN,UAAM,oBAAoB,KAAK;AAC/B,UAAM,kBAAkB,KAAK;AAE7B,UAAM,cAAc,IAAI,aAAa,kBAAkB,QAAQ,CAAC;AAIhE,aAAS,IAAI,GAAG,IAAI,kBAAkB,OAAO,KAAK,GAAG;AACnD,UAAI,aAAa;AAEjB,UAAI,iBAAiB;AACnB,qBAAa,gBAAgB,KAAK,CAAC,IAAI,gBAAgB,KAAK,IAAI,CAAC,IAAI,gBAAgB,KAAK,IAAI,CAAC;AAAA,MAChG;AAED,YAAM,EAAE,oBAAoB,mBAAmB,CAAC;AAChD,YAAM,EAAE,oBAAoB,mBAAmB,IAAI,CAAC;AACpD,YAAM,EAAE,oBAAoB,mBAAmB,IAAI,CAAC;AACpD,oBAAc,MAAM,QAAS;AAE7B,kBAAY,IAAI,CAAC,IAAI;AAAA,IACtB;AAKD,SAAK,eAAe,IAAI,aAAa,kBAAkB,QAAQ,CAAC;AAEhE,QAAI,kBAAkB;AAEtB,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,yBAAmB,YAAY,CAAC;AAEhC,WAAK,aAAa,CAAC,IAAI;AAAA,IACxB;AAED,WAAO;AAAA,EACR;AAAA,EAED,mBAAmB,gBAAgB;AACjC,SAAK,iBAAiB;AACtB,WAAO;AAAA,EACR;AAAA,EAED,OAAO,gBAAgB,cAAc,aAAa;AAChD,UAAM,YAAY,KAAK,gBAAiB;AACxC,WAAO,KAAK,WAAW,WAAW,gBAAgB,cAAc,WAAW;AAAA,EAC5E;AAAA,EAED,kBAAkB;AAChB,UAAM,kBAAkB,KAAK,aAAa,KAAK,aAAa,SAAS,CAAC;AACtE,WAAO,KAAK,aAAa,KAAK,eAAc,IAAK,eAAe;AAAA,EACjE;AAAA,EAED,aAAa,GAAG;AACd,UAAM,OAAO,KAAK;AAClB,QAAI,QAAQ;AACZ,QAAI,MAAM,KAAK,SAAS;AAExB,QAAI,QAAQ;AAEZ,WAAO,SAAS,KAAK;AACnB,YAAM,MAAM,KAAK,MAAM,QAAQ,OAAO,CAAC;AAEvC,UAAI,QAAQ,KAAM,KAAK,MAAM,CAAC,KAAK,KAAK,KAAK,GAAG,IAAI,GAAI;AACtD,gBAAQ;AAER;AAAA,MACD,WAAU,IAAI,KAAK,GAAG,GAAG;AACxB,cAAM,MAAM;AAAA,MACpB,OAAa;AACL,gBAAQ,MAAM;AAAA,MACf;AAAA,IACF;AAED,WAAO;AAAA,EACR;AAAA,EAED,WAAW,WAAW,gBAAgB,cAAc,aAAa;AAC/D,QAAI,IAAI,KAAK,eAAgB;AAC7B,QAAI,IAAI,KAAK,eAAgB;AAE7B,QAAI,IAAI,IAAI,GAAG;AACb,UAAI,IAAI;AACR,UAAI,IAAI;AAAA,IACT;AAED,UAAM,EAAE,oBAAoB,KAAK,mBAAmB,YAAY,CAAC;AACjE,UAAM,EAAE,oBAAoB,KAAK,mBAAmB,YAAY,IAAI,CAAC;AACrE,UAAM,EAAE,oBAAoB,KAAK,mBAAmB,YAAY,IAAI,CAAC;AAErE,mBACG,IAAI,GAAG,GAAG,CAAC,EACX,gBAAgB,MAAM,GAAG,CAAC,EAC1B,gBAAgB,MAAM,GAAG,CAAC,EAC1B,gBAAgB,MAAM,GAAG,KAAK,IAAI,EAAE;AAEvC,QAAI,iBAAiB,QAAW;AAC9B,YAAM,UAAU,YAAY;AAAA,IAC7B;AAED,QAAI,gBAAgB,UAAa,KAAK,mBAAmB,QAAW;AAClE,YAAM,EAAE,oBAAoB,KAAK,gBAAgB,YAAY,CAAC;AAC9D,YAAM,EAAE,oBAAoB,KAAK,gBAAgB,YAAY,IAAI,CAAC;AAClE,YAAM,EAAE,oBAAoB,KAAK,gBAAgB,YAAY,IAAI,CAAC;AAElE,aACG,IAAI,GAAG,GAAG,CAAC,EACX,gBAAgB,MAAM,GAAG,CAAC,EAC1B,gBAAgB,MAAM,GAAG,CAAC,EAC1B,gBAAgB,MAAM,GAAG,KAAK,IAAI,EAAE;AAEvC,kBAAY,IAAI,OAAO;AACvB,kBAAY,IAAI,OAAO;AACvB,kBAAY,IAAI,OAAO;AAAA,IACxB;AAED,WAAO;AAAA,EACR;AACH;;"}