master
howard 2021-03-30 16:20:24 -07:00
parent 1a602c5f58
commit 6e9359138f
15 changed files with 352 additions and 431 deletions

2
dist/index.html vendored
View File

@ -40,7 +40,7 @@
<canvas id="c"></canvas> <canvas id="c"></canvas>
<div id="stats"></div> <div id="stats"></div>
<script src="index.bundle.js"></script> <script src="index.bundle.js"></script>
<script src="renderer.bundle.js"></script> <script src="scene.bundle.js"></script>
<script src="solver.js"></script> <script src="solver.js"></script>
<script src="lz-string.min.js"></script> <script src="lz-string.min.js"></script>
</body> </body>

View File

@ -1,143 +0,0 @@
import * as THREE from '../node_modules/three/src/Three';
// import { OrbitControls } from './utils/OrbitControls'
import { TrackballControls } from './utils/trackball'
import { Sketcher } from './sketcher/Sketcher'
import Stats from './utils/stats.module.js';
import { add3DPoint } from './datums'
import { extrude } from './sketcher/extrude'
import { onHover } from './mouseEvents';
// class Scene extends THREE.Scene {
// constructor() {
// }
// }
export function Renderer(store) {
this.store = store
this.stats = new Stats();
this.stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
document.getElementById('stats').appendChild(this.stats.dom);
this.canvas = document.querySelector('#c');
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas });
this.scene = new THREE.Scene();
this.raycaster = new THREE.Raycaster();
window.scene = this.scene;
this.scene.background = new THREE.Color(0x888888);
// this.scene.background = new THREE.Color(0xffffff);
const helpersGroup = new THREE.Group();
helpersGroup.name = "helpersGroup"
this.scene.add(helpersGroup);
const axesHelper = new THREE.AxesHelper(5);
helpersGroup.add(axesHelper);
const size = 1;
const near = 0;
const far = 100;
this.camera = new THREE.OrthographicCamera(-size, size, size, -size, near, far);
this.camera.zoom = 0.1;
this.camera.position.set(0, 0, 50);
// const controls = new OrbitControls(camera, view1Elem);
const controls = new TrackballControls(this.camera, this.canvas);
controls.target.set(0, 0, 0);
controls.update()
const color = 0xFFFFFF;
const intensity = 1;
const light1 = new THREE.DirectionalLight(color, intensity);
light1.position.set(10, 10, 10);
this.scene.add(light1);
const light2 = new THREE.DirectionalLight(color, intensity);
light2.position.set(-10, -10, -5);
this.scene.add(light2);
const ambient = new THREE.AmbientLight(color, intensity);
this.scene.add(ambient);
this.hovered = []
this.selected = new Set()
this.render = render.bind(this)
this.resizeCanvas = resizeCanvas.bind(this)
this.addSketch = addSketch.bind(this)
this.extrude = extrude.bind(this)
this.onHover = onHover.bind(this);
controls.addEventListener('change', this.render);
controls.addEventListener('start', this.render);
window.addEventListener('resize', this.render);
this.render()
}
function render() {
this.stats.begin();
if (this.resizeCanvas(this.renderer)) {
const canvas = this.renderer.domElement;
this.camera.left = -canvas.clientWidth / canvas.clientHeight;
this.camera.right = canvas.clientWidth / canvas.clientHeight;
this.camera.updateProjectionMatrix();
}
this.renderer.render(scene, this.camera);
this.stats.end();
}
function resizeCanvas(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
async function addSketch() {
const result = []
for (let i = 0; i < 3; i++) {
const pt = await new Promise((res, rej) => {
this.canvas.addEventListener('pointerdown', (e) => res(getPoint(e, this.camera)), { once: true })
})
result.push(pt)
}
const sketcher = new Sketcher(this.camera, this.canvas, this.store)
this.scene.add(sketcher)
sketcher.align(...result)
sketcher.activate()
sketcher.addEventListener('change', this.render);
window.sketcher = sketcher
this.render()
this.store.dispatch({ type: 'rx-sketch', obj: sketcher })
}
function getPoint(e, camera) {
const mouse = new THREE.Vector2(
(e.clientX / window.innerWidth) * 2 - 1,
- (e.clientY / window.innerHeight) * 2 + 1
)
return new THREE.Vector3(mouse.x, mouse.y, 0).unproject(camera)
}
window.renderInst = new Renderer(store);

201
src/Scene.js Normal file
View File

@ -0,0 +1,201 @@
import * as THREE from 'three/src/Three';
// import { OrbitControls } from './utils/OrbitControls'
import { TrackballControls } from './utils/trackball'
import { Sketcher } from './sketcher/Sketcher'
import Stats from './utils/stats.module.js';
import { add3DPoint } from './datums'
import { extrude } from './extrude'
import { onHover, onPick } from './utils/mouseEvents';
import { _vec2, _vec3 } from './utils/static'
import { Vector3 } from 'three/src/Three';
const eq = (a1, a2) => {
if (a1.length != a2.length) return false
for (let i = 0; i < a1.length; i++) {
if (a1[i] != a2[i]) return false
}
return true
}
export class Scene extends THREE.Scene {
constructor(store) {
super()
this.name = 'Scene'
this.store = store;
this.canvas = document.querySelector('#c');
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas });
const size = 1;
const near = 0;
const far = 100;
this.camera = new THREE.OrthographicCamera(-size, size, size, -size, near, far);
this.camera.zoom = 0.1;
this.camera.position.set(50, 50, 50);
// const controls = new OrbitControls(camera, view1Elem);
const controls = new TrackballControls(this.camera, this.canvas);
controls.target.set(0, 0, 0);
controls.update();
this.background = new THREE.Color(0x888888);
const helpersGroup = new THREE.Group();
helpersGroup.name = "helpersGroup";
this.add(helpersGroup);
const axesHelper = new THREE.AxesHelper(0.4);
helpersGroup.add(axesHelper);
const pxy = new THREE.Mesh(
new THREE.PlaneGeometry(5, 5),
new THREE.MeshBasicMaterial({
color: 0xff0000,
opacity: 0.2,
side: THREE.DoubleSide,
transparent: true,
depthWrite: false,
toneMapped: false
})
);
pxy.name = "Plane"
helpersGroup.add(pxy);
const pyz = pxy.clone().rotateY(Math.PI / 2);
pyz.material = pyz.material.clone();
const pxz = pxy.clone().rotateX(-Math.PI / 2);
pxz.material = pxz.material.clone();
helpersGroup.add(pyz);
helpersGroup.add(pxz);
const color = 0xFFFFFF;
const intensity = 1;
const light1 = new THREE.DirectionalLight(color, intensity);
light1.position.set(10, 10, 10);
this.add(light1);
const light2 = new THREE.DirectionalLight(color, intensity);
light2.position.set(-10, -10, -5);
this.add(light2);
const ambient = new THREE.AmbientLight(color, intensity);
this.add(ambient);
this.render = render.bind(this);
this.resizeCanvas = resizeCanvas.bind(this);
this.addSketch = addSketch.bind(this);
this.extrude = extrude.bind(this);
this.onHover = onHover.bind(this);
this.onPick = onPick.bind(this);
this.addEventListener('change', this.render);
controls.addEventListener('change', this.render);
controls.addEventListener('start', this.render);
window.addEventListener('resize', this.render);
this.stats = new Stats();
this.stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
document.getElementById('stats').appendChild(this.stats.dom);
this.hovered = [];
this.selected = [];
this.render();
}
}
function render() {
this.stats.begin();
if (this.resizeCanvas(this.renderer)) {
const canvas = this.renderer.domElement;
this.camera.left = -canvas.clientWidth / canvas.clientHeight;
this.camera.right = canvas.clientWidth / canvas.clientHeight;
this.camera.updateProjectionMatrix();
}
this.renderer.render(this, this.camera);
this.stats.end();
}
function resizeCanvas(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
async function addSketch() {
let references = this.selected.slice()
if (references.length == 0) {
while (references.length < 3) {
let pt;
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 })
})
if (pt.type == 'Points') {
references.push(pt)
} else if (pt.name == 'Plane') {
references = [pt]
break;
}
} catch (e) {
if (e.key == 'Escape') {
console.log('cancelled')
return;
}
}
}
}
const sketcher = new Sketcher(this.camera, this.canvas, this.store)
if (references.length == 1 && references[0].name == 'Plane') {
this.add(sketcher)
sketcher.matrix = references[0].matrix
sketcher.plane.applyMatrix4(sketcher.matrix)
sketcher.inverse = sketcher.matrix.clone().invert()
} else if (references.length == 3) {
this.add(sketcher)
sketcher.align(
...references.map(
el => new Vector3(...el.geometry.attributes.position.array).applyMatrix4(el.matrixWorld)
)
)
} else {
console.log('cancelled')
return;
}
sketcher.activate()
sketcher.addEventListener('change', this.render);
this.render()
this.store.dispatch({ type: 'rx-sketch', obj: sketcher })
window.sketcher = sketcher
}
window.sc = new Scene(store);

