Buckets:
ktongue/docker_container / simsite /frontend /node_modules /troika-three-utils /src /BezierMeshMaterial.js
| import { createDerivedMaterial } from './DerivedMaterial.js' | |
| import { Vector3 } from 'three' | |
| /* | |
| Input geometry is a cylinder with r=1, height in y dimension from 0 to 1, | |
| divided into a reasonable number of height segments. | |
| */ | |
| const vertexDefs = ` | |
| uniform vec3 pointA; | |
| uniform vec3 controlA; | |
| uniform vec3 controlB; | |
| uniform vec3 pointB; | |
| uniform float radius; | |
| varying float bezierT; | |
| vec3 cubicBezier(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) { | |
| float t2 = 1.0 - t; | |
| float b0 = t2 * t2 * t2; | |
| float b1 = 3.0 * t * t2 * t2; | |
| float b2 = 3.0 * t * t * t2; | |
| float b3 = t * t * t; | |
| return b0 * p1 + b1 * c1 + b2 * c2 + b3 * p2; | |
| } | |
| vec3 cubicBezierDerivative(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) { | |
| float t2 = 1.0 - t; | |
| return -3.0 * p1 * t2 * t2 + | |
| c1 * (3.0 * t2 * t2 - 6.0 * t2 * t) + | |
| c2 * (6.0 * t2 * t - 3.0 * t * t) + | |
| 3.0 * p2 * t * t; | |
| } | |
| ` | |
| const vertexTransform = ` | |
| float t = position.y; | |
| bezierT = t; | |
| vec3 bezierCenterPos = cubicBezier(pointA, controlA, controlB, pointB, t); | |
| vec3 bezierDir = normalize(cubicBezierDerivative(pointA, controlA, controlB, pointB, t)); | |
| // Make "sideways" always perpendicular to the camera ray; this ensures that any twists | |
| // in the cylinder occur where you won't see them: | |
| vec3 viewDirection = normalMatrix * vec3(0.0, 0.0, 1.0); | |
| if (bezierDir == viewDirection) { | |
| bezierDir = normalize(cubicBezierDerivative(pointA, controlA, controlB, pointB, t == 1.0 ? t - 0.0001 : t + 0.0001)); | |
| } | |
| vec3 sideways = normalize(cross(bezierDir, viewDirection)); | |
| vec3 upish = normalize(cross(sideways, bezierDir)); | |
| // Build a matrix for transforming this disc in the cylinder: | |
| mat4 discTx; | |
| discTx[0].xyz = sideways * radius; | |
| discTx[1].xyz = bezierDir * radius; | |
| discTx[2].xyz = upish * radius; | |
| discTx[3].xyz = bezierCenterPos; | |
| discTx[3][3] = 1.0; | |
| // Apply transform, ignoring original y | |
| position = (discTx * vec4(position.x, 0.0, position.z, 1.0)).xyz; | |
| normal = normalize(mat3(discTx) * normal); | |
| ` | |
| const fragmentDefs = ` | |
| uniform vec3 dashing; | |
| varying float bezierT; | |
| ` | |
| const fragmentMainIntro = ` | |
| if (dashing.x + dashing.y > 0.0) { | |
| float dashFrac = mod(bezierT - dashing.z, dashing.x + dashing.y); | |
| if (dashFrac > dashing.x) { | |
| discard; | |
| } | |
| } | |
| ` | |
| // Debugging: separate color for each of the 6 sides: | |
| // const fragmentColorTransform = ` | |
| // float sideNum = floor(vUV.x * 6.0); | |
| // vec3 mixColor = sideNum < 1.0 ? vec3(1.0, 0.0, 0.0) : | |
| // sideNum < 2.0 ? vec3(0.0, 1.0, 1.0) : | |
| // sideNum < 3.0 ? vec3(1.0, 1.0, 0.0) : | |
| // sideNum < 4.0 ? vec3(0.0, 0.0, 1.0) : | |
| // sideNum < 5.0 ? vec3(0.0, 1.0, 0.0) : | |
| // vec3(1.0, 0.0, 1.0); | |
| // gl_FragColor.xyz = mix(gl_FragColor.xyz, mixColor, 0.5); | |
| // ` | |
| export function createBezierMeshMaterial(baseMaterial) { | |
| return createDerivedMaterial( | |
| baseMaterial, | |
| { | |
| chained: true, | |
| uniforms: { | |
| pointA: {value: new Vector3()}, | |
| controlA: {value: new Vector3()}, | |
| controlB: {value: new Vector3()}, | |
| pointB: {value: new Vector3()}, | |
| radius: {value: 0.01}, | |
| dashing: {value: new Vector3()} //on, off, offset | |
| }, | |
| vertexDefs, | |
| vertexTransform, | |
| fragmentDefs, | |
| fragmentMainIntro | |
| } | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 3.16 kB
- Xet hash:
- f5fb78c28e6916eedc7870f92822fc96c2ece4fe4fc6df7727d15edb75232063
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.