Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2018
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.08 KB | None | 0 0
  1. import React, {Component} from "react";
  2.  
  3. import * as THREE from "three";
  4. import * as OrbitControls from 'three-orbitcontrols';
  5.  
  6. import MTLLoader from "../../three/MTLLoader";
  7. import OBJLoader from "../../three/OBJLoader";
  8.  
  9. import MeshUpload from "../MeshUpload/MeshUpload";
  10. import Spinner from 'react-spinkit';
  11. import './Viewer.css';
  12.  
  13. const promisifyLoad = (loader) => {
  14. function onProgress(xhr) {
  15. }
  16.  
  17. return url => new Promise((resolve, reject) => {
  18. loader.load(url, resolve, onProgress, reject);
  19. });
  20. };
  21.  
  22. class Viewer extends Component {
  23. state = {
  24. view_angle: 10,
  25. near: 1,
  26. far: 10000000,
  27. z_position: 1000,
  28. count: 0,
  29. OBJmaterials: null,
  30. count_parent: 0,
  31. };
  32.  
  33. componentDidMount() {
  34. this.init();
  35. }
  36.  
  37. init = () => {
  38. const {width, height} = this.getRendererSize();
  39.  
  40. this.scene = new THREE.Scene();
  41.  
  42. this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
  43. this.renderer.setPixelRatio(window.devicePixelRatio);
  44. this.renderer.setSize(width, height);
  45. this.renderer.autoClear = false;
  46. this.root.appendChild(this.renderer.domElement);
  47. this.root.children[0].style.display = "none";
  48.  
  49. this.camera = new THREE.PerspectiveCamera(this.state.view_angle, width / height, this.state.near, this.state.far);
  50. this.camera.position.z = this.state.z_position;
  51.  
  52. this.controls = new OrbitControls(this.camera, this.renderer.domElement);
  53. this.controls.enableZoom = true;
  54. this.controls.enablePan = false;
  55.  
  56. this.controls.minDistance= 600;
  57. this.controls.maxDistance= 1500;
  58.  
  59. this.controls.minPolarAngle = 1;
  60. this.controls.maxPolarAngle = 2.4;
  61.  
  62. this.props.onUpload();
  63.  
  64. let ambientLight = new THREE.AmbientLight(0xeeeeee); // soft white light
  65. this.scene.add(ambientLight);
  66.  
  67. this.light = new THREE.DirectionalLight(0xeeeeee, 1);
  68. this.light.position.set( -1, 1.5, 1).normalize();
  69. this.scene.add(this.light);
  70. };
  71.  
  72. renderScene = () => {
  73. this.controls.update();
  74.  
  75. this.renderer.render(this.scene, this.camera);
  76. };
  77.  
  78. handleResize = () => {
  79. const {width, height} = this.getRendererSize();
  80. this.camera.aspect = width / height;
  81. this.camera.updateProjectionMatrix();
  82.  
  83. this.renderer.setSize(width, height);
  84.  
  85. this.resizeOBJ();
  86. };
  87.  
  88. animate = () => {
  89. requestAnimationFrame(this.animate);
  90. this.renderScene();
  91.  
  92. if(this.root.children[0].style.display === "none"){
  93. this.spin.style.display = "none";
  94. this.root.children[0].style.display = "";
  95.  
  96. this.uris.pieces.forEach(piece => {
  97. if(('' + piece.reference).toLowerCase() === this.uris.parent_reference){
  98. this.applyTexture(piece);
  99. }
  100. });
  101.  
  102. window.addEventListener('resize', this.handleResize);
  103. }
  104.  
  105. if(this.state.count === 0) {
  106. this.resizeOBJ();
  107. }
  108. };
  109.  
  110. resizeOBJ = () => {
  111. const {width, height} = this.getRendererSize();
  112.  
  113. let maxSizeBox = Math.max(this.pixelCoordScale(this.model, width, height).x, this.pixelCoordScale(this.model, width, height).y);
  114. let minSizeBox = Math.min(this.pixelCoordScale(this.model, width, height).x, this.pixelCoordScale(this.model, width, height).y);
  115.  
  116. let windowDim;
  117. maxSizeBox === this.pixelCoordScale(this.model, width, height).x ? windowDim = (width - 40) : windowDim = (height - 40);
  118.  
  119. this.model.position.multiplyScalar(0);
  120.  
  121. if (maxSizeBox > windowDim) {
  122.  
  123. let scale = (this.model.scale.x * windowDim) / maxSizeBox;
  124.  
  125. this.model.scale.set(scale, scale, scale);
  126. } else {
  127. if(this.pixelCoordScale(this.model, width, height).x > width || this.pixelCoordScale(this.model, width, height).y > height) {
  128. let scale = (this.model.scale.x * windowDim) / maxSizeBox;
  129. let diference = maxSizeBox / minSizeBox;
  130. scale = scale - ((diference * 1.15)/10);
  131. this.model.scale.set(scale, scale, scale);
  132. this.setState({count: 1});
  133. }
  134. this.setState({count: 1});
  135. }
  136.  
  137. let box = new THREE.Box3().setFromObject(this.model);
  138. box.getCenter(this.model.position);
  139. this.model.worldToLocal(box);
  140. this.model.position.multiplyScalar(-1);
  141.  
  142. window.scrollTo(0, 0);
  143. };
  144.  
  145. loadMaterial(materialUri, textures) {
  146. const mtlLoader = new MTLLoader();
  147. const texturePathMap = {};
  148.  
  149. textures.forEach(texture => {
  150. texturePathMap[texture.name] = texture.uri;
  151. });
  152.  
  153. mtlLoader.setMaterialOptions({texturePathMap, side: THREE.DoubleSide});
  154.  
  155. return promisifyLoad(mtlLoader)(materialUri)
  156. .then((materials) => {
  157. materials.preload();
  158. this.materialsload = materials;
  159. return materials;
  160. });
  161. }
  162.  
  163. getRendererSize() {
  164. let containerWidth = document.getElementById('sectionLine').getBoundingClientRect().width;
  165. let canvasHeight = (containerWidth * 9) / 16;
  166. const width = containerWidth;
  167. const height = canvasHeight;
  168.  
  169. return {width, height};
  170. }
  171.  
  172. loadObject(objectUri, materials) {
  173. const objLoader = new OBJLoader();
  174. objLoader.setMaterials(materials);
  175.  
  176. return promisifyLoad(objLoader)(objectUri);
  177. }
  178.  
  179. computeScreenSpaceBoundingBox = (mesh, camera) => {
  180. let vertices = [];
  181. for (let i = 0; i < this.model.children.length; i++) {
  182. let geometry = new THREE.Geometry().fromBufferGeometry( this.model.children[i].geometry);
  183.  
  184. vertices.length === 0 ? vertices = geometry.vertices : vertices = vertices.concat(geometry.vertices);
  185. }
  186. let vertex = new THREE.Vector3();
  187. let min = new THREE.Vector3(1);
  188. let max = new THREE.Vector3(-1);
  189.  
  190. for (let i = 0; i < vertices.length; i++) {
  191. let vertexWorldCoord = vertex.copy(vertices[i]).applyMatrix4(mesh.matrixWorld);
  192. let vertexScreenSpace = vertexWorldCoord.project(camera);
  193. min.min(vertexScreenSpace);
  194. max.max(vertexScreenSpace);
  195. }
  196.  
  197. return new THREE.Box2(min, max);
  198. };
  199.  
  200. normalizedToPixels = (coord, renderWidthPixels, renderHeightPixels) => {
  201. let halfScreen = new THREE.Vector2(renderWidthPixels/2, renderHeightPixels/2);
  202. return coord.clone().multiply(halfScreen);
  203. };
  204.  
  205. pixelCoordScale = (model, width, height) => {
  206. let boundingBox2D = this.computeScreenSpaceBoundingBox(model, this.camera);
  207.  
  208. let pixelCoordScale = this.normalizedToPixels(boundingBox2D.getSize(model.position), width, height);
  209.  
  210. return pixelCoordScale;
  211. };
  212.  
  213. loop = (mesh) => {
  214. mesh.children.forEach(mesh => {
  215. let meshName = mesh.name.substring(mesh.name.search('_'), mesh.name.length);
  216. if(meshName === '___snap' || meshName === '___collision'){
  217. mesh.visible = false;
  218. }
  219.  
  220. if(meshName === '___shadow'){
  221. mesh.side = 1;
  222. }
  223. })
  224. };
  225.  
  226. applyTexture = (pieceComplete) => {
  227. pieceComplete.model.metadata.materials.forEach(material => {
  228. Object.keys(pieceComplete.model.options).forEach(piece => {
  229. if(material.label === piece){
  230. material.textures.forEach( texture => {
  231. if(pieceComplete.model.options[piece] === texture.index) {
  232. this.uris.textures.forEach(allTexture => {
  233. if(texture.filename === allTexture.name){
  234. if(!this.materialsload.materials[material.id].map.image) {
  235. return;
  236. }
  237. this.materialsload.materials[material.id].map.image.src = allTexture.uri;
  238. }
  239. });
  240. }
  241. });
  242. }
  243. });
  244. });
  245. };
  246.  
  247. frames = (textures) =>{
  248. let bundleFrames = [];
  249.  
  250. textures.forEach(texture => {
  251. if(texture.name.substring(0,'frame'.length) === 'frame'){
  252. bundleFrames.push(texture);
  253. }
  254. });
  255.  
  256. return(bundleFrames);
  257. };
  258.  
  259. addObject = (object) => {
  260. let objectsHide = [];
  261. object.children.forEach(objectHide => {
  262. if((objectHide.name.substring(objectHide.name.length -4, objectHide.name.length)).toLowerCase() === 'hide'){
  263. objectsHide.push(objectHide);
  264. }
  265. });
  266.  
  267. let bundle = [this.uris, this.controls, this.materialsload, objectsHide, this.frames(this.uris.textures)];
  268. this.props.onUpload(bundle);
  269.  
  270. if (this.model) {
  271. this.scene.remove(this.model);
  272. }
  273.  
  274. this.loop(object);
  275.  
  276. const mesh = object.children[0];
  277.  
  278. for(let i=0; i < object.children.length; i++) {
  279. if(object.children[i]['name'].search('shadow') > 1) {
  280. object.children[i].material.side = 3;
  281. }
  282. }
  283.  
  284. mesh.material.side = THREE.DoubleSide;
  285.  
  286. this.model = object;
  287. this.scene.add(this.model);
  288.  
  289. this.model.rotation.set(.25, -.25, 0);
  290.  
  291. let box1 = new THREE.Box3().setFromObject(this.model);
  292. box1.getCenter(this.model.position);
  293. this.model.localToWorld(box1);
  294. this.model.position.multiplyScalar(-1);
  295. };
  296.  
  297. load = ({objectUri, materialUri, textures, cleanup}) => {
  298. let loadMaterialPromise = Promise.resolve(null);
  299. if (materialUri) {
  300. loadMaterialPromise = this.loadMaterial(materialUri, textures);
  301. }
  302.  
  303. return loadMaterialPromise
  304. .then(materials => this.loadObject(objectUri, materials))
  305. .then(this.addObject)
  306. .then(cleanup);
  307. };
  308.  
  309. onLoadError = (...args) => {
  310. console.error(args);
  311. };
  312.  
  313. handleUpload = (uris) => {
  314. this.uris = uris;
  315.  
  316. this.load(uris)
  317. .then(() => this.animate())
  318. .catch(this.onLoadError);
  319. };
  320.  
  321. render() {
  322.  
  323. return (
  324. <div>
  325. <div className={"load"}
  326. ref={(spin) => {
  327. this.spin = spin;
  328. }}>
  329. <Spinner name="ball-spin-fade-loader" />
  330. </div>
  331. <MeshUpload onUpload={this.handleUpload} params={this.props.model.params}/>
  332. <div
  333. className={"Viewer"}
  334. ref={(root) => {
  335. this.root = root;
  336. }}>
  337. </div>
  338. </div>
  339. );
  340. }
  341. }
  342.  
  343. export default Viewer;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement