something is slow

master
howard 2021-03-25 21:30:35 -07:00
parent 23da7dcf83
commit 5d56145221
9 changed files with 341 additions and 117 deletions

View File

@ -47,7 +47,7 @@ function main() {
const canvas = document.querySelector('#c');
const view1Elem = document.querySelector('#view1');
const view2Elem = document.querySelector('#view2');
// const view2Elem = document.querySelector('#view2');
const renderer = new THREE.WebGLRenderer({ canvas });
const scene = new THREE.Scene();
@ -68,8 +68,8 @@ function main() {
// const controls = new TrackballControls(camera, view1Elem);
controls.target.set(0, 0, 0);
controls.update()
const cameraHelper = new THREE.CameraHelper(camera);
helpersGroup.add(cameraHelper);
// const cameraHelper = new THREE.CameraHelper(camera);
// helpersGroup.add(cameraHelper);
// const camera2 = new THREE.PerspectiveCamera(
@ -78,6 +78,13 @@ function main() {
// 0.1, // near
// 500, // far
// );
// const c2size = 10;
// const c2near = 5;
// const c2far = 200;
// const camera2 = new THREE.OrthographicCamera(-c2size, c2size, c2size, -c2size, c2near, c2far);
// camera2.zoom = 0.5
// camera2.position.set(16, 28, 40);
// camera2.lookAt(0, 5, 0);
// const controls2 = new OrbitControls(camera2, view2Elem);
@ -94,20 +101,30 @@ function main() {
window.sketcher = sketcher
scene.add(sketcher)
const color = 0xFFFFFF;
const intensity = 1;
const light1 = new THREE.DirectionalLight(color, intensity);
light1.position.set(10, 10, 10);
scene.add(light1);
// const lightHelper = new THREE.DirectionalLightHelper(light1, 5);
// helpersGroup.add(lightHelper);
const light2 = new THREE.DirectionalLight(color, intensity);
light2.position.set(-10, -10, -5);
scene.add(light2);
// const lightHelper2 = new THREE.DirectionalLightHelper(light2, 5);
// helpersGroup.add(lightHelper2);
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(0, 10, 0);
light.target.position.set(-5, 0, 0);
const light = new THREE.AmbientLight(color, intensity);
scene.add(light);
scene.add(light.target);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
@ -151,8 +168,12 @@ function main() {
camera.left = -aspect;
camera.right = aspect;
camera.updateProjectionMatrix();
cameraHelper.update();
cameraHelper.visible = false;
// cameraHelper.update();
// cameraHelper.visible = false;
// lightHelper.visible = false;
// lightHelper2.visible = false;
scene.background.set(0xb0b0b0);
renderer.render(scene, camera);
}
// {
@ -160,6 +181,9 @@ function main() {
// camera2.aspect = aspect;
// camera2.updateProjectionMatrix();
// cameraHelper.visible = true;
// lightHelper.visible = true;
// lightHelper2.visible = true;
// scene.background.set(0x000040);
// renderer.render(scene, camera2);
// }

View File

@ -3,8 +3,11 @@ import { Matrix4 } from 'three';
import * as THREE from 'three/src/Three'
import { onClick_1, onClick_2, beforeClick_2, clear } from './drawEvents'
import { drawOnClick1, drawOnClick2, drawPreClick2, drawClear } from './drawEvents'
import { onHover, onDrag, onPick, onRelease } from './pickEvents'
import { addDimension, setCoincident } from './constraintEvents'
import { get3PtArc } from './sketchArc'
import { extrude } from './extrude'
const lineMaterial = new THREE.LineBasicMaterial({
@ -12,6 +15,7 @@ const lineMaterial = new THREE.LineBasicMaterial({
color: 0x555555,
})
const pointMaterial = new THREE.PointsMaterial({
color: 0x555555,
size: 4,
@ -31,7 +35,7 @@ class Sketcher extends THREE.Group {
this.raycaster = new THREE.Raycaster();
this.raycaster.params.Line.threshold = 0.4;
this.raycaster.params.Points.threshold = 0.4;
this.raycaster.params.Points.threshold = 2;
// [0]:x, [1]:y, [2]:z
this.objIdx = new Map()
@ -55,13 +59,13 @@ class Sketcher extends THREE.Group {
this.constraintsBuf = new Float32Array(this.max_constraints * 6).fill(NaN)
this.contraintNum = {
'coincident': 0,
'parallel': 1
'distance': 1
}
this.onClick_1 = onClick_1.bind(this);
this.beforeClick_2 = beforeClick_2.bind(this);
this.onClick_2 = onClick_2.bind(this);
this.drawOnClick1 = drawOnClick1.bind(this);
this.drawPreClick2 = drawPreClick2.bind(this);
this.drawOnClick2 = drawOnClick2.bind(this);
this.onHover = onHover.bind(this);
this.onPick = onPick.bind(this);
@ -77,6 +81,7 @@ class Sketcher extends THREE.Group {
this.mode = ""
this.subsequent = false;
this.selected = new Set()
this.hovered = []
this.target = new THREE.Vector3();
}
@ -94,23 +99,32 @@ class Sketcher extends THREE.Group {
onKeyPress(e) {
switch (e.key) {
case 'Escape':
clear.bind(this)()
drawClear.bind(this)()
this.mode = ""
break;
case 'l':
if (this.mode == 'line') {
this.clear()
drawClear.bind(this)()
}
this.domElement.addEventListener('pointerdown', this.onClick_1)
this.domElement.addEventListener('pointerdown', this.drawOnClick1)
this.mode = "line"
break;
case 'a':
this.domElement.addEventListener('pointerdown', this.onClick_1)
this.domElement.addEventListener('pointerdown', this.drawOnClick1)
this.mode = "arc"
break;
case 'd':
case 'x':
this.deleteSelected()
break;
case 'c':
setCoincident.call(this)
this.updateOtherBuffers()
this.solve()
this.mode = ""
break;
case 'e':
extrude.call(this)
break;
case '=':
this.plane.applyMatrix4(new Matrix4().makeRotationY(0.1))
this.orientSketcher()
@ -133,7 +147,8 @@ class Sketcher extends THREE.Group {
minI = Math.min(minI, this.delete(obj))
}
this.updatePointsBuffer(minI)
// this.updatePointsBuffer(minI)
this.updatePointsBuffer()
this.updateOtherBuffers()
this.selected.clear()
@ -265,12 +280,27 @@ class Sketcher extends THREE.Group {
pos.needsUpdate = true;
}
this.dispatchEvent({ type: 'change' })
Module._free(pts_buffer)
Module._free(links_buffer)
Module._free(constraints_buffer)
for (let [k, obj] of this.linkedObjs) {
if (obj[0] == 'line') continue;
const [p1, p2, c, arc] = obj[1]
const points = get3PtArc(
p1.geometry.attributes.position.array,
p2.geometry.attributes.position.array,
c.geometry.attributes.position.array
);
arc.geometry.attributes.position.set(points)
arc.needsUpdate = true;
}
this.dispatchEvent({ type: 'change' })
}
}

View File

@ -0,0 +1,80 @@
import * as THREE from 'three/src/Three'
import { lineMaterial, pointMaterial } from './Sketcher'
export function addDimension(ent1, ent2, distance) {
// if (ent1.type ==)
this.constraints.set(++this.c_id,
[
'distance', distance,
[p1, p2, -1, -1]
]
)
ent1.constraints.add(this.c_id)
ent2.constraints.add(this.c_id)
}
// function findTouching(node) {
// const res = [node]
// for (let t of node.constraints) {
// if (this.constraints.get(t)[0] != 'coincident') continue
// for (let i = 0; i < 2; i++) {
// let d = this.constraints.get(t)[2][i]
// if (d != node) res.push(d)
// }
// }
// return res
// }
// export function setCoincident(ent1, ent2) {
// for (let n1 of findTouching.call(this,ent1)) {
// for (let n2 of findTouching.call(this,ent2)) {
// this.constraints.set(++this.c_id,
// [
// 'coincident', -1,
// [n1, n2, -1, -1]
// ]
// )
// n1.constraints.add(this.c_id)
// n2.constraints.add(this.c_id)
// }
// }
// }
export function setCoincident() {
const s = new Set()
const toComb = []
for (let node of this.selected) {
const xc = node.geometry.attributes.position.array[0]
if (!s.has(xc)) {
toComb.push(node)
s.add(xc)
}
}
for (let i = 1; i < toComb.length; i++) {
this.constraints.set(++this.c_id,
[
'coincident', -1,
[toComb[i - 1], toComb[i], -1, -1]
]
)
toComb[i].constraints.add(this.c_id)
toComb[i - 1].constraints.add(this.c_id)
}
}

View File

@ -2,9 +2,9 @@
import { sketchArc, sketchArc2 } from './sketchArc'
import { sketchLine, sketchLine2 } from './sketchLine'
export function onClick_1(e) {
export function drawOnClick1(e) {
if (e.buttons !== 1) return
this.domElement.removeEventListener('pointerdown', this.onClick_1)
this.domElement.removeEventListener('pointerdown', this.drawOnClick1)
const mouseLoc = this.getLocation(e);
if (this.mode == "line") {
@ -22,12 +22,12 @@ export function onClick_1(e) {
}
this.l_id += 1
this.domElement.addEventListener('pointermove', this.beforeClick_2)
this.domElement.addEventListener('pointerdown', this.onClick_2)
this.domElement.addEventListener('pointermove', this.drawPreClick2)
this.domElement.addEventListener('pointerdown', this.drawOnClick2)
}
export function beforeClick_2(e) {
export function drawPreClick2(e) {
const mouseLoc = this.getLocation(e);
if (this.mode == "line") {
@ -39,10 +39,10 @@ export function beforeClick_2(e) {
this.dispatchEvent({ type: 'change' })
}
export function onClick_2(e) {
export function drawOnClick2(e) {
if (e.buttons !== 1) return;
this.domElement.removeEventListener('pointermove', this.beforeClick_2);
this.domElement.removeEventListener('pointerdown', this.onClick_2);
this.domElement.removeEventListener('pointermove', this.drawPreClick2);
this.domElement.removeEventListener('pointerdown', this.drawOnClick2);
this.updatePointsBuffer(this.updatePoint)
this.updateOtherBuffers()
@ -50,20 +50,20 @@ export function onClick_2(e) {
if (this.mode == "line") {
this.subsequent = true
this.onClick_1(e)
this.drawOnClick1(e)
} else if (this.mode == "arc") {
// this.domElement.addEventListener('pointermove', this.beforeClick_3)
}
}
export function clear() {
export function drawClear() {
if (this.mode == "") return
if (this.mode == "line") {
this.domElement.removeEventListener('pointerdown', this.onClick_1)
this.domElement.removeEventListener('pointermove', this.beforeClick_2);
this.domElement.removeEventListener('pointerdown', this.onClick_2);
this.domElement.removeEventListener('pointerdown', this.drawOnClick1)
this.domElement.removeEventListener('pointermove', this.drawPreClick2);
this.domElement.removeEventListener('pointerdown', this.drawOnClick2);
this.delete(this.children[this.children.length - 1])

72
src/sketcher/extrude.js Normal file
View File

@ -0,0 +1,72 @@
import * as THREE from 'three/src/Three'
export function extrude() {
let constraints = this.constraints;
let linkedObjs = this.linkedObjs;
let children = this.children;
let visited = new Set()
let v2s = []
function findPair(node) {
visited.add(node)
let linkedObj = linkedObjs.get(node.l_id)
console.log(linkedObj)
let arr;
if (linkedObj[0] == 'line') {
arr = linkedObj[1][2].geometry.attributes.position.array
} else if (linkedObj[0] == 'arc') {
arr = linkedObj[1][3].geometry.attributes.position.array
}
for (let i = 0; i < arr.length; i += 3) {
v2s.push(new THREE.Vector2(arr[i], arr[i + 1]))
}
for (let i = 0; i < 2; i++) {
let d = linkedObj[1][i]
if (d == -1 || d == node) continue;
if (d == children[1]) {
console.log('pair found')
};
findTouching(d)
}
}
function findTouching(node) {
for (let t of node.constraints) {
if (constraints.get(t)[0] != 'coincident') continue
for (let d of constraints.get(t)[2]) {
if (d == -1 || d == node) continue;
if (d == children[1]) {
console.log('touching found')
} else {
if (!visited.has(d)) {
findPair(d)
}
};
}
}
}
findPair(children[1])
const shape = new THREE.Shape(v2s);
const extrudeSettings = { amount: 8, bevelEnabled: false};
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const phong = new THREE.MeshPhongMaterial( { color: 0x156289, emissive: 0x072534, side: THREE.DoubleSide, flatShading: true } );
const mesh = new THREE.Mesh(geometry, phong);
this.add(mesh)
}

View File

@ -1,50 +1 @@
export function get2PtArc(p1, p2, divisions = 36) {
const dx = p2[0] - p1[0]
const dy = p2[1] - p1[1]
const dist = Math.sqrt(dx ** 2 + dy ** 2)
const midAngle = (Math.atan2(dy, dx) - Math.PI / 2) % (2 * Math.PI)
let a1 = midAngle - Math.PI / 6
let a2 = midAngle + Math.PI / 6
a1 = a1 < 0 ? a1 + 2 * Math.PI : a1
a2 = a2 < 0 ? a2 + 2 * Math.PI : a1
const factor = Math.tan(Math.PI / 3)
const cx = (p1[0] + p2[0] - dy * factor) / 2
const cy = (p1[1] + p2[1] + dx * factor) / 2
const radius = dist
const deltaAngle = Math.PI / 3
let points = new Float32Array((divisions + 1) * 3)
for (let d = 0; d <= divisions; d++) {
const angle = a1 + (d / divisions) * deltaAngle;
points[3 * d] = cx + radius * Math.cos(angle);
points[3 * d + 1] = cy + radius * Math.sin(angle);
}
return [points, [cx, cy]];
}
export function get3PtArc(p1, p2, c, divisions = 36) {
const v1 = [p1[0] - c[0], p1[1] - c[1]]
const v2 = [p2[0] - c[0], p2[1] - c[1]]
let a1 = Math.atan2(v1[1], v1[0])
let a2 = Math.atan2(v2[1], v2[0])
const radius = Math.sqrt(v1[0] ** 2 + v1[1] ** 2)
const deltaAngle = a2 - a1
let points = new Float32Array((divisions + 1) * 3)
for (let d = 0; d <= divisions; d++) {
const angle = a1 + (d / divisions) * deltaAngle;
points[3 * d] = c[0] + radius * Math.cos(angle);
points[3 * d + 1] = c[1] + radius * Math.sin(angle);
}
return points;
}

View File

@ -2,8 +2,15 @@ import * as THREE from 'three/src/Three'
export function onHover(e) {
if (this.mode || e.buttons) return
if (this.hovered && !this.selected.has(this.hovered)) {
this.hovered.material.color.set(0x555555)
if (this.hovered.length) {
for (let ob of this.hovered) {
if (ob && !this.selected.has(ob)) {
ob.material.color.set(0x555555)
}
}
this.hovered = []
this.dispatchEvent({ type: 'change' })
}
this.raycaster.setFromCamera(
@ -15,42 +22,46 @@ export function onHover(e) {
);
const hoverPts = this.raycaster.intersectObjects(this.children)
// console.log(hoverPts)
// console.log(hoverPts)
if (hoverPts.length) {
let minDist = Infinity;
let idx = 0
let idx = []
for (let i = 0; i < hoverPts.length; i++) {
if (hoverPts[i].distanceToRay && hoverPts[i].distanceToRay <= minDist) {
if (!hoverPts[i].distanceToRay) continue;
if (hoverPts[i].distanceToRay < minDist) {
minDist = hoverPts[i].distanceToRay
idx = i
idx = [i]
} else if (hoverPts[i].distanceToRay == minDist) {
idx.push(i)
}
}
hoverPts[idx].object.material.color.set(0xff0000)
this.hovered = hoverPts[idx].object
// if (!idx.length) idx.push(0)
for (let i of idx) {
hoverPts[i].object.material.color.set(0x00ff00)
// hoverPts[i].object.material.color.set(0xff0000)
this.hovered.push(hoverPts[i].object)
}
this.dispatchEvent({ type: 'change' })
return
}
if (this.hovered) {
this.hovered = null;
this.dispatchEvent({ type: 'change' })
}
}
export function onPick(e) {
if (this.mode || e.buttons != 1) return
if (this.hovered) {
this.selected.add(this.hovered)
if (this.hovered.type === "Points") {
this.grabPtIdx = this.children.indexOf(
this.hovered
)
if (this.hovered.length) {
for (let h of this.hovered) {
this.selected.add(h)
}
if (this.hovered[0].type == "Points") {
this.domElement.addEventListener('pointermove', this.onDrag);
this.domElement.addEventListener('pointerup', this.onRelease)
}
@ -66,10 +77,12 @@ export function onPick(e) {
export function onDrag(e) {
const mouseLoc = this.getLocation(e);
this.ptsBuf.set(
mouseLoc,
this.objIdx.get(this.children[this.grabPtIdx].id) * 3
)
for (let h of this.hovered) {
this.ptsBuf.set(
mouseLoc,
this.objIdx.get(h.id) * 3
)
}
this.solve()
this.dispatchEvent({ type: 'change' })
@ -79,6 +92,10 @@ export function onDrag(e) {
export function onRelease() {
this.domElement.removeEventListener('pointermove', this.onDrag)
this.domElement.removeEventListener('pointerup', this.onRelease)
this.children[this.grabPtIdx].geometry.computeBoundingSphere()
for (let ii of this.hovered) {
ii.geometry.computeBoundingSphere()
}
}

View File

@ -1,6 +1,5 @@
import * as THREE from 'three/src/Three'
import { get2PtArc, get3PtArc } from './geometry'
import {lineMaterial, pointMaterial} from './Sketcher'
export function sketchArc(mouseLoc) {
@ -60,4 +59,56 @@ export function sketchArc2(mouseLoc, toPush) {
p3.geometry.attributes.position.set(center);
p3.geometry.attributes.position.needsUpdate = true;
p3.geometry.computeBoundingSphere()
}
export function get2PtArc(p1, p2, divisions = 36) {
const dx = p2[0] - p1[0]
const dy = p2[1] - p1[1]
const dist = Math.sqrt(dx ** 2 + dy ** 2)
const midAngle = (Math.atan2(dy, dx) - Math.PI / 2) % (2 * Math.PI)
let a1 = midAngle - Math.PI / 6
let a2 = midAngle + Math.PI / 6
a1 = a1 < 0 ? a1 + 2 * Math.PI : a1
a2 = a2 < 0 ? a2 + 2 * Math.PI : a1
const factor = Math.tan(Math.PI / 3)
const cx = (p1[0] + p2[0] - dy * factor) / 2
const cy = (p1[1] + p2[1] + dx * factor) / 2
const radius = dist
const deltaAngle = Math.PI / 3
let points = new Float32Array((divisions + 1) * 3)
for (let d = 0; d <= divisions; d++) {
const angle = a1 + (d / divisions) * deltaAngle;
points[3 * d] = cx + radius * Math.cos(angle);
points[3 * d + 1] = cy + radius * Math.sin(angle);
}
return [points, [cx, cy]];
}
export function get3PtArc(p1, p2, c, divisions = 36) {
const v1 = [p1[0] - c[0], p1[1] - c[1]]
const v2 = [p2[0] - c[0], p2[1] - c[1]]
let a1 = Math.atan2(v1[1], v1[0])
let a2 = Math.atan2(v2[1], v2[0])
const radius = Math.sqrt(v1[0] ** 2 + v1[1] ** 2)
let deltaAngle = a2 - a1
if (deltaAngle <0) deltaAngle += Math.PI*2
// console.log(deltaAngle)
let points = new Float32Array((divisions + 1) * 3)
for (let d = 0; d <= divisions; d++) {
const angle = a1 + (d / divisions) * deltaAngle;
points[3 * d] = c[0] + radius * Math.cos(angle);
points[3 * d + 1] = c[1] + radius * Math.sin(angle);
}
return points;
}

View File

@ -39,7 +39,7 @@ export function sketchLine(mouseLoc) {
if (this.subsequent) {
this.constraints.set(this.c_id,
this.constraints.set(++this.c_id,
[
'coincident', -1,
[this.children[this.children.length - 2], p1, -1, -1]
@ -48,7 +48,6 @@ export function sketchLine(mouseLoc) {
p1.constraints.add(this.c_id)
this.children[this.children.length - 2].constraints.add(this.c_id)
this.c_id += 1
}