diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d373849f..25fd9e4b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,12 +25,14 @@ registration or heartbeat to Clowder that will restrict use of that extractor to
- Documentation on how to do easy testing of pull requests
- Previewer source URL in the documentation to point to the Clowder GitHub repo. [#395](https://github.com/clowder-framework/clowder/issues/395)
- Added a citation.cff file
+- Added Google's model viewer within viewer_three.js previewer
### Fixed
- Updated lastModifiesDate when updating file or metadata to a dataset, added lastModified to UI [386](https://github.com/clowder-framework/clowder/issues/386)
- Disabled button while create dataset ajax call is still going on [#311](https://github.com/clowder-framework/clowder/issues/311)
- Changed default to 'Viewer' while inviting users to new spaces [#375](https://github.com/clowder-framework/clowder/issues/375)
- Fixed bug where complex JSON metadata objects using arrays were not being indexed properly for search.
+- Fixed positioning problems related to how the 3D models appear on the screen
## 1.21.0 - 2022-08-23
diff --git a/public/javascripts/previewers/ifc_previewer/package.json b/public/javascripts/previewers/ifc_previewer/package.json
index de59e479f..17e354593 100644
--- a/public/javascripts/previewers/ifc_previewer/package.json
+++ b/public/javascripts/previewers/ifc_previewer/package.json
@@ -2,5 +2,5 @@
"name": "IFC-Viewer",
"main": "ifc_viewer.js",
"file": true,
- "contentType": ["model/ifc", "model/IFC", "application/octet-stream"]
+ "contentType": ["model/ifc", "model/IFC"]
}
\ No newline at end of file
diff --git a/public/javascripts/previewers/three_js/package.json b/public/javascripts/previewers/three_js/package.json
index a4b9bf6a2..4cb94b49a 100644
--- a/public/javascripts/previewers/three_js/package.json
+++ b/public/javascripts/previewers/three_js/package.json
@@ -1,6 +1,6 @@
{
- "name": "Three-JS",
+ "name": "3D Viewer",
"main": "viewer_three.js",
"file": true,
- "contentType": [ "model/fbx", "model/FBX","model/gltf","model/GLTF", "model/glb","model/GLB", "application/octet-stream"]
+ "contentType": [ "model/fbx", "model/FBX","model/gltf","model/GLTF", "model/glb","model/GLB"]
}
\ No newline at end of file
diff --git a/public/javascripts/previewers/three_js/loading_screen.css b/public/javascripts/previewers/three_js/style.css
similarity index 97%
rename from public/javascripts/previewers/three_js/loading_screen.css
rename to public/javascripts/previewers/three_js/style.css
index c4a6cfe6c..4d48d161e 100644
--- a/public/javascripts/previewers/three_js/loading_screen.css
+++ b/public/javascripts/previewers/three_js/style.css
@@ -84,4 +84,9 @@ html, body {
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
+}
+
+model-viewer {
+ width: 640px;
+ height: 480px;
}
\ No newline at end of file
diff --git a/public/javascripts/previewers/three_js/viewer_three.js b/public/javascripts/previewers/three_js/viewer_three.js
index 30bfa1488..523e21451 100644
--- a/public/javascripts/previewers/three_js/viewer_three.js
+++ b/public/javascripts/previewers/three_js/viewer_three.js
@@ -15,6 +15,8 @@
* First functional version
* + 11/08/21 (cc): Added loading screen and ability
* to load gltf files
+ *
+ * + 07/05/22 (cc): Bug fixes
****************************************************************/
@@ -42,247 +44,272 @@
****************************************************************/
- let fileNameExtension;
- let loader;
-
- (function ($, Configuration) {
- let useTab = Configuration.tab;
- let referenceUrl = Configuration.url;
- let previewer = Configuration.previewer;
-
- $(useTab).append('\n' +
- '\n' +
- '\t\n' +
- '\n' +
- '')
-
- $(useTab).append('');
-
- let fileName = $('#file-name-title').text().trim();
- fileNameExtension = fileName.split('.').pop();
-
- let scripts = [
- "three.min.js",
- "stats.min.js",
- "OrbitControls.js",
- "FBXLoader.js",
- "GLTFLoader.js",
- "DRACOLoader.js",
- "fflate.min.js"
- ];
-
- for (let index = 0; index < scripts.length; index++) {
- let s = document.createElement("script");
- s.type = "text/javascript";
- s.src = previewer + "/js/" + scripts[index];
- $(useTab).append(s);
- }
-
- $(document).ready(function () {
- init(referenceUrl);
- animate();
- });
-
- }(jQuery, Configuration));
-
- let camera, scene, renderer, stats;
- const clock = new THREE.Clock();
- let mixer;
- let previewerWidth = 640;
- let previewerHeight = 480;
-
- function init(urlAddress) {
- const container = document.getElementById(Configuration.tab.replace("#", ""));
-
- renderer = new THREE.WebGLRenderer({antialias: false, powerPreference: "high-performance"});
- renderer.setPixelRatio(window.devicePixelRatio);
- renderer.setSize(previewerWidth, previewerHeight);
- renderer.shadowMap.enabled = true;
-
- camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 2000000);
- camera.position.set(0, 100, 1250);
-
- scene = new THREE.Scene();
- scene.background = new THREE.Color(0x444444);
- //scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
-
- const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
- hemiLight.position.set(0, 200, 0);
- scene.add(hemiLight);
-
- const dirLight = new THREE.DirectionalLight(0xffffff);
- dirLight.position.set(0, 200, 100);
- dirLight.castShadow = true;
- dirLight.shadow.camera.top = 180;
- dirLight.shadow.camera.bottom = -100;
- dirLight.shadow.camera.left = -120;
- dirLight.shadow.camera.right = 120;
- scene.add(dirLight);
-
- const controls = new THREE.OrbitControls(camera, renderer.domElement);
- controls.target.set(0, 100, 0);
- controls.update();
- container.appendChild(renderer.domElement);
-
- // scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );
-
- // ground
- // const mesh = new THREE.Mesh(
- // new THREE.PlaneGeometry( 4000, 4000 ),
- // new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } )
- // );
- //
- // mesh.rotation.x = - Math.PI / 2;
- // mesh.receiveShadow = true;
- // scene.add( mesh );
- //
- // const grid = new THREE.GridHelper( 4000, 20, 0x000000, 0x000000 );
- // grid.material.opacity = 0.2;
- // grid.material.transparent = true;
- // scene.add( grid );
-
- const loadingManager = new THREE.LoadingManager(() => {
- const loadingScreen = document.getElementById('loading-screen');
- loadingScreen.classList.add('fade-out');
- loadingScreen.addEventListener('transitionend', onTransitionEnd);
- });
-
- if (fileNameExtension === 'fbx') {
- loader = new THREE.FBXLoader(loadingManager);
- }
-
- if (fileNameExtension === 'gltf' || fileNameExtension === 'glb') {
- let dracopath = "/assets/javascripts/previewers/three_js/draco/"
-
- loader = new THREE.GLTFLoader(loadingManager);
-
- const dracoLoader = new THREE.DRACOLoader(loadingManager);
-
- dracoLoader.setDecoderPath(dracopath);
-
- dracoLoader.setDecoderConfig({ type: 'js' });
-
- loader.setDRACOLoader(dracoLoader);
- }
-
- loader.setPath(urlAddress);
-
- //loader.setPath("/assets/javascripts/previewers/three_js/models/chimpanzee/source/");
-
- //const texture = new THREE.TextureLoader().setPath('/assets/javascripts/previewers/three_js/models/chimpanzee/source/');
-
- loader.load('', function (object) {
-
- if (fileNameExtension === 'gltf' || fileNameExtension === 'glb') {
- object = object.scene;
- }
-
- object.traverse(function (child) {
-
- if (child.isMesh) {
-
- child.castShadow = true;
- child.receiveShadow = true;
-
- }
-
- });
-
- if (object.animations[0]) {
- mixer = new THREE.AnimationMixer(object);
-
- const action = mixer.clipAction(object.animations[0]);
- action.play();
- }
-
- const box = new THREE.Box3().setFromObject(object);
- const size = box.getSize(new THREE.Vector3()).length();
- const center = box.getCenter(new THREE.Vector3());
-
- controls.reset();
-
- object.position.x += (object.position.x - center.x);
- object.position.y += (object.position.y - center.y);
- object.position.z += (object.position.z - center.z);
-
- controls.maxDistance = size * 10;
- camera.near = size / 100;
- camera.far = size * 100;
-
- camera.updateProjectionMatrix();
- scene.add(object);
-
- // object.traverse( function ( child ) {
- //
- // if ( child.isMesh ) {
- // child.castShadow = true;
- // child.receiveShadow = true;
- //
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('EYESLP_defaultMat_BaseColor.png')});
- // }
- //
- // if ( child.isMesh ) {
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('EYESLP_defaultMat_Normal.png')});
- // }
- //
- // if ( child.isMesh ) {
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('LOW_POLY_defaultMat_AO.png')});
- // }
- // //
- // if ( child.isMesh ) {
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('LOW_POLY_defaultMat_BaseColor.png')});
- // }
- // //
- // if ( child.isMesh ) {
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('LOW_POLY_defaultMat_Metallic.png')});
- // }
- // //
- // if ( child.isMesh ) {
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('LOW_POLY_defaultMat_Roughness.png')});
- // }
- //
- // if ( child.isMesh ) {
- // child.material = new THREE.MeshBasicMaterial({map: texture.load('Pruyebanm.jpg')});
- // }
- //
- // } );
- //
- // scene.add( object );
-
- });
-
-
- window.addEventListener('resize', onWindowResize);
-
- // stats
- stats = new Stats();
- //container.appendChild( stats.dom );
-
- }
-
- function onWindowResize() {
-
- camera.aspect = window.innerWidth / window.innerHeight;
- camera.updateProjectionMatrix();
-
- renderer.setSize(window.innerWidth, window.innerHeight);
-
- }
-
- function onTransitionEnd(event) {
-
- event.target.remove();
-
- }
-
- function animate() {
- requestAnimationFrame(animate);
-
- const delta = clock.getDelta();
-
- if (mixer) mixer.update(delta);
-
- renderer.render(scene, camera);
-
- stats.update();
- }
\ No newline at end of file
+/**
+ * Jquery
+ */
+
+let loader;
+let useTab;
+let referenceUrl;
+let previewer;
+let fileName;
+let fileNameExtension;
+
+let scripts = [
+ "three.min.js",
+ "stats.min.js",
+ "OrbitControls.js",
+ "FBXLoader.js",
+ // "GLTFLoader.js",
+ // "DRACOLoader.js",
+ "fflate.min.js"
+];
+
+(function ($, Configuration) {
+ useTab = Configuration.tab;
+ referenceUrl = Configuration.url;
+ previewer = Configuration.previewer;
+
+ fileName = $('#file-name-title').text().trim();
+ fileNameExtension = fileName.split('.').pop();
+
+ $(useTab).append('');
+
+ /**
+ * Decipher whether the uploaded file is an
+ * FBX or a GLTF (GLB) file and load the appropriate model loader
+ * For the special case of GLTF/GLB model usel Google's
+ * model viewer
+ */
+
+ for (let index = 0; index < scripts.length; index++) {
+ let s = document.createElement("script");
+ s.type = "text/javascript";
+ s.src = previewer + "/js/" + scripts[index];
+ $(useTab).append(s);
+ }
+
+ if (fileNameExtension === 'fbx') {
+
+ $(useTab).append('\n' +
+ '\n' +
+ '\t\n' +
+ '\n' +
+ '')
+
+ $(document).ready(function () {
+ init(referenceUrl);
+ animate();
+ });
+ }
+
+ if (fileNameExtension === 'gltf' || fileNameExtension === 'glb') {
+
+ $(useTab).append('')
+
+
+ $(useTab).append("")
+ }
+
+}(jQuery, Configuration));
+
+/**
+ * Three.js
+ */
+
+let camera, scene, renderer, stats;
+let mixer;
+let previewerWidth = 640;
+let previewerHeight = 480;
+const clock = new THREE.Clock();
+
+function init(urlAddress) {
+ const container = document.getElementById(Configuration.tab.replace("#", ""));
+
+
+ /**
+ * Renderer
+ */
+
+ renderer = new THREE.WebGLRenderer(
+ {
+ antialias: false
+ }
+ );
+
+ //renderer.physicallyCorrectLights = true;
+ renderer.outputEncoding = THREE.sRGBEncoding;
+ renderer.setClearColor(0xcccccc);
+ renderer.setPixelRatio(window.devicePixelRatio);
+ renderer.setSize(previewerWidth, previewerHeight);
+ renderer.shadowMap.enabled = true;
+
+ /**
+ * Camera
+ */
+
+ camera = new THREE.PerspectiveCamera(55, previewerWidth / previewerHeight, 0.1, 1000);
+ //camera.position.set(0, 20, 100);
+
+ /**
+ * Scene
+ */
+
+ scene = new THREE.Scene();
+ scene.background = new THREE.Color("White");
+ //scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
+
+ /**
+ * Lights
+ */
+
+ const hemiLight1 = new THREE.HemisphereLight(0xffffff, 0x444444);
+ const hemiLight2 = new THREE.HemisphereLight(0xffffff, 1);
+ //hemiLight.position.set(0, -20, 0);
+ scene.add(hemiLight1, hemiLight2);
+
+ const ambientLight = new THREE.AmbientLight(0xffffff, 1);
+ //ambientLight.position.set(0, 200, 0);
+ scene.add(ambientLight);
+
+ const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
+ //dirLight.position.set(0, 4, 4);
+
+ // const helper = new THREE.DirectionalLightHelper(dirLight, 2);
+ // scene.add(helper);
+ dirLight.castShadow = true;
+ // dirLight.shadow.camera.top = 180;
+ // dirLight.shadow.camera.bottom = -100;
+ // dirLight.shadow.camera.left = -120;
+ // dirLight.shadow.camera.right = 120;
+ scene.add(dirLight);
+
+ /**
+ * Orbit controls
+ */
+
+ const controls = new THREE.OrbitControls(camera, renderer.domElement);
+ //controls.target.set(0, 100, 0);
+ controls.update();
+ container.appendChild(renderer.domElement);
+
+ // scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );
+
+ // ground
+ // const mesh = new THREE.Mesh(
+ // new THREE.PlaneGeometry(1000, 1000),
+ // new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false })
+ // );
+ // mesh.rotation.x = - Math.PI / 2;
+ // mesh.receiveShadow = true;
+ // mesh.material.transparent = false;
+ // scene.add(mesh);
+
+ // const grid = new THREE.GridHelper(1000, 100, 0x000000, 0x000000);
+ // grid.material.opacity = 0.3;
+ // grid.material.transparent = true;
+ // scene.add(grid);
+
+ /**
+ * Loading manager
+ */
+
+ // The loading manager is needed for the loading screen
+
+ const loadingManager = new THREE.LoadingManager(() => {
+ const loadingScreen = document.getElementById('loading-screen');
+ loadingScreen.classList.add('fade-out');
+ loadingScreen.addEventListener('transitionend', onTransitionEnd);
+ });
+
+ loader = new THREE.FBXLoader(loadingManager);
+
+ // Set loader's path to the url address of the file
+
+ loader.setPath(urlAddress);
+
+ //loader.setPath("/assets/javascripts/previewers/three_js/models/chimpanzee/source/");
+
+ loader.load('', function (object) {
+
+ if (fileNameExtension === 'gltf' || fileNameExtension === 'glb') {
+ object = object.scene;
+ }
+
+ object.traverse(function (child) {
+
+ if (child.isMesh) {
+
+ child.castShadow = true;
+ child.receiveShadow = true;
+
+ }
+
+ });
+
+ if (object.animations[0]) {
+ mixer = new THREE.AnimationMixer(object);
+
+ const action = mixer.clipAction(object.animations[0]);
+ action.play();
+ }
+
+ const box = new THREE.Box3().setFromObject(object);
+ const size = box.getSize(new THREE.Vector3()).length();
+ const center = box.getCenter(new THREE.Vector3());
+
+ //controls.reset();
+
+ object.position.x += (object.position.x - center.x);
+ object.position.y += (object.position.y - center.y);
+ object.position.z += (object.position.z - center.z);
+
+ controls.maxDistance = size * 10;
+ controls.minDistance = size;
+
+ camera.near = size / 100;
+ camera.far = size * 100;
+ camera.updateProjectionMatrix();
+ camera.position.copy(center);
+ camera.position.x += size / 2.0;
+ camera.position.y += size / 5.0;
+ camera.position.z += size / 2.0;
+ camera.lookAt(center);
+ controls.update();
+
+ scene.add(object);
+ });
+
+ window.addEventListener('resize', onWindowResize);
+
+ // stats
+ stats = new Stats();
+ //container.appendChild( stats.dom );
+}
+
+function onWindowResize() {
+
+ camera.aspect = window.innerWidth / window.innerHeight;
+ camera.updateProjectionMatrix();
+
+ renderer.setSize(window.innerWidth, window.innerHeight);
+
+}
+
+function onTransitionEnd(event) {
+
+ event.target.remove();
+
+}
+
+function animate() {
+ requestAnimationFrame(animate);
+
+ const delta = clock.getDelta();
+
+ if (mixer) mixer.update(delta);
+
+ renderer.render(scene, camera);
+
+ stats.update();
+}
\ No newline at end of file