flexy-bend
Version:
A library that bends three.js box geometries along Bezier Curves
2 lines (1 loc) • 4.35 kB
JavaScript
;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function L(n,c){const t=c.getAttribute("position"),e=new n.Box3;e.center=new n.Vector3;for(let o=0;o<t.count;o++){const r=new n.Vector3;r.fromBufferAttribute(t,o),e.expandByPoint(r);const m=t[o],C=t[o+1],i=t[o+2];e.center.add(new n.Vector3(m,C,i))}return e.center.divideScalar(t.count/3),e}const N=function({THREE:n,curve:c,quaternion:t,orientation:e,bufferGeometry:o,axis:r,preserveDimensions:m=!1,scene:C}){const i=L(n,o),u=m?M(c):0,s=o.attributes.position.array;for(let a=0;a<s.length;a+=3){const l=parseFloat(s[a]),x=parseFloat(s[a+1]),P=parseFloat(s[a+2]);if(r==="x"){let y=(l-i.min.x)/(i.max.x-i.min.x);const p=i.max.x-i.min.x;if(m&&p<=u){const w=p/u,z=.5-w/2,V=.5+w/2;y=z+y*(V-z)}const g=c.getPointAt(y),f=c.getTangent(y),h=(e||new n.Vector3(0,0,1).applyQuaternion(t).normalize().multiplyScalar(1e6)).clone().cross(f.clone()).normalize(),A=new n.Quaternion().setFromAxisAngle(f.clone(),Math.atan2(P,x));h.applyQuaternion(A);const B=h.clone().setLength(new n.Vector3(0,x,P).length()),d=g.clone().add(B);s[a]=d.x,s[a+1]=d.y,s[a+2]=d.z}else if(r==="z"){let y=(P-i.min.z)/(i.max.z-i.min.z);const p=i.max.z-i.min.z;if(m&&p<=u){const w=p/u,z=.5-w/2,V=.5+w/2;y=z+y*(V-z)}const g=c.getPointAt(y),f=c.getTangent(y),h=(e||new n.Vector3(1,0,0).applyQuaternion(t).normalize().multiplyScalar(1e6)).clone().cross(f.clone()).normalize(),A=new n.Quaternion().setFromAxisAngle(f.clone(),Math.atan2(x,l)+Math.PI/2);h.applyQuaternion(A);const B=h.clone().setLength(new n.Vector3(l,x,0).length()),d=g.clone().add(B);s[a]=d.x,s[a+1]=d.y,s[a+2]=d.z}else if(r==="y"){let y=(x-i.min.y)/(i.max.y-i.min.y);const p=i.max.y-i.min.y;if(m&&p<=u){const w=p/u,z=.5-w/2,V=.5+w/2;y=z+y*(V-z)}const g=c.getPointAt(y),f=c.getTangent(y),h=(e||new n.Vector3(1,0,0).applyQuaternion(t).normalize().multiplyScalar(1e6)).clone().cross(f.clone()).normalize(),A=new n.Quaternion().setFromAxisAngle(f.clone(),Math.atan2(l,P));h.applyQuaternion(A);const B=h.clone().setLength(new n.Vector3(l,0,P).length()),d=g.clone().add(B);s[a]=d.x,s[a+1]=d.y,s[a+2]=d.z}}o.attributes.position.needsUpdate=!0},O=function({THREE:n,surface:c,castingRectangular:t,resolution:e,scene:o}){const r={};for(let m=0;m<=e;m++){const C=b(n,t.A,t.D,e)[m],i=b(n,t.B,t.C,e)[m];b(n,C,i,e).forEach(s=>{const l=new n.Raycaster(s,t.direction.normalize()).intersectObject(c);l.length>0&&(r[Q(s.x,s.y,s.z,e)]={normal:{x:l[0].face.normal.x,y:l[0].face.normal.y,z:l[0].face.normal.z},point:{x:l[0].point.x,y:l[0].point.y,z:l[0].point.z}})})}return{data:r,castingRectangular:{A:{x:t.A.x,y:t.A.y,z:t.A.z},B:{x:t.B.x,y:t.B.y,z:t.B.z},C:{x:t.C.x,y:t.C.y,z:t.C.z},D:{x:t.D.x,y:t.D.y,z:t.D.z},direction:{x:t.direction.x,y:t.direction.y,z:t.direction.z}},resolution:e}},S=function({THREE:n,pointToFaceNormalMap:c,obj:t,scene:e}){const o=c.castingRectangular,r=new n.Vector3(o.A.x,o.A.y,o.A.z),m=new n.Vector3(o.B.x,o.B.y,o.B.z),C=new n.Vector3(o.C.x,o.C.y,o.C.z),i=new n.Vector3().subVectors(m,r),u=new n.Vector3().subVectors(C,r),s=new n.Vector3().crossVectors(i,u).normalize(),a=new n.Plane().setFromNormalAndCoplanarPoint(s,r),l=t.geometry.attributes.position.array;for(let x=0;x<l.length;x+=3){const P=parseFloat(l[x]),y=parseFloat(l[x+1]),p=parseFloat(l[x+2]),g=new n.Vector3(P,y,p),f=t.matrixWorld.clone();g.applyMatrix4(f.clone());const F=g.clone().sub(r).dot(a.normal),h=a.normal.clone().multiplyScalar(F/a.normal.lengthSq()),A=g.clone().sub(h),B=Q(A.x,A.y,A.z,c.resolution),d=c.data[B];if(!d)throw new Error(`Cannot find face normal for posision ${P} - ${y} - ${p}`);const w=new n.Vector3(d.normal.x,d.normal.y,d.normal.z),z=new n.Object3D;z.lookAt(w);const V=new n.Vector3(P,y,p).applyQuaternion(z.quaternion.clone());l[x]=V.x,l[x+1]=V.y,l[x+2]=V.z}t.geometry.attributes.position.needsUpdate=!0};function Q(n,c,t,e){function o(s,a){return Math.round(s/a)*a}function r(s){return s==="-0.0"?"0.0":s}const m=1/e,C=r(o(n,m).toFixed(1)),i=r(o(c,m).toFixed(1)),u=r(o(t,m).toFixed(1));return`${C}^${i}^${u}`}function b(n,c,t,e){const o=[];for(let r=0;r<=e;r++){const m=new n.Vector3(c.x+(t.x-c.x)*(r/e),c.y+(t.y-c.y)*(r/e),c.z+(t.z-c.z)*(r/e));o.push(m)}return o}function M(n){let t=0,e=n.getPointAt(0);for(let o=1;o<=100;o++){const r=n.getPointAt(o/100);t+=r.distanceTo(e),e=r}return t}exports.bend=N;exports.getPointToFaceNormalMap=O;exports.wrap=S;