master
howard 2021-04-03 17:59:14 -07:00
parent fdf5dc628b
commit 399537e08c
7 changed files with 483 additions and 217 deletions

View File

@ -9,7 +9,7 @@ import { get3PtArc } from './drawArc'
import { _vec2, _vec3, raycaster, awaitPts } from '../utils/shared'
import { replacer, reviver } from '../utils/mapJSONReplacer'
import { AxesHelper } from '../utils/axes'
import { drawDimensionPre } from './drawDimension'
import { drawDimension } from './drawDimension';
@ -107,9 +107,9 @@ class Sketch {
this.drawOnClick1 = drawOnClick1.bind(this);
this.drawPreClick2 = drawPreClick2.bind(this);
this.drawOnClick2 = drawOnClick2.bind(this);
this.drawDimension = drawDimension.bind(this)
this.awaitPts = awaitPts.bind(this);
this.drawDimensionPre = drawDimensionPre.bind(this);
this.onHover = onHover.bind(this);
this.onPick = onPick.bind(this);
@ -180,7 +180,8 @@ class Sketch {
this.mode = "arc"
break;
case 'd':
this.drawDimensionPre()
this.drawDimension()
this.mode = ""
break;
case 'x':
this.deleteSelected()
@ -310,7 +311,7 @@ class Sketch {
raycaster.ray.intersectPlane(this.plane, _vec3).applyMatrix4(this.obj3d.inverse)
return _vec3.toArray()
return _vec3
}
solve() {

View File

@ -1,162 +1,122 @@
import * as THREE from '../../node_modules/three/src/Three';
import { ptObj, lineObj, awaitPts } from '../utils/shared'
const color = {
hover: 0x00ff00,
lighting: 0xFFFFFF,
emissive: 0x072534,
d: 0xf5bc42, //datums: planes
p: 0x555555, //points
l: 0x555555, //lines
m: 0x156289, //mesh: extrude
}
const lineMaterial = new THREE.LineBasicMaterial({
linewidth: 2,
color: color.l,
color: 0x156289,
})
const pointMaterial = new THREE.PointsMaterial({
color: color.p,
color: 0x156289,
size: 4,
})
const DptObj = (n) => {
const ret = new THREE.Points(
export async function drawDimension() {
let pts;
// try {
// pts = await this.awaitPts(2)
// } catch {
// }
pts = await this.awaitPts(2)
console.log('here', pts)
const p1 = new THREE.Vector2(...pts[0].geometry.attributes.position.array.slice(0, 2))
const p2 = new THREE.Vector2(...pts[1].geometry.attributes.position.array.slice(0, 2))
const p3 = new THREE.Vector2()
const lineGeom = new THREE.Float32BufferAttribute(3 * 8, 3)
const line = new THREE.LineSegments(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(n || 3, 3)
),
pointMaterial.clone()
);
ret.name = 'p' + nid++
ret.matrixAutoUpdate = false;
ret.userData.constraints = []
ret.userData.construction = true
return ret
}
const DlineObj = (n = 1) => {
const ret = new THREE.Line(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(3 * (n + 1), 3)
lineGeom
),
lineMaterial.clone()
);
ret.name = 'l' + nid++
ret.matrixAutoUpdate = false;
ret.userData.constraints = []
return ret
}
export async function drawDimensionPre() {
let [p1, p2] = await this.awaitPts(2)
const lines = [
DlineObj(), // 0:
DlineObj(), // 1:
DlineObj(), // 2:
]
const points = [
p1, // 0:
DptObj(), // 1: |
DptObj(), // 2: |
DptObj(), // 3: |
DptObj(), // 4: |
DptObj(), // 5: |
DptObj(), // 6: |
p2, // 7:
]
this.constraints.set(++this.c_id, //???
[
'pt_pt_distance', 10,
[p1.name, p2.name, -1, -1]
]
const ptGeom = new THREE.Float32BufferAttribute(3, 3)
const point = new THREE.Points(
new THREE.BufferGeometry().setAttribute('position',
ptGeom
),
pointMaterial.clone()
)
p1.userData.constraints.push(this.c_id)
p2.userData.constraints.push(this.c_id)
// this.updateOtherBuffers()
// console.log(points)
const updatePoint = this.obj3d.children.length
for (let i = 1; i < points.length; i++) {
if (i % 2) {
this.constraints.set(++this.c_id, //??? increment investigation
[
'points_coincident', -1,
[points[i - 1].name, points[i].name, -1, -1]
]
)
points[i - 1].userData.constraints.push(this.c_id)
points[i].userData.constraints.push(this.c_id)
this.obj3d.children[0].add(line)
this.obj3d.children[0].add(point)
} else { // even
let dir, hyp, proj, perp, p1e, p2e, loc;
const onMove = (e) => {
loc = this.getLocation(e)
p3.set(loc.x, loc.y)
const toPush = [...points.slice(i - 1, i + 1), lines[i / 2 - 1]]
dir = p2.clone().sub(p1).normalize()
hyp = p3.clone().sub(p1)
proj = dir.multiplyScalar(hyp.dot(dir))
perp = hyp.sub(proj)
this.linkedObjs.set(this.l_id, ['line', toPush.map(e => e.name)])
for (let obj of toPush) {
obj.userData.l_id = this.l_id
}
this.l_id += 1
p1e = p1.clone().add(perp).toArray()
p2e = p2.clone().add(perp).toArray()
if (i == 4 || i == 6) {
this.constraints.set(++this.c_id, //???
[
'perpendicular', -1,
[-1, -1, lines[i / 2 - 2].name, lines[i / 2 - 1].name]
]
)
lines[i / 2 - 2].userData.constraints.push(this.c_id)
lines[i / 2 - 1].userData.constraints.push(this.c_id)
lineGeom.set(p1.toArray(), 0)
lineGeom.set(p1e, 3)
lineGeom.set(p1e, 6)
lineGeom.set(p2e, 9)
lineGeom.set(p2e, 12)
lineGeom.set(p2.toArray(), 15)
lineGeom.set(p1e, 18)
lineGeom.set(p3.toArray(), 21)
ptGeom.set(p3.toArray())
line.geometry.attributes.position.needsUpdate = true;
point.geometry.attributes.position.needsUpdate = true;
sc.render()
}
this.obj3d.add(...toPush) // not to be confused with this.topush
}
if (i<=3) { // move pts to their respective spots to spread them
points[i].geometry.attributes.position.set(p1.geometry.attributes.position.array)
} else {
points[i].geometry.attributes.position.set(p2.geometry.attributes.position.array)
}
}
lines[0].userData.construction = true
lines[2].userData.construction = true
let onEnd, onKey;
let ret = await new Promise((res, rej) => {
this.updatePointsBuffer(updatePoint)
onEnd = (e) => {
res(true)
this.updateOtherBuffers()
// line[1].geometry.attributes.position.set(p1.geometry.attributes.position.array)
// line[1].geometry.attributes.position.set(p1.geometry.attributes.position.array, 3)
// line[0].geometry.attributes.position.set(p1.geometry.attributes.position.array)
// line[0].geometry.attributes.position.set(p2.geometry.attributes.position.array, 3)
}
onKey = (e) => {
if (e.key == 'Escape') res(false)
}
this.canvas.addEventListener('pointermove', onMove)
this.canvas.addEventListener('pointerdown', onEnd)
window.addEventListener('keydown', onKey)
})
// line[2].geometry.attributes.position.set(p2.geometry.attributes.position.array)
// line[2].geometry.attributes.position.set(p2.geometry.attributes.position.array, 3)
console.log(ret, 'here')
this.canvas.removeEventListener('pointermove', onMove)
this.canvas.removeEventListener('pointerdown', onEnd)
this.canvas.removeEventListener('keydown', onKey)
// this.constraints.set(++this.c_id, //???
// [
// 'pt_pt_distance', 10,
// [_p1.name, _p2.name, -1, -1]
// ]
// )
// _p1.userData.constraints.push(this.c_id)
// _p2.userData.constraints.push(this.c_id)
@ -166,41 +126,3 @@ export async function drawDimensionPre() {
return
}
export function drawLine(mouseLoc) {
line.geometry.attributes.position.set(mouseLoc)
p1.geometry.attributes.position.set(mouseLoc)
if (this.subsequent) {
this.constraints.set(++this.c_id,
[
'points_coincident', -1,
[this.obj3d.children[this.obj3d.children.length - 2].name, p1.name, -1, -1]
]
)
p1.userData.constraints.push(this.c_id)
this.obj3d.children[this.obj3d.children.length - 2].userData.constraints.push(this.c_id)
}
return [p1, p2, line];
}
export function drawLine2(mouseLoc, toPush) {
const [p1, p2, line] = toPush
p2.geometry.attributes.position.set(mouseLoc);
p2.geometry.attributes.position.needsUpdate = true;
p2.geometry.computeBoundingSphere();
line.geometry.attributes.position.set(mouseLoc, 3)
line.geometry.attributes.position.needsUpdate = true;
}

View File

@ -1,34 +1,37 @@
import { drawArc, drawArc2 } from './drawArc'
import { drawLine, drawLine2 } from './drawLine'
// import { drawDimension } from "./drawDimension";
export function drawOnClick1(e) {
if (e.buttons !== 1) return
this.canvas.removeEventListener('pointerdown', this.drawOnClick1)
const mouseLoc = this.getLocation(e);
this.canvas.addEventListener('pointermove', this.drawPreClick2)
this.canvas.addEventListener('pointerdown', this.drawOnClick2)
const mouseLoc = this.getLocation(e).toArray();
if (this.mode == "line") {
this.toPush = drawLine.call(this, mouseLoc)
} else if (this.mode == "arc") {
this.toPush = drawArc(mouseLoc)
} else if (this.mode == 'dim') {
this.curDimension = drawDimension.call(this)
}
this.updatePoint = this.obj3d.children.length
this.obj3d.add(...this.toPush)
this.linkedObjs.set(this.l_id, [this.mode, this.toPush.map(e => e.name)])
for (let obj of this.toPush) {
obj.userData.l_id = this.l_id
}
this.l_id += 1
this.canvas.addEventListener('pointermove', this.drawPreClick2)
this.canvas.addEventListener('pointerdown', this.drawOnClick2)
}
export function drawPreClick2(e) {
const mouseLoc = this.getLocation(e);
const mouseLoc = this.getLocation(e).toArray();
if (this.mode == "line") {
drawLine2(mouseLoc, this.toPush)
@ -36,7 +39,8 @@ export function drawPreClick2(e) {
drawArc2(mouseLoc, this.toPush)
}
this.obj3d.dispatchEvent({ type: 'change' })
sc.render()
}
export function drawOnClick2(e) {
@ -53,10 +57,29 @@ export function drawOnClick2(e) {
this.drawOnClick1(e)
} else if (this.mode == "arc") {
// this.canvas.addEventListener('pointermove', this.beforeClick_3)
this.toPush = []
// this.canvas.addEventListener('pointermove', this.drawPreClick3)
// this.canvas.addEventListener('pointerdown', this.drawOnClick3)
}
}
export function drawPreClick3(e) {
const mouseLoc = this.getLocation(e).toArray();
sc.render()
}
export function drawOnClick3(e) {
if (e.buttons !== 1) return;
this.canvas.removeEventListener('pointermove', this.drawPreClick3);
this.canvas.removeEventListener('pointerdown', this.drawOnClick3);
}
export function drawClear() {
if (this.mode == "") return
@ -69,5 +92,6 @@ export function drawClear() {
this.obj3d.dispatchEvent({ type: 'change' })
this.subsequent = false
this.toPush = []
}
}

81
src/sketcher/rect.js Normal file
View File

@ -0,0 +1,81 @@
const lines = [
DlineObj(), // 0:
DlineObj(), // 1:
DlineObj(), // 2:
DlineObj(), // 2:
]
const points = [
DptObj(), // 1: |
DptObj(), // 1: |
DptObj(), // 1: |
DptObj(), // 2: |
DptObj(), // 3: |
DptObj(), // 4: |
DptObj(), // 5: |
DptObj(), // 6: |
]
const updatePoint = this.obj3d.children.length
let prev = points[points.length - 1]
for (let i = 0, j = 0; i < points.length; i++) {
const cur = points[i]
if (i % 2 == 0) {
this.constraints.set(++this.c_id, //??? increment investigation
[
'points_coincident', -1,
[prev.name, cur.name, -1, -1]
]
)
cur.userData.constraints.push(this.c_id)
prev.userData.constraints.push(this.c_id)
} else {
const toPush = [prev, cur, lines[j]]
this.linkedObjs.set(this.l_id, ['line', toPush.map(e => e.name)])
for (let obj of toPush) {
obj.userData.l_id = this.l_id
}
this.l_id += 1
if (j > 0) {
this.constraints.set(++this.c_id, //???
[
'perpendicular', -1,
[-1, -1, lines[j - 1].name, lines[j].name]
]
)
lines[j - 1].userData.constraints.push(this.c_id)
lines[j].userData.constraints.push(this.c_id)
}
this.obj3d.add(...toPush)
j += 1
}
if (i >= 3 && i <= 6) {
points[i].geometry.attributes.position.set(p2.geometry.attributes.position.array)
} else {
points[i].geometry.attributes.position.set(p1.geometry.attributes.position.array)
}
prev = cur
}
this.constraints.set(++this.c_id, //??? increment investigation
[
'points_coincident', -1,
[p2.name, points[5].name, -1, -1]
]
)
points[5].userData.constraints.push(this.c_id)
p2.userData.constraints.push(this.c_id)
this.constraints.set(++this.c_id, //??? increment investigation
[
'points_coincident', -1,
[p1.name, points[0].name, -1, -1]
]
)
points[0].userData.constraints.push(this.c_id)
p1.userData.constraints.push(this.c_id)

212
src/sketcher/threetest.js Normal file
View File

@ -0,0 +1,212 @@
attribute float size;
attribute vec3 customColor;
varying vec3 vColor;
void main() {
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;
}
uniform vec3 color;
uniform sampler2D pointTexture;
varying vec3 vColor;
void main() {
gl_FragColor = vec4( color * vColor, 1.0 );
gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
if ( gl_FragColor.a < ALPHATEST ) discard;
}
import * as THREE from '../build/three.module.js';
import Stats from './jsm/libs/stats.module.js';
import { BufferGeometryUtils } from './jsm/utils/BufferGeometryUtils.js';
let renderer, scene, camera, stats;
let particles;
const PARTICLE_SIZE = 20;
let raycaster, intersects;
let pointer, INTERSECTED;
init();
animate();
function init() {
const container = document.getElementById( 'container' );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 250;
//
let boxGeometry = new THREE.BoxGeometry( 200, 200, 200, 16, 16, 16 );
// if normal and uv attributes are not removed, mergeVertices() can't consolidate indentical vertices with different normal/uv data
boxGeometry.deleteAttribute( 'normal' );
boxGeometry.deleteAttribute( 'uv' );
boxGeometry = BufferGeometryUtils.mergeVertices( boxGeometry );
//
const positionAttribute = boxGeometry.getAttribute( 'position' );
const colors = [];
const sizes = [];
const color = new THREE.Color();
for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
color.setHSL( 0.01 + 0.1 * ( i / l ), 1.0, 0.5 );
color.toArray( colors, i * 3 );
sizes[ i ] = PARTICLE_SIZE * 0.5;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', positionAttribute );
geometry.setAttribute( 'customColor', new THREE.Float32BufferAttribute( colors, 3 ) );
geometry.setAttribute( 'size', new THREE.Float32BufferAttribute( sizes, 1 ) );
//
const material = new THREE.ShaderMaterial( {
uniforms: {
color: { value: new THREE.Color( 0xffffff ) },
pointTexture: { value: new THREE.TextureLoader().load( 'textures/sprites/disc.png' ) }
},
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
alphaTest: 0.9
} );
//
particles = new THREE.Points( geometry, material );
scene.add( particles );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//
raycaster = new THREE.Raycaster();
pointer = new THREE.Vector2();
//
stats = new Stats();
container.appendChild( stats.dom );
//
window.addEventListener( 'resize', onWindowResize );
document.addEventListener( 'pointermove', onPointerMove );
}
function onPointerMove( event ) {
pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;
const geometry = particles.geometry;
const attributes = geometry.attributes;
raycaster.setFromCamera( pointer, camera );
intersects = raycaster.intersectObject( particles );
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].index ) {
attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE;
INTERSECTED = intersects[ 0 ].index;
attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE * 1.25;
attributes.size.needsUpdate = true;
}
} else if ( INTERSECTED !== null ) {
attributes.size.array[ INTERSECTED ] = PARTICLE_SIZE;
attributes.size.needsUpdate = true;
INTERSECTED = null;
}
renderer.render( scene, camera );
}

View File

@ -24,10 +24,10 @@ export function onHover(e) {
let minDist = Infinity;
for (let i = 0; i < hoverPts.length; i++) {
if (!hoverPts[i].distanceToRay) continue;
if (hoverPts[i].distanceToRay < minDist) {
if (hoverPts[i].distanceToRay < minDist-0.0001) {
minDist = hoverPts[i].distanceToRay
idx = [i]
} else if (hoverPts[i].distanceToRay == minDist) {
} else if (Math.abs(hoverPts[i].distanceToRay - minDist) < 0.0001) {
idx.push(i)
}
}
@ -38,17 +38,25 @@ export function onHover(e) {
if (idx.length) {
if (hoverPts[idx[0]].object != this.hovered[0]) {
const obj = this.hovered[this.hovered.length - 1]
// const obj = this.hovered[this.hovered.length - 1]
// if (obj && !this.selected.includes(obj)) {
// obj.material.color.set(color[obj.name[0]])
// }
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
if (obj && !this.selected.includes(obj)) {
obj.material.color.set(color[obj.name[0]])
}
}
this.hovered = []
for (let x = 0; x < idx.length; x++) {
const i = idx[x]
this.hovered.push(hoverPts[i].object)
const obj = hoverPts[idx[x]].object
obj.material.color.set(color.hover)
this.hovered.push(obj)
}
this.hovered[this.hovered.length - 1].material.color.set(color.hover)
// console.log('render1')
this.obj3d.dispatchEvent({ type: 'change' })
@ -56,10 +64,18 @@ export function onHover(e) {
} else {
if (this.hovered.length) {
const obj = this.hovered[this.hovered.length - 1]
if (obj && !this.selected.includes(obj)) {
// const obj = this.hovered[this.hovered.length - 1]
// if (obj && !this.selected.includes(obj)) {
// obj.material.color.set(color[obj.name[0]])
// }
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
// console.log(obj, 'here')
if (!this.selected.includes(obj)) {
obj.material.color.set(color[obj.name[0]])
}
}
this.hovered = []
// console.log('render2')
@ -81,8 +97,8 @@ export function onPick(e) {
this.canvas.addEventListener('pointerup', this.onRelease)
}
} else {
for (let obj of this.selected) {
// obj.material.color.set(0x555555)
for (let x = 0; x < this.selected.length; x++) {
const obj = this.selected[x]
obj.material.color.set(color[obj.name[0]])
}
this.obj3d.dispatchEvent({ type: 'change' })
@ -91,21 +107,20 @@ export function onPick(e) {
}
export function onDrag(e) {
const mouseLoc = this.getLocation(e);
// for (let x = 0; x < this.hovered.length; x++) {
// const obj = this.hovered[x]
// const obj = this.hovered[this.hovered.length-1]
// this.ptsBuf.set(
// mouseLoc,
// this.getLocation(e).toArray(),
// this.objIdx.get(obj.name) * 3
// )
// }
const obj = this.hovered[this.hovered.length-1]
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
this.ptsBuf.set(
mouseLoc,
this.getLocation(e).toArray(),
this.objIdx.get(obj.name) * 3
)
}
this.solve()
this.obj3d.dispatchEvent({ type: 'change' })

View File

@ -59,30 +59,41 @@ const lineObj = (n = 1) => {
async function awaitPts(n) {
let references = this.selected.slice()
if (references.length == 0) {
while (references.length < n) {
let end = false;
while (references.length < n && !end) {
let pt;
let onEnd, onKey;
try {
pt = await new Promise((res, rej) => {
this.canvas.addEventListener('pointerdown', () => res(this.hovered[0]), { once: true })
window.addEventListener('keydown', (e) => rej(e), { once: true })
onKey = (e) => {
if (e.key != 'Escape') return
console.log(e.key, 'key')
rej()
}
onEnd = (e) => {
res(this.hovered[0])
}
this.canvas.addEventListener('pointerdown', onEnd)
window.addEventListener('keydown', onKey)
})
if (pt.name[0] == 'p') {
references.push(pt)
} else if (pt.name[0] == 'd') {
references = [pt]
break;
end = true;
}
} catch (e) {
if (e.key == 'Escape') {
console.log('cancelled')
return;
}
}
end = true;
}
window.removeEventListener('keydown', onKey)
this.canvas.removeEventListener('pointerdown', onEnd)
}
return references
}