2d raycaster aabb demo

 avatar
unknown
javascript
9 months ago
12 kB
5
Indexable
(()=>{var f=class{toString(){return`${this.constructor.name}(${this.toArray().join(", ")})`}};var e=class s extends f{constructor(t=0,i=0){super();this.x=t;this.y=i;this.x=t,this.y=i}static get UP(){return new s(0,-1)}static get DOWN(){return new s(0,1)}static get LEFT(){return new s(-1,0)}static get RIGHT(){return new s(1,0)}static get TOP_LEFT(){return new s(-1,1)}static get TOP_RIGHT(){return new s(1,1)}static get BOTTOM_LEFT(){return new s(-1,-1)}static get BOTTOM_RIGHT(){return new s(1,-1)}static get ZERO(){return new s(0,0)}absolute(){return this.x=Math.abs(this.x),this.y=Math.abs(this.y),this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}angle(t){return t===void 0?Math.atan2(this.y,this.x):Math.atan2(t.y-this.y,t.x-this.x)}aspect(){return this.x/this.y}centre(t){return t?(this.x=(this.x+t.x)/2,this.y=(this.y+t.y)/2,this):(this.x/=2,this.y/=2,this)}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}clamp(t,i){return this.x=Math.min(Math.max(this.x,t),i),this.y=Math.min(Math.max(this.y,t),i),this}clone(){return new s(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}cross(t){return this.x*t.y-this.y*t.x}direction(t){return this.x=t.x-this.x,this.y=t.y-this.y,this}distance(t){return Math.hypot(t.x-this.x,t.y-this.y)}distanceSquared(t){return(t.x-this.x)**2+(t.y-this.y)**2}diverge(t){return this.x=t.x-this.x,this.y=t.y-this.y,this}dot(t){return this.x*t.x+this.y*t.y}equals(t){return this.x===t.x&&this.y===t.y}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}fromAngle(t){return this.x=Math.cos(t),this.y=Math.sin(t),this}fromArray(t){return this.x=t[0],this.y=t[1],this}gradient(t){return(t.y-this.y)/(t.x-this.x)}isFinite(){return Number.isFinite(this.x)&&Number.isFinite(this.y)}isNaN(){return Number.isNaN(this.x)||Number.isNaN(this.y)}isNormalised(){return this.lengthSquared()===1}isUnit(){return this.length()===1}isZero(){return this.x===0&&this.y===0}length(){return Math.hypot(this.x,this.y)}lengthSquared(){return this.x**2+this.y**2}lerp(t,i){return this.x+=(t.x-this.x)*i,this.y+=(t.y-this.y)*i,this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}midpoint(t){return this.x=(this.x+t.x)/2,this.y=(this.y+t.y)/2,this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}multiply(t){return this.x*=t.x,this.y*=t.y,this}negate(){return this.x=-this.x,this.y=-this.y,this}normal(t){return t?this.centre(t).normal(t.centre(this)):this.fromArray([-this.y,this.x]).normalise()}normalise(){let t=this.length();return this.x/=t,this.y/=t,this}perpendicular(){let t=this.x;return this.x=-this.y,this.y=t,this}project(t){let i;return this.isNormalised()?i=this.dot(t):i=this.dot(t)/t.lengthSquared(),this.x=t.x*i,this.y=t.y*i,this}reflect(t){let i=2*this.dot(t);return this.x-=t.x*i,this.y-=t.y*i,this}reject(t){let i;return this.isNormalised()?i=this.dot(t):i=this.dot(t)/t.lengthSquared(),this.x-=t.x*i,this.y-=t.y*i,this}remainder(t){return this.x%=t.x,this.y%=t.y,this}rotate(t){let i=Math.cos(t),r=Math.sin(t),n=this.x,h=this.y;return this.x=n*i-h*r,this.y=n*r+h*i,this}rotateAround(t,i){let r=Math.cos(i),n=Math.sin(i),h=this.x-t.x,c=this.y-t.y;return this.x=h*r-c*n+t.x,this.y=h*n+c*r+t.y,this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}polar(t,i,r){return r===void 0&&(r=new s),r.x=t*Math.cos(i),r.y=t*Math.sin(i),this}scale(t){return this.x*=t,this.y*=t,this}set(t){return t instanceof s?(this.x=t.x,this.y=t.y):(this.x=t[0],this.y=t[1]),this}setScalar(t){return this.x=t,this.y=t,this}sign(){return this.x=Math.sign(this.x),this.y=Math.sign(this.y),this}slerp(t,i){let r=this.angle(t);return this.x=Math.cos(r)*i,this.y=Math.sin(r)*i,this}subtract(t){return this.x-=t.x,this.y-=t.y,this}substractScalar(t){return this.x-=t,this.y-=t,this}toArray(){return[this.x,this.y]}unit(){let t=this.length();return this.x/=t,this.y/=t,this}zero(){return this.x=0,this.y=0,this}*[Symbol.iterator](){yield this.x,yield this.y}};var p=class{toString(){return`${this.constructor.name}(${this.toArray().join(", ")})`}};var d=class s extends p{constructor(t=0,i=0,r=1,n=1){super();this.x=t;this.y=i;this.width=r;this.height=n;this.x=t,this.y=i,this.width=r,this.height=n}area(){return this.width*this.height}centre(t){return t?new e(this.x+this.width/2+(t.x+t.width/2),this.y+this.height/2+(t.y+t.height/2)):new e(this.x+this.width/2,this.y+this.height/2)}clone(){return new s(this.x,this.y,this.width,this.height)}combine(t){let i=Math.min(this.x,t.x),r=Math.min(this.y,t.y),n=Math.max(this.x+this.width,t.x+t.width)-i,h=Math.max(this.y+this.height,t.y+t.height)-r;return this.fromArray([i,r,n,h])}contains(t){return this.x<=t.x&&this.y<=t.y&&this.x+this.width>=t.x+t.width&&this.y+this.height>=t.y+t.height}copy(t){return this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this}difference(t){return this.fromArray([Math.min(this.x,t.x),Math.min(this.y,t.y),Math.max(this.x+this.width,t.x+t.width)-Math.min(this.x,t.x),Math.max(this.y+this.height,t.y+t.height)-Math.min(this.y,t.y)])}equals(t){return this.x===t.x&&this.y===t.y&&this.width===t.width&&this.height===t.height}fromArray(t){return this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],this}intersect(t){let i=Math.max(this.x,t.x),r=Math.max(this.y,t.y),n=Math.min(this.x+this.width,t.x+t.width),h=Math.min(this.y+this.height,t.y+t.height),c=Math.max(0,n-i),u=Math.max(0,h-r);return this.fromArray([i,r,c,u])}intersects(t){return this.x<t.x+t.width&&this.x+this.width>t.x&&this.y<t.y+t.height&&this.y+this.height>t.y}perimeter(){return 2*(this.width+this.height)}toArray(){return[this.x,this.y,this.width,this.height]}};var A=class s extends d{constructor(t=new e,i=new e){super();this.min=t;this.max=i}area(){return(this.max.x-this.min.x)*(this.max.y-this.min.y)}centre(t){return t?new e((this.min.x+this.max.x)/2+(t.min.x+t.max.x)/2,(this.min.y+this.max.y)/2+(t.min.y+t.max.y)/2):new e((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2)}clone(){return new s(this.min.clone(),this.max.clone())}combine(t){let i=Math.min(this.min.x,t.min.x),r=Math.min(this.min.y,t.min.y),n=Math.max(this.max.x,t.max.x)-i,h=Math.max(this.max.y,t.max.y)-r;return this.fromArray([i,r,n,h])}contains(t){return this.min.x<=t.min.x&&this.min.y<=t.min.y&&this.max.x>=t.max.x&&this.max.y>=t.max.y}copy(t){return this.min.copy(t.min),this.max.copy(t.max),this}difference(t){let i=Math.max(this.min.x,t.min.x),r=Math.max(this.min.y,t.min.y),n=Math.min(this.max.x,t.max.x)-i,h=Math.min(this.max.y,t.max.y)-r;return this.fromArray([i,r,n,h])}equals(t){return this.min.equals(t.min)&&this.max.equals(t.max)}intersect(t){let i=Math.max(this.min.x,t.min.x),r=Math.max(this.min.y,t.min.y),n=Math.min(this.max.x,t.max.x)-i,h=Math.min(this.max.y,t.max.y)-r;return this.fromArray([i,r,n,h])}intersectBox(t){let i=Math.max(this.min.x,t.x),r=Math.max(this.min.y,t.y),n=Math.min(this.max.x,t.x+t.width)-i,h=Math.min(this.max.y,t.y+t.height)-r;return this.fromArray([i,r,n,h])}intersectCircle(t){let i=Math.max(this.min.x,t.x-t.radius),r=Math.max(this.min.y,t.y-t.radius),n=Math.min(this.max.x,t.x+t.radius)-i,h=Math.min(this.max.y,t.y+t.radius)-r;return this.fromArray([i,r,n,h])}intersects(t){return!(this.max.x<t.min.x||this.min.x>t.max.x||this.max.y<t.min.y||this.min.y>t.max.y)}intersectsBox(t){return!(this.max.x<t.x||this.min.x>t.x+t.width||this.max.y<t.y||this.min.y>t.y+t.height)}intersectsCircle(t){let i=Math.max(this.min.x-t.x,0,t.x-this.max.x),r=Math.max(this.min.y-t.y,0,t.y-this.max.y);return i**2+r**2<=t.radius**2}normal(t){return t?this.centre(t).normal(t.centre(this)):new e(this.max.y-this.min.y,this.min.x-this.max.x).normalise()}perimeter(){return 2*(this.max.x-this.min.x+(this.max.y-this.min.y))}toArray(){return[this.min.x,this.min.y,this.max.x,this.max.y]}};var M=class{toString(){return`${this.constructor.name}(${this.toArray().join(", ")})`}};var y=class extends M{constructor(t=new e,i=new e){super();this.origin=t;this.direction=i;this.origin=t,this.direction=i}angle(t){return t===void 0?Math.atan2(this.direction.y,this.direction.x):Math.atan2(t.y-this.origin.y,t.x-this.origin.x)}cast(t,i){return t&&(this.direction=new e(t.x-this.origin.x,t.y-this.origin.y)),i&&(this.direction=this.direction.normalise().scale(i)),new e(this.origin.x+this.direction.x,this.origin.y+this.direction.y)}centre(t){return t?new e((this.origin.x+t.x)/2,(this.origin.y+t.y)/2):new e(this.origin.x+this.direction.x/2,this.origin.y+this.direction.y/2)}intersect(t){let[i,r,n,h]=t,c=(r-this.origin.y)/this.direction.y,u=(h-this.origin.y)/this.direction.y,g=(i-this.origin.x)/this.direction.x,v=(n-this.origin.x)/this.direction.x,w=Math.max(Math.min(c,u),Math.min(g,v)),B=Math.min(Math.max(c,u),Math.max(g,v));if(B<0&&w>B)throw new Error("intersection not found");return new e(this.origin.x+w*this.direction.x,this.origin.y+w*this.direction.y)}intersectAABB(t){if(this.direction.x===0||this.direction.y===0)throw new Error("direction cannot be zero");let i=(t.min.x-this.origin.x)/this.direction.x,r=(t.max.x-this.origin.x)/this.direction.x,n=(t.min.y-this.origin.y)/this.direction.y,h=(t.max.y-this.origin.y)/this.direction.y,c=Math.max(Math.min(i,r),Math.min(n,h)),u=Math.min(Math.max(i,r),Math.max(n,h));if(u<0&&c>u)throw new Error("intersection not found");return new e(this.origin.x+c*this.direction.x,this.origin.y+c*this.direction.y)}intersectCircle(t){let i=this.origin.x-t.x,r=this.origin.y-t.y,n=this.direction.dot(this.direction),h=2*this.direction.dot(new e(i,r)),c=i**2+r**2-t.radius**2,u=h**2-4*n*c;if(u<0)return[new e,new e];let g=(-h+Math.sqrt(u))/(2*n),v=(-h-Math.sqrt(u))/(2*n);return[new e(this.origin.x+g*this.direction.x,this.origin.y+g*this.direction.y),new e(this.origin.x+v*this.direction.x,this.origin.y+v*this.direction.y)]}intersectLineSegment(t,i){let r=i.x-t.x,n=i.y-t.y,h=((this.origin.x-t.x)*n-(this.origin.y-t.y)*r)/(this.direction.x*n-this.direction.y*r);if(h<0||h>1)throw new Error("intersection not found");let c=((this.origin.x-t.x)*this.direction.y-(this.origin.y-t.y)*this.direction.x)/(this.direction.x*n-this.direction.y*r);if(c<0||c>1)throw new Error("intersection not found");return new e(t.x+h*r,t.y+h*n)}normal(){return new e(this.direction.y,-this.direction.x)}normalise(){let t=this.direction.lengthSquared();if(t===0)throw new Error("cannot normalise zero-length vector");return this.direction.x/=t,this.direction.y/=t,this}toArray(){return[this.origin.x,this.origin.y,this.origin.x+this.direction.x,this.origin.y+this.direction.y]}};var Bt=Math.PI*Math.PI,V=Math.PI*2,St=Math.PI/2,Rt=Math.PI/4,Ct=Math.PI/180,qt=180/Math.PI;var m=document.createElement("canvas");m.width=640;m.height=480;document.body.appendChild(m);var o=m.getContext("2d"),x=new A(new e(m.width/2-50,m.height/2-50),new e(m.width/2+50,m.height/2+50)),b=new y(x.centre(),e.RIGHT),l=new y(x.centre(),e.LEFT);function E(){b.origin=x.centre().add(new e(100,0).rotate(b.angle())),l.origin=x.centre().add(new e(100,0).rotate(l.angle())),b.direction.rotate(-.03),l.direction.rotate(.01)}function $(){o.clearRect(0,0,m.width,m.height),o.fillStyle="black",o.fillRect(0,0,m.width,m.height),D(x,"white"),O(x.centre(),"blue"),S(b,"yellow"),S(l,"yellow");let s=b.intersectAABB(x),a=l.intersectAABB(x);s&&a&&N([s,a],"yellow"),T(x,b,l)}function R(){E(),$(),requestAnimationFrame(R)}function T(s,a,t){let i=a.intersectAABB(s),r=t.intersectAABB(s);i&&r&&(o.fillStyle="rgba(255, 255, 0, 0.5)",o.beginPath(),o.moveTo(s.centre().x,s.centre().y),o.lineTo(i.x,i.y),o.lineTo(r.x,r.y),o.closePath(),o.fill())}function S(s,a){o.strokeStyle=a,o.beginPath(),o.moveTo(s.origin.x,s.origin.y),o.lineTo(s.origin.x+s.direction.x*1e3,s.origin.y+s.direction.y*1e3),o.stroke()}function N(s,a){o.fillStyle=a;for(let t of s)o.beginPath(),o.arc(t.x,t.y,5,0,V),o.fill()}function O(s,a){o.fillStyle=a,o.beginPath(),o.arc(s.x,s.y,5,0,V),o.fill()}function D(s,a){o.strokeStyle=a,o.strokeRect(s.min.x,s.min.y,s.max.x-s.min.x,s.max.y-s.min.y)}document.addEventListener("DOMContentLoaded",function(){R()});})();
//# sourceMappingURL=main.js.map
Editor is loading...
Leave a Comment