working 3d hover

master
howard 2021-03-29 22:13:13 -07:00
parent 254cf7c5c3
commit 1a602c5f58
6 changed files with 198 additions and 79 deletions

View File

@ -8,9 +8,17 @@ import { Sketcher } from './sketcher/Sketcher'
import Stats from './utils/stats.module.js';
import { add3DPoint } from './datums'
import {extrude} from './sketcher/extrude'
import { extrude } from './sketcher/extrude'
import { onHover } from './mouseEvents';
// class Scene extends THREE.Scene {
// constructor() {
// }
// }
export function Renderer(store) {
this.store = store
@ -29,7 +37,7 @@ export function Renderer(store) {
// this.scene.background = new THREE.Color(0xffffff);
const helpersGroup = new THREE.Group();
helpersGroup.name= "helpersGroup"
helpersGroup.name = "helpersGroup"
this.scene.add(helpersGroup);
const axesHelper = new THREE.AxesHelper(5);
helpersGroup.add(axesHelper);
@ -46,8 +54,6 @@ export function Renderer(store) {
controls.target.set(0, 0, 0);
controls.update()
const color = 0xFFFFFF;
const intensity = 1;
const light1 = new THREE.DirectionalLight(color, intensity);
@ -61,54 +67,6 @@ export function Renderer(store) {
this.scene.add(ambient);
// this.defaultPlanes = [
// new THREE.Plane(new THREE.Vector3(0, 0, 1), 0),
// new THREE.Plane(new THREE.Vector3(0, 1, 0), 0),
// new THREE.Plane(new THREE.Vector3(1, 0, 0), 0),
// ]
// this.defaultPlanes.forEach(pl => {
// const helper = new THREE.PlaneHelper(pl, 10, 0xffffff)
// this.scene.add(helper);
// })
const unsubscribe = store.subscribe(handleChange.bind(this))
let state;
function handleChange() {
let prevState = state
state = store.getState()
// if (prevState.sketches.length < state.sketches.length) {
// }
// if (state.toggle) {
// window.addEventListener('keydown', this.sketcher.onKeyPress)
// canvas.addEventListener('pointerdown', this.sketcher.onPick)
// canvas.addEventListener('pointermove', this.sketcher.onHover)
// canvas.removeEventListener('pointerdown', this.add3DPoint)
// } else {
// window.removeEventListener('keydown', this.sketcher.onKeyPress)
// canvas.removeEventListener('pointerdown', this.sketcher.onPick)
// canvas.removeEventListener('pointermove', this.sketcher.onHover)
// canvas.addEventListener('pointerdown', this.add3DPoint)
// }
}
this.hovered = []
this.selected = new Set()
@ -116,7 +74,8 @@ export function Renderer(store) {
this.resizeCanvas = resizeCanvas.bind(this)
this.addSketch = addSketch.bind(this)
this.extrude = extrude.bind(this)
// this.waitPoint = waitPoint.bind(this)
this.onHover = onHover.bind(this);
controls.addEventListener('change', this.render);
controls.addEventListener('start', this.render);
@ -169,12 +128,10 @@ async function addSketch() {
window.sketcher = sketcher
this.render()
this.store.dispatch({ type: 'rx-sketch', obj:sketcher })
this.store.dispatch({ type: 'rx-sketch', obj: sketcher })
}
function getPoint(e, camera) {
const mouse = new THREE.Vector2(
(e.clientX / window.innerWidth) * 2 - 1,

View File

@ -1,6 +1,6 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import './app.scss'
import { Provider, useDispatch, useSelector } from 'react-redux'
@ -12,25 +12,52 @@ export const Root = ({ store }) => (
</Provider>
);
function treeId2Obj(id) {
return renderInst.scene.getObjectById(parseInt(id.slice(1)))
}
const App = () => {
const dispatch = useDispatch()
const treeEntries = useSelector(state => state.treeEntries)
const activeSketch = useSelector(state => state.activeSketch)
// const [state, setState] = useState('x')
// useEffect(()=>{
// console.log('hereeee')
// },[state])
useEffect(() => {
if (!activeSketch) {
renderInst.canvas.addEventListener('pointermove', renderInst.onHover)
return () => renderInst.canvas.removeEventListener('pointermove', renderInst.onHover)
}
}, [activeSketch])
return <>
<div className='buttons-group'>
<button onClick={() => dispatch({ type: 'toggle', payload: true })}> true</button>
<button onClick={() => dispatch({ type: 'toggle', payload: false })}> false </button>
{activeSketch ?
<button onClick={() => treeId2Obj(activeSketch).deactivate()}>
Exit sketch
</button> :
<button onClick={renderInst.addSketch}> addsketch </button>
<button onClick={()=>renderInst.extrude(4)}> extrude </button>
}
<button onClick={() => renderInst.extrude(treeId2Obj(activeSketch))}> extrude </button>
{/* <button onClick={() => setState('')}> test </button> */}
</div>
<div className='feature-tree'>
{treeEntries.allIds.map((entId, idx) => (
<div key={idx}
onClick={()=>{
renderInst.extrude(treeEntries.byId[entId])
}}
onClick={() => {
if (activeSketch) {
treeId2Obj(activeSketch).deactivate()
}
treeId2Obj(entId).activate()
}
}
>{entId}</div>
))}
</div>

View File

@ -21,7 +21,14 @@ function reducer(state = {}, action) {
byId: { ...state.treeEntries.byId, [id]: action.obj },
allIds: [...state.treeEntries.allIds, id]
},
env: id
}
case 'set-active-sketch':
return {
...state, activeSketch:'s'+action.sketch.id
}
case 'exit-sketch':
return {
...state, activeSketch:''
}
case 'rx-extrusion':
id = 'e' + action.mesh.id
@ -36,8 +43,6 @@ function reducer(state = {}, action) {
['s' + action.sketch.id]: id
}
}
case 'incsk':
return { ...state, id: _sketchID++ }
default:
return state
}

120
src/mouseEvents.js Normal file
View File

@ -0,0 +1,120 @@
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,7 +3,7 @@
import * as THREE from '../../node_modules/three/src/Three';
import { drawOnClick1, drawOnClick2, drawPreClick2, drawClear } from './drawEvents'
import { onHover, onDrag, onPick, onRelease } from './pickEvents'
import { onHover, onDrag, onPick, onRelease } from './sketchMouseEvents'
import { addDimension, setCoincident } from './constraintEvents'
import { get3PtArc } from './sketchArc'
import { extrude } from './extrude'
@ -18,6 +18,7 @@ class Sketcher extends THREE.Group {
constructor(camera, domElement, store) {
super()
this.name = "sketch"
this.matrixAutoUpdate = false;
this.camera = camera;
this.domElement = domElement;
this.store = store;
@ -43,7 +44,17 @@ class Sketcher extends THREE.Group {
this.c_id = 0;
this.constraintsBuf = new Float32Array(this.max_constraints * 6).fill(NaN)
this.bindHandlers()
this.selected = new Set()
this.hovered = []
this.mode = ""
this.subsequent = false;
}
bindHandlers() {
this.drawOnClick1 = drawOnClick1.bind(this);
this.drawPreClick2 = drawPreClick2.bind(this);
this.drawOnClick2 = drawOnClick2.bind(this);
@ -54,21 +65,21 @@ class Sketcher extends THREE.Group {
this.onRelease = onRelease.bind(this);
this.onKeyPress = this.onKeyPress.bind(this);
this.matrixAutoUpdate = false;
this.selected = new Set()
this.hovered = []
this.mode = ""
this.subsequent = false;
}
activate() {
window.addEventListener('keydown', this.onKeyPress)
this.domElement.addEventListener('pointerdown', this.onPick)
this.domElement.addEventListener('pointermove', this.onHover)
this.store.dispatch({ type: 'set-active-sketch', sketch: this })
}
deactivate() {
window.removeEventListener('keydown', this.onKeyPress)
this.domElement.removeEventListener('pointerdown', this.onPick)
this.domElement.removeEventListener('pointermove', this.onHover)
this.store.dispatch({ type: 'exit-sketch' })
}
@ -224,7 +235,6 @@ class Sketcher extends THREE.Group {
}
updatePointsBuffer(startingIdx = 0) {
for (let i = startingIdx; i < this.children.length; i++) {
const obj = this.children[i]

View File

@ -1,4 +1,4 @@
import * as THREE from '../../node_modules/three/src/Three';
import * as THREE from 'three/src/Three';
import {raycaster} from '../utils/static';
export function onHover(e) {