Platform implementation
The platform, based on Potree native functions and proposed modifications of the Vizcaya museum project, aims to simplify the exploration of a 3D digital model of a cultural heritage site. With this goal, the implementation focused on the definition of simple and easy-to-reproduce functionalities that could guide even non-experienced users through the inspected and reconstructed structure. This has been achieved using a combination of:
Annotation actions triggered by the user click on a given hotspot inside the 3D scene;
Camera animations that allow to explore a given scene using a pre-defined navigation path;
Pop-up windows that make possible to see in more detailes images or to include text contents;
Shortcut buttons used to simplify into a single command more operations.
The work has been articulated on 2 different perspectives, dividing the entire model into 2 scenes:
Outdoor scene referring to the outside of the 3 surveyed bastions of the castle, for which drones were adopted in addition to total station and GNSS antennas;
Indoor scene of the only bastion (San Giacomo one) which was accessible at the moment of the survey and that was subject to a laser scanner survey.
Data preparation and loading
The platform includes different formats and types of 3D objects and entities: * Point clouds, discrete sets of data points in space representing the 3D shape of the castle. They are the results of the combined photogrammetric and laser scanning survey of the site. The need to be converted from .las/.lax to a .json format with the PotreeConverter in order to be used in the viewer. * Meshes, the structural build of a 3D model consisting of polygons. The projects include one mesh for each documentes historical construction step. * Annotations, a set of descriptive labels georeferenced in the 3D space. They have a unique title and different descriptions that includes multimedia or actions for moving within the scene. * Images, their orientation parameters and camera calibration options, photos taken during the field survey of the site and used in the photogrammetric reconstruction of the castle, obtaining their coordinated and orientation on the same reference system of the point clouds. * Animations, ordered sequences of camera viewpoints that when interpolated results in a virtual first-person tour in the viewer.
All the JavaScript scripts for loading the different file formats are included on the GitHub repository on the dedicated JS folder.
Control icons
Due to their peculiarities inherited by survey methods and instrumentation too, the 2 scenes require the implementation of 2 distinct groups of navigation solutions to better fit their needs. However, some useful common functionalities have been mantained for both scenes. In particular, the main structure of the viewer has been designed to always mantain visible 4 commands:
Castle evolution (castle_phases) button associated to the dynamic paragraph (castle_phase_text) containg the description of the shown phase;
Oriented images (camera_icon) visibility control;
Refresh page (refresh_icon) option;
Navigation instructions (question_icon) command;
Full screen view (fullscreen_icon) button.
All these buttons, positioned on the upper right position of the screen and thought as shortcuts for common operations.
Their style and appearances have been defined as the following example in the assets/css/style.css file:
#refresh_icon {
/*display: none;*/
width: 80%;
height: 80%;
position: fixed;
top: 15px;
right: 160px;
/*130px*/
cursor: pointer;
max-height: 70px !important;
max-width: 70px !important;
z-index: 2;
background: rgba(0, 0, 0, 0.3);
border-radius: 35px;
}
Then, the control icons (and their image logos) have been included in the body section of the index.html file as follow, linking each button to a specific custom function triggered by the user click:
...
<!--Control Icons-->
<img id="camera_icon" onclick="" src="./assets/camera.svg" title="Activate Images" />
<img id="refresh_icon" onclick="refreshButton()" src="./assets/refresh.svg" title="Refresh Page" />
<img id="question_icon" onclick="" src="./assets/question.svg" title="Tutorial" />
<img id="fullscreen_icon" onclick="toggleFullScreen()" src="./assets/fullscreen.svg" title="Fullscreen" />
<img id="castle_phases" onclick="" src="./assets/back-to-the-future.svg" title="Castle phases"> </button>
<p id="castle_phase_text">Current state</p>
...
Then, each function has been defined.
Castle phases evolution
This shortcut has been inserted in the main homepage for guiding easily non expert users in switching the 3D outdoor views between consequent historical reconstruction.
...
let visiblePhase = -1;
let phases = ['fase1', 'fase2', 'fase3', 'fase4', 'fase5', 'fase6', 'fase7', 'fase8', 'fase9']
let phases_text = ['Before 1547', 'September 1547', 'November 1547', 'Winter 1547-1548', 'January 1550', 'June 1550', 'August 1550', 'October 1551', 'May 1553']
function changeVisible(modelNumber) {
if (modelNumber==-1) {
viewer.scene.pointclouds[0].visible = true;
viewer.scene.pointclouds[1].visible = true;
document.getElementById("castle_phase_text").textContent= "Current state";
} else {
viewer.scene.pointclouds[0].visible = false;
viewer.scene.pointclouds[1].visible = false;
viewer.scene.scene.children.find(element => element.name == phases[modelNumber]).visible = true;
document.getElementById("castle_phase_text").textContent= phases_text[modelNumber];
}
for (let i in phases) {
if (i != modelNumber) {
//hide specific model i
viewer.scene.scene.children.find(element => element.name == phases[i]).visible = false;
console.log("Elemento nascosto: " + phases[i])
}
}
}
let castlePhasesButton = document.getElementById("castle_phases");
castlePhasesButton.onclick = () => {
visiblePhase += 1;
if (visiblePhase >= phases.length) {
visiblePhase = -1;
}
changeVisible(visiblePhase);
};
...
Oriented images visibility
This button is needed to have a easy-to-use shortcut for hiding or making visible all the loaded oriented images on the model. By default, as understandable by checking the assets/js/loadphotos.js file, all the images are hidden to have a cleaner view of the model at first loading. However, the click on the camera icon make them visible by triggering the following function included at the end of the index.html that switch the visibility conditions of all the loaded images chunks:
$("#camera_icon").click(function () {
console.log('Hai cliccato sulla camera');
viewer.scene.orientedImages[0].visible = !viewer.scene.orientedImages[0].visible;
viewer.scene.orientedImages[1].visible = !viewer.scene.orientedImages[1].visible;
viewer.scene.orientedImages[2].visible = !viewer.scene.orientedImages[2].visible;
});
Refresh page
This icon is simply linked to the refreshButton() function included in the assets/js/main.js:
function refreshButton() {
window.top.location.reload();
}
Fullscreen mode
In this case, the function has been defined in the assets/js/main.js file. It is based on a series of conditions that check if the current view of the platform is already fullscreen and, based on that information, define if the click on the button will exit or enter the fullscreen mode for the user.
function toggleFullScreen() {
if ((document.fullScreenElement && document.fullScreenElement !== null) ||
(!document.mozFullScreen && !document.webkitIsFullScreen)) {
if (document.documentElement.requestFullScreen) {
document.documentElement.requestFullScreen();
} else if (document.documentElement.mozRequestFullScreen) {
document.documentElement.mozRequestFullScreen();
} else if (document.documentElement.webkitRequestFullScreen) {
document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}
} else {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
}
}