Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions invenio.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ from cds_rdm.inspire_harvester.transformer import InspireJsonTransformer
from cds_rdm.inspire_harvester.writer import InspireWriter
from invenio_app_rdm.config import STATS_EVENTS as _APP_RDM_STATS_EVENTS, \
STATS_AGGREGATIONS as _APP_RDM_STATS_AGGREGATIONS, APP_RDM_ROUTES
from invenio_previewer.config import PREVIEWER_PREFERENCE as DEFAULT_PREVIEWER_PREFERENCE
from invenio_rdm_records.checks import requests as checks_requests
from invenio_rdm_records.config import (always_valid, RDM_RECORDS_PERSONORG_SCHEMES,
RDM_RECORDS_IDENTIFIERS_SCHEMES as RDM_RECORDS_RELATED_IDENTIFIERS_SCHEMES
Expand Down Expand Up @@ -523,10 +524,9 @@ APP_RDM_RECORD_LANDING_PAGE_EXTERNAL_LINKS = [

# Invenio-Previewer
# =========================
# TODO-EV uncomment this line
# PREVIEWER_PREFERENCE = DEFAULT_PREVIEWER_PREFERENCE + [
# "cds_rdm_gltf_previewer",
# ]
PREVIEWER_PREFERENCE = DEFAULT_PREVIEWER_PREFERENCE + [
"cds_rdm_gltf_previewer",
]

# Invenio-Preservation-Sync
# =========================
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,115 @@
// TODO-EV
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";

document.addEventListener("DOMContentLoaded", () => {
class ThreeScene {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe could we declare the class outside of the event handler and call just create + init the app inside it? The class not being top-level looks a little unusual

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, but I don't think it will make any difference: I really hope that DOMContentLoaded is fired only once! I will move it.

constructor(config) {
this.config = config;
this.container = config.container;

this.scene = null;
this.camera = null;
this.renderer = null;
this.controls = null;
}

init() {
this.initScene();
this.initCamera();
this.initRenderer();
this.initControls();
this.addEventListeners();
this.loadModel();
this.startRendering();
}

initScene() {
this.scene = new THREE.Scene();
}

initCamera() {
const { camera_x, camera_y, camera_z } = this.config;
const width = window.innerWidth;
const height = window.innerHeight;

this.camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 1000);
this.camera.position.set(camera_x, camera_y, camera_z);
}

initRenderer() {
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setPixelRatio(window.devicePixelRatio || 1);
this.renderer.setClearColor(this.config.background, 1);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.container.appendChild(this.renderer.domElement);
}

initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.zoomSpeed = 0.5;
}

addEventListeners() {
window.addEventListener("resize", () => {
const width = window.innerWidth;
const height = window.innerHeight;

this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(width, height);
});
}

loadModel() {
const loader = new GLTFLoader();
const { fileURI } = this.config;

const progressBar = document.getElementById("progress");
const percentText = document.getElementById("percent");
Comment on lines +68 to +69
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be slightly precarious in case we happen to have other elements with these IDs on the page as they're quite generic. Maybe we could use more specific names, e.g. gltf-previewer-progress


if (progressBar) progressBar.style.visibility = "visible";

loader.load(
fileURI,
(gltf) => {
this.scene.add(gltf.scene);
if (progressBar) progressBar.style.visibility = "hidden";
if (percentText) percentText.textContent = "";
},
(xhr) => {
if (percentText && xhr.total) {
const percentComplete = Math.round((xhr.loaded / xhr.total) * 100);
percentText.textContent = `${percentComplete}`;
console.debug(`${percentComplete}% loaded`);
}
},
(error) => {
console.error("An error occurred loading the GLB file:", error);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this show a visible error to the user? E.g. if the user is on an unstable network it's quite likely that the load would fail so we should make sure it's communicated clearly

}
);
}

startRendering() {
const renderLoop = () => {
requestAnimationFrame(renderLoop);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move this to the end of renderLoop to avoid running the next update before the current one accidentally? It probably won't make a huge difference if the render is fast but I've usually seen this call at the end rather than the start.

this.controls.update();
this.renderer.render(this.scene, this.camera);
};
renderLoop();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the official recommendation is to use this.renderer.setAnimationLoop instead of manually calling requestAnimationFrame to ensure the loop timing works on all devices: https://threejs.org/docs/#WebGLRenderer.setAnimationLoop

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. see the "Rendering the scene" example: https://threejs.org/manual/#en/creating-a-scene

}
}

// Configuration
const config = {
container: document.getElementById("container"),
background: 0x000000,
camera_x: 5,
camera_y: 5,
camera_z: 10,
fileURI: document.getElementById("gltf-previewer").getAttribute("data-file-uri"),
};

const app = new ThreeScene(config);
app.init();
});
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
// TODO-EV
#gltf-previewer {
canvas {
width: 100%;
height: 100%;
}

#progress {
border: none;
position: absolute;
text-align: center;
top: 50%;
width: 100%;
padding: 5px;
color: white;
visibility: hidden;
}
}
2 changes: 1 addition & 1 deletion site/cds_rdm/previewer/gltf_previewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from invenio_previewer.proxies import current_previewer
from invenio_previewer.utils import dotted_exts

previewable_extensions = ["gltf"]
previewable_extensions = ["glb", "gltf"]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to get all the possible extensions

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a necessary addition. The GLTFLoader of three.js handles both transparently.



def can_preview(file):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
{%- extends config.PREVIEWER_ABSTRACT_TEMPLATE %}

{% block panel %}
<!-- TODO-EV -->
<div>TODO</div>
<div id="gltf-previewer" data-file-uri="{{ file.uri }}">
<div id="progress">Loading <span id="percent"></span>%</div>
<div id="container"></div>
</div>
{% endblock %}
4 changes: 4 additions & 0 deletions site/cds_rdm/webpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"gltf_previewer_js": "./js/cds_rdm/previewers/gltf-previewer.js",
"gltf_previewer_css": "./less/cds_rdm/previewers/gltf-previewer.less",
},
dependencies={
"three": "^0.180.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just updated to 0.181.0 a few minutes ago: https://github.com/mrdoob/three.js/releases/tag/r181

"three-addons": "^1.2.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if there's any alternative but this was archived in 2021 and last publish 7 years ago. https://github.com/marcofugaro/three-addons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw it, however, I am a big fan of code that does not change and it works :)

},
),
},
)