master
howard 2021-04-06 11:31:14 -07:00
parent b6bc0cb2e0
commit c7457f9c58
9 changed files with 176 additions and 253 deletions

View File

@ -14,6 +14,7 @@ import { onHover, onPick } from './utils/mouseEvents';
import { _vec2, _vec3, color, awaitPts } from './utils/shared' import { _vec2, _vec3, color, awaitPts } from './utils/shared'
import { Vector3 } from 'three/src/Three'; import { Vector3 } from 'three/src/Three';
import { AxesHelper } from './utils/axes' import { AxesHelper } from './utils/axes'
import { Patch } from './utils/patch'
import CSG from "./utils/three-csg.js" import CSG from "./utils/three-csg.js"
@ -37,13 +38,18 @@ export class Scene {
this.canvas = document.querySelector('#c'); this.canvas = document.querySelector('#c');
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas }); this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas });
const size = 1; const size = 1;
const near = 0; const near = 0;
const far = 100; const far = 100;
this.camera = new THREE.OrthographicCamera(-size, size, size, -size, near, far); this.camera = new THREE.OrthographicCamera(-size, size, size, -size, near, far);
this.camera.zoom = 0.1; this.camera.zoom = 0.1;
this.camera.position.set(50, 50, 50); const cameraDist = 50
const xzAngle = 30 * Math.PI / 180
this.camera.position.set(
cameraDist * Math.sin(xzAngle),
cameraDist * Math.tan(30 * Math.PI / 180),
cameraDist * Math.cos(xzAngle)
);
// const controls = new OrbitControls(camera, view1Elem); // const controls = new OrbitControls(camera, view1Elem);
const controls = new TrackballControls(this.camera, this.canvas); const controls = new TrackballControls(this.camera, this.canvas);
@ -52,19 +58,27 @@ export class Scene {
this.obj3d = new THREE.Scene() this.obj3d = new THREE.Scene()
this.obj3d.background = new THREE.Color(0x888888); this.obj3d.background = new THREE.Color(color.background);
const helpersGroup = new THREE.Group(); const helpersGroup = new THREE.Group();
helpersGroup.name = "helpersGroup"; helpersGroup.name = "helpersGroup";
this.obj3d.add(helpersGroup); this.obj3d.add(helpersGroup);
const axesHelper = new AxesHelper(0.4);
helpersGroup.add(axesHelper);
// console.log(color) // const axesHelper = new AxesHelper(0.4);
// helpersGroup.add(axesHelper);
const patch = new Patch(0.5);
helpersGroup.add(patch);
const planeGeom = new THREE.PlaneGeometry(5, 5)
const pxy = new THREE.Mesh( const pxy = new THREE.Mesh(
new THREE.PlaneGeometry(5, 5), planeGeom,
new THREE.MeshBasicMaterial({ new THREE.MeshBasicMaterial({
color: color.plane, color: color.plane,
opacity: 0.2, opacity: 0.05,
side: THREE.DoubleSide, side: THREE.DoubleSide,
transparent: true, transparent: true,
depthWrite: false, depthWrite: false,
@ -72,16 +86,22 @@ export class Scene {
}) })
); );
pxy.name = 'd' + nid++
pxy.userData.type = 'plane' pxy.userData.type = 'plane'
helpersGroup.add(pxy);
pxy.add(
new THREE.LineSegments(
new THREE.EdgesGeometry(planeGeom),
new THREE.LineBasicMaterial({ color: color.planeBorder })
)
)
const pyz = pxy.clone().rotateY(Math.PI / 2); const pyz = pxy.clone().rotateY(Math.PI / 2);
pyz.material = pyz.material.clone(); pyz.material = pyz.material.clone();
const pxz = pxy.clone().rotateX(-Math.PI / 2); const pxz = pxy.clone().rotateX(-Math.PI / 2);
pxz.material = pxz.material.clone(); pxz.material = pxz.material.clone();
helpersGroup.add(pxy);
helpersGroup.add(pyz); helpersGroup.add(pyz);
helpersGroup.add(pxz); helpersGroup.add(pxz);
@ -173,6 +193,20 @@ export class Scene {
this.store.dispatch({ type: 'restore-state', state }) this.store.dispatch({ type: 'restore-state', state })
} }
clearSelection() {
for (let x = 0; x < this.selected.length; x++) {
const obj = this.selected[x]
obj.material.color.set(color[obj.userData.type])
}
for (let x = 0; x < this.hovered.length; x++) {
const obj = this.selected[x]
obj.material.color.set(color[obj.userData.type])
}
this.obj3d.dispatchEvent({ type: 'change' })
this.selected = []
console.log('fireed')
}
} }
@ -249,7 +283,7 @@ async function addSketch() {
} }
this.clearSelection()
sketch.activate() sketch.activate()
this.activeSketch = sketch this.activeSketch = sketch

View File

