244 lines
5.2 KiB
JavaScript
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 } |