three-pathfinding
Advanced tools
Comparing version 0.10.0 to 0.11.0
@@ -1,2 +0,2 @@ | ||
var e=function(){};e.computeCentroids=function(e){var t,r,n;for(t=0,r=e.faces.length;t<r;t++)(n=e.faces[t]).centroid=new THREE.Vector3(0,0,0),n.centroid.add(e.vertices[n.a]),n.centroid.add(e.vertices[n.b]),n.centroid.add(e.vertices[n.c]),n.centroid.divideScalar(3)},e.roundNumber=function(e,t){return Number(e.toFixed(t))},e.sample=function(e){return e[Math.floor(Math.random()*e.length)]},e.mergeVertexIds=function(e,t){var r=[];if(e.forEach(function(e){t.indexOf(e)>=0&&r.push(e)}),r.length<2)return[];r.includes(e[0])&&r.includes(e[e.length-1])&&e.push(e.shift()),r.includes(t[0])&&r.includes(t[t.length-1])&&t.push(t.shift()),r=[],e.forEach(function(e){t.includes(e)&&r.push(e)});for(var n=r[1],o=r[0],i=e.slice();i[0]!==n;)i.push(i.shift());for(var s=0,a=t.slice();a[0]!==o;)if(a.push(a.shift()),s++>10)throw new Error("Unexpected state");return a.shift(),a.pop(),i=i.concat(a)},e.setPolygonCentroid=function(e,t){var r=new THREE.Vector3,n=t.vertices;e.vertexIds.forEach(function(e){r.add(n[e])}),r.divideScalar(e.vertexIds.length),e.centroid.copy(r)},e.cleanPolygon=function(e,t){for(var r=[],n=t.vertices,o=0;o<e.vertexIds.length;o++){var i,s,a,h=n[e.vertexIds[o]];0===o?(i=e.vertexIds[1],s=e.vertexIds[e.vertexIds.length-1]):o===e.vertexIds.length-1?(i=e.vertexIds[0],s=e.vertexIds[e.vertexIds.length-2]):(i=e.vertexIds[o+1],s=e.vertexIds[o-1]),a=n[s];var c=n[i].clone().sub(h),u=a.clone().sub(h),l=c.angleTo(u);if(l>Math.PI-.01&&l<Math.PI+.01){var d=[];e.neighbours.forEach(function(t){t.vertexIds.includes(e.vertexIds[o])||d.push(t)}),e.neighbours=d}else r.push(e.vertexIds[o])}e.vertexIds=r,this.setPolygonCentroid(e,t)},e.isConvex=function(e,t){var r=t.vertices;if(e.vertexIds.length<3)return!1;for(var n=!0,o=[],i=0;i<e.vertexIds.length;i++){var s,a,h=r[e.vertexIds[i]];0===i?(s=r[e.vertexIds[1]],a=r[e.vertexIds[e.vertexIds.length-1]]):i===e.vertexIds.length-1?(s=r[e.vertexIds[0]],a=r[e.vertexIds[e.vertexIds.length-2]]):(s=r[e.vertexIds[i+1]],a=r[e.vertexIds[i-1]]);var c=s.clone().sub(h),u=a.clone().sub(h),l=c.angleTo(u);if(l===Math.PI||0===l)return!1;var d=c.cross(u).y;o.push(d)}return o.forEach(function(e){0===e&&(n=!1)}),o.forEach(o[0]>0?function(e){e<0&&(n=!1)}:function(e){e>0&&(n=!1)}),n},e.distanceToSquared=function(e,t){var r=e.x-t.x,n=e.y-t.y,o=e.z-t.z;return r*r+n*n+o*o},e.isPointInPoly=function(e,t){for(var r=!1,n=-1,o=e.length,i=o-1;++n<o;i=n)(e[n].z<=t.z&&t.z<e[i].z||e[i].z<=t.z&&t.z<e[n].z)&&t.x<(e[i].x-e[n].x)*(t.z-e[n].z)/(e[i].z-e[n].z)+e[n].x&&(r=!r);return r},e.isVectorInPolygon=function(e,t,r){var n=1e5,o=-1e5,i=[];return t.vertexIds.forEach(function(e){n=Math.min(r[e].y,n),o=Math.max(r[e].y,o),i.push(r[e])}),!!(e.y<o+.5&&e.y>n-.5&&this.isPointInPoly(i,e))},e.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},e.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var t=function(e){this.content=[],this.scoreFunction=e};t.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},t.prototype.pop=function(){var e=this.content[0],t=this.content.pop();return this.content.length>0&&(this.content[0]=t,this.bubbleUp(0)),e},t.prototype.remove=function(e){var t=this.content.indexOf(e),r=this.content.pop();t!==this.content.length-1&&(this.content[t]=r,this.scoreFunction(r)<this.scoreFunction(e)?this.sinkDown(t):this.bubbleUp(t))},t.prototype.size=function(){return this.content.length},t.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},t.prototype.sinkDown=function(e){for(var t=this.content[e];e>0;){var r=(e+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(t)<this.scoreFunction(n)))break;this.content[r]=t,this.content[e]=n,e=r}},t.prototype.bubbleUp=function(e){for(var t=this.content.length,r=this.content[e],n=this.scoreFunction(r);;){var o=e+1<<1,i=o-1,s=null,a=void 0;if(i<t)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<t)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}};var r=function(){};r.init=function(e){for(var t=0;t<e.length;t++){var r=e[t];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},r.cleanUp=function(e){for(var t=0;t<e.length;t++){var r=e[t];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},r.heap=function(){return new t(function(e){return e.f})},r.search=function(e,t,r){this.init(e);var n=this.heap();for(n.push(t);n.size()>0;){var o=n.pop();if(o===r){for(var i=o,s=[];i.parent;)s.push(i),i=i.parent;return this.cleanUp(s),s.reverse()}o.closed=!0;for(var a=this.neighbours(e,o),h=0,c=a.length;h<c;h++){var u=a[h];if(!u.closed){var l=o.g+u.cost,d=u.visited;if(!d||l<u.g){if(u.visited=!0,u.parent=o,!u.centroid||!r.centroid)throw new Error("Unexpected state");u.h=u.h||this.heuristic(u.centroid,r.centroid),u.g=l,u.f=u.g+u.h,d?n.rescoreElement(u):n.push(u)}}}}return[]},r.heuristic=function(t,r){return e.distanceToSquared(t,r)},r.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var n=1,o=function(){};o.buildZone=function(t){var r=this,n=this._buildNavigationMesh(t),o={};n.vertices.forEach(function(t){t.x=e.roundNumber(t.x,2),t.y=e.roundNumber(t.y,2),t.z=e.roundNumber(t.z,2)}),o.vertices=n.vertices;var i=this._buildPolygonGroups(n);return o.groups=new Array(i.length),i.forEach(function(t,n){var i={};t.forEach(function(e,t){i[e.id]=t});var s=new Array(t.length);t.forEach(function(t,n){var o=[];t.neighbours.forEach(function(e){return o.push(i[e.id])});var a=[];t.neighbours.forEach(function(e){return a.push(r._getSharedVerticesInOrder(t,e))}),t.centroid.x=e.roundNumber(t.centroid.x,2),t.centroid.y=e.roundNumber(t.centroid.y,2),t.centroid.z=e.roundNumber(t.centroid.z,2),s[n]={id:n,neighbours:o,vertexIds:t.vertexIds,centroid:t.centroid,portals:a}}),o.groups[n]=s}),o},o._buildNavigationMesh=function(t){return e.computeCentroids(t),t.mergeVertices(),this._buildPolygonsFromGeometry(t)},o._buildPolygonGroups=function(e){var t=[],r=function(e){e.neighbours.forEach(function(t){void 0===t.group&&(t.group=e.group,r(t))})};return e.polygons.forEach(function(e){void 0!==e.group?t[e.group].push(e):(e.group=t.length,r(e),t.push([e]))}),t},o._buildPolygonNeighbours=function(e,t){var r=new Set,n=t[e.vertexIds[1]],o=t[e.vertexIds[2]];return t[e.vertexIds[0]].forEach(function(t){t!==e&&(n.includes(t)||o.includes(t))&&r.add(t)}),n.forEach(function(t){t!==e&&o.includes(t)&&r.add(t)}),r},o._buildPolygonsFromGeometry=function(e){for(var t=this,r=[],o=e.vertices,i=e.faceVertexUvs,s=new Array(o.length),a=0;a<o.length;a++)s[a]=[];return e.faces.forEach(function(e){var t={id:n++,vertexIds:[e.a,e.b,e.c],centroid:e.centroid,normal:e.normal,neighbours:null};r.push(t),s[e.a].push(t),s[e.b].push(t),s[e.c].push(t)}),r.forEach(function(e){e.neighbours=t._buildPolygonNeighbours(e,s)}),{polygons:r,vertices:o,faceVertexUvs:i}},o._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=t.vertexIds,o=new Set;if(r.forEach(function(e){n.includes(e)&&o.add(e)}),o.size<2)return[];o.has(r[0])&&o.has(r[r.length-1])&&r.push(r.shift()),o.has(n[0])&&o.has(n[n.length-1])&&n.push(n.shift());var i=[];return r.forEach(function(e){n.includes(e)&&i.push(e)}),i};var i=function(){this.portals=[]};i.prototype.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},i.prototype.stringPull=function(){var t,r,n,o=this.portals,i=[],s=0,a=0,h=0;r=o[0].left,n=o[0].right,i.push(t=o[0].left);for(var c=1;c<o.length;c++){var u=o[c].left,l=o[c].right;if(e.triarea2(t,n,l)<=0){if(!(e.vequal(t,n)||e.triarea2(t,r,l)>0)){i.push(r),r=t=r,n=t,a=s=a,h=s,c=s;continue}n=l,h=c}if(e.triarea2(t,r,u)>=0){if(!(e.vequal(t,r)||e.triarea2(t,n,u)<0)){i.push(n),r=t=n,n=t,a=s=h,h=s,c=s;continue}r=u,a=c}}return 0!==i.length&&e.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i};var s,a=function(){this.zones={}};a.createZone=function(e){return e.isGeometry?console.warn("[three-pathfinding]: Use THREE.BufferGeometry, not THREE.Geometry, to create zone."):e=(new THREE.Geometry).fromBufferGeometry(e),o.buildZone(e)},a.prototype.setZoneData=function(e,t){this.zones[e]=t},a.prototype.getRandomNode=function(t,r,n,o){if(!this.zones[t])return new THREE.Vector3;n=n||null,o=o||0;var i=[];return this.zones[t].groups[r].forEach(function(t){n&&o?e.distanceToSquared(n,t.centroid)<o*o&&i.push(t.centroid):i.push(t.centroid)}),e.sample(i)||new THREE.Vector3},a.prototype.getClosestNode=function(t,r,n,o){void 0===o&&(o=!1);var i=this.zones[r].vertices,s=null,a=Infinity;return this.zones[r].groups[n].forEach(function(r){var n=e.distanceToSquared(r.centroid,t);n<a&&(!o||e.isVectorInPolygon(t,r,i))&&(s=r,a=n)}),s},a.prototype.findPath=function(e,t,n,o){var s=this.zones[n].groups[o],a=this.zones[n].vertices,h=this.getClosestNode(e,n,o,!0),c=this.getClosestNode(t,n,o,!0);if(!h||!c)return null;var u=r.search(s,h,c),l=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},d=new i;d.push(e);for(var p=0;p<u.length;p++){var f=u[p+1];if(f){var v=l(u[p],f);d.push(a[v[0]],a[v[1]])}}d.push(t),d.stringPull();var g=d.path.map(function(e){return new THREE.Vector3(e.x,e.y,e.z)});return g.shift(),g},a.prototype.getGroup=(s=new THREE.Plane,function(t,r,n){if(void 0===n&&(n=!1),!this.zones[t])return null;for(var o=null,i=Math.pow(50,2),a=this.zones[t],h=0;h<a.groups.length;h++)for(var c=0,u=a.groups[h];c<u.length;c+=1){var l=u[c];if(n&&(s.setFromCoplanarPoints(a.vertices[l.vertexIds[0]],a.vertices[l.vertexIds[1]],a.vertices[l.vertexIds[2]]),Math.abs(s.distanceToPoint(r))<.01&&e.isPointInPoly([a.vertices[l.vertexIds[0]],a.vertices[l.vertexIds[1]],a.vertices[l.vertexIds[2]]],r)))return h;var d=e.distanceToSquared(l.centroid,r);d<i&&(o=h,i=d)}return o}),a.prototype.clampStep=function(){var e,t,r=new THREE.Vector3,n=new THREE.Plane,o=new THREE.Triangle,i=new THREE.Vector3,s=new THREE.Vector3;return function(a,h,c,u,l,d){var p=this.zones[u].vertices,f=this.zones[u].groups[l],v=[c],g={};g[c.id]=0,e=void 0,s.set(0,0,0),t=Infinity,n.setFromCoplanarPoints(p[c.vertexIds[0]],p[c.vertexIds[1]],p[c.vertexIds[2]]),n.projectPoint(h,r),i.copy(r);for(var E=v.pop();E;E=v.pop()){o.set(p[E.vertexIds[0]],p[E.vertexIds[1]],p[E.vertexIds[2]]),o.closestPointToPoint(i,r),r.distanceToSquared(i)<t&&(e=E,s.copy(r),t=r.distanceToSquared(i));var x=g[E];if(!(x>2))for(var y=0;y<E.neighbours.length;y++){var T=f[E.neighbours[y]];T.id in g||(v.push(T),g[T.id]=x+1)}}return d.copy(s),e}}();var h={PLAYER:new THREE.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new THREE.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new THREE.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new THREE.Color(4417387).convertGammaToLinear(2.2).getHex()},c=function(e){function t(){var t=this;e.call(this),this._playerMarker=new THREE.Mesh(new THREE.SphereGeometry(.25,32,32),new THREE.MeshBasicMaterial({color:h.PLAYER})),this._targetMarker=new THREE.Mesh(new THREE.BoxGeometry(.3,.3,.3),new THREE.MeshBasicMaterial({color:h.TARGET})),this._nodeMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,.8,.1),new THREE.MeshBasicMaterial({color:h.CLOSEST_NODE})),this._stepMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,1,.1),new THREE.MeshBasicMaterial({color:h.CLAMPED_STEP})),this._pathMarker=new THREE.Object3D,this._pathLineMaterial=new THREE.LineBasicMaterial({color:h.PATH,linewidth:2}),this._pathPointMaterial=new THREE.MeshBasicMaterial({color:h.WAYPOINT}),this._pathPointGeometry=new THREE.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,t.add(e)})}return e&&(t.__proto__=e),(t.prototype=Object.create(e&&e.prototype)).constructor=t,t.prototype.setPath=function(e){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);e=[this._playerMarker.position].concat(e);for(var t=new THREE.Geometry,r=0;r<e.length;r++)t.vertices.push(e[r].clone().add(new THREE.Vector3(0,.2,0)));this._pathMarker.add(new THREE.Line(t,this._pathLineMaterial));for(var n=0;n<e.length-1;n++){var o=new THREE.Mesh(this._pathPointGeometry,this._pathPointMaterial);o.position.copy(e[n]),o.position.y+=.2,this._pathMarker.add(o)}return this._pathMarker.visible=!0,this},t.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},t.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},t.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},t.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},t.prototype.reset=function(){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);return this._markers.forEach(function(e){e.visible=!1}),this},t}(THREE.Object3D);exports.Pathfinding=a,exports.PathfindingHelper=c; | ||
var e=function(){};e.roundNumber=function(e,t){var r=Math.pow(10,t);return Math.round(e*r)/r},e.sample=function(e){return e[Math.floor(Math.random()*e.length)]},e.distanceToSquared=function(e,t){var r=e.x-t.x,n=e.y-t.y,o=e.z-t.z;return r*r+n*n+o*o},e.isPointInPoly=function(e,t){for(var r=!1,n=-1,o=e.length,i=o-1;++n<o;i=n)(e[n].z<=t.z&&t.z<e[i].z||e[i].z<=t.z&&t.z<e[n].z)&&t.x<(e[i].x-e[n].x)*(t.z-e[n].z)/(e[i].z-e[n].z)+e[n].x&&(r=!r);return r},e.isVectorInPolygon=function(e,t,r){var n=1e5,o=-1e5,i=[];return t.vertexIds.forEach(function(e){n=Math.min(r[e].y,n),o=Math.max(r[e].y,o),i.push(r[e])}),!!(e.y<o+.5&&e.y>n-.5&&this.isPointInPoly(i,e))},e.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},e.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var t=function(e){this.content=[],this.scoreFunction=e};t.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},t.prototype.pop=function(){var e=this.content[0],t=this.content.pop();return this.content.length>0&&(this.content[0]=t,this.bubbleUp(0)),e},t.prototype.remove=function(e){var t=this.content.indexOf(e),r=this.content.pop();t!==this.content.length-1&&(this.content[t]=r,this.scoreFunction(r)<this.scoreFunction(e)?this.sinkDown(t):this.bubbleUp(t))},t.prototype.size=function(){return this.content.length},t.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},t.prototype.sinkDown=function(e){for(var t=this.content[e];e>0;){var r=(e+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(t)<this.scoreFunction(n)))break;this.content[r]=t,this.content[e]=n,e=r}},t.prototype.bubbleUp=function(e){for(var t=this.content.length,r=this.content[e],n=this.scoreFunction(r);;){var o=e+1<<1,i=o-1,s=null,a=void 0;if(i<t)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<t)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}};var r=function(){};r.init=function(e){for(var t=0;t<e.length;t++){var r=e[t];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},r.cleanUp=function(e){for(var t=0;t<e.length;t++){var r=e[t];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},r.heap=function(){return new t(function(e){return e.f})},r.search=function(e,t,r){this.init(e);var n=this.heap();for(n.push(t);n.size()>0;){var o=n.pop();if(o===r){for(var i=o,s=[];i.parent;)s.push(i),i=i.parent;return this.cleanUp(s),s.reverse()}o.closed=!0;for(var a=this.neighbours(e,o),h=0,c=a.length;h<c;h++){var u=a[h];if(!u.closed){var p=o.g+u.cost,l=u.visited;if(!l||p<u.g){if(u.visited=!0,u.parent=o,!u.centroid||!r.centroid)throw new Error("Unexpected state");u.h=u.h||this.heuristic(u.centroid,r.centroid),u.g=p,u.f=u.g+u.h,l?n.rescoreElement(u):n.push(u)}}}}return[]},r.heuristic=function(t,r){return e.distanceToSquared(t,r)},r.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var n=function(){};n.buildZone=function(t){var r=this,n=this._buildNavigationMesh(t),o={};n.vertices.forEach(function(t){t.x=e.roundNumber(t.x,2),t.y=e.roundNumber(t.y,2),t.z=e.roundNumber(t.z,2)}),o.vertices=n.vertices;var i=this._buildPolygonGroups(n);return o.groups=new Array(i.length),i.forEach(function(t,n){var i=new Map;t.forEach(function(e,t){i.set(e,t)});var s=new Array(t.length);t.forEach(function(t,n){var a=[];t.neighbours.forEach(function(e){return a.push(i.get(e))});var h=[];t.neighbours.forEach(function(e){return h.push(r._getSharedVerticesInOrder(t,e))});var c=new THREE.Vector3(0,0,0);c.add(o.vertices[t.vertexIds[0]]),c.add(o.vertices[t.vertexIds[1]]),c.add(o.vertices[t.vertexIds[2]]),c.divideScalar(3),c.x=e.roundNumber(c.x,2),c.y=e.roundNumber(c.y,2),c.z=e.roundNumber(c.z,2),s[n]={id:n,neighbours:a,vertexIds:t.vertexIds,centroid:c,portals:h}}),o.groups[n]=s}),o},n._buildNavigationMesh=function(e){return e.mergeVertices(),this._buildPolygonsFromGeometry(e)},n._buildPolygonGroups=function(e){var t=[],r=function(e){e.neighbours.forEach(function(t){void 0===t.group&&(t.group=e.group,r(t))})};return e.polygons.forEach(function(e){void 0!==e.group?t[e.group].push(e):(e.group=t.length,r(e),t.push([e]))}),t},n._buildPolygonNeighbours=function(e,t){var r=new Set,n=t[e.vertexIds[1]],o=t[e.vertexIds[2]];return t[e.vertexIds[0]].forEach(function(t){t!==e&&(n.includes(t)||o.includes(t))&&r.add(t)}),n.forEach(function(t){t!==e&&o.includes(t)&&r.add(t)}),r},n._buildPolygonsFromGeometry=function(e){for(var t=this,r=[],n=e.vertices,o=new Array(n.length),i=0;i<n.length;i++)o[i]=[];return e.faces.forEach(function(e){var t={vertexIds:[e.a,e.b,e.c],neighbours:null};r.push(t),o[e.a].push(t),o[e.b].push(t),o[e.c].push(t)}),r.forEach(function(e){e.neighbours=t._buildPolygonNeighbours(e,o)}),{polygons:r,vertices:n}},n._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=r[0],o=r[1],i=r[2],s=t.vertexIds,a=s.includes(n),h=s.includes(o),c=s.includes(i);return a&&h&&c?Array.from(r):a&&h?[n,o]:h&&c?[o,i]:a&&c?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])};var o=function(){this.portals=[]};o.prototype.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},o.prototype.stringPull=function(){var t,r,n,o=this.portals,i=[],s=0,a=0,h=0;r=o[0].left,n=o[0].right,i.push(t=o[0].left);for(var c=1;c<o.length;c++){var u=o[c].left,p=o[c].right;if(e.triarea2(t,n,p)<=0){if(!(e.vequal(t,n)||e.triarea2(t,r,p)>0)){i.push(r),r=t=r,n=t,a=s=a,h=s,c=s;continue}n=p,h=c}if(e.triarea2(t,r,u)>=0){if(!(e.vequal(t,r)||e.triarea2(t,n,u)<0)){i.push(n),r=t=n,n=t,a=s=h,h=s,c=s;continue}r=u,a=c}}return 0!==i.length&&e.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i};var i,s=function(){this.zones={}};s.createZone=function(e){return e.isGeometry?console.warn("[three-pathfinding]: Use THREE.BufferGeometry, not THREE.Geometry, to create zone."):e=(new THREE.Geometry).fromBufferGeometry(e),n.buildZone(e)},s.prototype.setZoneData=function(e,t){this.zones[e]=t},s.prototype.getRandomNode=function(t,r,n,o){if(!this.zones[t])return new THREE.Vector3;n=n||null,o=o||0;var i=[];return this.zones[t].groups[r].forEach(function(t){n&&o?e.distanceToSquared(n,t.centroid)<o*o&&i.push(t.centroid):i.push(t.centroid)}),e.sample(i)||new THREE.Vector3},s.prototype.getClosestNode=function(t,r,n,o){void 0===o&&(o=!1);var i=this.zones[r].vertices,s=null,a=Infinity;return this.zones[r].groups[n].forEach(function(r){var n=e.distanceToSquared(r.centroid,t);n<a&&(!o||e.isVectorInPolygon(t,r,i))&&(s=r,a=n)}),s},s.prototype.findPath=function(e,t,n,i){var s=this.zones[n].groups[i],a=this.zones[n].vertices,h=this.getClosestNode(e,n,i,!0),c=this.getClosestNode(t,n,i,!0);if(!h||!c)return null;var u=r.search(s,h,c),p=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},l=new o;l.push(e);for(var f=0;f<u.length;f++){var d=u[f+1];if(d){var v=p(u[f],d);l.push(a[v[0]],a[v[1]])}}l.push(t),l.stringPull();var E=l.path.map(function(e){return new THREE.Vector3(e.x,e.y,e.z)});return E.shift(),E},s.prototype.getGroup=(i=new THREE.Plane,function(t,r,n){if(void 0===n&&(n=!1),!this.zones[t])return null;for(var o=null,s=Math.pow(50,2),a=this.zones[t],h=0;h<a.groups.length;h++)for(var c=0,u=a.groups[h];c<u.length;c+=1){var p=u[c];if(n&&(i.setFromCoplanarPoints(a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]),Math.abs(i.distanceToPoint(r))<.01&&e.isPointInPoly([a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]],r)))return h;var l=e.distanceToSquared(p.centroid,r);l<s&&(o=h,s=l)}return o}),s.prototype.clampStep=function(){var e,t,r=new THREE.Vector3,n=new THREE.Plane,o=new THREE.Triangle,i=new THREE.Vector3,s=new THREE.Vector3;return function(a,h,c,u,p,l){var f=this.zones[u].vertices,d=this.zones[u].groups[p],v=[c],E={};E[c.id]=0,e=void 0,s.set(0,0,0),t=Infinity,n.setFromCoplanarPoints(f[c.vertexIds[0]],f[c.vertexIds[1]],f[c.vertexIds[2]]),n.projectPoint(h,r),i.copy(r);for(var g=v.pop();g;g=v.pop()){o.set(f[g.vertexIds[0]],f[g.vertexIds[1]],f[g.vertexIds[2]]),o.closestPointToPoint(i,r),r.distanceToSquared(i)<t&&(e=g,s.copy(r),t=r.distanceToSquared(i));var y=E[g];if(!(y>2))for(var T=0;T<g.neighbours.length;T++){var M=d[g.neighbours[T]];M.id in E||(v.push(M),E[M.id]=y+1)}}return l.copy(s),e}}();var a={PLAYER:new THREE.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new THREE.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new THREE.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new THREE.Color(4417387).convertGammaToLinear(2.2).getHex()},h=function(e){function t(){var t=this;e.call(this),this._playerMarker=new THREE.Mesh(new THREE.SphereGeometry(.25,32,32),new THREE.MeshBasicMaterial({color:a.PLAYER})),this._targetMarker=new THREE.Mesh(new THREE.BoxGeometry(.3,.3,.3),new THREE.MeshBasicMaterial({color:a.TARGET})),this._nodeMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,.8,.1),new THREE.MeshBasicMaterial({color:a.CLOSEST_NODE})),this._stepMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,1,.1),new THREE.MeshBasicMaterial({color:a.CLAMPED_STEP})),this._pathMarker=new THREE.Object3D,this._pathLineMaterial=new THREE.LineBasicMaterial({color:a.PATH,linewidth:2}),this._pathPointMaterial=new THREE.MeshBasicMaterial({color:a.WAYPOINT}),this._pathPointGeometry=new THREE.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,t.add(e)})}return e&&(t.__proto__=e),(t.prototype=Object.create(e&&e.prototype)).constructor=t,t.prototype.setPath=function(e){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);e=[this._playerMarker.position].concat(e);for(var t=new THREE.Geometry,r=0;r<e.length;r++)t.vertices.push(e[r].clone().add(new THREE.Vector3(0,.2,0)));this._pathMarker.add(new THREE.Line(t,this._pathLineMaterial));for(var n=0;n<e.length-1;n++){var o=new THREE.Mesh(this._pathPointGeometry,this._pathPointMaterial);o.position.copy(e[n]),o.position.y+=.2,this._pathMarker.add(o)}return this._pathMarker.visible=!0,this},t.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},t.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},t.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},t.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},t.prototype.reset=function(){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);return this._markers.forEach(function(e){e.visible=!1}),this},t}(THREE.Object3D);exports.Pathfinding=s,exports.PathfindingHelper=h; | ||
//# sourceMappingURL=three-pathfinding.js.map |
@@ -1,2 +0,2 @@ | ||
var e=function(){};e.computeCentroids=function(e){var t,r,n;for(t=0,r=e.faces.length;t<r;t++)(n=e.faces[t]).centroid=new THREE.Vector3(0,0,0),n.centroid.add(e.vertices[n.a]),n.centroid.add(e.vertices[n.b]),n.centroid.add(e.vertices[n.c]),n.centroid.divideScalar(3)},e.roundNumber=function(e,t){return Number(e.toFixed(t))},e.sample=function(e){return e[Math.floor(Math.random()*e.length)]},e.mergeVertexIds=function(e,t){var r=[];if(e.forEach(function(e){t.indexOf(e)>=0&&r.push(e)}),r.length<2)return[];r.includes(e[0])&&r.includes(e[e.length-1])&&e.push(e.shift()),r.includes(t[0])&&r.includes(t[t.length-1])&&t.push(t.shift()),r=[],e.forEach(function(e){t.includes(e)&&r.push(e)});for(var n=r[1],o=r[0],i=e.slice();i[0]!==n;)i.push(i.shift());for(var s=0,a=t.slice();a[0]!==o;)if(a.push(a.shift()),s++>10)throw new Error("Unexpected state");return a.shift(),a.pop(),i=i.concat(a)},e.setPolygonCentroid=function(e,t){var r=new THREE.Vector3,n=t.vertices;e.vertexIds.forEach(function(e){r.add(n[e])}),r.divideScalar(e.vertexIds.length),e.centroid.copy(r)},e.cleanPolygon=function(e,t){for(var r=[],n=t.vertices,o=0;o<e.vertexIds.length;o++){var i,s,a,h=n[e.vertexIds[o]];0===o?(i=e.vertexIds[1],s=e.vertexIds[e.vertexIds.length-1]):o===e.vertexIds.length-1?(i=e.vertexIds[0],s=e.vertexIds[e.vertexIds.length-2]):(i=e.vertexIds[o+1],s=e.vertexIds[o-1]),a=n[s];var c=n[i].clone().sub(h),u=a.clone().sub(h),l=c.angleTo(u);if(l>Math.PI-.01&&l<Math.PI+.01){var d=[];e.neighbours.forEach(function(t){t.vertexIds.includes(e.vertexIds[o])||d.push(t)}),e.neighbours=d}else r.push(e.vertexIds[o])}e.vertexIds=r,this.setPolygonCentroid(e,t)},e.isConvex=function(e,t){var r=t.vertices;if(e.vertexIds.length<3)return!1;for(var n=!0,o=[],i=0;i<e.vertexIds.length;i++){var s,a,h=r[e.vertexIds[i]];0===i?(s=r[e.vertexIds[1]],a=r[e.vertexIds[e.vertexIds.length-1]]):i===e.vertexIds.length-1?(s=r[e.vertexIds[0]],a=r[e.vertexIds[e.vertexIds.length-2]]):(s=r[e.vertexIds[i+1]],a=r[e.vertexIds[i-1]]);var c=s.clone().sub(h),u=a.clone().sub(h),l=c.angleTo(u);if(l===Math.PI||0===l)return!1;var d=c.cross(u).y;o.push(d)}return o.forEach(function(e){0===e&&(n=!1)}),o.forEach(o[0]>0?function(e){e<0&&(n=!1)}:function(e){e>0&&(n=!1)}),n},e.distanceToSquared=function(e,t){var r=e.x-t.x,n=e.y-t.y,o=e.z-t.z;return r*r+n*n+o*o},e.isPointInPoly=function(e,t){for(var r=!1,n=-1,o=e.length,i=o-1;++n<o;i=n)(e[n].z<=t.z&&t.z<e[i].z||e[i].z<=t.z&&t.z<e[n].z)&&t.x<(e[i].x-e[n].x)*(t.z-e[n].z)/(e[i].z-e[n].z)+e[n].x&&(r=!r);return r},e.isVectorInPolygon=function(e,t,r){var n=1e5,o=-1e5,i=[];return t.vertexIds.forEach(function(e){n=Math.min(r[e].y,n),o=Math.max(r[e].y,o),i.push(r[e])}),!!(e.y<o+.5&&e.y>n-.5&&this.isPointInPoly(i,e))},e.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},e.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var t=function(e){this.content=[],this.scoreFunction=e};t.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},t.prototype.pop=function(){var e=this.content[0],t=this.content.pop();return this.content.length>0&&(this.content[0]=t,this.bubbleUp(0)),e},t.prototype.remove=function(e){var t=this.content.indexOf(e),r=this.content.pop();t!==this.content.length-1&&(this.content[t]=r,this.scoreFunction(r)<this.scoreFunction(e)?this.sinkDown(t):this.bubbleUp(t))},t.prototype.size=function(){return this.content.length},t.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},t.prototype.sinkDown=function(e){for(var t=this.content[e];e>0;){var r=(e+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(t)<this.scoreFunction(n)))break;this.content[r]=t,this.content[e]=n,e=r}},t.prototype.bubbleUp=function(e){for(var t=this.content.length,r=this.content[e],n=this.scoreFunction(r);;){var o=e+1<<1,i=o-1,s=null,a=void 0;if(i<t)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<t)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}};var r=function(){};r.init=function(e){for(var t=0;t<e.length;t++){var r=e[t];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},r.cleanUp=function(e){for(var t=0;t<e.length;t++){var r=e[t];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},r.heap=function(){return new t(function(e){return e.f})},r.search=function(e,t,r){this.init(e);var n=this.heap();for(n.push(t);n.size()>0;){var o=n.pop();if(o===r){for(var i=o,s=[];i.parent;)s.push(i),i=i.parent;return this.cleanUp(s),s.reverse()}o.closed=!0;for(var a=this.neighbours(e,o),h=0,c=a.length;h<c;h++){var u=a[h];if(!u.closed){var l=o.g+u.cost,d=u.visited;if(!d||l<u.g){if(u.visited=!0,u.parent=o,!u.centroid||!r.centroid)throw new Error("Unexpected state");u.h=u.h||this.heuristic(u.centroid,r.centroid),u.g=l,u.f=u.g+u.h,d?n.rescoreElement(u):n.push(u)}}}}return[]},r.heuristic=function(t,r){return e.distanceToSquared(t,r)},r.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var n=1,o=function(){};o.buildZone=function(t){var r=this,n=this._buildNavigationMesh(t),o={};n.vertices.forEach(function(t){t.x=e.roundNumber(t.x,2),t.y=e.roundNumber(t.y,2),t.z=e.roundNumber(t.z,2)}),o.vertices=n.vertices;var i=this._buildPolygonGroups(n);return o.groups=new Array(i.length),i.forEach(function(t,n){var i={};t.forEach(function(e,t){i[e.id]=t});var s=new Array(t.length);t.forEach(function(t,n){var o=[];t.neighbours.forEach(function(e){return o.push(i[e.id])});var a=[];t.neighbours.forEach(function(e){return a.push(r._getSharedVerticesInOrder(t,e))}),t.centroid.x=e.roundNumber(t.centroid.x,2),t.centroid.y=e.roundNumber(t.centroid.y,2),t.centroid.z=e.roundNumber(t.centroid.z,2),s[n]={id:n,neighbours:o,vertexIds:t.vertexIds,centroid:t.centroid,portals:a}}),o.groups[n]=s}),o},o._buildNavigationMesh=function(t){return e.computeCentroids(t),t.mergeVertices(),this._buildPolygonsFromGeometry(t)},o._buildPolygonGroups=function(e){var t=[],r=function(e){e.neighbours.forEach(function(t){void 0===t.group&&(t.group=e.group,r(t))})};return e.polygons.forEach(function(e){void 0!==e.group?t[e.group].push(e):(e.group=t.length,r(e),t.push([e]))}),t},o._buildPolygonNeighbours=function(e,t){var r=new Set,n=t[e.vertexIds[1]],o=t[e.vertexIds[2]];return t[e.vertexIds[0]].forEach(function(t){t!==e&&(n.includes(t)||o.includes(t))&&r.add(t)}),n.forEach(function(t){t!==e&&o.includes(t)&&r.add(t)}),r},o._buildPolygonsFromGeometry=function(e){for(var t=this,r=[],o=e.vertices,i=e.faceVertexUvs,s=new Array(o.length),a=0;a<o.length;a++)s[a]=[];return e.faces.forEach(function(e){var t={id:n++,vertexIds:[e.a,e.b,e.c],centroid:e.centroid,normal:e.normal,neighbours:null};r.push(t),s[e.a].push(t),s[e.b].push(t),s[e.c].push(t)}),r.forEach(function(e){e.neighbours=t._buildPolygonNeighbours(e,s)}),{polygons:r,vertices:o,faceVertexUvs:i}},o._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=t.vertexIds,o=new Set;if(r.forEach(function(e){n.includes(e)&&o.add(e)}),o.size<2)return[];o.has(r[0])&&o.has(r[r.length-1])&&r.push(r.shift()),o.has(n[0])&&o.has(n[n.length-1])&&n.push(n.shift());var i=[];return r.forEach(function(e){n.includes(e)&&i.push(e)}),i};var i=function(){this.portals=[]};i.prototype.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},i.prototype.stringPull=function(){var t,r,n,o=this.portals,i=[],s=0,a=0,h=0;r=o[0].left,n=o[0].right,i.push(t=o[0].left);for(var c=1;c<o.length;c++){var u=o[c].left,l=o[c].right;if(e.triarea2(t,n,l)<=0){if(!(e.vequal(t,n)||e.triarea2(t,r,l)>0)){i.push(r),r=t=r,n=t,a=s=a,h=s,c=s;continue}n=l,h=c}if(e.triarea2(t,r,u)>=0){if(!(e.vequal(t,r)||e.triarea2(t,n,u)<0)){i.push(n),r=t=n,n=t,a=s=h,h=s,c=s;continue}r=u,a=c}}return 0!==i.length&&e.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i};var s,a=function(){this.zones={}};a.createZone=function(e){return e.isGeometry?console.warn("[three-pathfinding]: Use THREE.BufferGeometry, not THREE.Geometry, to create zone."):e=(new THREE.Geometry).fromBufferGeometry(e),o.buildZone(e)},a.prototype.setZoneData=function(e,t){this.zones[e]=t},a.prototype.getRandomNode=function(t,r,n,o){if(!this.zones[t])return new THREE.Vector3;n=n||null,o=o||0;var i=[];return this.zones[t].groups[r].forEach(function(t){n&&o?e.distanceToSquared(n,t.centroid)<o*o&&i.push(t.centroid):i.push(t.centroid)}),e.sample(i)||new THREE.Vector3},a.prototype.getClosestNode=function(t,r,n,o){void 0===o&&(o=!1);var i=this.zones[r].vertices,s=null,a=Infinity;return this.zones[r].groups[n].forEach(function(r){var n=e.distanceToSquared(r.centroid,t);n<a&&(!o||e.isVectorInPolygon(t,r,i))&&(s=r,a=n)}),s},a.prototype.findPath=function(e,t,n,o){var s=this.zones[n].groups[o],a=this.zones[n].vertices,h=this.getClosestNode(e,n,o,!0),c=this.getClosestNode(t,n,o,!0);if(!h||!c)return null;var u=r.search(s,h,c),l=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},d=new i;d.push(e);for(var p=0;p<u.length;p++){var f=u[p+1];if(f){var v=l(u[p],f);d.push(a[v[0]],a[v[1]])}}d.push(t),d.stringPull();var g=d.path.map(function(e){return new THREE.Vector3(e.x,e.y,e.z)});return g.shift(),g},a.prototype.getGroup=(s=new THREE.Plane,function(t,r,n){if(void 0===n&&(n=!1),!this.zones[t])return null;for(var o=null,i=Math.pow(50,2),a=this.zones[t],h=0;h<a.groups.length;h++)for(var c=0,u=a.groups[h];c<u.length;c+=1){var l=u[c];if(n&&(s.setFromCoplanarPoints(a.vertices[l.vertexIds[0]],a.vertices[l.vertexIds[1]],a.vertices[l.vertexIds[2]]),Math.abs(s.distanceToPoint(r))<.01&&e.isPointInPoly([a.vertices[l.vertexIds[0]],a.vertices[l.vertexIds[1]],a.vertices[l.vertexIds[2]]],r)))return h;var d=e.distanceToSquared(l.centroid,r);d<i&&(o=h,i=d)}return o}),a.prototype.clampStep=function(){var e,t,r=new THREE.Vector3,n=new THREE.Plane,o=new THREE.Triangle,i=new THREE.Vector3,s=new THREE.Vector3;return function(a,h,c,u,l,d){var p=this.zones[u].vertices,f=this.zones[u].groups[l],v=[c],g={};g[c.id]=0,e=void 0,s.set(0,0,0),t=Infinity,n.setFromCoplanarPoints(p[c.vertexIds[0]],p[c.vertexIds[1]],p[c.vertexIds[2]]),n.projectPoint(h,r),i.copy(r);for(var E=v.pop();E;E=v.pop()){o.set(p[E.vertexIds[0]],p[E.vertexIds[1]],p[E.vertexIds[2]]),o.closestPointToPoint(i,r),r.distanceToSquared(i)<t&&(e=E,s.copy(r),t=r.distanceToSquared(i));var y=g[E];if(!(y>2))for(var x=0;x<E.neighbours.length;x++){var T=f[E.neighbours[x]];T.id in g||(v.push(T),g[T.id]=y+1)}}return d.copy(s),e}}();var h={PLAYER:new THREE.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new THREE.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new THREE.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new THREE.Color(4417387).convertGammaToLinear(2.2).getHex()},c=function(e){function t(){var t=this;e.call(this),this._playerMarker=new THREE.Mesh(new THREE.SphereGeometry(.25,32,32),new THREE.MeshBasicMaterial({color:h.PLAYER})),this._targetMarker=new THREE.Mesh(new THREE.BoxGeometry(.3,.3,.3),new THREE.MeshBasicMaterial({color:h.TARGET})),this._nodeMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,.8,.1),new THREE.MeshBasicMaterial({color:h.CLOSEST_NODE})),this._stepMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,1,.1),new THREE.MeshBasicMaterial({color:h.CLAMPED_STEP})),this._pathMarker=new THREE.Object3D,this._pathLineMaterial=new THREE.LineBasicMaterial({color:h.PATH,linewidth:2}),this._pathPointMaterial=new THREE.MeshBasicMaterial({color:h.WAYPOINT}),this._pathPointGeometry=new THREE.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,t.add(e)})}return e&&(t.__proto__=e),(t.prototype=Object.create(e&&e.prototype)).constructor=t,t.prototype.setPath=function(e){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);e=[this._playerMarker.position].concat(e);for(var t=new THREE.Geometry,r=0;r<e.length;r++)t.vertices.push(e[r].clone().add(new THREE.Vector3(0,.2,0)));this._pathMarker.add(new THREE.Line(t,this._pathLineMaterial));for(var n=0;n<e.length-1;n++){var o=new THREE.Mesh(this._pathPointGeometry,this._pathPointMaterial);o.position.copy(e[n]),o.position.y+=.2,this._pathMarker.add(o)}return this._pathMarker.visible=!0,this},t.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},t.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},t.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},t.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},t.prototype.reset=function(){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);return this._markers.forEach(function(e){e.visible=!1}),this},t}(THREE.Object3D);export{a as Pathfinding,c as PathfindingHelper}; | ||
var e=function(){};e.roundNumber=function(e,t){var r=Math.pow(10,t);return Math.round(e*r)/r},e.sample=function(e){return e[Math.floor(Math.random()*e.length)]},e.distanceToSquared=function(e,t){var r=e.x-t.x,n=e.y-t.y,o=e.z-t.z;return r*r+n*n+o*o},e.isPointInPoly=function(e,t){for(var r=!1,n=-1,o=e.length,i=o-1;++n<o;i=n)(e[n].z<=t.z&&t.z<e[i].z||e[i].z<=t.z&&t.z<e[n].z)&&t.x<(e[i].x-e[n].x)*(t.z-e[n].z)/(e[i].z-e[n].z)+e[n].x&&(r=!r);return r},e.isVectorInPolygon=function(e,t,r){var n=1e5,o=-1e5,i=[];return t.vertexIds.forEach(function(e){n=Math.min(r[e].y,n),o=Math.max(r[e].y,o),i.push(r[e])}),!!(e.y<o+.5&&e.y>n-.5&&this.isPointInPoly(i,e))},e.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},e.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var t=function(e){this.content=[],this.scoreFunction=e};t.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},t.prototype.pop=function(){var e=this.content[0],t=this.content.pop();return this.content.length>0&&(this.content[0]=t,this.bubbleUp(0)),e},t.prototype.remove=function(e){var t=this.content.indexOf(e),r=this.content.pop();t!==this.content.length-1&&(this.content[t]=r,this.scoreFunction(r)<this.scoreFunction(e)?this.sinkDown(t):this.bubbleUp(t))},t.prototype.size=function(){return this.content.length},t.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},t.prototype.sinkDown=function(e){for(var t=this.content[e];e>0;){var r=(e+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(t)<this.scoreFunction(n)))break;this.content[r]=t,this.content[e]=n,e=r}},t.prototype.bubbleUp=function(e){for(var t=this.content.length,r=this.content[e],n=this.scoreFunction(r);;){var o=e+1<<1,i=o-1,s=null,a=void 0;if(i<t)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<t)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}};var r=function(){};r.init=function(e){for(var t=0;t<e.length;t++){var r=e[t];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},r.cleanUp=function(e){for(var t=0;t<e.length;t++){var r=e[t];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},r.heap=function(){return new t(function(e){return e.f})},r.search=function(e,t,r){this.init(e);var n=this.heap();for(n.push(t);n.size()>0;){var o=n.pop();if(o===r){for(var i=o,s=[];i.parent;)s.push(i),i=i.parent;return this.cleanUp(s),s.reverse()}o.closed=!0;for(var a=this.neighbours(e,o),h=0,c=a.length;h<c;h++){var u=a[h];if(!u.closed){var p=o.g+u.cost,l=u.visited;if(!l||p<u.g){if(u.visited=!0,u.parent=o,!u.centroid||!r.centroid)throw new Error("Unexpected state");u.h=u.h||this.heuristic(u.centroid,r.centroid),u.g=p,u.f=u.g+u.h,l?n.rescoreElement(u):n.push(u)}}}}return[]},r.heuristic=function(t,r){return e.distanceToSquared(t,r)},r.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var n=function(){};n.buildZone=function(t){var r=this,n=this._buildNavigationMesh(t),o={};n.vertices.forEach(function(t){t.x=e.roundNumber(t.x,2),t.y=e.roundNumber(t.y,2),t.z=e.roundNumber(t.z,2)}),o.vertices=n.vertices;var i=this._buildPolygonGroups(n);return o.groups=new Array(i.length),i.forEach(function(t,n){var i=new Map;t.forEach(function(e,t){i.set(e,t)});var s=new Array(t.length);t.forEach(function(t,n){var a=[];t.neighbours.forEach(function(e){return a.push(i.get(e))});var h=[];t.neighbours.forEach(function(e){return h.push(r._getSharedVerticesInOrder(t,e))});var c=new THREE.Vector3(0,0,0);c.add(o.vertices[t.vertexIds[0]]),c.add(o.vertices[t.vertexIds[1]]),c.add(o.vertices[t.vertexIds[2]]),c.divideScalar(3),c.x=e.roundNumber(c.x,2),c.y=e.roundNumber(c.y,2),c.z=e.roundNumber(c.z,2),s[n]={id:n,neighbours:a,vertexIds:t.vertexIds,centroid:c,portals:h}}),o.groups[n]=s}),o},n._buildNavigationMesh=function(e){return e.mergeVertices(),this._buildPolygonsFromGeometry(e)},n._buildPolygonGroups=function(e){var t=[],r=function(e){e.neighbours.forEach(function(t){void 0===t.group&&(t.group=e.group,r(t))})};return e.polygons.forEach(function(e){void 0!==e.group?t[e.group].push(e):(e.group=t.length,r(e),t.push([e]))}),t},n._buildPolygonNeighbours=function(e,t){var r=new Set,n=t[e.vertexIds[1]],o=t[e.vertexIds[2]];return t[e.vertexIds[0]].forEach(function(t){t!==e&&(n.includes(t)||o.includes(t))&&r.add(t)}),n.forEach(function(t){t!==e&&o.includes(t)&&r.add(t)}),r},n._buildPolygonsFromGeometry=function(e){for(var t=this,r=[],n=e.vertices,o=new Array(n.length),i=0;i<n.length;i++)o[i]=[];return e.faces.forEach(function(e){var t={vertexIds:[e.a,e.b,e.c],neighbours:null};r.push(t),o[e.a].push(t),o[e.b].push(t),o[e.c].push(t)}),r.forEach(function(e){e.neighbours=t._buildPolygonNeighbours(e,o)}),{polygons:r,vertices:n}},n._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=r[0],o=r[1],i=r[2],s=t.vertexIds,a=s.includes(n),h=s.includes(o),c=s.includes(i);return a&&h&&c?Array.from(r):a&&h?[n,o]:h&&c?[o,i]:a&&c?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])};var o=function(){this.portals=[]};o.prototype.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},o.prototype.stringPull=function(){var t,r,n,o=this.portals,i=[],s=0,a=0,h=0;r=o[0].left,n=o[0].right,i.push(t=o[0].left);for(var c=1;c<o.length;c++){var u=o[c].left,p=o[c].right;if(e.triarea2(t,n,p)<=0){if(!(e.vequal(t,n)||e.triarea2(t,r,p)>0)){i.push(r),r=t=r,n=t,a=s=a,h=s,c=s;continue}n=p,h=c}if(e.triarea2(t,r,u)>=0){if(!(e.vequal(t,r)||e.triarea2(t,n,u)<0)){i.push(n),r=t=n,n=t,a=s=h,h=s,c=s;continue}r=u,a=c}}return 0!==i.length&&e.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i};var i,s=function(){this.zones={}};s.createZone=function(e){return e.isGeometry?console.warn("[three-pathfinding]: Use THREE.BufferGeometry, not THREE.Geometry, to create zone."):e=(new THREE.Geometry).fromBufferGeometry(e),n.buildZone(e)},s.prototype.setZoneData=function(e,t){this.zones[e]=t},s.prototype.getRandomNode=function(t,r,n,o){if(!this.zones[t])return new THREE.Vector3;n=n||null,o=o||0;var i=[];return this.zones[t].groups[r].forEach(function(t){n&&o?e.distanceToSquared(n,t.centroid)<o*o&&i.push(t.centroid):i.push(t.centroid)}),e.sample(i)||new THREE.Vector3},s.prototype.getClosestNode=function(t,r,n,o){void 0===o&&(o=!1);var i=this.zones[r].vertices,s=null,a=Infinity;return this.zones[r].groups[n].forEach(function(r){var n=e.distanceToSquared(r.centroid,t);n<a&&(!o||e.isVectorInPolygon(t,r,i))&&(s=r,a=n)}),s},s.prototype.findPath=function(e,t,n,i){var s=this.zones[n].groups[i],a=this.zones[n].vertices,h=this.getClosestNode(e,n,i,!0),c=this.getClosestNode(t,n,i,!0);if(!h||!c)return null;var u=r.search(s,h,c),p=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},l=new o;l.push(e);for(var f=0;f<u.length;f++){var d=u[f+1];if(d){var v=p(u[f],d);l.push(a[v[0]],a[v[1]])}}l.push(t),l.stringPull();var E=l.path.map(function(e){return new THREE.Vector3(e.x,e.y,e.z)});return E.shift(),E},s.prototype.getGroup=(i=new THREE.Plane,function(t,r,n){if(void 0===n&&(n=!1),!this.zones[t])return null;for(var o=null,s=Math.pow(50,2),a=this.zones[t],h=0;h<a.groups.length;h++)for(var c=0,u=a.groups[h];c<u.length;c+=1){var p=u[c];if(n&&(i.setFromCoplanarPoints(a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]),Math.abs(i.distanceToPoint(r))<.01&&e.isPointInPoly([a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]],r)))return h;var l=e.distanceToSquared(p.centroid,r);l<s&&(o=h,s=l)}return o}),s.prototype.clampStep=function(){var e,t,r=new THREE.Vector3,n=new THREE.Plane,o=new THREE.Triangle,i=new THREE.Vector3,s=new THREE.Vector3;return function(a,h,c,u,p,l){var f=this.zones[u].vertices,d=this.zones[u].groups[p],v=[c],E={};E[c.id]=0,e=void 0,s.set(0,0,0),t=Infinity,n.setFromCoplanarPoints(f[c.vertexIds[0]],f[c.vertexIds[1]],f[c.vertexIds[2]]),n.projectPoint(h,r),i.copy(r);for(var g=v.pop();g;g=v.pop()){o.set(f[g.vertexIds[0]],f[g.vertexIds[1]],f[g.vertexIds[2]]),o.closestPointToPoint(i,r),r.distanceToSquared(i)<t&&(e=g,s.copy(r),t=r.distanceToSquared(i));var y=E[g];if(!(y>2))for(var T=0;T<g.neighbours.length;T++){var M=d[g.neighbours[T]];M.id in E||(v.push(M),E[M.id]=y+1)}}return l.copy(s),e}}();var a={PLAYER:new THREE.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new THREE.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new THREE.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new THREE.Color(4417387).convertGammaToLinear(2.2).getHex()},h=function(e){function t(){var t=this;e.call(this),this._playerMarker=new THREE.Mesh(new THREE.SphereGeometry(.25,32,32),new THREE.MeshBasicMaterial({color:a.PLAYER})),this._targetMarker=new THREE.Mesh(new THREE.BoxGeometry(.3,.3,.3),new THREE.MeshBasicMaterial({color:a.TARGET})),this._nodeMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,.8,.1),new THREE.MeshBasicMaterial({color:a.CLOSEST_NODE})),this._stepMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,1,.1),new THREE.MeshBasicMaterial({color:a.CLAMPED_STEP})),this._pathMarker=new THREE.Object3D,this._pathLineMaterial=new THREE.LineBasicMaterial({color:a.PATH,linewidth:2}),this._pathPointMaterial=new THREE.MeshBasicMaterial({color:a.WAYPOINT}),this._pathPointGeometry=new THREE.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,t.add(e)})}return e&&(t.__proto__=e),(t.prototype=Object.create(e&&e.prototype)).constructor=t,t.prototype.setPath=function(e){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);e=[this._playerMarker.position].concat(e);for(var t=new THREE.Geometry,r=0;r<e.length;r++)t.vertices.push(e[r].clone().add(new THREE.Vector3(0,.2,0)));this._pathMarker.add(new THREE.Line(t,this._pathLineMaterial));for(var n=0;n<e.length-1;n++){var o=new THREE.Mesh(this._pathPointGeometry,this._pathPointMaterial);o.position.copy(e[n]),o.position.y+=.2,this._pathMarker.add(o)}return this._pathMarker.visible=!0,this},t.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},t.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},t.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},t.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},t.prototype.reset=function(){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);return this._markers.forEach(function(e){e.visible=!1}),this},t}(THREE.Object3D);export{s as Pathfinding,h as PathfindingHelper}; | ||
//# sourceMappingURL=three-pathfinding.module.js.map |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.threePathfinding={})}(this,function(e){var t=function(){};t.computeCentroids=function(e){var t,r,n;for(t=0,r=e.faces.length;t<r;t++)(n=e.faces[t]).centroid=new THREE.Vector3(0,0,0),n.centroid.add(e.vertices[n.a]),n.centroid.add(e.vertices[n.b]),n.centroid.add(e.vertices[n.c]),n.centroid.divideScalar(3)},t.roundNumber=function(e,t){return Number(e.toFixed(t))},t.sample=function(e){return e[Math.floor(Math.random()*e.length)]},t.mergeVertexIds=function(e,t){var r=[];if(e.forEach(function(e){t.indexOf(e)>=0&&r.push(e)}),r.length<2)return[];r.includes(e[0])&&r.includes(e[e.length-1])&&e.push(e.shift()),r.includes(t[0])&&r.includes(t[t.length-1])&&t.push(t.shift()),r=[],e.forEach(function(e){t.includes(e)&&r.push(e)});for(var n=r[1],o=r[0],i=e.slice();i[0]!==n;)i.push(i.shift());for(var s=0,a=t.slice();a[0]!==o;)if(a.push(a.shift()),s++>10)throw new Error("Unexpected state");return a.shift(),a.pop(),i=i.concat(a)},t.setPolygonCentroid=function(e,t){var r=new THREE.Vector3,n=t.vertices;e.vertexIds.forEach(function(e){r.add(n[e])}),r.divideScalar(e.vertexIds.length),e.centroid.copy(r)},t.cleanPolygon=function(e,t){for(var r=[],n=t.vertices,o=0;o<e.vertexIds.length;o++){var i,s,a,h=n[e.vertexIds[o]];0===o?(i=e.vertexIds[1],s=e.vertexIds[e.vertexIds.length-1]):o===e.vertexIds.length-1?(i=e.vertexIds[0],s=e.vertexIds[e.vertexIds.length-2]):(i=e.vertexIds[o+1],s=e.vertexIds[o-1]),a=n[s];var c=n[i].clone().sub(h),u=a.clone().sub(h),d=c.angleTo(u);if(d>Math.PI-.01&&d<Math.PI+.01){var l=[];e.neighbours.forEach(function(t){t.vertexIds.includes(e.vertexIds[o])||l.push(t)}),e.neighbours=l}else r.push(e.vertexIds[o])}e.vertexIds=r,this.setPolygonCentroid(e,t)},t.isConvex=function(e,t){var r=t.vertices;if(e.vertexIds.length<3)return!1;for(var n=!0,o=[],i=0;i<e.vertexIds.length;i++){var s,a,h=r[e.vertexIds[i]];0===i?(s=r[e.vertexIds[1]],a=r[e.vertexIds[e.vertexIds.length-1]]):i===e.vertexIds.length-1?(s=r[e.vertexIds[0]],a=r[e.vertexIds[e.vertexIds.length-2]]):(s=r[e.vertexIds[i+1]],a=r[e.vertexIds[i-1]]);var c=s.clone().sub(h),u=a.clone().sub(h),d=c.angleTo(u);if(d===Math.PI||0===d)return!1;var l=c.cross(u).y;o.push(l)}return o.forEach(function(e){0===e&&(n=!1)}),o.forEach(o[0]>0?function(e){e<0&&(n=!1)}:function(e){e>0&&(n=!1)}),n},t.distanceToSquared=function(e,t){var r=e.x-t.x,n=e.y-t.y,o=e.z-t.z;return r*r+n*n+o*o},t.isPointInPoly=function(e,t){for(var r=!1,n=-1,o=e.length,i=o-1;++n<o;i=n)(e[n].z<=t.z&&t.z<e[i].z||e[i].z<=t.z&&t.z<e[n].z)&&t.x<(e[i].x-e[n].x)*(t.z-e[n].z)/(e[i].z-e[n].z)+e[n].x&&(r=!r);return r},t.isVectorInPolygon=function(e,t,r){var n=1e5,o=-1e5,i=[];return t.vertexIds.forEach(function(e){n=Math.min(r[e].y,n),o=Math.max(r[e].y,o),i.push(r[e])}),!!(e.y<o+.5&&e.y>n-.5&&this.isPointInPoly(i,e))},t.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},t.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var r=function(e){this.content=[],this.scoreFunction=e};r.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},r.prototype.pop=function(){var e=this.content[0],t=this.content.pop();return this.content.length>0&&(this.content[0]=t,this.bubbleUp(0)),e},r.prototype.remove=function(e){var t=this.content.indexOf(e),r=this.content.pop();t!==this.content.length-1&&(this.content[t]=r,this.scoreFunction(r)<this.scoreFunction(e)?this.sinkDown(t):this.bubbleUp(t))},r.prototype.size=function(){return this.content.length},r.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},r.prototype.sinkDown=function(e){for(var t=this.content[e];e>0;){var r=(e+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(t)<this.scoreFunction(n)))break;this.content[r]=t,this.content[e]=n,e=r}},r.prototype.bubbleUp=function(e){for(var t=this.content.length,r=this.content[e],n=this.scoreFunction(r);;){var o=e+1<<1,i=o-1,s=null,a=void 0;if(i<t)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<t)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}};var n=function(){};n.init=function(e){for(var t=0;t<e.length;t++){var r=e[t];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},n.cleanUp=function(e){for(var t=0;t<e.length;t++){var r=e[t];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},n.heap=function(){return new r(function(e){return e.f})},n.search=function(e,t,r){this.init(e);var n=this.heap();for(n.push(t);n.size()>0;){var o=n.pop();if(o===r){for(var i=o,s=[];i.parent;)s.push(i),i=i.parent;return this.cleanUp(s),s.reverse()}o.closed=!0;for(var a=this.neighbours(e,o),h=0,c=a.length;h<c;h++){var u=a[h];if(!u.closed){var d=o.g+u.cost,l=u.visited;if(!l||d<u.g){if(u.visited=!0,u.parent=o,!u.centroid||!r.centroid)throw new Error("Unexpected state");u.h=u.h||this.heuristic(u.centroid,r.centroid),u.g=d,u.f=u.g+u.h,l?n.rescoreElement(u):n.push(u)}}}}return[]},n.heuristic=function(e,r){return t.distanceToSquared(e,r)},n.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var o=1,i=function(){};i.buildZone=function(e){var r=this,n=this._buildNavigationMesh(e),o={};n.vertices.forEach(function(e){e.x=t.roundNumber(e.x,2),e.y=t.roundNumber(e.y,2),e.z=t.roundNumber(e.z,2)}),o.vertices=n.vertices;var i=this._buildPolygonGroups(n);return o.groups=new Array(i.length),i.forEach(function(e,n){var i={};e.forEach(function(e,t){i[e.id]=t});var s=new Array(e.length);e.forEach(function(e,n){var o=[];e.neighbours.forEach(function(e){return o.push(i[e.id])});var a=[];e.neighbours.forEach(function(t){return a.push(r._getSharedVerticesInOrder(e,t))}),e.centroid.x=t.roundNumber(e.centroid.x,2),e.centroid.y=t.roundNumber(e.centroid.y,2),e.centroid.z=t.roundNumber(e.centroid.z,2),s[n]={id:n,neighbours:o,vertexIds:e.vertexIds,centroid:e.centroid,portals:a}}),o.groups[n]=s}),o},i._buildNavigationMesh=function(e){return t.computeCentroids(e),e.mergeVertices(),this._buildPolygonsFromGeometry(e)},i._buildPolygonGroups=function(e){var t=[],r=function(e){e.neighbours.forEach(function(t){void 0===t.group&&(t.group=e.group,r(t))})};return e.polygons.forEach(function(e){void 0!==e.group?t[e.group].push(e):(e.group=t.length,r(e),t.push([e]))}),t},i._buildPolygonNeighbours=function(e,t){var r=new Set,n=t[e.vertexIds[1]],o=t[e.vertexIds[2]];return t[e.vertexIds[0]].forEach(function(t){t!==e&&(n.includes(t)||o.includes(t))&&r.add(t)}),n.forEach(function(t){t!==e&&o.includes(t)&&r.add(t)}),r},i._buildPolygonsFromGeometry=function(e){for(var t=this,r=[],n=e.vertices,i=e.faceVertexUvs,s=new Array(n.length),a=0;a<n.length;a++)s[a]=[];return e.faces.forEach(function(e){var t={id:o++,vertexIds:[e.a,e.b,e.c],centroid:e.centroid,normal:e.normal,neighbours:null};r.push(t),s[e.a].push(t),s[e.b].push(t),s[e.c].push(t)}),r.forEach(function(e){e.neighbours=t._buildPolygonNeighbours(e,s)}),{polygons:r,vertices:n,faceVertexUvs:i}},i._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=t.vertexIds,o=new Set;if(r.forEach(function(e){n.includes(e)&&o.add(e)}),o.size<2)return[];o.has(r[0])&&o.has(r[r.length-1])&&r.push(r.shift()),o.has(n[0])&&o.has(n[n.length-1])&&n.push(n.shift());var i=[];return r.forEach(function(e){n.includes(e)&&i.push(e)}),i};var s=function(){this.portals=[]};s.prototype.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},s.prototype.stringPull=function(){var e,r,n,o=this.portals,i=[],s=0,a=0,h=0;r=o[0].left,n=o[0].right,i.push(e=o[0].left);for(var c=1;c<o.length;c++){var u=o[c].left,d=o[c].right;if(t.triarea2(e,n,d)<=0){if(!(t.vequal(e,n)||t.triarea2(e,r,d)>0)){i.push(r),r=e=r,n=e,a=s=a,h=s,c=s;continue}n=d,h=c}if(t.triarea2(e,r,u)>=0){if(!(t.vequal(e,r)||t.triarea2(e,n,u)<0)){i.push(n),r=e=n,n=e,a=s=h,h=s,c=s;continue}r=u,a=c}}return 0!==i.length&&t.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i};var a,h=function(){this.zones={}};h.createZone=function(e){return e.isGeometry?console.warn("[three-pathfinding]: Use THREE.BufferGeometry, not THREE.Geometry, to create zone."):e=(new THREE.Geometry).fromBufferGeometry(e),i.buildZone(e)},h.prototype.setZoneData=function(e,t){this.zones[e]=t},h.prototype.getRandomNode=function(e,r,n,o){if(!this.zones[e])return new THREE.Vector3;n=n||null,o=o||0;var i=[];return this.zones[e].groups[r].forEach(function(e){n&&o?t.distanceToSquared(n,e.centroid)<o*o&&i.push(e.centroid):i.push(e.centroid)}),t.sample(i)||new THREE.Vector3},h.prototype.getClosestNode=function(e,r,n,o){void 0===o&&(o=!1);var i=this.zones[r].vertices,s=null,a=Infinity;return this.zones[r].groups[n].forEach(function(r){var n=t.distanceToSquared(r.centroid,e);n<a&&(!o||t.isVectorInPolygon(e,r,i))&&(s=r,a=n)}),s},h.prototype.findPath=function(e,t,r,o){var i=this.zones[r].groups[o],a=this.zones[r].vertices,h=this.getClosestNode(e,r,o,!0),c=this.getClosestNode(t,r,o,!0);if(!h||!c)return null;var u=n.search(i,h,c),d=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},l=new s;l.push(e);for(var f=0;f<u.length;f++){var p=u[f+1];if(p){var v=d(u[f],p);l.push(a[v[0]],a[v[1]])}}l.push(t),l.stringPull();var g=l.path.map(function(e){return new THREE.Vector3(e.x,e.y,e.z)});return g.shift(),g},h.prototype.getGroup=(a=new THREE.Plane,function(e,r,n){if(void 0===n&&(n=!1),!this.zones[e])return null;for(var o=null,i=Math.pow(50,2),s=this.zones[e],h=0;h<s.groups.length;h++)for(var c=0,u=s.groups[h];c<u.length;c+=1){var d=u[c];if(n&&(a.setFromCoplanarPoints(s.vertices[d.vertexIds[0]],s.vertices[d.vertexIds[1]],s.vertices[d.vertexIds[2]]),Math.abs(a.distanceToPoint(r))<.01&&t.isPointInPoly([s.vertices[d.vertexIds[0]],s.vertices[d.vertexIds[1]],s.vertices[d.vertexIds[2]]],r)))return h;var l=t.distanceToSquared(d.centroid,r);l<i&&(o=h,i=l)}return o}),h.prototype.clampStep=function(){var e,t,r=new THREE.Vector3,n=new THREE.Plane,o=new THREE.Triangle,i=new THREE.Vector3,s=new THREE.Vector3;return function(a,h,c,u,d,l){var f=this.zones[u].vertices,p=this.zones[u].groups[d],v=[c],g={};g[c.id]=0,e=void 0,s.set(0,0,0),t=Infinity,n.setFromCoplanarPoints(f[c.vertexIds[0]],f[c.vertexIds[1]],f[c.vertexIds[2]]),n.projectPoint(h,r),i.copy(r);for(var E=v.pop();E;E=v.pop()){o.set(f[E.vertexIds[0]],f[E.vertexIds[1]],f[E.vertexIds[2]]),o.closestPointToPoint(i,r),r.distanceToSquared(i)<t&&(e=E,s.copy(r),t=r.distanceToSquared(i));var y=g[E];if(!(y>2))for(var x=0;x<E.neighbours.length;x++){var T=p[E.neighbours[x]];T.id in g||(v.push(T),g[T.id]=y+1)}}return l.copy(s),e}}();var c={PLAYER:new THREE.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new THREE.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new THREE.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new THREE.Color(4417387).convertGammaToLinear(2.2).getHex()},u=function(e){function t(){var t=this;e.call(this),this._playerMarker=new THREE.Mesh(new THREE.SphereGeometry(.25,32,32),new THREE.MeshBasicMaterial({color:c.PLAYER})),this._targetMarker=new THREE.Mesh(new THREE.BoxGeometry(.3,.3,.3),new THREE.MeshBasicMaterial({color:c.TARGET})),this._nodeMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,.8,.1),new THREE.MeshBasicMaterial({color:c.CLOSEST_NODE})),this._stepMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,1,.1),new THREE.MeshBasicMaterial({color:c.CLAMPED_STEP})),this._pathMarker=new THREE.Object3D,this._pathLineMaterial=new THREE.LineBasicMaterial({color:c.PATH,linewidth:2}),this._pathPointMaterial=new THREE.MeshBasicMaterial({color:c.WAYPOINT}),this._pathPointGeometry=new THREE.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,t.add(e)})}return e&&(t.__proto__=e),(t.prototype=Object.create(e&&e.prototype)).constructor=t,t.prototype.setPath=function(e){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);e=[this._playerMarker.position].concat(e);for(var t=new THREE.Geometry,r=0;r<e.length;r++)t.vertices.push(e[r].clone().add(new THREE.Vector3(0,.2,0)));this._pathMarker.add(new THREE.Line(t,this._pathLineMaterial));for(var n=0;n<e.length-1;n++){var o=new THREE.Mesh(this._pathPointGeometry,this._pathPointMaterial);o.position.copy(e[n]),o.position.y+=.2,this._pathMarker.add(o)}return this._pathMarker.visible=!0,this},t.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},t.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},t.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},t.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},t.prototype.reset=function(){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);return this._markers.forEach(function(e){e.visible=!1}),this},t}(THREE.Object3D);e.Pathfinding=h,e.PathfindingHelper=u}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.threePathfinding={})}(this,function(e){var t=function(){};t.roundNumber=function(e,t){var r=Math.pow(10,t);return Math.round(e*r)/r},t.sample=function(e){return e[Math.floor(Math.random()*e.length)]},t.distanceToSquared=function(e,t){var r=e.x-t.x,n=e.y-t.y,o=e.z-t.z;return r*r+n*n+o*o},t.isPointInPoly=function(e,t){for(var r=!1,n=-1,o=e.length,i=o-1;++n<o;i=n)(e[n].z<=t.z&&t.z<e[i].z||e[i].z<=t.z&&t.z<e[n].z)&&t.x<(e[i].x-e[n].x)*(t.z-e[n].z)/(e[i].z-e[n].z)+e[n].x&&(r=!r);return r},t.isVectorInPolygon=function(e,t,r){var n=1e5,o=-1e5,i=[];return t.vertexIds.forEach(function(e){n=Math.min(r[e].y,n),o=Math.max(r[e].y,o),i.push(r[e])}),!!(e.y<o+.5&&e.y>n-.5&&this.isPointInPoly(i,e))},t.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},t.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var r=function(e){this.content=[],this.scoreFunction=e};r.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},r.prototype.pop=function(){var e=this.content[0],t=this.content.pop();return this.content.length>0&&(this.content[0]=t,this.bubbleUp(0)),e},r.prototype.remove=function(e){var t=this.content.indexOf(e),r=this.content.pop();t!==this.content.length-1&&(this.content[t]=r,this.scoreFunction(r)<this.scoreFunction(e)?this.sinkDown(t):this.bubbleUp(t))},r.prototype.size=function(){return this.content.length},r.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},r.prototype.sinkDown=function(e){for(var t=this.content[e];e>0;){var r=(e+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(t)<this.scoreFunction(n)))break;this.content[r]=t,this.content[e]=n,e=r}},r.prototype.bubbleUp=function(e){for(var t=this.content.length,r=this.content[e],n=this.scoreFunction(r);;){var o=e+1<<1,i=o-1,s=null,a=void 0;if(i<t)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<t)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}};var n=function(){};n.init=function(e){for(var t=0;t<e.length;t++){var r=e[t];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},n.cleanUp=function(e){for(var t=0;t<e.length;t++){var r=e[t];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},n.heap=function(){return new r(function(e){return e.f})},n.search=function(e,t,r){this.init(e);var n=this.heap();for(n.push(t);n.size()>0;){var o=n.pop();if(o===r){for(var i=o,s=[];i.parent;)s.push(i),i=i.parent;return this.cleanUp(s),s.reverse()}o.closed=!0;for(var a=this.neighbours(e,o),h=0,c=a.length;h<c;h++){var u=a[h];if(!u.closed){var p=o.g+u.cost,l=u.visited;if(!l||p<u.g){if(u.visited=!0,u.parent=o,!u.centroid||!r.centroid)throw new Error("Unexpected state");u.h=u.h||this.heuristic(u.centroid,r.centroid),u.g=p,u.f=u.g+u.h,l?n.rescoreElement(u):n.push(u)}}}}return[]},n.heuristic=function(e,r){return t.distanceToSquared(e,r)},n.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var o=function(){};o.buildZone=function(e){var r=this,n=this._buildNavigationMesh(e),o={};n.vertices.forEach(function(e){e.x=t.roundNumber(e.x,2),e.y=t.roundNumber(e.y,2),e.z=t.roundNumber(e.z,2)}),o.vertices=n.vertices;var i=this._buildPolygonGroups(n);return o.groups=new Array(i.length),i.forEach(function(e,n){var i=new Map;e.forEach(function(e,t){i.set(e,t)});var s=new Array(e.length);e.forEach(function(e,n){var a=[];e.neighbours.forEach(function(e){return a.push(i.get(e))});var h=[];e.neighbours.forEach(function(t){return h.push(r._getSharedVerticesInOrder(e,t))});var c=new THREE.Vector3(0,0,0);c.add(o.vertices[e.vertexIds[0]]),c.add(o.vertices[e.vertexIds[1]]),c.add(o.vertices[e.vertexIds[2]]),c.divideScalar(3),c.x=t.roundNumber(c.x,2),c.y=t.roundNumber(c.y,2),c.z=t.roundNumber(c.z,2),s[n]={id:n,neighbours:a,vertexIds:e.vertexIds,centroid:c,portals:h}}),o.groups[n]=s}),o},o._buildNavigationMesh=function(e){return e.mergeVertices(),this._buildPolygonsFromGeometry(e)},o._buildPolygonGroups=function(e){var t=[],r=function(e){e.neighbours.forEach(function(t){void 0===t.group&&(t.group=e.group,r(t))})};return e.polygons.forEach(function(e){void 0!==e.group?t[e.group].push(e):(e.group=t.length,r(e),t.push([e]))}),t},o._buildPolygonNeighbours=function(e,t){var r=new Set,n=t[e.vertexIds[1]],o=t[e.vertexIds[2]];return t[e.vertexIds[0]].forEach(function(t){t!==e&&(n.includes(t)||o.includes(t))&&r.add(t)}),n.forEach(function(t){t!==e&&o.includes(t)&&r.add(t)}),r},o._buildPolygonsFromGeometry=function(e){for(var t=this,r=[],n=e.vertices,o=new Array(n.length),i=0;i<n.length;i++)o[i]=[];return e.faces.forEach(function(e){var t={vertexIds:[e.a,e.b,e.c],neighbours:null};r.push(t),o[e.a].push(t),o[e.b].push(t),o[e.c].push(t)}),r.forEach(function(e){e.neighbours=t._buildPolygonNeighbours(e,o)}),{polygons:r,vertices:n}},o._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=r[0],o=r[1],i=r[2],s=t.vertexIds,a=s.includes(n),h=s.includes(o),c=s.includes(i);return a&&h&&c?Array.from(r):a&&h?[n,o]:h&&c?[o,i]:a&&c?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])};var i=function(){this.portals=[]};i.prototype.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},i.prototype.stringPull=function(){var e,r,n,o=this.portals,i=[],s=0,a=0,h=0;r=o[0].left,n=o[0].right,i.push(e=o[0].left);for(var c=1;c<o.length;c++){var u=o[c].left,p=o[c].right;if(t.triarea2(e,n,p)<=0){if(!(t.vequal(e,n)||t.triarea2(e,r,p)>0)){i.push(r),r=e=r,n=e,a=s=a,h=s,c=s;continue}n=p,h=c}if(t.triarea2(e,r,u)>=0){if(!(t.vequal(e,r)||t.triarea2(e,n,u)<0)){i.push(n),r=e=n,n=e,a=s=h,h=s,c=s;continue}r=u,a=c}}return 0!==i.length&&t.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i};var s,a=function(){this.zones={}};a.createZone=function(e){return e.isGeometry?console.warn("[three-pathfinding]: Use THREE.BufferGeometry, not THREE.Geometry, to create zone."):e=(new THREE.Geometry).fromBufferGeometry(e),o.buildZone(e)},a.prototype.setZoneData=function(e,t){this.zones[e]=t},a.prototype.getRandomNode=function(e,r,n,o){if(!this.zones[e])return new THREE.Vector3;n=n||null,o=o||0;var i=[];return this.zones[e].groups[r].forEach(function(e){n&&o?t.distanceToSquared(n,e.centroid)<o*o&&i.push(e.centroid):i.push(e.centroid)}),t.sample(i)||new THREE.Vector3},a.prototype.getClosestNode=function(e,r,n,o){void 0===o&&(o=!1);var i=this.zones[r].vertices,s=null,a=Infinity;return this.zones[r].groups[n].forEach(function(r){var n=t.distanceToSquared(r.centroid,e);n<a&&(!o||t.isVectorInPolygon(e,r,i))&&(s=r,a=n)}),s},a.prototype.findPath=function(e,t,r,o){var s=this.zones[r].groups[o],a=this.zones[r].vertices,h=this.getClosestNode(e,r,o,!0),c=this.getClosestNode(t,r,o,!0);if(!h||!c)return null;var u=n.search(s,h,c),p=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},l=new i;l.push(e);for(var f=0;f<u.length;f++){var d=u[f+1];if(d){var v=p(u[f],d);l.push(a[v[0]],a[v[1]])}}l.push(t),l.stringPull();var E=l.path.map(function(e){return new THREE.Vector3(e.x,e.y,e.z)});return E.shift(),E},a.prototype.getGroup=(s=new THREE.Plane,function(e,r,n){if(void 0===n&&(n=!1),!this.zones[e])return null;for(var o=null,i=Math.pow(50,2),a=this.zones[e],h=0;h<a.groups.length;h++)for(var c=0,u=a.groups[h];c<u.length;c+=1){var p=u[c];if(n&&(s.setFromCoplanarPoints(a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]),Math.abs(s.distanceToPoint(r))<.01&&t.isPointInPoly([a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]],r)))return h;var l=t.distanceToSquared(p.centroid,r);l<i&&(o=h,i=l)}return o}),a.prototype.clampStep=function(){var e,t,r=new THREE.Vector3,n=new THREE.Plane,o=new THREE.Triangle,i=new THREE.Vector3,s=new THREE.Vector3;return function(a,h,c,u,p,l){var f=this.zones[u].vertices,d=this.zones[u].groups[p],v=[c],E={};E[c.id]=0,e=void 0,s.set(0,0,0),t=Infinity,n.setFromCoplanarPoints(f[c.vertexIds[0]],f[c.vertexIds[1]],f[c.vertexIds[2]]),n.projectPoint(h,r),i.copy(r);for(var g=v.pop();g;g=v.pop()){o.set(f[g.vertexIds[0]],f[g.vertexIds[1]],f[g.vertexIds[2]]),o.closestPointToPoint(i,r),r.distanceToSquared(i)<t&&(e=g,s.copy(r),t=r.distanceToSquared(i));var y=E[g];if(!(y>2))for(var T=0;T<g.neighbours.length;T++){var M=d[g.neighbours[T]];M.id in E||(v.push(M),E[M.id]=y+1)}}return l.copy(s),e}}();var h={PLAYER:new THREE.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new THREE.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new THREE.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new THREE.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new THREE.Color(4417387).convertGammaToLinear(2.2).getHex()},c=function(e){function t(){var t=this;e.call(this),this._playerMarker=new THREE.Mesh(new THREE.SphereGeometry(.25,32,32),new THREE.MeshBasicMaterial({color:h.PLAYER})),this._targetMarker=new THREE.Mesh(new THREE.BoxGeometry(.3,.3,.3),new THREE.MeshBasicMaterial({color:h.TARGET})),this._nodeMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,.8,.1),new THREE.MeshBasicMaterial({color:h.CLOSEST_NODE})),this._stepMarker=new THREE.Mesh(new THREE.BoxGeometry(.1,1,.1),new THREE.MeshBasicMaterial({color:h.CLAMPED_STEP})),this._pathMarker=new THREE.Object3D,this._pathLineMaterial=new THREE.LineBasicMaterial({color:h.PATH,linewidth:2}),this._pathPointMaterial=new THREE.MeshBasicMaterial({color:h.WAYPOINT}),this._pathPointGeometry=new THREE.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,t.add(e)})}return e&&(t.__proto__=e),(t.prototype=Object.create(e&&e.prototype)).constructor=t,t.prototype.setPath=function(e){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);e=[this._playerMarker.position].concat(e);for(var t=new THREE.Geometry,r=0;r<e.length;r++)t.vertices.push(e[r].clone().add(new THREE.Vector3(0,.2,0)));this._pathMarker.add(new THREE.Line(t,this._pathLineMaterial));for(var n=0;n<e.length-1;n++){var o=new THREE.Mesh(this._pathPointGeometry,this._pathPointMaterial);o.position.copy(e[n]),o.position.y+=.2,this._pathMarker.add(o)}return this._pathMarker.visible=!0,this},t.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},t.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},t.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},t.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},t.prototype.reset=function(){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);return this._markers.forEach(function(e){e.visible=!1}),this},t}(THREE.Object3D);e.Pathfinding=a,e.PathfindingHelper=c}); | ||
//# sourceMappingURL=three-pathfinding.umd.js.map |
{ | ||
"name": "three-pathfinding", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Navigation mesh toolkit for three.js, based on PatrolJS", | ||
@@ -5,0 +5,0 @@ "author": "Don McCurdy <dm@donmccurdy.com>", |
import { Utils } from './Utils'; | ||
let polygonId = 1; | ||
class Builder { | ||
@@ -33,4 +31,4 @@ /** | ||
const indexByPolygonId = {}; | ||
group.forEach((poly, polyIndex) => { indexByPolygonId[poly.id] = polyIndex; }); | ||
const indexByPolygon = new Map(); // { polygon: index in group } | ||
group.forEach((poly, polyIndex) => { indexByPolygon.set(poly, polyIndex); }); | ||
@@ -41,3 +39,3 @@ const newGroup = new Array(group.length); | ||
const neighbourIndices = []; | ||
poly.neighbours.forEach((n) => neighbourIndices.push(indexByPolygonId[n.id])); | ||
poly.neighbours.forEach((n) => neighbourIndices.push(indexByPolygon.get(n))); | ||
@@ -48,5 +46,10 @@ // Build a portal list to each neighbour | ||
poly.centroid.x = Utils.roundNumber(poly.centroid.x, 2); | ||
poly.centroid.y = Utils.roundNumber(poly.centroid.y, 2); | ||
poly.centroid.z = Utils.roundNumber(poly.centroid.z, 2); | ||
const centroid = new THREE.Vector3( 0, 0, 0 ); | ||
centroid.add( zone.vertices[ poly.vertexIds[0] ] ); | ||
centroid.add( zone.vertices[ poly.vertexIds[1] ] ); | ||
centroid.add( zone.vertices[ poly.vertexIds[2] ] ); | ||
centroid.divideScalar( 3 ); | ||
centroid.x = Utils.roundNumber(centroid.x, 2); | ||
centroid.y = Utils.roundNumber(centroid.y, 2); | ||
centroid.z = Utils.roundNumber(centroid.z, 2); | ||
@@ -57,3 +60,3 @@ newGroup[polyIndex] = { | ||
vertexIds: poly.vertexIds, | ||
centroid: poly.centroid, | ||
centroid: centroid, | ||
portals: portals | ||
@@ -75,3 +78,2 @@ }; | ||
static _buildNavigationMesh (geometry) { | ||
Utils.computeCentroids(geometry); | ||
geometry.mergeVertices(); | ||
@@ -141,3 +143,2 @@ return this._buildPolygonsFromGeometry(geometry); | ||
const vertices = geometry.vertices; | ||
const faceVertexUvs = geometry.faceVertexUvs; | ||
@@ -155,9 +156,3 @@ // Constructing the neighbor graph brute force is O(n²). To avoid that, | ||
geometry.faces.forEach((face) => { | ||
const poly = { | ||
id: polygonId++, | ||
vertexIds: [face.a, face.b, face.c], | ||
centroid: face.centroid, | ||
normal: face.normal, | ||
neighbours: null | ||
}; | ||
const poly = { vertexIds: [face.a, face.b, face.c], neighbours: null }; | ||
polygons.push(poly); | ||
@@ -176,4 +171,3 @@ vertexPolygonMap[face.a].push(poly); | ||
polygons: polygons, | ||
vertices: vertices, | ||
faceVertexUvs: faceVertexUvs | ||
vertices: vertices | ||
}; | ||
@@ -185,34 +179,24 @@ } | ||
const aList = a.vertexIds; | ||
const a0 = aList[0], a1 = aList[1], a2 = aList[2]; | ||
const bList = b.vertexIds; | ||
const shared0 = bList.includes(a0); | ||
const shared1 = bList.includes(a1); | ||
const shared2 = bList.includes(a2); | ||
const sharedVertices = new Set(); | ||
aList.forEach((vId) => { | ||
if (bList.includes(vId)) { | ||
sharedVertices.add(vId); | ||
} | ||
}); | ||
if (sharedVertices.size < 2) return []; | ||
if (sharedVertices.has(aList[0]) && sharedVertices.has(aList[aList.length - 1])) { | ||
// Vertices on both edges are bad, so shift them once to the left | ||
aList.push(aList.shift()); | ||
// it seems that we shouldn't have an a and b with <2 shared vertices here unless there's a bug | ||
// in the neighbor identification code, or perhaps a malformed input geometry; 3 shared vertices | ||
// is a kind of embarrassing but possible geometry we should handle | ||
if (shared0 && shared1 && shared2) { | ||
return Array.from(aList); | ||
} else if (shared0 && shared1) { | ||
return [a0, a1]; | ||
} else if (shared1 && shared2) { | ||
return [a1, a2]; | ||
} else if (shared0 && shared2) { | ||
return [a2, a0]; // this ordering will affect the string pull algorithm later, not clear if significant | ||
} else { | ||
console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."); | ||
return []; | ||
} | ||
if (sharedVertices.has(bList[0]) && sharedVertices.has(bList[bList.length - 1])) { | ||
// Vertices on both edges are bad, so shift them once to the left | ||
bList.push(bList.shift()); | ||
} | ||
// Again! | ||
const sharedVerticesOrdered = []; | ||
aList.forEach((vId) => { | ||
if (bList.includes(vId)) { | ||
sharedVerticesOrdered.push(vId); | ||
} | ||
}); | ||
return sharedVerticesOrdered; | ||
} | ||
@@ -219,0 +203,0 @@ } |
208
src/Utils.js
class Utils { | ||
static computeCentroids (geometry) { | ||
var f, fl, face; | ||
for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) { | ||
face = geometry.faces[ f ]; | ||
face.centroid = new THREE.Vector3( 0, 0, 0 ); | ||
face.centroid.add( geometry.vertices[ face.a ] ); | ||
face.centroid.add( geometry.vertices[ face.b ] ); | ||
face.centroid.add( geometry.vertices[ face.c ] ); | ||
face.centroid.divideScalar( 3 ); | ||
} | ||
} | ||
static roundNumber (value, decimals) { | ||
return Number(value.toFixed(decimals)); | ||
const factor = Math.pow(10, decimals); | ||
return Math.round(value * factor) / factor; | ||
} | ||
@@ -27,191 +12,2 @@ | ||
static mergeVertexIds (aList, bList) { | ||
var sharedVertices = []; | ||
aList.forEach((vID) => { | ||
if (bList.indexOf(vID) >= 0) { | ||
sharedVertices.push(vID); | ||
} | ||
}); | ||
if (sharedVertices.length < 2) return []; | ||
if (sharedVertices.includes(aList[0]) && sharedVertices.includes(aList[aList.length - 1])) { | ||
// Vertices on both edges are bad, so shift them once to the left | ||
aList.push(aList.shift()); | ||
} | ||
if (sharedVertices.includes(bList[0]) && sharedVertices.includes(bList[bList.length - 1])) { | ||
// Vertices on both edges are bad, so shift them once to the left | ||
bList.push(bList.shift()); | ||
} | ||
// Again! | ||
sharedVertices = []; | ||
aList.forEach((vId) => { | ||
if (bList.includes(vId)) { | ||
sharedVertices.push(vId); | ||
} | ||
}); | ||
var clockwiseMostSharedVertex = sharedVertices[1]; | ||
var counterClockwiseMostSharedVertex = sharedVertices[0]; | ||
var cList = aList.slice(); | ||
while (cList[0] !== clockwiseMostSharedVertex) { | ||
cList.push(cList.shift()); | ||
} | ||
var c = 0; | ||
var temp = bList.slice(); | ||
while (temp[0] !== counterClockwiseMostSharedVertex) { | ||
temp.push(temp.shift()); | ||
if (c++ > 10) throw new Error('Unexpected state'); | ||
} | ||
// Shave | ||
temp.shift(); | ||
temp.pop(); | ||
cList = cList.concat(temp); | ||
return cList; | ||
} | ||
static setPolygonCentroid (polygon, navigationMesh) { | ||
var sum = new THREE.Vector3(); | ||
var vertices = navigationMesh.vertices; | ||
polygon.vertexIds.forEach((vId) => { | ||
sum.add(vertices[vId]); | ||
}); | ||
sum.divideScalar(polygon.vertexIds.length); | ||
polygon.centroid.copy(sum); | ||
} | ||
static cleanPolygon (polygon, navigationMesh) { | ||
var newVertexIds = []; | ||
var vertices = navigationMesh.vertices; | ||
for (var i = 0; i < polygon.vertexIds.length; i++) { | ||
var vertex = vertices[polygon.vertexIds[i]]; | ||
var nextVertexId, previousVertexId; | ||
var nextVertex, previousVertex; | ||
if (i === 0) { | ||
nextVertexId = polygon.vertexIds[1]; | ||
previousVertexId = polygon.vertexIds[polygon.vertexIds.length - 1]; | ||
} else if (i === polygon.vertexIds.length - 1) { | ||
nextVertexId = polygon.vertexIds[0]; | ||
previousVertexId = polygon.vertexIds[polygon.vertexIds.length - 2]; | ||
} else { | ||
nextVertexId = polygon.vertexIds[i + 1]; | ||
previousVertexId = polygon.vertexIds[i - 1]; | ||
} | ||
nextVertex = vertices[nextVertexId]; | ||
previousVertex = vertices[previousVertexId]; | ||
var a = nextVertex.clone().sub(vertex); | ||
var b = previousVertex.clone().sub(vertex); | ||
var angle = a.angleTo(b); | ||
if (angle > Math.PI - 0.01 && angle < Math.PI + 0.01) { | ||
// Remove the neighbours who had this vertex | ||
var goodNeighbours = []; | ||
polygon.neighbours.forEach((neighbour) => { | ||
if (!neighbour.vertexIds.includes(polygon.vertexIds[i])) { | ||
goodNeighbours.push(neighbour); | ||
} | ||
}); | ||
polygon.neighbours = goodNeighbours; | ||
// TODO cleanup the list of vertices and rebuild vertexIds for all polygons | ||
} else { | ||
newVertexIds.push(polygon.vertexIds[i]); | ||
} | ||
} | ||
polygon.vertexIds = newVertexIds; | ||
this.setPolygonCentroid(polygon, navigationMesh); | ||
} | ||
static isConvex (polygon, navigationMesh) { | ||
var vertices = navigationMesh.vertices; | ||
if (polygon.vertexIds.length < 3) return false; | ||
var convex = true; | ||
var total = 0; | ||
var results = []; | ||
for (var i = 0; i < polygon.vertexIds.length; i++) { | ||
var vertex = vertices[polygon.vertexIds[i]]; | ||
var nextVertex, previousVertex; | ||
if (i === 0) { | ||
nextVertex = vertices[polygon.vertexIds[1]]; | ||
previousVertex = vertices[polygon.vertexIds[polygon.vertexIds.length - 1]]; | ||
} else if (i === polygon.vertexIds.length - 1) { | ||
nextVertex = vertices[polygon.vertexIds[0]]; | ||
previousVertex = vertices[polygon.vertexIds[polygon.vertexIds.length - 2]]; | ||
} else { | ||
nextVertex = vertices[polygon.vertexIds[i + 1]]; | ||
previousVertex = vertices[polygon.vertexIds[i - 1]]; | ||
} | ||
var a = nextVertex.clone().sub(vertex); | ||
var b = previousVertex.clone().sub(vertex); | ||
var angle = a.angleTo(b); | ||
total += angle; | ||
if (angle === Math.PI || angle === 0) return false; | ||
var r = a.cross(b).y; | ||
results.push(r); | ||
} | ||
// if ( total > (polygon.vertexIds.length-2)*Math.PI ) return false; | ||
results.forEach((r) => { | ||
if (r === 0) convex = false; | ||
}); | ||
if (results[0] > 0) { | ||
results.forEach((r) => { | ||
if (r < 0) convex = false; | ||
}); | ||
} else { | ||
results.forEach((r) => { | ||
if (r > 0) convex = false; | ||
}); | ||
} | ||
return convex; | ||
} | ||
static distanceToSquared (a, b) { | ||
@@ -218,0 +14,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4490419
2109