Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, {Component} from "react";
- import * as THREE from "three";
- import * as OrbitControls from 'three-orbitcontrols';
- import MTLLoader from "../../three/MTLLoader";
- import OBJLoader from "../../three/OBJLoader";
- import MeshUpload from "../MeshUpload/MeshUpload";
- import Spinner from 'react-spinkit';
- import './Viewer.css';
- const promisifyLoad = (loader) => {
- function onProgress(xhr) {
- }
- return url => new Promise((resolve, reject) => {
- loader.load(url, resolve, onProgress, reject);
- });
- };
- class Viewer extends Component {
- state = {
- view_angle: 10,
- near: 1,
- far: 10000000,
- z_position: 1000,
- count: 0,
- OBJmaterials: null,
- count_parent: 0,
- };
- componentDidMount() {
- this.init();
- }
- init = () => {
- const {width, height} = this.getRendererSize();
- this.scene = new THREE.Scene();
- this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
- this.renderer.setPixelRatio(window.devicePixelRatio);
- this.renderer.setSize(width, height);
- this.renderer.autoClear = false;
- this.root.appendChild(this.renderer.domElement);
- this.root.children[0].style.display = "none";
- this.camera = new THREE.PerspectiveCamera(this.state.view_angle, width / height, this.state.near, this.state.far);
- this.camera.position.z = this.state.z_position;
- this.controls = new OrbitControls(this.camera, this.renderer.domElement);
- this.controls.enableZoom = true;
- this.controls.enablePan = false;
- this.controls.minDistance= 600;
- this.controls.maxDistance= 1500;
- this.controls.minPolarAngle = 1;
- this.controls.maxPolarAngle = 2.4;
- this.props.onUpload();
- let ambientLight = new THREE.AmbientLight(0xeeeeee); // soft white light
- this.scene.add(ambientLight);
- this.light = new THREE.DirectionalLight(0xeeeeee, 1);
- this.light.position.set( -1, 1.5, 1).normalize();
- this.scene.add(this.light);
- };
- renderScene = () => {
- this.controls.update();
- this.renderer.render(this.scene, this.camera);
- };
- handleResize = () => {
- const {width, height} = this.getRendererSize();
- this.camera.aspect = width / height;
- this.camera.updateProjectionMatrix();
- this.renderer.setSize(width, height);
- this.resizeOBJ();
- };
- animate = () => {
- requestAnimationFrame(this.animate);
- this.renderScene();
- if(this.root.children[0].style.display === "none"){
- this.spin.style.display = "none";
- this.root.children[0].style.display = "";
- this.uris.pieces.forEach(piece => {
- if(('' + piece.reference).toLowerCase() === this.uris.parent_reference){
- this.applyTexture(piece);
- }
- });
- window.addEventListener('resize', this.handleResize);
- }
- if(this.state.count === 0) {
- this.resizeOBJ();
- }
- };
- resizeOBJ = () => {
- const {width, height} = this.getRendererSize();
- let maxSizeBox = Math.max(this.pixelCoordScale(this.model, width, height).x, this.pixelCoordScale(this.model, width, height).y);
- let minSizeBox = Math.min(this.pixelCoordScale(this.model, width, height).x, this.pixelCoordScale(this.model, width, height).y);
- let windowDim;
- maxSizeBox === this.pixelCoordScale(this.model, width, height).x ? windowDim = (width - 40) : windowDim = (height - 40);
- this.model.position.multiplyScalar(0);
- if (maxSizeBox > windowDim) {
- let scale = (this.model.scale.x * windowDim) / maxSizeBox;
- this.model.scale.set(scale, scale, scale);
- } else {
- if(this.pixelCoordScale(this.model, width, height).x > width || this.pixelCoordScale(this.model, width, height).y > height) {
- let scale = (this.model.scale.x * windowDim) / maxSizeBox;
- let diference = maxSizeBox / minSizeBox;
- scale = scale - ((diference * 1.15)/10);
- this.model.scale.set(scale, scale, scale);
- this.setState({count: 1});
- }
- this.setState({count: 1});
- }
- let box = new THREE.Box3().setFromObject(this.model);
- box.getCenter(this.model.position);
- this.model.worldToLocal(box);
- this.model.position.multiplyScalar(-1);
- window.scrollTo(0, 0);
- };
- loadMaterial(materialUri, textures) {
- const mtlLoader = new MTLLoader();
- const texturePathMap = {};
- textures.forEach(texture => {
- texturePathMap[texture.name] = texture.uri;
- });
- mtlLoader.setMaterialOptions({texturePathMap, side: THREE.DoubleSide});
- return promisifyLoad(mtlLoader)(materialUri)
- .then((materials) => {
- materials.preload();
- this.materialsload = materials;
- return materials;
- });
- }
- getRendererSize() {
- let containerWidth = document.getElementById('sectionLine').getBoundingClientRect().width;
- let canvasHeight = (containerWidth * 9) / 16;
- const width = containerWidth;
- const height = canvasHeight;
- return {width, height};
- }
- loadObject(objectUri, materials) {
- const objLoader = new OBJLoader();
- objLoader.setMaterials(materials);
- return promisifyLoad(objLoader)(objectUri);
- }
- computeScreenSpaceBoundingBox = (mesh, camera) => {
- let vertices = [];
- for (let i = 0; i < this.model.children.length; i++) {
- let geometry = new THREE.Geometry().fromBufferGeometry( this.model.children[i].geometry);
- vertices.length === 0 ? vertices = geometry.vertices : vertices = vertices.concat(geometry.vertices);
- }
- let vertex = new THREE.Vector3();
- let min = new THREE.Vector3(1);
- let max = new THREE.Vector3(-1);
- for (let i = 0; i < vertices.length; i++) {
- let vertexWorldCoord = vertex.copy(vertices[i]).applyMatrix4(mesh.matrixWorld);
- let vertexScreenSpace = vertexWorldCoord.project(camera);
- min.min(vertexScreenSpace);
- max.max(vertexScreenSpace);
- }
- return new THREE.Box2(min, max);
- };
- normalizedToPixels = (coord, renderWidthPixels, renderHeightPixels) => {
- let halfScreen = new THREE.Vector2(renderWidthPixels/2, renderHeightPixels/2);
- return coord.clone().multiply(halfScreen);
- };
- pixelCoordScale = (model, width, height) => {
- let boundingBox2D = this.computeScreenSpaceBoundingBox(model, this.camera);
- let pixelCoordScale = this.normalizedToPixels(boundingBox2D.getSize(model.position), width, height);
- return pixelCoordScale;
- };
- loop = (mesh) => {
- mesh.children.forEach(mesh => {
- let meshName = mesh.name.substring(mesh.name.search('_'), mesh.name.length);
- if(meshName === '___snap' || meshName === '___collision'){
- mesh.visible = false;
- }
- if(meshName === '___shadow'){
- mesh.side = 1;
- }
- })
- };
- applyTexture = (pieceComplete) => {
- pieceComplete.model.metadata.materials.forEach(material => {
- Object.keys(pieceComplete.model.options).forEach(piece => {
- if(material.label === piece){
- material.textures.forEach( texture => {
- if(pieceComplete.model.options[piece] === texture.index) {
- this.uris.textures.forEach(allTexture => {
- if(texture.filename === allTexture.name){
- if(!this.materialsload.materials[material.id].map.image) {
- return;
- }
- this.materialsload.materials[material.id].map.image.src = allTexture.uri;
- }
- });
- }
- });
- }
- });
- });
- };
- frames = (textures) =>{
- let bundleFrames = [];
- textures.forEach(texture => {
- if(texture.name.substring(0,'frame'.length) === 'frame'){
- bundleFrames.push(texture);
- }
- });
- return(bundleFrames);
- };
- addObject = (object) => {
- let objectsHide = [];
- object.children.forEach(objectHide => {
- if((objectHide.name.substring(objectHide.name.length -4, objectHide.name.length)).toLowerCase() === 'hide'){
- objectsHide.push(objectHide);
- }
- });
- let bundle = [this.uris, this.controls, this.materialsload, objectsHide, this.frames(this.uris.textures)];
- this.props.onUpload(bundle);
- if (this.model) {
- this.scene.remove(this.model);
- }
- this.loop(object);
- const mesh = object.children[0];
- for(let i=0; i < object.children.length; i++) {
- if(object.children[i]['name'].search('shadow') > 1) {
- object.children[i].material.side = 3;
- }
- }
- mesh.material.side = THREE.DoubleSide;
- this.model = object;
- this.scene.add(this.model);
- this.model.rotation.set(.25, -.25, 0);
- let box1 = new THREE.Box3().setFromObject(this.model);
- box1.getCenter(this.model.position);
- this.model.localToWorld(box1);
- this.model.position.multiplyScalar(-1);
- };
- load = ({objectUri, materialUri, textures, cleanup}) => {
- let loadMaterialPromise = Promise.resolve(null);
- if (materialUri) {
- loadMaterialPromise = this.loadMaterial(materialUri, textures);
- }
- return loadMaterialPromise
- .then(materials => this.loadObject(objectUri, materials))
- .then(this.addObject)
- .then(cleanup);
- };
- onLoadError = (...args) => {
- console.error(args);
- };
- handleUpload = (uris) => {
- this.uris = uris;
- this.load(uris)
- .then(() => this.animate())
- .catch(this.onLoadError);
- };
- render() {
- return (
- <div>
- <div className={"load"}
- ref={(spin) => {
- this.spin = spin;
- }}>
- <Spinner name="ball-spin-fade-loader" />
- </div>
- <MeshUpload onUpload={this.handleUpload} params={this.props.model.params}/>
- <div
- className={"Viewer"}
- ref={(root) => {
- this.root = root;
- }}>
- </div>
- </div>
- );
- }
- }
- export default Viewer;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement