update three-viewer

fix model position and scale

fix obj loader
This commit is contained in:
btzr-io 2018-07-19 19:31:00 -06:00
parent f0e364243e
commit f0035fda0a
5 changed files with 98 additions and 58 deletions

View file

@ -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();

View 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;

View file

@ -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;
}; };

View file

@ -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;
}; };

View file

@ -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;