@ -66,8 +66,9 @@ const App = () => {
const [_, forceUpdate] = useReducer(x => x + 1, 0); const [_, forceUpdate] = useReducer(x => x + 1, 0);
return <div className=''> return <>
<div className='absolute flex'> <div className='absolute flex ml-auto mr-auto left-0 right-0 justify-center'>
{/* <div className='absolute flex justify-center'> */}
{ {
btnz.map(([Icon, fcn, txt], idx) => ( btnz.map(([Icon, fcn, txt], idx) => (
<div className="btn flex items-center justify-start p-1 text-lg" key={idx} <div className="btn flex items-center justify-start p-1 text-lg" key={idx}
@ -80,13 +81,13 @@ const App = () => {
} }
</div> </div>
<div className='absolute left-0 top-10 w-40 flex flex-col'> <div className='absolute left-0 top-36 w-40 flex flex-col'>
{treeEntries.allIds.map((entId, idx) => ( {treeEntries.allIds.map((entId, idx) => (
<TreeEntry key={idx} entId={entId} /> <TreeEntry key={idx} entId={entId} />
))} ))}
</div> </div>
</div> </>
} }
@ -142,6 +143,7 @@ const TreeEntry = ({ entId }) => {
onClick={() => { onClick={() => {
activeSketchId && treeEntries[activeSketchId].deactivate() activeSketchId && treeEntries[activeSketchId].deactivate()
entry.activate() entry.activate()
sc.clearSelection()
sc.activeSketch = entry; sc.activeSketch = entry;
}} }}
> >

View File

@ -8,7 +8,7 @@ import { addDimension, setCoincident } from './constraintEvents'
import { get3PtArc } from './drawArc' import { get3PtArc } from './drawArc'
import { _vec2, _vec3, raycaster, awaitPts } from '../utils/shared' import { _vec2, _vec3, raycaster, awaitPts } from '../utils/shared'
import { replacer, reviver } from '../utils/mapJSONReplacer' import { replacer, reviver } from '../utils/mapJSONReplacer'
import { AxesHelper } from '../utils/axes' import { AxesHelper } from '../utils/sketchAxes'
import { drawDimension, _onMoveDimension, setDimLines, updateDim } from './drawDimension'; import { drawDimension, _onMoveDimension, setDimLines, updateDim } from './drawDimension';
@ -48,7 +48,7 @@ class Sketch {
this.constraints = new Map() this.constraints = new Map()
this.c_id = 0; this.c_id = 0;
this.obj3d.add(new THREE.Group().add(new AxesHelper(2))); this.obj3d.add(new THREE.Group().add(new AxesHelper(0.5)));
this.obj3d.add(new THREE.Group()); this.obj3d.add(new THREE.Group());
this.obj3d.add(new THREE.Group()); this.obj3d.add(new THREE.Group());
@ -134,6 +134,7 @@ class Sketch {
this.canvas.addEventListener('pointermove', this.onHover) this.canvas.addEventListener('pointermove', this.onHover)
this.store.dispatch({ type: 'set-active-sketch', sketch: this.obj3d.name }) this.store.dispatch({ type: 'set-active-sketch', sketch: this.obj3d.name })
this.setDimLines() this.setDimLines()
window.sketcher = this window.sketcher = this

View File

@ -1,212 +0,0 @@
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

@ -1,5 +1,5 @@
import * as THREE from 'three/src/Three'; import * as THREE from 'three/src/Three';
import { raycaster, color } from './shared'; import { raycaster, color, hoverColor } from './shared';
export function onHover(e) { export function onHover(e) {
if (this.mode || e.buttons) return if (this.mode || e.buttons) return
@ -38,19 +38,25 @@ export function onHover(e) {
// hoverPts = raycaster.intersectObjects(this.obj3d.children) // hoverPts = raycaster.intersectObjects(this.obj3d.children)
hoverPts = raycaster.intersectObjects(this.obj3d.children, true) hoverPts = raycaster.intersectObjects(this.obj3d.children, true)
// for (let i = 0; i < hoverPts.length; i++) {
// const obj = hoverPts[i].object
// if (obj.userData.type == "mesh" && obj.visible || obj.userData.type == "plane") {
// idx.push(i)
// }
// }
if (hoverPts.length) { if (hoverPts.length) {
// console.log(hoverPts) for (let i = 0; i < hoverPts.length; i++) {
if (!idx.length) idx.push(0) const obj = hoverPts[i].object
if (['point', 'plane'].includes(obj.userData.type)) {
idx.push(i)
break;
}
} }
if (!idx.length) {
const obj = hoverPts[0].object
if (obj.userData.type == "mesh" && obj.visible) {
idx.push(0)
} else {
idx.push(0)
}
}
}
@ -72,7 +78,7 @@ export function onHover(e) {
for (let x = 0; x < idx.length; x++) { for (let x = 0; x < idx.length; x++) {
const obj = hoverPts[idx[x]].object const obj = hoverPts[idx[x]].object
obj.material.color.set(color.hover) obj.material.color.set(hoverColor[obj.userData.type])
this.hovered.push(obj) this.hovered.push(obj)
} }
@ -81,7 +87,6 @@ export function onHover(e) {
} }
} else { // no hovered object after filtering } else { // no hovered object after filtering
if (this.hovered.length) { // if previously something was hovered, then we need to clear it if (this.hovered.length) { // if previously something was hovered, then we need to clear it
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]
// console.log(obj, 'here') // console.log(obj, 'here')

40
src/utils/patch.js Normal file
View File

@ -0,0 +1,40 @@
// import { LineSegments } from '../objects/LineSegments.js';
// import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
// import { Float32BufferAttribute } from '../core/BufferAttribute.js';
// import { BufferGeometry } from '../core/BufferGeometry.js';
import { LineSegments, MeshBasicMaterial, Float32BufferAttribute, BufferGeometry, Mesh, DoubleSide } from 'three/src/Three'
class Patch extends Mesh {
constructor(s = 1) {
const positions = [
0.5 * s, 0, 0,
0.3 * s, 0.08*s, 0,
0.3 * s, -0.08*s, 0
];
const geometry = new BufferGeometry();
geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
super(
geometry,
new MeshBasicMaterial({
color: 0x0000ff,
opacity: 0.2,
side: DoubleSide,
transparent: true,
depthWrite: false,
toneMapped: false
})
)
return this;
}
}
export { Patch };

View File

@ -12,16 +12,30 @@ raycaster.params.Points.threshold = 0.6;
const color = { const color = {
hover: 0x00ff00, background:0xbbbbbb,
lighting: 0xFFFFFF, lighting: 0xFFFFFF,
emissive: 0x072534, emissive: 0x072534,
hover: 0x00ff00,
point: 0x555555, //points point: 0x555555, //points
line: 0x555555, //lines line: 0x555555, //lines
mesh: 0x156289, //mesh: mesh: 0x156289, //mesh:
dimension: 0x891d15, // dimension: 0x891d15, //
plane: 0x891d15, //
plane: 0xdaacac, //
planeBorder: 0xc59797, //
} }
const hoverColor = {
hover: 0x00ff00,
point: 0x00ff00, //points
line: 0x00ff00, //lines
mesh: 0x00ff00, //mesh:
dimension: 0x00ff00, //
plane: 0xff0000, //
}
const lineMaterial = new THREE.LineBasicMaterial({ const lineMaterial = new THREE.LineBasicMaterial({
linewidth: 2, linewidth: 2,
color: color.line, color: color.line,
@ -129,4 +143,4 @@ async function awaitPts(...criteria) {
export { lineMaterial, pointMaterial, _vec2, _vec3, raycaster, color, ptObj, lineObj, awaitPts } export { lineMaterial, pointMaterial, _vec2, _vec3, raycaster, color, hoverColor, ptObj, lineObj, awaitPts }

34
src/utils/sketchAxes.js Normal file
View File

@ -0,0 +1,34 @@
// import { LineSegments } from '../objects/LineSegments.js';
// import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
// import { Float32BufferAttribute } from '../core/BufferAttribute.js';
// import { BufferGeometry } from '../core/BufferGeometry.js';
import { LineSegments, LineBasicMaterial, Float32BufferAttribute, BufferGeometry } from 'three/src/Three'
class AxesHelper extends LineSegments {
constructor(s = 1) {
const vertices = [
0, 0, 0, 0.5 * s, 0, 0,
0.5 * s, 0, 0, 0.35 * s, 0.08*s, 0,
0, 0, 0, 0, s, 0,
];
const geometry = new BufferGeometry();
geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
const material = new LineBasicMaterial({ color: 0xff0000, toneMapped: false });
super(geometry, material);
// this.type = 'AxesHelper';
}
}
export { AxesHelper };

View File

@ -1,10 +1,16 @@
fix css on design tree (a lot of work) \ fix css on design tree (a lot of work) \
clear dim on exit exit sketch / rehydrate when back or after loading \\\ done clear dim on exit exit sketch / rehydrate when back or after loading \\\ done
boolean flesh out refresh / replace mesh / delete mesh
- select sketch for extrusion
reattaching sketch
- need to auto hide ( consume) when new boolean created \\ - need to auto hide ( consume) when new boolean created \\
- create derived part using relationship as name \\ done
- sensible default names, like extrude 1, sketch 1, leverage react for this - sensible default names, like extrude 1, sketch 1, leverage react for this
boolean flesh out refresh / replace mesh / delete mesh
- create derived part using relationship as name \\ done
- hidden bodies messes up hover highlight \\ fixed - hidden bodies messes up hover highlight \\ fixed
- add for union and intersect - add for union and intersect
- auto update - auto update
@ -17,7 +23,6 @@ fix extrusion loop find
dimension to origin dimension to origin
reattaching sketch
file save file save
stl export stl export