three-pathfinding
Advanced tools
Comparing version 0.13.0 to 0.14.0
@@ -1,2 +0,2 @@ | ||
var e=require("three"),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(r){var n=this,o=this._buildNavigationMesh(r),i={};o.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)}),i.vertices=o.vertices;var s=this._buildPolygonGroups(o);return i.groups=new Array(s.length),s.forEach(function(r,o){var s=new Map;r.forEach(function(e,t){s.set(e,t)});var a=new Array(r.length);r.forEach(function(r,o){var h=[];r.neighbours.forEach(function(e){return h.push(s.get(e))});var c=[];r.neighbours.forEach(function(e){return c.push(n._getSharedVerticesInOrder(r,e))});var u=new e.Vector3(0,0,0);u.add(i.vertices[r.vertexIds[0]]),u.add(i.vertices[r.vertexIds[1]]),u.add(i.vertices[r.vertexIds[2]]),u.divideScalar(3),u.x=t.roundNumber(u.x,2),u.y=t.roundNumber(u.y,2),u.z=t.roundNumber(u.z,2),a[o]={id:o,neighbours:h,vertexIds:r.vertexIds,centroid:u,portals:c}}),i.groups[o]=a}),i},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(t){return t.isGeometry?console.warn("[three-pathfinding]: Use BufferGeometry, not Geometry, to create zone."):t=(new e.Geometry).fromBufferGeometry(t),o.buildZone(t)},a.prototype.setZoneData=function(e,t){this.zones[e]=t},a.prototype.getRandomNode=function(r,n,o,i){if(!this.zones[r])return new e.Vector3;o=o||null,i=i||0;var s=[];return this.zones[r].groups[n].forEach(function(e){o&&i?t.distanceToSquared(o,e.centroid)<i*i&&s.push(e.centroid):s.push(e.centroid)}),t.sample(s)||new e.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(t,r,o,s){var a=this.zones[o].groups[s],h=this.zones[o].vertices,c=this.getClosestNode(t,o,s,!0),u=this.getClosestNode(r,o,s,!0);if(!c||!u)return null;var p=n.search(a,c,u),l=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},f=new i;f.push(t);for(var d=0;d<p.length;d++){var v=p[d+1];if(v){var g=l(p[d],v);f.push(h[g[0]],h[g[1]])}}f.push(r),f.stringPull();var y=f.path.map(function(t){return new e.Vector3(t.x,t.y,t.z)});return y.shift(),y},a.prototype.getGroup=(s=new e.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 t,r,n=new e.Vector3,o=new e.Plane,i=new e.Triangle,s=new e.Vector3,a=new e.Vector3;return function(e,h,c,u,p,l){var f=this.zones[u].vertices,d=this.zones[u].groups[p],v=[c],g={};g[c.id]=0,t=void 0,a.set(0,0,0),r=Infinity,o.setFromCoplanarPoints(f[c.vertexIds[0]],f[c.vertexIds[1]],f[c.vertexIds[2]]),o.projectPoint(h,n),s.copy(n);for(var y=v.pop();y;y=v.pop()){i.set(f[y.vertexIds[0]],f[y.vertexIds[1]],f[y.vertexIds[2]]),i.closestPointToPoint(s,n),n.distanceToSquared(s)<r&&(t=y,a.copy(n),r=n.distanceToSquared(s));var M=g[y.id];if(!(M>2))for(var b=0;b<y.neighbours.length;b++){var m=d[y.neighbours[b]];m.id in g||(v.push(m),g[m.id]=M+1)}}return l.copy(a),t}}();var h={PLAYER:new e.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new e.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new e.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new e.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new e.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new e.Color(4417387).convertGammaToLinear(2.2).getHex()},c=function(t){function r(){var r=this;t.call(this),this._playerMarker=new e.Mesh(new e.SphereGeometry(.25,32,32),new e.MeshBasicMaterial({color:h.PLAYER})),this._targetMarker=new e.Mesh(new e.BoxGeometry(.3,.3,.3),new e.MeshBasicMaterial({color:h.TARGET})),this._nodeMarker=new e.Mesh(new e.BoxGeometry(.1,.8,.1),new e.MeshBasicMaterial({color:h.CLOSEST_NODE})),this._stepMarker=new e.Mesh(new e.BoxGeometry(.1,1,.1),new e.MeshBasicMaterial({color:h.CLAMPED_STEP})),this._pathMarker=new t,this._pathLineMaterial=new e.LineBasicMaterial({color:h.PATH,linewidth:2}),this._pathPointMaterial=new e.MeshBasicMaterial({color:h.WAYPOINT}),this._pathPointGeometry=new e.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,r.add(e)})}return t&&(r.__proto__=t),(r.prototype=Object.create(t&&t.prototype)).constructor=r,r.prototype.setPath=function(t){for(;this._pathMarker.children.length;)this._pathMarker.children[0].visible=!1,this._pathMarker.remove(this._pathMarker.children[0]);t=[this._playerMarker.position].concat(t);for(var r=new e.Geometry,n=0;n<t.length;n++)r.vertices.push(t[n].clone().add(new e.Vector3(0,.2,0)));this._pathMarker.add(new e.Line(r,this._pathLineMaterial));for(var o=0;o<t.length-1;o++){var i=new e.Mesh(this._pathPointGeometry,this._pathPointMaterial);i.position.copy(t[o]),i.position.y+=.2,this._pathMarker.add(i)}return this._pathMarker.visible=!0,this},r.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},r.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},r.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},r.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},r.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},r}(e.Object3D);exports.Pathfinding=a,exports.PathfindingHelper=c; | ||
var e,t=require("three"),r=function(){function e(){}return 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},e.mergeVertices=function(e,r){void 0===r&&(r=1e-4),r=Math.max(r,Number.EPSILON);for(var n={},o=e.getIndex(),i=e.getAttribute("position"),s=o?o.count:i.count,a=0,u=Object.keys(e.attributes),h={},c={},l=[],f=["getX","getY","getZ","getW"],p=0,v=u.length;p<v;p++)h[T=u[p]]=[],(_=e.morphAttributes[T])&&(c[T]=new Array(_.length).fill().map(function(){return[]}));var d=Math.log10(1/r),g=Math.pow(10,d);for(p=0;p<s;p++){var b=o?o.getX(p):p,y="",m=0;for(v=u.length;m<v;m++)for(var M=(x=e.getAttribute(T=u[m])).itemSize,w=0;w<M;w++)y+=~~(x[f[w]](b)*g)+",";if(y in n)l.push(n[y]);else{for(m=0,v=u.length;m<v;m++){var x=e.getAttribute(T=u[m]),_=e.morphAttributes[T],P=(M=x.itemSize,h[T]),z=c[T];for(w=0;w<M;w++){var k=f[w];if(P.push(x[k](b)),_)for(var I=0,E=_.length;I<E;I++)z[I].push(_[I][k](b))}}n[y]=a,l.push(a),a++}}var A=e.clone();for(p=0,v=u.length;p<v;p++){var T,S=e.getAttribute(T=u[p]),N=new S.array.constructor(h[T]);if(x=new t.BufferAttribute(N,S.itemSize,S.normalized),A.setAttribute(T,x),T in c)for(m=0;m<c[T].length;m++){var G=e.morphAttributes[T][m],B=(N=new G.array.constructor(c[T][m]),new t.BufferAttribute(N,G.itemSize,G.normalized));A.morphAttributes[T][m]=B}}return A.setIndex(l),A},e}(),n=function(){function e(e){this.content=[],this.scoreFunction=e}var t=e.prototype;return t.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},t.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.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.size=function(){return this.content.length},t.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},t.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.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),o<t&&this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o),null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}},e}(),o=function(){function e(){}return e.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}},e.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}},e.heap=function(){return new n(function(e){return e.f})},e.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),u=0,h=a.length;u<h;u++){var c=a[u];if(!c.closed){var l=o.g+c.cost,f=c.visited;if(!f||l<c.g){if(c.visited=!0,c.parent=o,!c.centroid||!r.centroid)throw new Error("Unexpected state");c.h=c.h||this.heuristic(c.centroid,r.centroid),c.g=l,c.f=c.g+c.h,f?n.rescoreElement(c):n.push(c)}}}}return[]},e.heuristic=function(e,t){return r.distanceToSquared(e,t)},e.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r},e}(),i=function(){function e(){}return e.buildZone=function(e){var n=this,o=this._buildNavigationMesh(e),i={};o.vertices.forEach(function(e){e.x=r.roundNumber(e.x,2),e.y=r.roundNumber(e.y,2),e.z=r.roundNumber(e.z,2)}),i.vertices=o.vertices;var s=this._buildPolygonGroups(o);return i.groups=new Array(s.length),s.forEach(function(e,o){var s=new Map;e.forEach(function(e,t){s.set(e,t)});var a=new Array(e.length);e.forEach(function(e,o){var u=[];e.neighbours.forEach(function(e){return u.push(s.get(e))});var h=[];e.neighbours.forEach(function(t){return h.push(n._getSharedVerticesInOrder(e,t))});var c=new t.Vector3(0,0,0);c.add(i.vertices[e.vertexIds[0]]),c.add(i.vertices[e.vertexIds[1]]),c.add(i.vertices[e.vertexIds[2]]),c.divideScalar(3),c.x=r.roundNumber(c.x,2),c.y=r.roundNumber(c.y,2),c.z=r.roundNumber(c.z,2),a[o]={id:o,neighbours:u,vertexIds:e.vertexIds,centroid:c,portals:h}}),i.groups[o]=a}),i},e._buildNavigationMesh=function(e){return e=r.mergeVertices(e),this._buildPolygonsFromGeometry(e)},e._buildPolygonGroups=function(e){var t=[],r=function e(t){t.neighbours.forEach(function(r){void 0===r.group&&(r.group=t.group,e(r))})};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},e._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},e._buildPolygonsFromGeometry=function(e){for(var r=this,n=[],o=[],i=e.attributes.position,s=e.index,a=[],u=0;u<i.count;u++)o.push((new t.Vector3).fromBufferAttribute(i,u)),a[u]=[];for(var h=0;h<e.index.count;h+=3){var c=s.getX(h),l=s.getX(h+1),f=s.getX(h+2),p={vertexIds:[c,l,f],neighbours:null};n.push(p),a[c].push(p),a[l].push(p),a[f].push(p)}return n.forEach(function(e){e.neighbours=r._buildPolygonNeighbours(e,a)}),{polygons:n,vertices:o}},e._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=r[0],o=r[1],i=r[2],s=t.vertexIds,a=s.includes(n),u=s.includes(o),h=s.includes(i);return a&&u&&h?Array.from(r):a&&u?[n,o]:u&&h?[o,i]:a&&h?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])},e}(),s=function(){function e(){this.portals=[]}var t=e.prototype;return t.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},t.stringPull=function(){var e,t,n,o=this.portals,i=[],s=0,a=0,u=0;t=o[0].left,n=o[0].right,i.push(e=o[0].left);for(var h=1;h<o.length;h++){var c=o[h].left,l=o[h].right;if(r.triarea2(e,n,l)<=0){if(!(r.vequal(e,n)||r.triarea2(e,t,l)>0)){i.push(t),t=e=t,n=e,a=s=a,u=s,h=s;continue}n=l,u=h}if(r.triarea2(e,t,c)>=0){if(!(r.vequal(e,t)||r.triarea2(e,n,c)<0)){i.push(n),t=e=n,n=e,a=s=u,u=s,h=s;continue}t=c,a=h}}return 0!==i.length&&r.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i},e}(),a=function(){function e(){this.zones={}}e.createZone=function(e){return i.buildZone(e)};var n=e.prototype;return n.setZoneData=function(e,t){this.zones[e]=t},n.getRandomNode=function(e,n,o,i){if(!this.zones[e])return new t.Vector3;o=o||null,i=i||0;var s=[];return this.zones[e].groups[n].forEach(function(e){o&&i?r.distanceToSquared(o,e.centroid)<i*i&&s.push(e.centroid):s.push(e.centroid)}),r.sample(s)||new t.Vector3},n.getClosestNode=function(e,t,n,o){void 0===o&&(o=!1);var i=this.zones[t].vertices,s=null,a=Infinity;return this.zones[t].groups[n].forEach(function(t){var n=r.distanceToSquared(t.centroid,e);n<a&&(!o||r.isVectorInPolygon(e,t,i))&&(s=t,a=n)}),s},n.findPath=function(e,r,n,i){var a=this.zones[n].groups[i],u=this.zones[n].vertices,h=this.getClosestNode(e,n,i,!0),c=this.getClosestNode(r,n,i,!0);if(!h||!c)return null;var l=o.search(a,h,c),f=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},p=new s;p.push(e);for(var v=0;v<l.length;v++){var d=l[v+1];if(d){var g=f(l[v],d);p.push(u[g[0]],u[g[1]])}}p.push(r),p.stringPull();var b=p.path.map(function(e){return new t.Vector3(e.x,e.y,e.z)});return b.shift(),b},e}();a.prototype.getGroup=(e=new t.Plane,function(t,n,o){if(void 0===o&&(o=!1),!this.zones[t])return null;for(var i=null,s=Math.pow(50,2),a=this.zones[t],u=0;u<a.groups.length;u++){var h=a.groups[u],c=Array.isArray(h),l=0;for(h=c?h:h[Symbol.iterator]();;){var f;if(c){if(l>=h.length)break;f=h[l++]}else{if((l=h.next()).done)break;f=l.value}var p=f;if(o&&(e.setFromCoplanarPoints(a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]),Math.abs(e.distanceToPoint(n))<.01&&r.isPointInPoly([a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]],n)))return u;var v=r.distanceToSquared(p.centroid,n);v<s&&(i=u,s=v)}}return i}),a.prototype.clampStep=function(){var e,r,n=new t.Vector3,o=new t.Plane,i=new t.Triangle,s=new t.Vector3,a=new t.Vector3;return function(t,u,h,c,l,f){var p=this.zones[c].vertices,v=this.zones[c].groups[l],d=[h],g={};g[h.id]=0,e=void 0,a.set(0,0,0),r=Infinity,o.setFromCoplanarPoints(p[h.vertexIds[0]],p[h.vertexIds[1]],p[h.vertexIds[2]]),o.projectPoint(u,n),s.copy(n);for(var b=d.pop();b;b=d.pop()){i.set(p[b.vertexIds[0]],p[b.vertexIds[1]],p[b.vertexIds[2]]),i.closestPointToPoint(s,n),n.distanceToSquared(s)<r&&(e=b,a.copy(n),r=n.distanceToSquared(s));var y=g[b.id];if(!(y>2))for(var m=0;m<b.neighbours.length;m++){var M=v[b.neighbours[m]];M.id in g||(d.push(M),g[M.id]=y+1)}}return f.copy(a),e}}();var u={PLAYER:new t.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new t.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new t.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new t.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new t.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new t.Color(4417387).convertGammaToLinear(2.2).getHex()},h=function(e){var r,n;function o(){var r;return(r=e.call(this)||this)._playerMarker=new t.Mesh(new t.SphereBufferGeometry(.25,32,32),new t.MeshBasicMaterial({color:u.PLAYER})),r._targetMarker=new t.Mesh(new t.BoxBufferGeometry(.3,.3,.3),new t.MeshBasicMaterial({color:u.TARGET})),r._nodeMarker=new t.Mesh(new t.BoxBufferGeometry(.1,.8,.1),new t.MeshBasicMaterial({color:u.CLOSEST_NODE})),r._stepMarker=new t.Mesh(new t.BoxBufferGeometry(.1,1,.1),new t.MeshBasicMaterial({color:u.CLAMPED_STEP})),r._pathMarker=new t.Object3D,r._pathLineMaterial=new t.LineBasicMaterial({color:u.PATH,linewidth:2}),r._pathPointMaterial=new t.MeshBasicMaterial({color:u.WAYPOINT}),r._pathPointGeometry=new t.SphereBufferGeometry(.08),r._markers=[r._playerMarker,r._targetMarker,r._nodeMarker,r._stepMarker,r._pathMarker],r._markers.forEach(function(e){e.visible=!1,r.add(e)}),r}n=e,(r=o).prototype=Object.create(n.prototype),r.prototype.constructor=r,r.__proto__=n;var i=o.prototype;return i.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);var r=new t.BufferGeometry;r.setAttribute("position",new t.BufferAttribute(new Float32Array(3*e.length),3));for(var n=0;n<e.length;n++)r.attributes.position.setXYZ(n,e[n].x,e[n].y+.2,e[n].z);this._pathMarker.add(new t.Line(r,this._pathLineMaterial));for(var o=0;o<e.length-1;o++){var i=new t.Mesh(this._pathPointGeometry,this._pathPointMaterial);i.position.copy(e[o]),i.position.y+=.2,this._pathMarker.add(i)}return this._pathMarker.visible=!0,this},i.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},i.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},i.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},i.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},i.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},o}(t.Object3D);exports.Pathfinding=a,exports.PathfindingHelper=h; | ||
//# sourceMappingURL=three-pathfinding.js.map |
@@ -1,2 +0,2 @@ | ||
import{Vector3 as t,Plane as e,Geometry as r,Triangle as n,Color as o,Object3D as i,LineBasicMaterial as s,MeshBasicMaterial as a,SphereBufferGeometry as h,BoxGeometry as u,Mesh as c,SphereGeometry as p,Line as l}from"three";var f=function(){};f.roundNumber=function(t,e){var r=Math.pow(10,e);return Math.round(t*r)/r},f.sample=function(t){return t[Math.floor(Math.random()*t.length)]},f.distanceToSquared=function(t,e){var r=t.x-e.x,n=t.y-e.y,o=t.z-e.z;return r*r+n*n+o*o},f.isPointInPoly=function(t,e){for(var r=!1,n=-1,o=t.length,i=o-1;++n<o;i=n)(t[n].z<=e.z&&e.z<t[i].z||t[i].z<=e.z&&e.z<t[n].z)&&e.x<(t[i].x-t[n].x)*(e.z-t[n].z)/(t[i].z-t[n].z)+t[n].x&&(r=!r);return r},f.isVectorInPolygon=function(t,e,r){var n=1e5,o=-1e5,i=[];return e.vertexIds.forEach(function(t){n=Math.min(r[t].y,n),o=Math.max(r[t].y,o),i.push(r[t])}),!!(t.y<o+.5&&t.y>n-.5&&this.isPointInPoly(i,t))},f.triarea2=function(t,e,r){return(r.x-t.x)*(e.z-t.z)-(e.x-t.x)*(r.z-t.z)},f.vequal=function(t,e){return this.distanceToSquared(t,e)<1e-5};var d=function(t){this.content=[],this.scoreFunction=t};d.prototype.push=function(t){this.content.push(t),this.sinkDown(this.content.length-1)},d.prototype.pop=function(){var t=this.content[0],e=this.content.pop();return this.content.length>0&&(this.content[0]=e,this.bubbleUp(0)),t},d.prototype.remove=function(t){var e=this.content.indexOf(t),r=this.content.pop();e!==this.content.length-1&&(this.content[e]=r,this.scoreFunction(r)<this.scoreFunction(t)?this.sinkDown(e):this.bubbleUp(e))},d.prototype.size=function(){return this.content.length},d.prototype.rescoreElement=function(t){this.sinkDown(this.content.indexOf(t))},d.prototype.sinkDown=function(t){for(var e=this.content[t];t>0;){var r=(t+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(e)<this.scoreFunction(n)))break;this.content[r]=e,this.content[t]=n,t=r}},d.prototype.bubbleUp=function(t){for(var e=this.content.length,r=this.content[t],n=this.scoreFunction(r);;){var o=t+1<<1,i=o-1,s=null,a=void 0;if(i<e)(a=this.scoreFunction(this.content[i]))<n&&(s=i);if(o<e)this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o);if(null===s)break;this.content[t]=this.content[s],this.content[s]=r,t=s}};var v=function(){};v.init=function(t){for(var e=0;e<t.length;e++){var r=t[e];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},v.cleanUp=function(t){for(var e=0;e<t.length;e++){var r=t[e];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},v.heap=function(){return new d(function(t){return t.f})},v.search=function(t,e,r){this.init(t);var n=this.heap();for(n.push(e);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(t,o),h=0,u=a.length;h<u;h++){var c=a[h];if(!c.closed){var p=o.g+c.cost,l=c.visited;if(!l||p<c.g){if(c.visited=!0,c.parent=o,!c.centroid||!r.centroid)throw new Error("Unexpected state");c.h=c.h||this.heuristic(c.centroid,r.centroid),c.g=p,c.f=c.g+c.h,l?n.rescoreElement(c):n.push(c)}}}}return[]},v.heuristic=function(t,e){return f.distanceToSquared(t,e)},v.neighbours=function(t,e){for(var r=[],n=0;n<e.neighbours.length;n++)r.push(t[e.neighbours[n]]);return r};var g=function(){};g.buildZone=function(e){var r=this,n=this._buildNavigationMesh(e),o={};n.vertices.forEach(function(t){t.x=f.roundNumber(t.x,2),t.y=f.roundNumber(t.y,2),t.z=f.roundNumber(t.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(t,e){i.set(t,e)});var s=new Array(e.length);e.forEach(function(e,n){var a=[];e.neighbours.forEach(function(t){return a.push(i.get(t))});var h=[];e.neighbours.forEach(function(t){return h.push(r._getSharedVerticesInOrder(e,t))});var u=new t(0,0,0);u.add(o.vertices[e.vertexIds[0]]),u.add(o.vertices[e.vertexIds[1]]),u.add(o.vertices[e.vertexIds[2]]),u.divideScalar(3),u.x=f.roundNumber(u.x,2),u.y=f.roundNumber(u.y,2),u.z=f.roundNumber(u.z,2),s[n]={id:n,neighbours:a,vertexIds:e.vertexIds,centroid:u,portals:h}}),o.groups[n]=s}),o},g._buildNavigationMesh=function(t){return t.mergeVertices(),this._buildPolygonsFromGeometry(t)},g._buildPolygonGroups=function(t){var e=[],r=function(t){t.neighbours.forEach(function(e){void 0===e.group&&(e.group=t.group,r(e))})};return t.polygons.forEach(function(t){void 0!==t.group?e[t.group].push(t):(t.group=e.length,r(t),e.push([t]))}),e},g._buildPolygonNeighbours=function(t,e){var r=new Set,n=e[t.vertexIds[1]],o=e[t.vertexIds[2]];return e[t.vertexIds[0]].forEach(function(e){e!==t&&(n.includes(e)||o.includes(e))&&r.add(e)}),n.forEach(function(e){e!==t&&o.includes(e)&&r.add(e)}),r},g._buildPolygonsFromGeometry=function(t){for(var e=this,r=[],n=t.vertices,o=new Array(n.length),i=0;i<n.length;i++)o[i]=[];return t.faces.forEach(function(t){var e={vertexIds:[t.a,t.b,t.c],neighbours:null};r.push(e),o[t.a].push(e),o[t.b].push(e),o[t.c].push(e)}),r.forEach(function(t){t.neighbours=e._buildPolygonNeighbours(t,o)}),{polygons:r,vertices:n}},g._getSharedVerticesInOrder=function(t,e){var r=t.vertexIds,n=r[0],o=r[1],i=r[2],s=e.vertexIds,a=s.includes(n),h=s.includes(o),u=s.includes(i);return a&&h&&u?Array.from(r):a&&h?[n,o]:h&&u?[o,i]:a&&u?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])};var y=function(){this.portals=[]};y.prototype.push=function(t,e){void 0===e&&(e=t),this.portals.push({left:t,right:e})},y.prototype.stringPull=function(){var t,e,r,n=this.portals,o=[],i=0,s=0,a=0;e=n[0].left,r=n[0].right,o.push(t=n[0].left);for(var h=1;h<n.length;h++){var u=n[h].left,c=n[h].right;if(f.triarea2(t,r,c)<=0){if(!(f.vequal(t,r)||f.triarea2(t,e,c)>0)){o.push(e),e=t=e,r=t,s=i=s,a=i,h=i;continue}r=c,a=h}if(f.triarea2(t,e,u)>=0){if(!(f.vequal(t,e)||f.triarea2(t,r,u)<0)){o.push(r),e=t=r,r=t,s=i=a,a=i,h=i;continue}e=u,s=h}}return 0!==o.length&&f.vequal(o[o.length-1],n[n.length-1].left)||o.push(n[n.length-1].left),this.path=o,o};var b,_=function(){this.zones={}};_.createZone=function(t){return t.isGeometry?console.warn("[three-pathfinding]: Use BufferGeometry, not Geometry, to create zone."):t=(new r).fromBufferGeometry(t),g.buildZone(t)},_.prototype.setZoneData=function(t,e){this.zones[t]=e},_.prototype.getRandomNode=function(e,r,n,o){if(!this.zones[e])return new t;n=n||null,o=o||0;var i=[];return this.zones[e].groups[r].forEach(function(t){n&&o?f.distanceToSquared(n,t.centroid)<o*o&&i.push(t.centroid):i.push(t.centroid)}),f.sample(i)||new t},_.prototype.getClosestNode=function(t,e,r,n){void 0===n&&(n=!1);var o=this.zones[e].vertices,i=null,s=Infinity;return this.zones[e].groups[r].forEach(function(e){var r=f.distanceToSquared(e.centroid,t);r<s&&(!n||f.isVectorInPolygon(t,e,o))&&(i=e,s=r)}),i},_.prototype.findPath=function(e,r,n,o){var i=this.zones[n].groups[o],s=this.zones[n].vertices,a=this.getClosestNode(e,n,o,!0),h=this.getClosestNode(r,n,o,!0);if(!a||!h)return null;var u=v.search(i,a,h),c=function(t,e){for(var r=0;r<t.neighbours.length;r++)if(t.neighbours[r]===e.id)return t.portals[r]},p=new y;p.push(e);for(var l=0;l<u.length;l++){var f=u[l+1];if(f){var d=c(u[l],f);p.push(s[d[0]],s[d[1]])}}p.push(r),p.stringPull();var g=p.path.map(function(e){return new t(e.x,e.y,e.z)});return g.shift(),g},_.prototype.getGroup=(b=new e,function(t,e,r){if(void 0===r&&(r=!1),!this.zones[t])return null;for(var n=null,o=Math.pow(50,2),i=this.zones[t],s=0;s<i.groups.length;s++)for(var a=0,h=i.groups[s];a<h.length;a+=1){var u=h[a];if(r&&(b.setFromCoplanarPoints(i.vertices[u.vertexIds[0]],i.vertices[u.vertexIds[1]],i.vertices[u.vertexIds[2]]),Math.abs(b.distanceToPoint(e))<.01&&f.isPointInPoly([i.vertices[u.vertexIds[0]],i.vertices[u.vertexIds[1]],i.vertices[u.vertexIds[2]]],e)))return s;var c=f.distanceToSquared(u.centroid,e);c<o&&(n=s,o=c)}return n}),_.prototype.clampStep=function(){var r,o,i=new t,s=new e,a=new n,h=new t,u=new t;return function(t,e,n,c,p,l){var f=this.zones[c].vertices,d=this.zones[c].groups[p],v=[n],g={};g[n.id]=0,r=void 0,u.set(0,0,0),o=Infinity,s.setFromCoplanarPoints(f[n.vertexIds[0]],f[n.vertexIds[1]],f[n.vertexIds[2]]),s.projectPoint(e,i),h.copy(i);for(var y=v.pop();y;y=v.pop()){a.set(f[y.vertexIds[0]],f[y.vertexIds[1]],f[y.vertexIds[2]]),a.closestPointToPoint(h,i),i.distanceToSquared(h)<o&&(r=y,u.copy(i),o=i.distanceToSquared(h));var b=g[y.id];if(!(b>2))for(var _=0;_<y.neighbours.length;_++){var w=d[y.neighbours[_]];w.id in g||(v.push(w),g[w.id]=b+1)}}return l.copy(u),r}}();var w={PLAYER:new o(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new o(14469912).convertGammaToLinear(2.2).getHex(),PATH:new o(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new o(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new o(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new o(4417387).convertGammaToLinear(2.2).getHex()},m=function(e){function n(){var t=this;e.call(this),this._playerMarker=new c(new p(.25,32,32),new a({color:w.PLAYER})),this._targetMarker=new c(new u(.3,.3,.3),new a({color:w.TARGET})),this._nodeMarker=new c(new u(.1,.8,.1),new a({color:w.CLOSEST_NODE})),this._stepMarker=new c(new u(.1,1,.1),new a({color:w.CLAMPED_STEP})),this._pathMarker=new e,this._pathLineMaterial=new s({color:w.PATH,linewidth:2}),this._pathPointMaterial=new a({color:w.WAYPOINT}),this._pathPointGeometry=new h(.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&&(n.__proto__=e),(n.prototype=Object.create(e&&e.prototype)).constructor=n,n.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 n=new r,o=0;o<e.length;o++)n.vertices.push(e[o].clone().add(new t(0,.2,0)));this._pathMarker.add(new l(n,this._pathLineMaterial));for(var i=0;i<e.length-1;i++){var s=new c(this._pathPointGeometry,this._pathPointMaterial);s.position.copy(e[i]),s.position.y+=.2,this._pathMarker.add(s)}return this._pathMarker.visible=!0,this},n.prototype.setPlayerPosition=function(t){return this._playerMarker.position.copy(t),this._playerMarker.visible=!0,this},n.prototype.setTargetPosition=function(t){return this._targetMarker.position.copy(t),this._targetMarker.visible=!0,this},n.prototype.setNodePosition=function(t){return this._nodeMarker.position.copy(t),this._nodeMarker.visible=!0,this},n.prototype.setStepPosition=function(t){return this._stepMarker.position.copy(t),this._stepMarker.visible=!0,this},n.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(t){t.visible=!1}),this},n}(i);export{_ as Pathfinding,m as PathfindingHelper}; | ||
import{BufferAttribute as t,Vector3 as e,Plane as r,Triangle as n,Color as o,BufferGeometry as i,Line as s,Mesh as a,SphereBufferGeometry as u,MeshBasicMaterial as h,BoxBufferGeometry as c,Object3D as l,LineBasicMaterial as f}from"three";var p,v=function(){function e(){}return e.roundNumber=function(t,e){var r=Math.pow(10,e);return Math.round(t*r)/r},e.sample=function(t){return t[Math.floor(Math.random()*t.length)]},e.distanceToSquared=function(t,e){var r=t.x-e.x,n=t.y-e.y,o=t.z-e.z;return r*r+n*n+o*o},e.isPointInPoly=function(t,e){for(var r=!1,n=-1,o=t.length,i=o-1;++n<o;i=n)(t[n].z<=e.z&&e.z<t[i].z||t[i].z<=e.z&&e.z<t[n].z)&&e.x<(t[i].x-t[n].x)*(e.z-t[n].z)/(t[i].z-t[n].z)+t[n].x&&(r=!r);return r},e.isVectorInPolygon=function(t,e,r){var n=1e5,o=-1e5,i=[];return e.vertexIds.forEach(function(t){n=Math.min(r[t].y,n),o=Math.max(r[t].y,o),i.push(r[t])}),!!(t.y<o+.5&&t.y>n-.5&&this.isPointInPoly(i,t))},e.triarea2=function(t,e,r){return(r.x-t.x)*(e.z-t.z)-(e.x-t.x)*(r.z-t.z)},e.vequal=function(t,e){return this.distanceToSquared(t,e)<1e-5},e.mergeVertices=function(e,r){void 0===r&&(r=1e-4),r=Math.max(r,Number.EPSILON);for(var n={},o=e.getIndex(),i=e.getAttribute("position"),s=o?o.count:i.count,a=0,u=Object.keys(e.attributes),h={},c={},l=[],f=["getX","getY","getZ","getW"],p=0,v=u.length;p<v;p++)h[A=u[p]]=[],(M=e.morphAttributes[A])&&(c[A]=new Array(M.length).fill().map(function(){return[]}));var d=Math.log10(1/r),g=Math.pow(10,d);for(p=0;p<s;p++){var b=o?o.getX(p):p,y="",m=0;for(v=u.length;m<v;m++)for(var w=(_=e.getAttribute(A=u[m])).itemSize,x=0;x<w;x++)y+=~~(_[f[x]](b)*g)+",";if(y in n)l.push(n[y]);else{for(m=0,v=u.length;m<v;m++){var _=e.getAttribute(A=u[m]),M=e.morphAttributes[A],z=(w=_.itemSize,h[A]),P=c[A];for(x=0;x<w;x++){var k=f[x];if(z.push(_[k](b)),M)for(var I=0,E=M.length;I<E;I++)P[I].push(M[I][k](b))}}n[y]=a,l.push(a),a++}}var T=e.clone();for(p=0,v=u.length;p<v;p++){var A,S=e.getAttribute(A=u[p]),N=new S.array.constructor(h[A]);if(_=new t(N,S.itemSize,S.normalized),T.setAttribute(A,_),A in c)for(m=0;m<c[A].length;m++){var G=e.morphAttributes[A][m],L=(N=new G.array.constructor(c[A][m]),new t(N,G.itemSize,G.normalized));T.morphAttributes[A][m]=L}}return T.setIndex(l),T},e}(),d=function(){function t(t){this.content=[],this.scoreFunction=t}var e=t.prototype;return e.push=function(t){this.content.push(t),this.sinkDown(this.content.length-1)},e.pop=function(){var t=this.content[0],e=this.content.pop();return this.content.length>0&&(this.content[0]=e,this.bubbleUp(0)),t},e.remove=function(t){var e=this.content.indexOf(t),r=this.content.pop();e!==this.content.length-1&&(this.content[e]=r,this.scoreFunction(r)<this.scoreFunction(t)?this.sinkDown(e):this.bubbleUp(e))},e.size=function(){return this.content.length},e.rescoreElement=function(t){this.sinkDown(this.content.indexOf(t))},e.sinkDown=function(t){for(var e=this.content[t];t>0;){var r=(t+1>>1)-1,n=this.content[r];if(!(this.scoreFunction(e)<this.scoreFunction(n)))break;this.content[r]=e,this.content[t]=n,t=r}},e.bubbleUp=function(t){for(var e=this.content.length,r=this.content[t],n=this.scoreFunction(r);;){var o=t+1<<1,i=o-1,s=null,a=void 0;if(i<e&&(a=this.scoreFunction(this.content[i]))<n&&(s=i),o<e&&this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o),null===s)break;this.content[t]=this.content[s],this.content[s]=r,t=s}},t}(),g=function(){function t(){}return t.init=function(t){for(var e=0;e<t.length;e++){var r=t[e];r.f=0,r.g=0,r.h=0,r.cost=1,r.visited=!1,r.closed=!1,r.parent=null}},t.cleanUp=function(t){for(var e=0;e<t.length;e++){var r=t[e];delete r.f,delete r.g,delete r.h,delete r.cost,delete r.visited,delete r.closed,delete r.parent}},t.heap=function(){return new d(function(t){return t.f})},t.search=function(t,e,r){this.init(t);var n=this.heap();for(n.push(e);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(t,o),u=0,h=a.length;u<h;u++){var c=a[u];if(!c.closed){var l=o.g+c.cost,f=c.visited;if(!f||l<c.g){if(c.visited=!0,c.parent=o,!c.centroid||!r.centroid)throw new Error("Unexpected state");c.h=c.h||this.heuristic(c.centroid,r.centroid),c.g=l,c.f=c.g+c.h,f?n.rescoreElement(c):n.push(c)}}}}return[]},t.heuristic=function(t,e){return v.distanceToSquared(t,e)},t.neighbours=function(t,e){for(var r=[],n=0;n<e.neighbours.length;n++)r.push(t[e.neighbours[n]]);return r},t}(),b=function(){function t(){}return t.buildZone=function(t){var r=this,n=this._buildNavigationMesh(t),o={};n.vertices.forEach(function(t){t.x=v.roundNumber(t.x,2),t.y=v.roundNumber(t.y,2),t.z=v.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(t,e){i.set(t,e)});var s=new Array(t.length);t.forEach(function(t,n){var a=[];t.neighbours.forEach(function(t){return a.push(i.get(t))});var u=[];t.neighbours.forEach(function(e){return u.push(r._getSharedVerticesInOrder(t,e))});var h=new e(0,0,0);h.add(o.vertices[t.vertexIds[0]]),h.add(o.vertices[t.vertexIds[1]]),h.add(o.vertices[t.vertexIds[2]]),h.divideScalar(3),h.x=v.roundNumber(h.x,2),h.y=v.roundNumber(h.y,2),h.z=v.roundNumber(h.z,2),s[n]={id:n,neighbours:a,vertexIds:t.vertexIds,centroid:h,portals:u}}),o.groups[n]=s}),o},t._buildNavigationMesh=function(t){return t=v.mergeVertices(t),this._buildPolygonsFromGeometry(t)},t._buildPolygonGroups=function(t){var e=[],r=function t(e){e.neighbours.forEach(function(r){void 0===r.group&&(r.group=e.group,t(r))})};return t.polygons.forEach(function(t){void 0!==t.group?e[t.group].push(t):(t.group=e.length,r(t),e.push([t]))}),e},t._buildPolygonNeighbours=function(t,e){var r=new Set,n=e[t.vertexIds[1]],o=e[t.vertexIds[2]];return e[t.vertexIds[0]].forEach(function(e){e!==t&&(n.includes(e)||o.includes(e))&&r.add(e)}),n.forEach(function(e){e!==t&&o.includes(e)&&r.add(e)}),r},t._buildPolygonsFromGeometry=function(t){for(var r=this,n=[],o=[],i=t.attributes.position,s=t.index,a=[],u=0;u<i.count;u++)o.push((new e).fromBufferAttribute(i,u)),a[u]=[];for(var h=0;h<t.index.count;h+=3){var c=s.getX(h),l=s.getX(h+1),f=s.getX(h+2),p={vertexIds:[c,l,f],neighbours:null};n.push(p),a[c].push(p),a[l].push(p),a[f].push(p)}return n.forEach(function(t){t.neighbours=r._buildPolygonNeighbours(t,a)}),{polygons:n,vertices:o}},t._getSharedVerticesInOrder=function(t,e){var r=t.vertexIds,n=r[0],o=r[1],i=r[2],s=e.vertexIds,a=s.includes(n),u=s.includes(o),h=s.includes(i);return a&&u&&h?Array.from(r):a&&u?[n,o]:u&&h?[o,i]:a&&h?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])},t}(),y=function(){function t(){this.portals=[]}var e=t.prototype;return e.push=function(t,e){void 0===e&&(e=t),this.portals.push({left:t,right:e})},e.stringPull=function(){var t,e,r,n=this.portals,o=[],i=0,s=0,a=0;e=n[0].left,r=n[0].right,o.push(t=n[0].left);for(var u=1;u<n.length;u++){var h=n[u].left,c=n[u].right;if(v.triarea2(t,r,c)<=0){if(!(v.vequal(t,r)||v.triarea2(t,e,c)>0)){o.push(e),e=t=e,r=t,s=i=s,a=i,u=i;continue}r=c,a=u}if(v.triarea2(t,e,h)>=0){if(!(v.vequal(t,e)||v.triarea2(t,r,h)<0)){o.push(r),e=t=r,r=t,s=i=a,a=i,u=i;continue}e=h,s=u}}return 0!==o.length&&v.vequal(o[o.length-1],n[n.length-1].left)||o.push(n[n.length-1].left),this.path=o,o},t}(),m=function(){function t(){this.zones={}}t.createZone=function(t){return b.buildZone(t)};var r=t.prototype;return r.setZoneData=function(t,e){this.zones[t]=e},r.getRandomNode=function(t,r,n,o){if(!this.zones[t])return new e;n=n||null,o=o||0;var i=[];return this.zones[t].groups[r].forEach(function(t){n&&o?v.distanceToSquared(n,t.centroid)<o*o&&i.push(t.centroid):i.push(t.centroid)}),v.sample(i)||new e},r.getClosestNode=function(t,e,r,n){void 0===n&&(n=!1);var o=this.zones[e].vertices,i=null,s=Infinity;return this.zones[e].groups[r].forEach(function(e){var r=v.distanceToSquared(e.centroid,t);r<s&&(!n||v.isVectorInPolygon(t,e,o))&&(i=e,s=r)}),i},r.findPath=function(t,r,n,o){var i=this.zones[n].groups[o],s=this.zones[n].vertices,a=this.getClosestNode(t,n,o,!0),u=this.getClosestNode(r,n,o,!0);if(!a||!u)return null;var h=g.search(i,a,u),c=function(t,e){for(var r=0;r<t.neighbours.length;r++)if(t.neighbours[r]===e.id)return t.portals[r]},l=new y;l.push(t);for(var f=0;f<h.length;f++){var p=h[f+1];if(p){var v=c(h[f],p);l.push(s[v[0]],s[v[1]])}}l.push(r),l.stringPull();var d=l.path.map(function(t){return new e(t.x,t.y,t.z)});return d.shift(),d},t}();m.prototype.getGroup=(p=new r,function(t,e,r){if(void 0===r&&(r=!1),!this.zones[t])return null;for(var n=null,o=Math.pow(50,2),i=this.zones[t],s=0;s<i.groups.length;s++){var a=i.groups[s],u=Array.isArray(a),h=0;for(a=u?a:a[Symbol.iterator]();;){var c;if(u){if(h>=a.length)break;c=a[h++]}else{if((h=a.next()).done)break;c=h.value}var l=c;if(r&&(p.setFromCoplanarPoints(i.vertices[l.vertexIds[0]],i.vertices[l.vertexIds[1]],i.vertices[l.vertexIds[2]]),Math.abs(p.distanceToPoint(e))<.01&&v.isPointInPoly([i.vertices[l.vertexIds[0]],i.vertices[l.vertexIds[1]],i.vertices[l.vertexIds[2]]],e)))return s;var f=v.distanceToSquared(l.centroid,e);f<o&&(n=s,o=f)}}return n}),m.prototype.clampStep=function(){var t,o,i=new e,s=new r,a=new n,u=new e,h=new e;return function(e,r,n,c,l,f){var p=this.zones[c].vertices,v=this.zones[c].groups[l],d=[n],g={};g[n.id]=0,t=void 0,h.set(0,0,0),o=Infinity,s.setFromCoplanarPoints(p[n.vertexIds[0]],p[n.vertexIds[1]],p[n.vertexIds[2]]),s.projectPoint(r,i),u.copy(i);for(var b=d.pop();b;b=d.pop()){a.set(p[b.vertexIds[0]],p[b.vertexIds[1]],p[b.vertexIds[2]]),a.closestPointToPoint(u,i),i.distanceToSquared(u)<o&&(t=b,h.copy(i),o=i.distanceToSquared(u));var y=g[b.id];if(!(y>2))for(var m=0;m<b.neighbours.length;m++){var w=v[b.neighbours[m]];w.id in g||(d.push(w),g[w.id]=y+1)}}return f.copy(h),t}}();var w={PLAYER:new o(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new o(14469912).convertGammaToLinear(2.2).getHex(),PATH:new o(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new o(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new o(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new o(4417387).convertGammaToLinear(2.2).getHex()},x=function(e){var r,n;function o(){var t;return(t=e.call(this)||this)._playerMarker=new a(new u(.25,32,32),new h({color:w.PLAYER})),t._targetMarker=new a(new c(.3,.3,.3),new h({color:w.TARGET})),t._nodeMarker=new a(new c(.1,.8,.1),new h({color:w.CLOSEST_NODE})),t._stepMarker=new a(new c(.1,1,.1),new h({color:w.CLAMPED_STEP})),t._pathMarker=new l,t._pathLineMaterial=new f({color:w.PATH,linewidth:2}),t._pathPointMaterial=new h({color:w.WAYPOINT}),t._pathPointGeometry=new u(.08),t._markers=[t._playerMarker,t._targetMarker,t._nodeMarker,t._stepMarker,t._pathMarker],t._markers.forEach(function(e){e.visible=!1,t.add(e)}),t}n=e,(r=o).prototype=Object.create(n.prototype),r.prototype.constructor=r,r.__proto__=n;var p=o.prototype;return p.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);var r=new i;r.setAttribute("position",new t(new Float32Array(3*e.length),3));for(var n=0;n<e.length;n++)r.attributes.position.setXYZ(n,e[n].x,e[n].y+.2,e[n].z);this._pathMarker.add(new s(r,this._pathLineMaterial));for(var o=0;o<e.length-1;o++){var u=new a(this._pathPointGeometry,this._pathPointMaterial);u.position.copy(e[o]),u.position.y+=.2,this._pathMarker.add(u)}return this._pathMarker.visible=!0,this},p.setPlayerPosition=function(t){return this._playerMarker.position.copy(t),this._playerMarker.visible=!0,this},p.setTargetPosition=function(t){return this._targetMarker.position.copy(t),this._targetMarker.visible=!0,this},p.setNodePosition=function(t){return this._nodeMarker.position.copy(t),this._nodeMarker.visible=!0,this},p.setStepPosition=function(t){return this._stepMarker.position.copy(t),this._stepMarker.visible=!0,this},p.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(t){t.visible=!1}),this},o}(l);export{m as Pathfinding,x as PathfindingHelper}; | ||
//# sourceMappingURL=three-pathfinding.module.js.map |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t(e.threePathfinding={},e.three)}(this,function(e,t){var r=function(){};r.roundNumber=function(e,t){var r=Math.pow(10,t);return Math.round(e*r)/r},r.sample=function(e){return e[Math.floor(Math.random()*e.length)]},r.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},r.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},r.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))},r.triarea2=function(e,t,r){return(r.x-e.x)*(t.z-e.z)-(t.x-e.x)*(r.z-e.z)},r.vequal=function(e,t){return this.distanceToSquared(e,t)<1e-5};var n=function(e){this.content=[],this.scoreFunction=e};n.prototype.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},n.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},n.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))},n.prototype.size=function(){return this.content.length},n.prototype.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},n.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}},n.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 o=function(){};o.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}},o.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}},o.heap=function(){return new n(function(e){return e.f})},o.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[]},o.heuristic=function(e,t){return r.distanceToSquared(e,t)},o.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r};var i=function(){};i.buildZone=function(e){var n=this,o=this._buildNavigationMesh(e),i={};o.vertices.forEach(function(e){e.x=r.roundNumber(e.x,2),e.y=r.roundNumber(e.y,2),e.z=r.roundNumber(e.z,2)}),i.vertices=o.vertices;var s=this._buildPolygonGroups(o);return i.groups=new Array(s.length),s.forEach(function(e,o){var s=new Map;e.forEach(function(e,t){s.set(e,t)});var a=new Array(e.length);e.forEach(function(e,o){var h=[];e.neighbours.forEach(function(e){return h.push(s.get(e))});var c=[];e.neighbours.forEach(function(t){return c.push(n._getSharedVerticesInOrder(e,t))});var u=new t.Vector3(0,0,0);u.add(i.vertices[e.vertexIds[0]]),u.add(i.vertices[e.vertexIds[1]]),u.add(i.vertices[e.vertexIds[2]]),u.divideScalar(3),u.x=r.roundNumber(u.x,2),u.y=r.roundNumber(u.y,2),u.z=r.roundNumber(u.z,2),a[o]={id:o,neighbours:h,vertexIds:e.vertexIds,centroid:u,portals:c}}),i.groups[o]=a}),i},i._buildNavigationMesh=function(e){return 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,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}},i._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 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,t,n,o=this.portals,i=[],s=0,a=0,h=0;t=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(r.triarea2(e,n,p)<=0){if(!(r.vequal(e,n)||r.triarea2(e,t,p)>0)){i.push(t),t=e=t,n=e,a=s=a,h=s,c=s;continue}n=p,h=c}if(r.triarea2(e,t,u)>=0){if(!(r.vequal(e,t)||r.triarea2(e,n,u)<0)){i.push(n),t=e=n,n=e,a=s=h,h=s,c=s;continue}t=u,a=c}}return 0!==i.length&&r.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 BufferGeometry, not Geometry, to create zone."):e=(new t.Geometry).fromBufferGeometry(e),i.buildZone(e)},h.prototype.setZoneData=function(e,t){this.zones[e]=t},h.prototype.getRandomNode=function(e,n,o,i){if(!this.zones[e])return new t.Vector3;o=o||null,i=i||0;var s=[];return this.zones[e].groups[n].forEach(function(e){o&&i?r.distanceToSquared(o,e.centroid)<i*i&&s.push(e.centroid):s.push(e.centroid)}),r.sample(s)||new t.Vector3},h.prototype.getClosestNode=function(e,t,n,o){void 0===o&&(o=!1);var i=this.zones[t].vertices,s=null,a=Infinity;return this.zones[t].groups[n].forEach(function(t){var n=r.distanceToSquared(t.centroid,e);n<a&&(!o||r.isVectorInPolygon(e,t,i))&&(s=t,a=n)}),s},h.prototype.findPath=function(e,r,n,i){var a=this.zones[n].groups[i],h=this.zones[n].vertices,c=this.getClosestNode(e,n,i,!0),u=this.getClosestNode(r,n,i,!0);if(!c||!u)return null;var p=o.search(a,c,u),l=function(e,t){for(var r=0;r<e.neighbours.length;r++)if(e.neighbours[r]===t.id)return e.portals[r]},f=new s;f.push(e);for(var d=0;d<p.length;d++){var v=p[d+1];if(v){var g=l(p[d],v);f.push(h[g[0]],h[g[1]])}}f.push(r),f.stringPull();var y=f.path.map(function(e){return new t.Vector3(e.x,e.y,e.z)});return y.shift(),y},h.prototype.getGroup=(a=new t.Plane,function(e,t,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 p=u[c];if(n&&(a.setFromCoplanarPoints(s.vertices[p.vertexIds[0]],s.vertices[p.vertexIds[1]],s.vertices[p.vertexIds[2]]),Math.abs(a.distanceToPoint(t))<.01&&r.isPointInPoly([s.vertices[p.vertexIds[0]],s.vertices[p.vertexIds[1]],s.vertices[p.vertexIds[2]]],t)))return h;var l=r.distanceToSquared(p.centroid,t);l<i&&(o=h,i=l)}return o}),h.prototype.clampStep=function(){var e,r,n=new t.Vector3,o=new t.Plane,i=new t.Triangle,s=new t.Vector3,a=new t.Vector3;return function(t,h,c,u,p,l){var f=this.zones[u].vertices,d=this.zones[u].groups[p],v=[c],g={};g[c.id]=0,e=void 0,a.set(0,0,0),r=Infinity,o.setFromCoplanarPoints(f[c.vertexIds[0]],f[c.vertexIds[1]],f[c.vertexIds[2]]),o.projectPoint(h,n),s.copy(n);for(var y=v.pop();y;y=v.pop()){i.set(f[y.vertexIds[0]],f[y.vertexIds[1]],f[y.vertexIds[2]]),i.closestPointToPoint(s,n),n.distanceToSquared(s)<r&&(e=y,a.copy(n),r=n.distanceToSquared(s));var M=g[y.id];if(!(M>2))for(var b=0;b<y.neighbours.length;b++){var m=d[y.neighbours[b]];m.id in g||(v.push(m),g[m.id]=M+1)}}return l.copy(a),e}}();var c={PLAYER:new t.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new t.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new t.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new t.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new t.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new t.Color(4417387).convertGammaToLinear(2.2).getHex()},u=function(e){function r(){var r=this;e.call(this),this._playerMarker=new t.Mesh(new t.SphereGeometry(.25,32,32),new t.MeshBasicMaterial({color:c.PLAYER})),this._targetMarker=new t.Mesh(new t.BoxGeometry(.3,.3,.3),new t.MeshBasicMaterial({color:c.TARGET})),this._nodeMarker=new t.Mesh(new t.BoxGeometry(.1,.8,.1),new t.MeshBasicMaterial({color:c.CLOSEST_NODE})),this._stepMarker=new t.Mesh(new t.BoxGeometry(.1,1,.1),new t.MeshBasicMaterial({color:c.CLAMPED_STEP})),this._pathMarker=new e,this._pathLineMaterial=new t.LineBasicMaterial({color:c.PATH,linewidth:2}),this._pathPointMaterial=new t.MeshBasicMaterial({color:c.WAYPOINT}),this._pathPointGeometry=new t.SphereBufferGeometry(.08),this._markers=[this._playerMarker,this._targetMarker,this._nodeMarker,this._stepMarker,this._pathMarker],this._markers.forEach(function(e){e.visible=!1,r.add(e)})}return e&&(r.__proto__=e),(r.prototype=Object.create(e&&e.prototype)).constructor=r,r.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 r=new t.Geometry,n=0;n<e.length;n++)r.vertices.push(e[n].clone().add(new t.Vector3(0,.2,0)));this._pathMarker.add(new t.Line(r,this._pathLineMaterial));for(var o=0;o<e.length-1;o++){var i=new t.Mesh(this._pathPointGeometry,this._pathPointMaterial);i.position.copy(e[o]),i.position.y+=.2,this._pathMarker.add(i)}return this._pathMarker.visible=!0,this},r.prototype.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},r.prototype.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},r.prototype.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},r.prototype.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},r.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},r}(t.Object3D);e.Pathfinding=h,e.PathfindingHelper=u}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t((e||self).threePathfinding={},e.THREE)}(this,function(e,t){var r,n=function(){function e(){}return 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},e.mergeVertices=function(e,r){void 0===r&&(r=1e-4),r=Math.max(r,Number.EPSILON);for(var n={},o=e.getIndex(),i=e.getAttribute("position"),s=o?o.count:i.count,a=0,u=Object.keys(e.attributes),h={},c={},f=[],l=["getX","getY","getZ","getW"],p=0,d=u.length;p<d;p++)h[A=u[p]]=[],(_=e.morphAttributes[A])&&(c[A]=new Array(_.length).fill().map(function(){return[]}));var v=Math.log10(1/r),g=Math.pow(10,v);for(p=0;p<s;p++){var b=o?o.getX(p):p,y="",m=0;for(d=u.length;m<d;m++)for(var M=(w=e.getAttribute(A=u[m])).itemSize,x=0;x<M;x++)y+=~~(w[l[x]](b)*g)+",";if(y in n)f.push(n[y]);else{for(m=0,d=u.length;m<d;m++){var w=e.getAttribute(A=u[m]),_=e.morphAttributes[A],P=(M=w.itemSize,h[A]),z=c[A];for(x=0;x<M;x++){var k=l[x];if(P.push(w[k](b)),_)for(var I=0,E=_.length;I<E;I++)z[I].push(_[I][k](b))}}n[y]=a,f.push(a),a++}}var T=e.clone();for(p=0,d=u.length;p<d;p++){var A,S=e.getAttribute(A=u[p]),N=new S.array.constructor(h[A]);if(w=new t.BufferAttribute(N,S.itemSize,S.normalized),T.setAttribute(A,w),A in c)for(m=0;m<c[A].length;m++){var G=e.morphAttributes[A][m],B=(N=new G.array.constructor(c[A][m]),new t.BufferAttribute(N,G.itemSize,G.normalized));T.morphAttributes[A][m]=B}}return T.setIndex(f),T},e}(),o=function(){function e(e){this.content=[],this.scoreFunction=e}var t=e.prototype;return t.push=function(e){this.content.push(e),this.sinkDown(this.content.length-1)},t.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.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.size=function(){return this.content.length},t.rescoreElement=function(e){this.sinkDown(this.content.indexOf(e))},t.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.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),o<t&&this.scoreFunction(this.content[o])<(null===s?n:a)&&(s=o),null===s)break;this.content[e]=this.content[s],this.content[s]=r,e=s}},e}(),i=function(){function e(){}return e.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}},e.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}},e.heap=function(){return new o(function(e){return e.f})},e.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),u=0,h=a.length;u<h;u++){var c=a[u];if(!c.closed){var f=o.g+c.cost,l=c.visited;if(!l||f<c.g){if(c.visited=!0,c.parent=o,!c.centroid||!r.centroid)throw new Error("Unexpected state");c.h=c.h||this.heuristic(c.centroid,r.centroid),c.g=f,c.f=c.g+c.h,l?n.rescoreElement(c):n.push(c)}}}}return[]},e.heuristic=function(e,t){return n.distanceToSquared(e,t)},e.neighbours=function(e,t){for(var r=[],n=0;n<t.neighbours.length;n++)r.push(e[t.neighbours[n]]);return r},e}(),s=function(){function e(){}return e.buildZone=function(e){var r=this,o=this._buildNavigationMesh(e),i={};o.vertices.forEach(function(e){e.x=n.roundNumber(e.x,2),e.y=n.roundNumber(e.y,2),e.z=n.roundNumber(e.z,2)}),i.vertices=o.vertices;var s=this._buildPolygonGroups(o);return i.groups=new Array(s.length),s.forEach(function(e,o){var s=new Map;e.forEach(function(e,t){s.set(e,t)});var a=new Array(e.length);e.forEach(function(e,o){var u=[];e.neighbours.forEach(function(e){return u.push(s.get(e))});var h=[];e.neighbours.forEach(function(t){return h.push(r._getSharedVerticesInOrder(e,t))});var c=new t.Vector3(0,0,0);c.add(i.vertices[e.vertexIds[0]]),c.add(i.vertices[e.vertexIds[1]]),c.add(i.vertices[e.vertexIds[2]]),c.divideScalar(3),c.x=n.roundNumber(c.x,2),c.y=n.roundNumber(c.y,2),c.z=n.roundNumber(c.z,2),a[o]={id:o,neighbours:u,vertexIds:e.vertexIds,centroid:c,portals:h}}),i.groups[o]=a}),i},e._buildNavigationMesh=function(e){return e=n.mergeVertices(e),this._buildPolygonsFromGeometry(e)},e._buildPolygonGroups=function(e){var t=[],r=function e(t){t.neighbours.forEach(function(r){void 0===r.group&&(r.group=t.group,e(r))})};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},e._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},e._buildPolygonsFromGeometry=function(e){for(var r=this,n=[],o=[],i=e.attributes.position,s=e.index,a=[],u=0;u<i.count;u++)o.push((new t.Vector3).fromBufferAttribute(i,u)),a[u]=[];for(var h=0;h<e.index.count;h+=3){var c=s.getX(h),f=s.getX(h+1),l=s.getX(h+2),p={vertexIds:[c,f,l],neighbours:null};n.push(p),a[c].push(p),a[f].push(p),a[l].push(p)}return n.forEach(function(e){e.neighbours=r._buildPolygonNeighbours(e,a)}),{polygons:n,vertices:o}},e._getSharedVerticesInOrder=function(e,t){var r=e.vertexIds,n=r[0],o=r[1],i=r[2],s=t.vertexIds,a=s.includes(n),u=s.includes(o),h=s.includes(i);return a&&u&&h?Array.from(r):a&&u?[n,o]:u&&h?[o,i]:a&&h?[i,n]:(console.warn("Error processing navigation mesh neighbors; neighbors with <2 shared vertices found."),[])},e}(),a=function(){function e(){this.portals=[]}var t=e.prototype;return t.push=function(e,t){void 0===t&&(t=e),this.portals.push({left:e,right:t})},t.stringPull=function(){var e,t,r,o=this.portals,i=[],s=0,a=0,u=0;t=o[0].left,r=o[0].right,i.push(e=o[0].left);for(var h=1;h<o.length;h++){var c=o[h].left,f=o[h].right;if(n.triarea2(e,r,f)<=0){if(!(n.vequal(e,r)||n.triarea2(e,t,f)>0)){i.push(t),t=e=t,r=e,a=s=a,u=s,h=s;continue}r=f,u=h}if(n.triarea2(e,t,c)>=0){if(!(n.vequal(e,t)||n.triarea2(e,r,c)<0)){i.push(r),t=e=r,r=e,a=s=u,u=s,h=s;continue}t=c,a=h}}return 0!==i.length&&n.vequal(i[i.length-1],o[o.length-1].left)||i.push(o[o.length-1].left),this.path=i,i},e}(),u=function(){function e(){this.zones={}}e.createZone=function(e){return s.buildZone(e)};var r=e.prototype;return r.setZoneData=function(e,t){this.zones[e]=t},r.getRandomNode=function(e,r,o,i){if(!this.zones[e])return new t.Vector3;o=o||null,i=i||0;var s=[];return this.zones[e].groups[r].forEach(function(e){o&&i?n.distanceToSquared(o,e.centroid)<i*i&&s.push(e.centroid):s.push(e.centroid)}),n.sample(s)||new t.Vector3},r.getClosestNode=function(e,t,r,o){void 0===o&&(o=!1);var i=this.zones[t].vertices,s=null,a=Infinity;return this.zones[t].groups[r].forEach(function(t){var r=n.distanceToSquared(t.centroid,e);r<a&&(!o||n.isVectorInPolygon(e,t,i))&&(s=t,a=r)}),s},r.findPath=function(e,r,n,o){var s=this.zones[n].groups[o],u=this.zones[n].vertices,h=this.getClosestNode(e,n,o,!0),c=this.getClosestNode(r,n,o,!0);if(!h||!c)return null;var f=i.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]},p=new a;p.push(e);for(var d=0;d<f.length;d++){var v=f[d+1];if(v){var g=l(f[d],v);p.push(u[g[0]],u[g[1]])}}p.push(r),p.stringPull();var b=p.path.map(function(e){return new t.Vector3(e.x,e.y,e.z)});return b.shift(),b},e}();u.prototype.getGroup=(r=new t.Plane,function(e,t,o){if(void 0===o&&(o=!1),!this.zones[e])return null;for(var i=null,s=Math.pow(50,2),a=this.zones[e],u=0;u<a.groups.length;u++){var h=a.groups[u],c=Array.isArray(h),f=0;for(h=c?h:h[Symbol.iterator]();;){var l;if(c){if(f>=h.length)break;l=h[f++]}else{if((f=h.next()).done)break;l=f.value}var p=l;if(o&&(r.setFromCoplanarPoints(a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]),Math.abs(r.distanceToPoint(t))<.01&&n.isPointInPoly([a.vertices[p.vertexIds[0]],a.vertices[p.vertexIds[1]],a.vertices[p.vertexIds[2]]],t)))return u;var d=n.distanceToSquared(p.centroid,t);d<s&&(i=u,s=d)}}return i}),u.prototype.clampStep=function(){var e,r,n=new t.Vector3,o=new t.Plane,i=new t.Triangle,s=new t.Vector3,a=new t.Vector3;return function(t,u,h,c,f,l){var p=this.zones[c].vertices,d=this.zones[c].groups[f],v=[h],g={};g[h.id]=0,e=void 0,a.set(0,0,0),r=Infinity,o.setFromCoplanarPoints(p[h.vertexIds[0]],p[h.vertexIds[1]],p[h.vertexIds[2]]),o.projectPoint(u,n),s.copy(n);for(var b=v.pop();b;b=v.pop()){i.set(p[b.vertexIds[0]],p[b.vertexIds[1]],p[b.vertexIds[2]]),i.closestPointToPoint(s,n),n.distanceToSquared(s)<r&&(e=b,a.copy(n),r=n.distanceToSquared(s));var y=g[b.id];if(!(y>2))for(var m=0;m<b.neighbours.length;m++){var M=d[b.neighbours[m]];M.id in g||(v.push(M),g[M.id]=y+1)}}return l.copy(a),e}}();var h={PLAYER:new t.Color(15631215).convertGammaToLinear(2.2).getHex(),TARGET:new t.Color(14469912).convertGammaToLinear(2.2).getHex(),PATH:new t.Color(41903).convertGammaToLinear(2.2).getHex(),WAYPOINT:new t.Color(41903).convertGammaToLinear(2.2).getHex(),CLAMPED_STEP:new t.Color(14472114).convertGammaToLinear(2.2).getHex(),CLOSEST_NODE:new t.Color(4417387).convertGammaToLinear(2.2).getHex()},c=function(e){var r,n;function o(){var r;return(r=e.call(this)||this)._playerMarker=new t.Mesh(new t.SphereBufferGeometry(.25,32,32),new t.MeshBasicMaterial({color:h.PLAYER})),r._targetMarker=new t.Mesh(new t.BoxBufferGeometry(.3,.3,.3),new t.MeshBasicMaterial({color:h.TARGET})),r._nodeMarker=new t.Mesh(new t.BoxBufferGeometry(.1,.8,.1),new t.MeshBasicMaterial({color:h.CLOSEST_NODE})),r._stepMarker=new t.Mesh(new t.BoxBufferGeometry(.1,1,.1),new t.MeshBasicMaterial({color:h.CLAMPED_STEP})),r._pathMarker=new t.Object3D,r._pathLineMaterial=new t.LineBasicMaterial({color:h.PATH,linewidth:2}),r._pathPointMaterial=new t.MeshBasicMaterial({color:h.WAYPOINT}),r._pathPointGeometry=new t.SphereBufferGeometry(.08),r._markers=[r._playerMarker,r._targetMarker,r._nodeMarker,r._stepMarker,r._pathMarker],r._markers.forEach(function(e){e.visible=!1,r.add(e)}),r}n=e,(r=o).prototype=Object.create(n.prototype),r.prototype.constructor=r,r.__proto__=n;var i=o.prototype;return i.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);var r=new t.BufferGeometry;r.setAttribute("position",new t.BufferAttribute(new Float32Array(3*e.length),3));for(var n=0;n<e.length;n++)r.attributes.position.setXYZ(n,e[n].x,e[n].y+.2,e[n].z);this._pathMarker.add(new t.Line(r,this._pathLineMaterial));for(var o=0;o<e.length-1;o++){var i=new t.Mesh(this._pathPointGeometry,this._pathPointMaterial);i.position.copy(e[o]),i.position.y+=.2,this._pathMarker.add(i)}return this._pathMarker.visible=!0,this},i.setPlayerPosition=function(e){return this._playerMarker.position.copy(e),this._playerMarker.visible=!0,this},i.setTargetPosition=function(e){return this._targetMarker.position.copy(e),this._targetMarker.visible=!0,this},i.setNodePosition=function(e){return this._nodeMarker.position.copy(e),this._nodeMarker.visible=!0,this},i.setStepPosition=function(e){return this._stepMarker.position.copy(e),this._stepMarker.visible=!0,this},i.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},o}(t.Object3D);e.Pathfinding=u,e.PathfindingHelper=c}); | ||
//# sourceMappingURL=three-pathfinding.umd.js.map |
{ | ||
"name": "three-pathfinding", | ||
"version": "0.13.0", | ||
"version": "0.14.0", | ||
"description": "Navigation mesh toolkit for three.js, based on PatrolJS", | ||
@@ -24,3 +24,3 @@ "author": "Don McCurdy <dm@donmccurdy.com>", | ||
"postversion": "git push && git push --tags && npm publish", | ||
"test": "node tests/index.test.js", | ||
"test": "node tests/index.test.js | tap-spec", | ||
"benchmark": "node benchmark/index.benchmark.js", | ||
@@ -53,7 +53,8 @@ "deploy": "npm run dist && npm test && now --static && now alias" | ||
"documentation": "^12.2.0", | ||
"microbundle": "^0.11.0", | ||
"microbundle": "^0.13.0", | ||
"replace-between": "0.0.8", | ||
"serve": "^11.3.0", | ||
"serve": "^11.3.2", | ||
"tap-spec": "^5.0.0", | ||
"tape": "^4.9.1", | ||
"three": "^0.115.0", | ||
"three": "^0.124.0", | ||
"uglify-js": "^3.3.3" | ||
@@ -60,0 +61,0 @@ }, |
@@ -6,3 +6,3 @@ # three-pathfinding | ||
[![License](https://img.shields.io/badge/license-MIT-007ec6.svg)](https://github.com/donmccurdy/three-pathfinding/blob/master/LICENSE) | ||
[![Build Status](https://travis-ci.com/donmccurdy/three-pathfinding.svg?branch=master)](https://travis-ci.com/donmccurdy/three-pathfinding) | ||
[![Build Status](https://github.com/donmccurdy/three-pathfinding/workflows/build/badge.svg?branch=master&event=push)](https://github.com/donmccurdy/three-pathfinding/actions?query=workflow%3Abuild) | ||
@@ -79,2 +79,4 @@ Navigation mesh toolkit for ThreeJS, based on [PatrolJS](https://github.com/nickjanssen/PatrolJS). Computes paths between points on a 3D nav mesh, supports multiple zones, and clamps movement vectors for FPS controls. To learn how to create a navigation mesh using Blender, see [Creating a Nav Mesh](https://www.donmccurdy.com/2017/08/20/creating-a-nav-mesh-for-a-webvr-scene/). | ||
The origin of an agent should initially be placed on the surface of the nav mesh. If needed, a dummy object can be used for pathfinding logic, and the rendered model for that agent may be placed at on offset as needed. | ||
### Running the demo locally | ||
@@ -81,0 +83,0 @@ |
@@ -1,4 +0,2 @@ | ||
import { | ||
Vector3, | ||
} from 'three'; | ||
import { Vector3 } from 'three'; | ||
@@ -10,3 +8,3 @@ import { Utils } from './Utils'; | ||
* Constructs groups from the given navigation mesh. | ||
* @param {Geometry} geometry | ||
* @param {BufferGeometry} geometry | ||
* @return {Zone} | ||
@@ -75,7 +73,7 @@ */ | ||
* Constructs a navigation mesh from the given geometry. | ||
* @param {Geometry} geometry | ||
* @param {BufferGeometry} geometry | ||
* @return {Object} | ||
*/ | ||
static _buildNavigationMesh (geometry) { | ||
geometry.mergeVertices(); | ||
geometry = Utils.mergeVertices(geometry); | ||
return this._buildPolygonsFromGeometry(geometry); | ||
@@ -143,4 +141,7 @@ } | ||
const polygons = []; | ||
const vertices = geometry.vertices; | ||
const vertices = []; | ||
const position = geometry.attributes.position; | ||
const index = geometry.index; | ||
// Constructing the neighbor graph brute force is O(n²). To avoid that, | ||
@@ -150,4 +151,8 @@ // create a map from vertices to the polygons that contain them, and use it | ||
// is related to connectivity of the mesh. | ||
const vertexPolygonMap = new Array(vertices.length); // array of polygon objects by vertex index | ||
for (let i = 0; i < vertices.length; i++) { | ||
/** Array of polygon objects by vertex index. */ | ||
const vertexPolygonMap = []; | ||
for (let i = 0; i < position.count; i++) { | ||
vertices.push(new Vector3().fromBufferAttribute(position, i)); | ||
vertexPolygonMap[i] = []; | ||
@@ -157,9 +162,12 @@ } | ||
// Convert the faces into a custom format that supports more than 3 vertices | ||
geometry.faces.forEach((face) => { | ||
const poly = { vertexIds: [face.a, face.b, face.c], neighbours: null }; | ||
for (let i = 0; i < geometry.index.count; i += 3) { | ||
const a = index.getX(i); | ||
const b = index.getX(i + 1); | ||
const c = index.getX(i + 2); | ||
const poly = {vertexIds: [a, b, c], neighbours: null}; | ||
polygons.push(poly); | ||
vertexPolygonMap[face.a].push(poly); | ||
vertexPolygonMap[face.b].push(poly); | ||
vertexPolygonMap[face.c].push(poly); | ||
}); | ||
vertexPolygonMap[a].push(poly); | ||
vertexPolygonMap[b].push(poly); | ||
vertexPolygonMap[c].push(poly); | ||
} | ||
@@ -166,0 +174,0 @@ // Build a list of adjacent polygons |
import { | ||
Vector3, | ||
Plane, | ||
Geometry, | ||
Triangle, | ||
@@ -27,10 +26,2 @@ } from 'three'; | ||
static createZone (geometry) { | ||
if ( geometry.isGeometry ) { | ||
// Haven't actually implemented support for BufferGeometry yet, but Geometry is somewhat | ||
// not-recommended these days, so go ahead and start warning. | ||
console.warn('[three-pathfinding]: Use BufferGeometry, not Geometry, to create zone.'); | ||
} else { | ||
geometry = new Geometry().fromBufferGeometry(geometry); | ||
} | ||
return Builder.buildZone(geometry); | ||
@@ -37,0 +28,0 @@ } |
import { | ||
BoxBufferGeometry, | ||
BufferAttribute, | ||
BufferGeometry, | ||
Color, | ||
Object3D, | ||
Line, | ||
LineBasicMaterial, | ||
Mesh, | ||
MeshBasicMaterial, | ||
Object3D, | ||
SphereBufferGeometry, | ||
BoxGeometry, | ||
Mesh, | ||
SphereGeometry, | ||
Geometry, | ||
Vector3, | ||
Line, | ||
} from 'three'; | ||
@@ -34,3 +34,3 @@ | ||
this._playerMarker = new Mesh( | ||
new SphereGeometry( 0.25, 32, 32 ), | ||
new SphereBufferGeometry( 0.25, 32, 32 ), | ||
new MeshBasicMaterial( { color: colors.PLAYER } ) | ||
@@ -40,15 +40,15 @@ ); | ||
this._targetMarker = new Mesh( | ||
new BoxGeometry( 0.3, 0.3, 0.3 ), | ||
new BoxBufferGeometry( 0.3, 0.3, 0.3 ), | ||
new MeshBasicMaterial( { color: colors.TARGET } ) | ||
); | ||
this._nodeMarker = new Mesh( | ||
new BoxGeometry( 0.1, 0.8, 0.1 ), | ||
new BoxBufferGeometry( 0.1, 0.8, 0.1 ), | ||
new MeshBasicMaterial( { color: colors.CLOSEST_NODE } ) | ||
); | ||
this._stepMarker = new Mesh( | ||
new BoxGeometry( 0.1, 1, 0.1 ), | ||
new BoxBufferGeometry( 0.1, 1, 0.1 ), | ||
new MeshBasicMaterial( { color: colors.CLAMPED_STEP } ) | ||
@@ -97,5 +97,6 @@ ); | ||
// Draw debug lines | ||
const geometry = new Geometry(); | ||
const geometry = new BufferGeometry(); | ||
geometry.setAttribute('position', new BufferAttribute(new Float32Array(path.length * 3), 3)); | ||
for (let i = 0; i < path.length; i++) { | ||
geometry.vertices.push( path[ i ].clone().add( new Vector3( 0, OFFSET, 0 ) ) ); | ||
geometry.attributes.position.setXYZ(i, path[ i ].x, path[ i ].y + OFFSET, path[ i ].z); | ||
} | ||
@@ -102,0 +103,0 @@ this._pathMarker.add( new Line( geometry, this._pathLineMaterial ) ); |
154
src/Utils.js
@@ -0,1 +1,3 @@ | ||
import { BufferAttribute } from 'three'; | ||
class Utils { | ||
@@ -64,4 +66,156 @@ | ||
} | ||
/** | ||
* Copied from BufferGeometryUtils.mergeVertices, because importing ES modules | ||
* from a sub-directory makes Node.js (as of v14) angry. | ||
* | ||
* @param {THREE.BufferGeometry} geometry | ||
* @param {number} tolerance | ||
* @return {THREE.BufferGeometry>} | ||
*/ | ||
static mergeVertices (geometry, tolerance = 1e-4) { | ||
tolerance = Math.max( tolerance, Number.EPSILON ); | ||
// Generate an index buffer if the geometry doesn't have one, or optimize it | ||
// if it's already available. | ||
var hashToIndex = {}; | ||
var indices = geometry.getIndex(); | ||
var positions = geometry.getAttribute( 'position' ); | ||
var vertexCount = indices ? indices.count : positions.count; | ||
// next value for triangle indices | ||
var nextIndex = 0; | ||
// attributes and new attribute arrays | ||
var attributeNames = Object.keys( geometry.attributes ); | ||
var attrArrays = {}; | ||
var morphAttrsArrays = {}; | ||
var newIndices = []; | ||
var getters = [ 'getX', 'getY', 'getZ', 'getW' ]; | ||
// initialize the arrays | ||
for ( var i = 0, l = attributeNames.length; i < l; i ++ ) { | ||
var name = attributeNames[ i ]; | ||
attrArrays[ name ] = []; | ||
var morphAttr = geometry.morphAttributes[ name ]; | ||
if ( morphAttr ) { | ||
morphAttrsArrays[ name ] = new Array( morphAttr.length ).fill().map( () => [] ); | ||
} | ||
} | ||
// convert the error tolerance to an amount of decimal places to truncate to | ||
var decimalShift = Math.log10( 1 / tolerance ); | ||
var shiftMultiplier = Math.pow( 10, decimalShift ); | ||
for ( var i = 0; i < vertexCount; i ++ ) { | ||
var index = indices ? indices.getX( i ) : i; | ||
// Generate a hash for the vertex attributes at the current index 'i' | ||
var hash = ''; | ||
for ( var j = 0, l = attributeNames.length; j < l; j ++ ) { | ||
var name = attributeNames[ j ]; | ||
var attribute = geometry.getAttribute( name ); | ||
var itemSize = attribute.itemSize; | ||
for ( var k = 0; k < itemSize; k ++ ) { | ||
// double tilde truncates the decimal value | ||
hash += `${ ~ ~ ( attribute[ getters[ k ] ]( index ) * shiftMultiplier ) },`; | ||
} | ||
} | ||
// Add another reference to the vertex if it's already | ||
// used by another index | ||
if ( hash in hashToIndex ) { | ||
newIndices.push( hashToIndex[ hash ] ); | ||
} else { | ||
// copy data to the new index in the attribute arrays | ||
for ( var j = 0, l = attributeNames.length; j < l; j ++ ) { | ||
var name = attributeNames[ j ]; | ||
var attribute = geometry.getAttribute( name ); | ||
var morphAttr = geometry.morphAttributes[ name ]; | ||
var itemSize = attribute.itemSize; | ||
var newarray = attrArrays[ name ]; | ||
var newMorphArrays = morphAttrsArrays[ name ]; | ||
for ( var k = 0; k < itemSize; k ++ ) { | ||
var getterFunc = getters[ k ]; | ||
newarray.push( attribute[ getterFunc ]( index ) ); | ||
if ( morphAttr ) { | ||
for ( var m = 0, ml = morphAttr.length; m < ml; m ++ ) { | ||
newMorphArrays[ m ].push( morphAttr[ m ][ getterFunc ]( index ) ); | ||
} | ||
} | ||
} | ||
} | ||
hashToIndex[ hash ] = nextIndex; | ||
newIndices.push( nextIndex ); | ||
nextIndex ++; | ||
} | ||
} | ||
// Generate typed arrays from new attribute arrays and update | ||
// the attributeBuffers | ||
const result = geometry.clone(); | ||
for ( var i = 0, l = attributeNames.length; i < l; i ++ ) { | ||
var name = attributeNames[ i ]; | ||
var oldAttribute = geometry.getAttribute( name ); | ||
var buffer = new oldAttribute.array.constructor( attrArrays[ name ] ); | ||
var attribute = new BufferAttribute( buffer, oldAttribute.itemSize, oldAttribute.normalized ); | ||
result.setAttribute( name, attribute ); | ||
// Update the attribute arrays | ||
if ( name in morphAttrsArrays ) { | ||
for ( var j = 0; j < morphAttrsArrays[ name ].length; j ++ ) { | ||
var oldMorphAttribute = geometry.morphAttributes[ name ][ j ]; | ||
var buffer = new oldMorphAttribute.array.constructor( morphAttrsArrays[ name ][ j ] ); | ||
var morphAttribute = new BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized ); | ||
result.morphAttributes[ name ][ j ] = morphAttribute; | ||
} | ||
} | ||
} | ||
// indices | ||
result.setIndex( newIndices ); | ||
return result; | ||
} | ||
} | ||
export { Utils }; |
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
Sorry, the diff of this file is too big to display
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
803826
20
14599
344
0
9