three.cad/src/shared.js
2021-04-25 23:04:24 -07:00

244 lines
5.2 KiB
JavaScript

import * as THREE from '../node_modules/three/src/Three';
const _vec2 = new THREE.Vector2()
const _vec3 = new THREE.Vector3()
const raycaster = new THREE.Raycaster();
raycaster.params.Line.threshold = 1;
raycaster.params.Points.threshold = 1;
const color = {
background: 0x18181B,
lighting: 0xFFFFFF,
emissive: 0x072534,
meshTempHover: 0x9DCFED,
point: 0xffffff,
selpoint: 0xff0000,
line: 0xffffff,
mesh: 0x9DCFED,
dimension: 0x0000ff,
plane: 0xffff00,
planeBorder: 0x2e2e00,
opacity: 0.02
}
const hoverColor = {
emissive: 0x343407,
point: 0x10B981,
selpoint: 0xff0000,
line: 0x10B981,
mesh: 0xFAB601,
dimension: 0x10B981,
plane: 0xffff00,
planeBorder: 0x919100,
opacity: 0.06
}
const lineMaterial = new THREE.LineBasicMaterial({
linewidth: 1,
color: color.line,
depthTest: false
})
const pointMaterial = new THREE.PointsMaterial({
color: color.point,
size: 4,
depthTest: false
})
const ptObj = (n, visibility = true) => {
const ret = new THREE.Points(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(n || 3, 3)
),
pointMaterial.clone()
);
ret.name = "p" + id++
ret.userData.type = 'point'
ret.visible = visibility
ret.renderOrder = 1
return ret
}
const lineObj = (n = 1) => {
const ret = new THREE.Line(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(3 * (n + 1), 3)
),
lineMaterial.clone()
);
ret.name = 'l' + id++
ret.userData.type = 'line'
ret.renderOrder = 1
return ret
}
async function awaitSelection(...criteria) {
function fullfilled() {
for (let i = criteria.length - 1; i >= 0; i--) {
const crit = criteria[i]
let nfilled = 0;
for (let k in counter) {
if (!crit[k] || counter[k] > crit[k]) {
criteria.splice(i, 1)
break;
} else if (counter[k] == crit[k]) {
nfilled += 1
}
}
if (nfilled == Object.keys(crit).length) return true
}
return false
}
const counter = {}
let references = (this.selected || this.scene.selected).slice()
for (let ob of references) {
const type = ob.userData.type
if (counter[type]) {
counter[type] += 1;
} else {
counter[type] = 1;
}
}
if (fullfilled()) return references
let end = false;
while (criteria.length && !end) {
let pt;
let onEnd, onKey;
try {
pt = await new Promise((res, rej) => {
onKey = (e) => e.key == 'Escape' && rej()
onEnd = (e) => this.hovered.length && res(this.hovered[0])
this.canvas.addEventListener('pointerdown', onEnd)
window.addEventListener('keydown', onKey)
})
references.push(pt)
const type = pt.userData.type
if (counter[type]) {
counter[type] += 1;
} else {
counter[type] = 1;
}
if (fullfilled()) return references
} catch (e) {
end = true;
}
this.canvas.removeEventListener('pointerdown', onEnd)
window.removeEventListener('keydown', onKey)
}
console.log('fail')
return null
}
function setHover(obj, state, meshHover = true) {
let colObj = state == 1 ? hoverColor : color
switch (obj.userData.type) {
case 'plane':
obj.material.opacity = colObj.opacity
obj.children[0].material.color.set(colObj['planeBorder'])
break;
case 'sketch':
obj.traverse(ele => {
if (ele.userData.type == 'line') {
ele.material.color.set(colObj['line'])
}
})
break;
case 'mesh':
if (meshHover) {
obj.material.emissive.set(colObj.emissive)
} else {
break
}
case 'point':
obj.material.color.set(colObj[obj.userData.type])
obj.material.size = state ? 8 : 4
default:
obj.material.color.set(colObj[obj.userData.type])
break;
}
}
const vertexShader = `
uniform float edgeSize;
uniform float pointWidth;
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = (pointWidth + edgeSize);
gl_Position = projectionMatrix * mvPosition;
}
`
const fragmentShader = `
uniform vec3 color;
uniform vec3 edgeColor;
uniform float edgeSize;
uniform float pointWidth;
void main() {
gl_FragColor = vec4(color, 1.0);
float distance = length(2.0 * gl_PointCoord - 1.0);
float totalWidth = pointWidth + edgeSize;
float edgeStart = pointWidth;
float edgeEnd = pointWidth + 2.0;
float sEdge = smoothstep(edgeStart, edgeEnd, distance * totalWidth);
// transition from edgeColor to color along the edge
gl_FragColor = ( vec4(edgeColor, 1.0) * sEdge) + ((1.0 - sEdge) * gl_FragColor);
if (distance > 1.0) {
discard;
}
}
`
const sz = 4
const custPtMat = new THREE.ShaderMaterial({
uniforms: {
color: { value: new THREE.Color(0xff0000) },
edgeColor: { value: new THREE.Color(0x770000) },
pointWidth: { value: sz },
edgeSize: { value: sz },
},
vertexShader,
fragmentShader,
depthTest: false
// depthWrite:false
});
window.rc = raycaster
export { lineMaterial, pointMaterial, custPtMat, _vec2, _vec3, raycaster, color, hoverColor, ptObj, lineObj, awaitSelection, setHover }