update three-viewer
fix model position and scale fix obj loader
This commit is contained in:
parent
f0e364243e
commit
f0035fda0a
5 changed files with 98 additions and 58 deletions
|
@ -4,6 +4,7 @@ import LoadingScreen from 'component/common/loading-screen';
|
||||||
// ThreeJS
|
// ThreeJS
|
||||||
import * as THREE from './internal/three';
|
import * as THREE from './internal/three';
|
||||||
import detectWebGL from './internal/detector';
|
import detectWebGL from './internal/detector';
|
||||||
|
import ThreeGrid from './internal/grid';
|
||||||
import ThreeScene from './internal/scene';
|
import ThreeScene from './internal/scene';
|
||||||
import ThreeLoader from './internal/loader';
|
import ThreeLoader from './internal/loader';
|
||||||
import ThreeRenderer from './internal/renderer';
|
import ThreeRenderer from './internal/renderer';
|
||||||
|
@ -77,6 +78,12 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
window.removeEventListener('resize', this.handleResize, false);
|
window.removeEventListener('resize', this.handleResize, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transformGroup(group) {
|
||||||
|
this.fitMeshToCamera(group);
|
||||||
|
this.createWireFrame(group);
|
||||||
|
this.updateControlsTarget(group.position);
|
||||||
|
}
|
||||||
|
|
||||||
createOrbitControls(camera, canvas) {
|
createOrbitControls(camera, canvas) {
|
||||||
const { autoRotate } = this.props;
|
const { autoRotate } = this.props;
|
||||||
const controls = new THREE.OrbitControls(camera, canvas);
|
const controls = new THREE.OrbitControls(camera, canvas);
|
||||||
|
@ -87,6 +94,7 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
controls.minDistance = 1;
|
controls.minDistance = 1;
|
||||||
controls.maxDistance = 50;
|
controls.maxDistance = 50;
|
||||||
controls.autoRotate = autoRotate;
|
controls.autoRotate = autoRotate;
|
||||||
|
controls.enablePan = false;
|
||||||
return controls;
|
return controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,32 +122,6 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
group.add(this.wireframe);
|
group.add(this.wireframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
createMesh(geometry) {
|
|
||||||
const material = new THREE.MeshPhongMaterial({
|
|
||||||
opacity: 1,
|
|
||||||
transparent: true,
|
|
||||||
depthWrite: true,
|
|
||||||
vertexColors: THREE.FaceColors,
|
|
||||||
// Positive value pushes polygon further away
|
|
||||||
polygonOffsetFactor: 1,
|
|
||||||
polygonOffsetUnits: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set material color
|
|
||||||
material.color.set(this.materialColors.green);
|
|
||||||
|
|
||||||
const mesh = new THREE.Mesh(geometry, material);
|
|
||||||
|
|
||||||
// Assign name
|
|
||||||
mesh.name = 'objectGroup';
|
|
||||||
|
|
||||||
this.scene.add(mesh);
|
|
||||||
this.fitMeshToCamera(mesh);
|
|
||||||
this.createWireFrame(mesh);
|
|
||||||
this.updateControlsTarget(mesh.position);
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleWireFrame(show = false) {
|
toggleWireFrame(show = false) {
|
||||||
this.wireframe.opacity = show ? 1 : 0;
|
this.wireframe.opacity = show ? 1 : 0;
|
||||||
this.mesh.material.opacity = show ? 0 : 1;
|
this.mesh.material.opacity = show ? 0 : 1;
|
||||||
|
@ -151,7 +133,7 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
|
|
||||||
group.traverse(child => {
|
group.traverse(child => {
|
||||||
if (child instanceof THREE.Mesh) {
|
if (child instanceof THREE.Mesh) {
|
||||||
const box = new THREE.Box3().setFromObject(group);
|
const box = new THREE.Box3().setFromObject(child);
|
||||||
// Max
|
// Max
|
||||||
max.x = box.max.x > max.x ? box.max.x : max.x;
|
max.x = box.max.x > max.x ? box.max.x : max.x;
|
||||||
max.y = box.max.y > max.y ? box.max.y : max.y;
|
max.y = box.max.y > max.y ? box.max.y : max.y;
|
||||||
|
@ -165,12 +147,18 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
|
|
||||||
const meshY = Math.abs(max.y - min.y);
|
const meshY = Math.abs(max.y - min.y);
|
||||||
const meshX = Math.abs(max.x - min.x);
|
const meshX = Math.abs(max.x - min.x);
|
||||||
const scaleFactor = 15 / Math.max(meshX, meshY);
|
|
||||||
|
const scaleFactor = 10 / Math.max(meshX, meshY);
|
||||||
|
|
||||||
group.scale.set(scaleFactor, scaleFactor, scaleFactor);
|
group.scale.set(scaleFactor, scaleFactor, scaleFactor);
|
||||||
group.position.setY((meshY / 2) * scaleFactor);
|
group.position.setY((meshY / 2) * scaleFactor);
|
||||||
|
|
||||||
|
// Reset object position
|
||||||
|
const box = new THREE.Box3().setFromObject(group);
|
||||||
|
box.getCenter(group.position);
|
||||||
|
|
||||||
group.position.multiplyScalar(-1);
|
group.position.multiplyScalar(-1);
|
||||||
group.position.setY((meshY * scaleFactor) / 2);
|
group.position.setY(group.position.y + meshY * scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
startLoader() {
|
startLoader() {
|
||||||
|
@ -217,12 +205,52 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
this.controls.update();
|
this.controls.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderModel(fileType, data) {
|
renderStl(data) {
|
||||||
const geometry = this.createGeometry(data);
|
const geometry = this.createGeometry(data);
|
||||||
this.mesh = this.createMesh(geometry);
|
const group = new THREE.Mesh(geometry, this.material);
|
||||||
|
// Assign name
|
||||||
|
group.name = 'objectGroup';
|
||||||
|
this.scene.add(group);
|
||||||
|
this.transformGroup(group);
|
||||||
|
this.mesh = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderObj(event) {
|
||||||
|
const mesh = event.detail.loaderRootNode;
|
||||||
|
const group = new THREE.Group();
|
||||||
|
group.name = 'objGroup';
|
||||||
|
|
||||||
|
// Assign new material
|
||||||
|
mesh.traverse(child => {
|
||||||
|
if (child instanceof THREE.Mesh) {
|
||||||
|
// Get geometry from child
|
||||||
|
const geometry = new THREE.Geometry();
|
||||||
|
geometry.fromBufferGeometry(child.geometry);
|
||||||
|
// Create and regroup inner objects
|
||||||
|
const innerObj = new THREE.Mesh(geometry, this.material);
|
||||||
|
group.add(innerObj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.scene.add(group);
|
||||||
|
this.transformGroup(group);
|
||||||
|
this.mesh = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderModel(fileType, parsedData) {
|
||||||
|
const renderTypes = {
|
||||||
|
stl: data => this.renderStl(data),
|
||||||
|
obj: data => this.renderObj(data),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (renderTypes[fileType]) {
|
||||||
|
renderTypes[fileType](parsedData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderScene() {
|
renderScene() {
|
||||||
|
const { gridColor, centerLineColor } = this.theme;
|
||||||
|
|
||||||
this.renderer = ThreeRenderer({
|
this.renderer = ThreeRenderer({
|
||||||
antialias: true,
|
antialias: true,
|
||||||
shadowMap: true,
|
shadowMap: true,
|
||||||
|
@ -230,20 +258,40 @@ class ThreeViewer extends React.PureComponent<Props> {
|
||||||
|
|
||||||
this.scene = ThreeScene({
|
this.scene = ThreeScene({
|
||||||
showFog: true,
|
showFog: true,
|
||||||
showGrid: true,
|
|
||||||
...this.theme,
|
...this.theme,
|
||||||
});
|
});
|
||||||
|
|
||||||
const viewer = this.viewer.current;
|
const viewer = this.viewer.current;
|
||||||
const canvas = this.renderer.domElement;
|
const canvas = this.renderer.domElement;
|
||||||
const { offsetWidth: width, offsetHeight: height } = viewer;
|
const { offsetWidth: width, offsetHeight: height } = viewer;
|
||||||
|
|
||||||
|
// Grid
|
||||||
|
this.grid = ThreeGrid({ size: 100, gridColor, centerLineColor });
|
||||||
|
this.scene.add(this.grid);
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
this.camera = new THREE.PerspectiveCamera(80, width / height, 0.1, 1000);
|
this.camera = new THREE.PerspectiveCamera(80, width / height, 0.1, 1000);
|
||||||
this.camera.position.set(-9.5, 14, 11);
|
this.camera.position.set(-9.5, 14, 11);
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
this.controls = this.createOrbitControls(this.camera, canvas);
|
this.controls = this.createOrbitControls(this.camera, canvas);
|
||||||
|
|
||||||
// Set viewer size
|
// Set viewer size
|
||||||
this.renderer.setSize(width, height);
|
this.renderer.setSize(width, height);
|
||||||
|
|
||||||
|
// Create model material
|
||||||
|
this.material = new THREE.MeshPhongMaterial({
|
||||||
|
opacity: 1,
|
||||||
|
transparent: true,
|
||||||
|
// depthWrite: true,
|
||||||
|
vertexColors: THREE.FaceColors,
|
||||||
|
// Positive value pushes polygon further away
|
||||||
|
// polygonOffsetFactor: 1,
|
||||||
|
// polygonOffsetUnits: 1,
|
||||||
|
});
|
||||||
|
// Set material color
|
||||||
|
this.material.color.set(this.materialColors.green);
|
||||||
|
|
||||||
// Load file and render mesh
|
// Load file and render mesh
|
||||||
this.startLoader();
|
this.startLoader();
|
||||||
|
|
||||||
|
|
13
src/renderer/component/viewers/threeViewer/internal/grid.js
Normal file
13
src/renderer/component/viewers/threeViewer/internal/grid.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { GridHelper, Color } from './three';
|
||||||
|
|
||||||
|
const ThreeGrid = ({ size, gridColor, centerLineColor }) => {
|
||||||
|
const divisions = size / 2;
|
||||||
|
const grid = new GridHelper(size, divisions, new Color(centerLineColor), new Color(gridColor));
|
||||||
|
|
||||||
|
grid.material.opacity = 0.4;
|
||||||
|
grid.material.transparent = true;
|
||||||
|
|
||||||
|
return grid;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThreeGrid;
|
|
@ -1,4 +1,4 @@
|
||||||
import { LoadingManager, STLLoader, OBJLoader } from './three';
|
import { LoadingManager, STLLoader, OBJLoader2 } from './three';
|
||||||
|
|
||||||
const Manager = ({ onLoad, onStart, onError }) => {
|
const Manager = ({ onLoad, onStart, onError }) => {
|
||||||
const manager = new LoadingManager();
|
const manager = new LoadingManager();
|
||||||
|
@ -12,7 +12,7 @@ const Manager = ({ onLoad, onStart, onError }) => {
|
||||||
const Loader = (fileType, manager) => {
|
const Loader = (fileType, manager) => {
|
||||||
const fileTypes = {
|
const fileTypes = {
|
||||||
stl: () => new STLLoader(manager),
|
stl: () => new STLLoader(manager),
|
||||||
obj: () => new OBJLoader(manager),
|
obj: () => new OBJLoader2(manager),
|
||||||
};
|
};
|
||||||
return fileTypes[fileType] ? fileTypes[fileType]() : null;
|
return fileTypes[fileType] ? fileTypes[fileType]() : null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,18 +1,5 @@
|
||||||
import * as THREE from './three';
|
import * as THREE from './three';
|
||||||
|
|
||||||
const addGrid = (scene, { gridColor, centerLineColor, size }) => {
|
|
||||||
const divisions = size / 2;
|
|
||||||
const grid = new THREE.GridHelper(
|
|
||||||
size,
|
|
||||||
divisions,
|
|
||||||
new THREE.Color(centerLineColor),
|
|
||||||
new THREE.Color(gridColor)
|
|
||||||
);
|
|
||||||
grid.material.opacity = 0.4;
|
|
||||||
grid.material.transparent = true;
|
|
||||||
scene.add(grid);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addLights = (scene, color, groundColor) => {
|
const addLights = (scene, color, groundColor) => {
|
||||||
// Light color
|
// Light color
|
||||||
const lightColor = new THREE.Color(color);
|
const lightColor = new THREE.Color(color);
|
||||||
|
@ -30,7 +17,7 @@ const addLights = (scene, color, groundColor) => {
|
||||||
scene.add(shadowLight);
|
scene.add(shadowLight);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Scene = ({ backgroundColor, groundColor, showFog, showGrid, gridColor, centerLineColor }) => {
|
const Scene = ({ backgroundColor, groundColor, showFog }) => {
|
||||||
// Convert color
|
// Convert color
|
||||||
const bgColor = new THREE.Color(backgroundColor);
|
const bgColor = new THREE.Color(backgroundColor);
|
||||||
// New scene
|
// New scene
|
||||||
|
@ -39,17 +26,8 @@ const Scene = ({ backgroundColor, groundColor, showFog, showGrid, gridColor, cen
|
||||||
scene.background = bgColor;
|
scene.background = bgColor;
|
||||||
// Fog effect
|
// Fog effect
|
||||||
scene.fog = showFog === true ? new THREE.Fog(bgColor, 1, 95) : null;
|
scene.fog = showFog === true ? new THREE.Fog(bgColor, 1, 95) : null;
|
||||||
// Add grid
|
|
||||||
if (showGrid) {
|
|
||||||
addGrid(scene, {
|
|
||||||
size: 100,
|
|
||||||
gridColor,
|
|
||||||
centerLineColor,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Add basic lights
|
// Add basic lights
|
||||||
addLights(scene, '#FFFFFF', groundColor);
|
addLights(scene, '#FFFFFF', groundColor);
|
||||||
|
|
||||||
// Return new three scene
|
// Return new three scene
|
||||||
return scene;
|
return scene;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,8 @@ import * as THREE from 'three';
|
||||||
// Fix: https://github.com/mrdoob/three.js/issues/9562#issuecomment-383390251
|
// Fix: https://github.com/mrdoob/three.js/issues/9562#issuecomment-383390251
|
||||||
global.THREE = THREE;
|
global.THREE = THREE;
|
||||||
require('three/examples/js/controls/OrbitControls');
|
require('three/examples/js/controls/OrbitControls');
|
||||||
require('three/examples/js/loaders/OBJLoader');
|
require('three/examples/js/loaders/LoaderSupport');
|
||||||
|
require('three/examples/js/loaders/OBJLoader2');
|
||||||
require('three/examples/js/loaders/STLLoader');
|
require('three/examples/js/loaders/STLLoader');
|
||||||
|
|
||||||
module.exports = global.THREE;
|
module.exports = global.THREE;
|
||||||
|
|
Loading…
Reference in a new issue