View File

@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
import './app.scss' import './app.scss'
import { Provider, useDispatch, useSelector } from 'react-redux' import { Provider, useDispatch, useSelector } from 'react-redux'
// import { renderInst } from './index' // import { sc } from './index'
export const Root = ({ store }) => ( export const Root = ({ store }) => (
<Provider store={store}> <Provider store={store}>
@ -15,7 +15,8 @@ export const Root = ({ store }) => (
function treeId2Obj(id) { function treeId2Obj(id) {
return renderInst.scene.getObjectById(parseInt(id.slice(1))) // return sc.scene.getObjectById(parseInt(id.slice(1)))
return sc.getObjectById(parseInt(id.slice(1)))
} }
const App = () => { const App = () => {
@ -30,8 +31,12 @@ const App = () => {
useEffect(() => { useEffect(() => {
if (!activeSketch) { if (!activeSketch) {
renderInst.canvas.addEventListener('pointermove', renderInst.onHover) sc.canvas.addEventListener('pointermove', sc.onHover)
return () => renderInst.canvas.removeEventListener('pointermove', renderInst.onHover) sc.canvas.addEventListener('pointerdown', sc.onPick)
return () => {
sc.canvas.removeEventListener('pointermove', sc.onHover)
sc.canvas.removeEventListener('pointerdown', sc.onPick)
}
} }
}, [activeSketch]) }, [activeSketch])
@ -42,9 +47,9 @@ const App = () => {
<button onClick={() => treeId2Obj(activeSketch).deactivate()}> <button onClick={() => treeId2Obj(activeSketch).deactivate()}>
Exit sketch Exit sketch
</button> : </button> :
<button onClick={renderInst.addSketch}> addsketch </button> <button onClick={sc.addSketch}> addsketch </button>
} }
<button onClick={() => renderInst.extrude(treeId2Obj(activeSketch))}> extrude </button> <button onClick={() => sc.extrude(treeId2Obj(activeSketch))}> extrude </button>
{/* <button onClick={() => setState('')}> test </button> */} {/* <button onClick={() => setState('')}> test </button> */}
</div> </div>

View File

@ -46,7 +46,7 @@ export function add3DPoint(e) {
if (hoverPts[idx[0]].object != this.hovered[0]) { if (hoverPts[idx[0]].object != this.hovered[0]) {
for (let ob of this.hovered) { for (let ob of this.hovered) {
if (ob && !this.selected.has(ob)) { if (ob && !this.selected.includes(ob)) {
ob.material.color.set(0x555555) ob.material.color.set(0x555555)
} }
} }
@ -62,7 +62,7 @@ export function add3DPoint(e) {
} else { } else {
if (this.hovered.length) { if (this.hovered.length) {
for (let ob of this.hovered) { for (let ob of this.hovered) {
if (ob && !this.selected.has(ob)) { if (ob && !this.selected.includes(ob)) {
ob.material.color.set(0x555555) ob.material.color.set(0x555555)
} }
} }

View File

@ -1,5 +1,5 @@
import * as THREE from '../../node_modules/three/src/Three'; import * as THREE from 'three/src/Three';
import { pointMaterial } from '../utils/static' import { color, ptObj } from './utils/static'
export function extrude(sketch) { export function extrude(sketch) {
let constraints = sketch.constraints; let constraints = sketch.constraints;
@ -8,13 +8,13 @@ export function extrude(sketch) {
let objIdx = sketch.objIdx; let objIdx = sketch.objIdx;
let visited = new Set() let visited = new Set()
let v2s = [] let v2s = []
let offSetPts = []
function findPair(node) { function findPair(node) {
visited.add(node) visited.add(node)
let linkedObj = linkedObjs.get(node.l_id) let linkedObj = linkedObjs.get(node.l_id)
let arr; let arr;
if (linkedObj[0] == 'line') { if (linkedObj[0] == 'line') {
// console.log(children, objIdx, linkedObj)
arr = children[objIdx.get(linkedObj[1][2])].geometry.attributes.position.array arr = children[objIdx.get(linkedObj[1][2])].geometry.attributes.position.array
} else if (linkedObj[0] == 'arc') { } else if (linkedObj[0] == 'arc') {
arr = children[objIdx.get(linkedObj[1][3])].geometry.attributes.position.array arr = children[objIdx.get(linkedObj[1][3])].geometry.attributes.position.array
@ -23,6 +23,9 @@ export function extrude(sketch) {
v2s.push(new THREE.Vector2(arr[i], arr[i + 1])) v2s.push(new THREE.Vector2(arr[i], arr[i + 1]))
} }
offSetPts.push(arr[0], arr[1])
offSetPts.push(arr[arr.length - 3], arr[arr.length - 2])
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
// let d = linkedObj[1][i] // let d = linkedObj[1][i]
let d = children[objIdx.get(linkedObj[1][i])] let d = children[objIdx.get(linkedObj[1][i])]
@ -60,21 +63,28 @@ export function extrude(sketch) {
const shape = new THREE.Shape(v2s); const shape = new THREE.Shape(v2s);
const extrudeSettings = { depth: 8, bevelEnabled: false }; const extrudeSettings = { depth: 8, bevelEnabled: false };
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const phong = new THREE.MeshPhongMaterial({ color: 0x156289, emissive: 0x072534, side: THREE.DoubleSide, flatShading: true }); const phong = new THREE.MeshPhongMaterial({
color: color.extrude,
emissive: color.emissive,
flatShading: true
});
const mesh = new THREE.Mesh(geometry, phong) const mesh = new THREE.Mesh(geometry, phong)
// mesh.applyMatrix4(sketch.inverse)
// mesh.matrix.premultiply(sketch.matrix).multiply(sketch.inverse) for (let i = 0; i < offSetPts.length; i += 2) {
if (
offSetPts[i] == offSetPts[i - 2] &&
offSetPts[i + 1] == offSetPts[i - 1]
) continue;
mesh.add(
ptObj([offSetPts[i], offSetPts[i + 1], 8])
)
}
mesh.matrixAutoUpdate = false; mesh.matrixAutoUpdate = false;
mesh.matrix.multiply(sketch.matrix) mesh.matrix.multiply(sketch.matrix)
this.scene.add(mesh) this.add(mesh)
const wireframe = new THREE.WireframeGeometry(geometry);
const pts = new THREE.Points(wireframe, pointMaterial);
// pts.matrixAutoUpdate = false;
// pts.matrix.multiply(sketch.matrix)
mesh.add(pts)
this.render() this.render()

View File

@ -1,120 +0,0 @@
import * as THREE from 'three/src/Three';
import {raycaster} from './utils/static';
export function onHover(e) {
if (this.mode || e.buttons) return
raycaster.setFromCamera(
new THREE.Vector2(
(e.clientX / window.innerWidth) * 2 - 1,
- (e.clientY / window.innerHeight) * 2 + 1
),
this.camera
);
const hoverPts = raycaster.intersectObjects(this.scene.children)
let idx = []
if (hoverPts.length) {
let minDist = Infinity;
for (let i = 0; i < hoverPts.length; i++) {
if (!hoverPts[i].distanceToRay) continue;
if (hoverPts[i].distanceToRay < minDist) {
minDist = hoverPts[i].distanceToRay
idx = [i]
} else if (hoverPts[i].distanceToRay == minDist) {
idx.push(i)
}
}
if (!idx.length) idx.push(0)
}
if (idx.length) {
if (hoverPts[idx[0]].object != this.hovered[0]) {
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
if (obj && !this.selected.has(obj)) {
obj.material.color.set(0x555555)
}
}
this.hovered = []
for (let x = 0; x < idx.length; x++) {
const i = idx[x]
hoverPts[i].object.material.color.set(0x00ff00)
this.hovered.push(hoverPts[i].object)
}
// console.log('render1')
this.render()
}
} else {
if (this.hovered.length) {
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
if (obj && !this.selected.has(obj)) {
obj.material.color.set(0x555555)
}
}
this.hovered = []
// console.log('render2')
this.render()
}
}
}
export function onPick(e) {
if (this.mode || e.buttons != 1) return
if (this.hovered.length) {
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
this.selected.add(obj)
}
if (this.hovered[0].type == "Points") {
this.domElement.addEventListener('pointermove', this.onDrag);
this.domElement.addEventListener('pointerup', this.onRelease)
}
} else {
for (let obj of this.selected) {
obj.material.color.set(0x555555)
}
this.dispatchEvent({ type: 'change' })
this.selected.clear()
}
}
export function onDrag(e) {
const mouseLoc = this.getLocation(e);
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
this.ptsBuf.set(
mouseLoc,
this.objIdx.get(obj.id) * 3
)
}
this.solve()
this.dispatchEvent({ type: 'change' })
}
export function onRelease() {
this.domElement.removeEventListener('pointermove', this.onDrag)
this.domElement.removeEventListener('pointerup', this.onRelease)
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x]
obj.geometry.computeBoundingSphere()
}
}

View File

@ -3,10 +3,9 @@
import * as THREE from '../../node_modules/three/src/Three'; import * as THREE from '../../node_modules/three/src/Three';
import { drawOnClick1, drawOnClick2, drawPreClick2, drawClear } from './drawEvents' import { drawOnClick1, drawOnClick2, drawPreClick2, drawClear } from './drawEvents'
import { onHover, onDrag, onPick, onRelease } from './sketchMouseEvents' import { onHover, onDrag, onPick, onRelease } from '../utils/mouseEvents'
import { addDimension, setCoincident } from './constraintEvents' import { addDimension, setCoincident } from './constraintEvents'
import { get3PtArc } from './sketchArc' import { get3PtArc } from './sketchArc'
import { extrude } from './extrude'
import { _vec2, _vec3, raycaster } from '../utils/static' import { _vec2, _vec3, raycaster } from '../utils/static'
@ -15,12 +14,12 @@ import { _vec2, _vec3, raycaster } from '../utils/static'
class Sketcher extends THREE.Group { class Sketcher extends THREE.Group {
constructor(camera, domElement, store) { constructor(camera, canvas, store) {
super() super()
this.name = "sketch" this.name = "Sketch"
this.matrixAutoUpdate = false; this.matrixAutoUpdate = false;
this.camera = camera; this.camera = camera;
this.domElement = domElement; this.canvas = canvas;
this.store = store; this.store = store;
this.sub = new THREE.Group(); this.sub = new THREE.Group();
@ -28,8 +27,12 @@ class Sketcher extends THREE.Group {
const axesHelper = new THREE.AxesHelper(2); const axesHelper = new THREE.AxesHelper(2);
this.sub.add(axesHelper); this.sub.add(axesHelper);
this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
// [0]:x, [1]:y, [2]:z // [0]:x, [1]:y, [2]:z
this.objIdx = new Map() this.objIdx = new Map()
this.ptsBuf = new Float32Array(this.max_pts * 3).fill(NaN) this.ptsBuf = new Float32Array(this.max_pts * 3).fill(NaN)
@ -47,7 +50,8 @@ class Sketcher extends THREE.Group {
this.bindHandlers() this.bindHandlers()
this.selected = new Set() // this.selected = new Set()
this.selected = []
this.hovered = [] this.hovered = []
this.mode = "" this.mode = ""
this.subsequent = false; this.subsequent = false;
@ -70,27 +74,25 @@ class Sketcher extends THREE.Group {
activate() { activate() {
window.addEventListener('keydown', this.onKeyPress) window.addEventListener('keydown', this.onKeyPress)
this.domElement.addEventListener('pointerdown', this.onPick) this.canvas.addEventListener('pointerdown', this.onPick)
this.domElement.addEventListener('pointermove', this.onHover) this.canvas.addEventListener('pointermove', this.onHover)
this.store.dispatch({ type: 'set-active-sketch', sketch: this }) this.store.dispatch({ type: 'set-active-sketch', sketch: this })
} }
deactivate() { deactivate() {
window.removeEventListener('keydown', this.onKeyPress) window.removeEventListener('keydown', this.onKeyPress)
this.domElement.removeEventListener('pointerdown', this.onPick) this.canvas.removeEventListener('pointerdown', this.onPick)
this.domElement.removeEventListener('pointermove', this.onHover) this.canvas.removeEventListener('pointermove', this.onHover)
this.store.dispatch({ type: 'exit-sketch' }) this.store.dispatch({ type: 'exit-sketch' })
} }
align(origin, x_dir, y_dir) { align(origin, x_dir, y_dir) {
// this.updateWorldMatrix(true, false); const up = _vec3.subVectors(y_dir, origin).normalize();
const up = new THREE.Vector3().subVectors(y_dir, origin).normalize();
const _m1 = new THREE.Matrix4()
const te = _m1.elements; const te = _m1.elements;
const _x = new THREE.Vector3().subVectors(x_dir, origin).normalize(); _x.subVectors(x_dir, origin).normalize();
const _z = new THREE.Vector3().crossVectors(_x, up).normalize(); _z.crossVectors(_x, up).normalize();
const _y = new THREE.Vector3().crossVectors(_z, _x); _y.crossVectors(_z, _x);
te[0] = _x.x; te[4] = _y.x; te[8] = _z.x; te[0] = _x.x; te[4] = _y.x; te[8] = _z.x;
te[1] = _x.y; te[5] = _y.y; te[9] = _z.y; te[1] = _x.y; te[5] = _y.y; te[9] = _z.y;
@ -99,11 +101,11 @@ class Sketcher extends THREE.Group {
this.quaternion.setFromRotationMatrix(_m1); this.quaternion.setFromRotationMatrix(_m1);
const parent = this.parent; const parent = this.parent;
_m1.extractRotation(parent.matrixWorld); _m1.extractRotation(parent.matrixWorld);
const _q1 = new THREE.Quaternion().setFromRotationMatrix(_m1); _q1.setFromRotationMatrix(_m1);
this.quaternion.premultiply(_q1.invert()); this.quaternion.premultiply(_q1.invert());
this.updateMatrix(); this.updateMatrix();
this.matrix.setPosition(origin) this.matrix.setPosition(origin)
this.plane.applyMatrix4(this.matrix) this.plane.applyMatrix4(this.matrix)
this.inverse = this.matrix.clone().invert() this.inverse = this.matrix.clone().invert()
} }
@ -120,11 +122,11 @@ class Sketcher extends THREE.Group {
if (this.mode == 'line') { if (this.mode == 'line') {
drawClear.bind(this)() drawClear.bind(this)()
} }
this.domElement.addEventListener('pointerdown', this.drawOnClick1) this.canvas.addEventListener('pointerdown', this.drawOnClick1)
this.mode = "line" this.mode = "line"
break; break;
case 'a': case 'a':
this.domElement.addEventListener('pointerdown', this.drawOnClick1) this.canvas.addEventListener('pointerdown', this.drawOnClick1)
this.mode = "arc" this.mode = "arc"
break; break;
case 'x': case 'x':
@ -136,9 +138,7 @@ class Sketcher extends THREE.Group {
this.mode = "" this.mode = ""
break; break;
case 'e':
extrude.call(this)
break;
case 'z': case 'z':
var string = JSON.stringify(this.toJSON()); var string = JSON.stringify(this.toJSON());
window.string = string; window.string = string;
@ -167,7 +167,7 @@ class Sketcher extends THREE.Group {
this.updatePointsBuffer(toDelete[toDelete.length - 1]) this.updatePointsBuffer(toDelete[toDelete.length - 1])
this.updateOtherBuffers() this.updateOtherBuffers()
this.selected.clear() this.selected = []
this.dispatchEvent({ type: 'change' }) this.dispatchEvent({ type: 'change' })
} }
@ -328,7 +328,11 @@ class Sketcher extends THREE.Group {
} }
const _m1 = new THREE.Matrix4()
const _q1 = new THREE.Quaternion()
const _x = new THREE.Vector3();
const _y = new THREE.Vector3();
const _z = new THREE.Vector3();
Object.assign(Sketcher.prototype, Object.assign(Sketcher.prototype,

View File

@ -18,41 +18,6 @@ export function addDimension(ent1, ent2, distance) {
} }
// 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() { export function setCoincident() {
const s = new Set() const s = new Set()
const toComb = [] const toComb = []
@ -83,6 +48,6 @@ export function setCoincident() {
obj.geometry.computeBoundingSphere() obj.geometry.computeBoundingSphere()
obj.material.color.set(0x555555) obj.material.color.set(0x555555)
} }
this.selected.clear() this.selected = []
this.dispatchEvent({ type: 'change' }) this.dispatchEvent({ type: 'change' })
} }

View File

@ -4,7 +4,7 @@ import { sketchLine, sketchLine2 } from './sketchLine'
export function drawOnClick1(e) { export function drawOnClick1(e) {
if (e.buttons !== 1) return if (e.buttons !== 1) return
this.domElement.removeEventListener('pointerdown', this.drawOnClick1) this.canvas.removeEventListener('pointerdown', this.drawOnClick1)
const mouseLoc = this.getLocation(e); const mouseLoc = this.getLocation(e);
if (this.mode == "line") { if (this.mode == "line") {
@ -22,8 +22,8 @@ export function drawOnClick1(e) {
} }
this.l_id += 1 this.l_id += 1
this.domElement.addEventListener('pointermove', this.drawPreClick2) this.canvas.addEventListener('pointermove', this.drawPreClick2)
this.domElement.addEventListener('pointerdown', this.drawOnClick2) this.canvas.addEventListener('pointerdown', this.drawOnClick2)
} }
@ -41,8 +41,8 @@ export function drawPreClick2(e) {
export function drawOnClick2(e) { export function drawOnClick2(e) {
if (e.buttons !== 1) return; if (e.buttons !== 1) return;
this.domElement.removeEventListener('pointermove', this.drawPreClick2); this.canvas.removeEventListener('pointermove', this.drawPreClick2);
this.domElement.removeEventListener('pointerdown', this.drawOnClick2); this.canvas.removeEventListener('pointerdown', this.drawOnClick2);
this.updatePointsBuffer(this.updatePoint) this.updatePointsBuffer(this.updatePoint)
this.updateOtherBuffers() this.updateOtherBuffers()
@ -53,7 +53,7 @@ export function drawOnClick2(e) {
this.drawOnClick1(e) this.drawOnClick1(e)
} else if (this.mode == "arc") { } else if (this.mode == "arc") {
// this.domElement.addEventListener('pointermove', this.beforeClick_3) // this.canvas.addEventListener('pointermove', this.beforeClick_3)
} }
} }
@ -61,9 +61,9 @@ export function drawClear() {
if (this.mode == "") return if (this.mode == "") return
if (this.mode == "line") { if (this.mode == "line") {
this.domElement.removeEventListener('pointerdown', this.drawOnClick1) this.canvas.removeEventListener('pointerdown', this.drawOnClick1)
this.domElement.removeEventListener('pointermove', this.drawPreClick2); this.canvas.removeEventListener('pointermove', this.drawPreClick2);
this.domElement.removeEventListener('pointerdown', this.drawOnClick2); this.canvas.removeEventListener('pointerdown', this.drawOnClick2);
this.delete(this.children[this.updatePoint]) this.delete(this.children[this.updatePoint])

View File

@ -2,41 +2,24 @@
import * as THREE from '../../node_modules/three/src/Three'; import * as THREE from '../../node_modules/three/src/Three';
import {lineMaterial, pointMaterial} from '../utils/static' import {lineMaterial, pointMaterial} from '../utils/static'
import {ptObj, lineObj} from '../utils/static'
const n = 30
export function sketchArc(mouseLoc) { export function sketchArc(mouseLoc) {
const p1Geom = new THREE.BufferGeometry().setAttribute('position',
new THREE.BufferAttribute(new Float32Array(mouseLoc), 3) const p1 = ptObj(mouseLoc)
)
const p1 = new THREE.Points(p1Geom,
new THREE.PointsMaterial().copy(pointMaterial)
);
p1.matrixAutoUpdate = false; p1.matrixAutoUpdate = false;
p1.constraints = new Set() p1.constraints = new Set()
const p2Geom = new THREE.BufferGeometry().setAttribute('position', const p2 = ptObj()
new THREE.BufferAttribute(new Float32Array(3), 3)
)
const p2 = new THREE.Points(
p2Geom,
new THREE.PointsMaterial().copy(pointMaterial)
);
p2.matrixAutoUpdate = false; p2.matrixAutoUpdate = false;
p2.constraints = new Set() p2.constraints = new Set()
const arcGeom = new THREE.BufferGeometry().setAttribute('position', const arc = lineObj(n)
new THREE.BufferAttribute(new Float32Array(3 * 37), 3)
)
const arc = new THREE.Line(arcGeom,
new THREE.LineBasicMaterial().copy(lineMaterial)
);
arc.frustumCulled = false; arc.frustumCulled = false;
const p3Geom = new THREE.BufferGeometry().setAttribute('position', const p3 = ptObj()
new THREE.BufferAttribute(new Float32Array(3), 3)
)
const p3 = new THREE.Points(p3Geom,
new THREE.PointsMaterial().copy(pointMaterial)
);
return [p1, p2, p3, arc] return [p1, p2, p3, arc]
} }
@ -61,7 +44,7 @@ export function sketchArc2(mouseLoc, toPush) {
p3.geometry.computeBoundingSphere() p3.geometry.computeBoundingSphere()
} }
export function get2PtArc(p1, p2, divisions = 36) { export function get2PtArc(p1, p2, divisions = n) {
const dx = p2[0] - p1[0] const dx = p2[0] - p1[0]
const dy = p2[1] - p1[1] const dy = p2[1] - p1[1]
@ -90,7 +73,7 @@ export function get2PtArc(p1, p2, divisions = 36) {
} }
export function get3PtArc(p1, p2, c, divisions = 36) { export function get3PtArc(p1, p2, c, divisions = n) {
const v1 = [p1[0] - c[0], p1[1] - c[1]] const v1 = [p1[0] - c[0], p1[1] - c[1]]
const v2 = [p2[0] - c[0], p2[1] - c[1]] const v2 = [p2[0] - c[0], p2[1] - c[1]]

View File

@ -1,40 +1,25 @@
import * as THREE from '../../node_modules/three/src/Three'; import * as THREE from '../../node_modules/three/src/Three';
import {lineMaterial, pointMaterial} from '../utils/static' import {ptObj, lineObj} from '../utils/static'
export function sketchLine(mouseLoc) { export function sketchLine(mouseLoc) {
const p1Geom = new THREE.BufferGeometry().setAttribute('position', const p1 = ptObj()
new THREE.BufferAttribute(new Float32Array(3), 3)
)
const p1 = new THREE.Points(p1Geom,
new THREE.PointsMaterial().copy(pointMaterial)
);
p1.matrixAutoUpdate = false; p1.matrixAutoUpdate = false;
p1.constraints = new Set() p1.constraints = new Set()
const p2Geom = new THREE.BufferGeometry().setAttribute('position', const p2 = ptObj()
new THREE.BufferAttribute(new Float32Array(3), 3)
)
const p2 = new THREE.Points(
p2Geom,
new THREE.PointsMaterial().copy(pointMaterial)
);
p2.matrixAutoUpdate = false; p2.matrixAutoUpdate = false;
p2.constraints = new Set() p2.constraints = new Set()
const lineGeom = new THREE.BufferGeometry().setAttribute('position', const line = lineObj()
new THREE.BufferAttribute(new Float32Array(6), 3)
);
const line = new THREE.Line(lineGeom,
new THREE.LineBasicMaterial().copy(lineMaterial)
);
line.matrixAutoUpdate = false; line.matrixAutoUpdate = false;
line.frustumCulled = false; line.frustumCulled = false;
line.constraints = new Set() line.constraints = new Set()
lineGeom.attributes.position.set(mouseLoc) line.geometry.attributes.position.set(mouseLoc)
p1Geom.attributes.position.set(mouseLoc) p1.geometry.attributes.position.set(mouseLoc)
if (this.subsequent) { if (this.subsequent) {

View File

@ -1,5 +1,5 @@
import * as THREE from 'three/src/Three'; import * as THREE from 'three/src/Three';
import {raycaster} from '../utils/static'; import { raycaster, color } from './static';
export function onHover(e) { export function onHover(e) {
if (this.mode || e.buttons) return if (this.mode || e.buttons) return
@ -12,10 +12,16 @@ export function onHover(e) {
this.camera this.camera
); );
const hoverPts = raycaster.intersectObjects(this.children) let hoverPts;
if (this.name == 'Scene') {
hoverPts = raycaster.intersectObjects(this.children, true)
} else {
hoverPts = raycaster.intersectObjects(this.children)
}
let idx = [] let idx = []
if (hoverPts.length) { if (hoverPts.length) {
// console.log(hoverPts)
let minDist = Infinity; let minDist = Infinity;
for (let i = 0; i < hoverPts.length; i++) { for (let i = 0; i < hoverPts.length; i++) {
if (!hoverPts[i].distanceToRay) continue; if (!hoverPts[i].distanceToRay) continue;
@ -34,7 +40,7 @@ export function onHover(e) {
for (let x = 0; x < this.hovered.length; x++) { for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x] const obj = this.hovered[x]
if (obj && !this.selected.has(obj)) { if (obj && !this.selected.includes(obj)) {
obj.material.color.set(0x555555) obj.material.color.set(0x555555)
} }
} }
@ -42,7 +48,7 @@ export function onHover(e) {
for (let x = 0; x < idx.length; x++) { for (let x = 0; x < idx.length; x++) {
const i = idx[x] const i = idx[x]
hoverPts[i].object.material.color.set(0x00ff00) hoverPts[i].object.material.color.set(color.hover)
this.hovered.push(hoverPts[i].object) this.hovered.push(hoverPts[i].object)
} }
@ -54,7 +60,8 @@ export function onHover(e) {
for (let x = 0; x < this.hovered.length; x++) { for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x] const obj = this.hovered[x]
if (obj && !this.selected.has(obj)) { if (obj && !this.selected.includes(obj)) {
// console.log(obj)
obj.material.color.set(0x555555) obj.material.color.set(0x555555)
} }
} }
@ -72,21 +79,18 @@ export function onPick(e) {
if (this.hovered.length) { if (this.hovered.length) {
for (let x = 0; x < this.hovered.length; x++) { this.selected.push(this.hovered[this.hovered.length-1])
const obj = this.hovered[x]
this.selected.add(obj)
}
if (this.hovered[0].type == "Points") { if (this.hovered[0].type == "Points") {
this.domElement.addEventListener('pointermove', this.onDrag); this.canvas.addEventListener('pointermove', this.onDrag);
this.domElement.addEventListener('pointerup', this.onRelease) this.canvas.addEventListener('pointerup', this.onRelease)
} }
} else { } else {
for (let obj of this.selected) { for (let obj of this.selected) {
obj.material.color.set(0x555555) obj.material.color.set(0x555555)
} }
this.dispatchEvent({ type: 'change' }) this.dispatchEvent({ type: 'change' })
this.selected.clear() this.selected = []
} }
} }
@ -107,8 +111,8 @@ export function onDrag(e) {
export function onRelease() { export function onRelease() {
this.domElement.removeEventListener('pointermove', this.onDrag) this.canvas.removeEventListener('pointermove', this.onDrag)
this.domElement.removeEventListener('pointerup', this.onRelease) this.canvas.removeEventListener('pointerup', this.onRelease)
for (let x = 0; x < this.hovered.length; x++) { for (let x = 0; x < this.hovered.length; x++) {
const obj = this.hovered[x] const obj = this.hovered[x]

View File

@ -1,16 +1,7 @@
import * as THREE from '../../node_modules/three/src/Three'; import * as THREE from '../../node_modules/three/src/Three';
const lineMaterial = new THREE.LineBasicMaterial({
linewidth: 2,
color: 0x555555,
})
const pointMaterial = new THREE.PointsMaterial({
color: 0x555555,
size: 4,
})
const _vec2 = new THREE.Vector2() const _vec2 = new THREE.Vector2()
const _vec3 = new THREE.Vector3() const _vec3 = new THREE.Vector3()
@ -20,4 +11,40 @@ raycaster.params.Line.threshold = 0.8;
raycaster.params.Points.threshold = 1.5; raycaster.params.Points.threshold = 1.5;
export { lineMaterial, pointMaterial, _vec2, _vec3, raycaster } const color = {
dark1: 0x555555,
hover: 0x00ff00,
extrude: 0x156289,
emissive: 0x072534
}
const lineMaterial = new THREE.LineBasicMaterial({
linewidth: 2,
color: color.dark1,
})
const pointMaterial = new THREE.PointsMaterial({
color: color.dark1,
size: 4,
})
const ptObj = (n) => new THREE.Points(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(n || 3, 3)
),
pointMaterial.clone()
);
const lineObj = (n=1) => new THREE.Line(
new THREE.BufferGeometry().setAttribute('position',
new THREE.Float32BufferAttribute(3 * (n+1), 3)
),
lineMaterial.clone()
);
export { lineMaterial, pointMaterial, _vec2, _vec3, raycaster, color, ptObj, lineObj }

View File

@ -3,7 +3,7 @@ const path = require('path');
module.exports = { module.exports = {
entry: { entry: {
index: './src/index.js', index: './src/index.js',
renderer: './src/Renderer.js', scene: './src/Scene.js',
}, },
output: { output: {
filename: '[name].bundle.js', filename: '[name].bundle.js',