mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-03 04:06:45 +02:00
233 lines
8.3 KiB
QML
233 lines
8.3 KiB
QML
import QtQuick 2.15
|
|
import Qt3D.Core 2.15
|
|
import Qt3D.Render 2.15
|
|
import Qt3D.Extras 2.15
|
|
import QtQuick.Scene3D 2.15
|
|
import "Materials"
|
|
import Utils 1.0
|
|
|
|
|
|
/**
|
|
* MediaLoader provides a single entry point for 3D media loading.
|
|
* It encapsulates all available plugins/loaders.
|
|
*/
|
|
Entity {
|
|
id: root
|
|
|
|
property url source
|
|
property bool loading: false
|
|
property int status: SceneLoader.None
|
|
property var object: null
|
|
property int renderMode
|
|
|
|
/// Scene's current camera
|
|
property Camera camera: null
|
|
|
|
property bool cached: false
|
|
|
|
onSourceChanged: {
|
|
if (cached) {
|
|
root.status = SceneLoader.Ready
|
|
return
|
|
}
|
|
|
|
// clear previously created object if any
|
|
if (object) {
|
|
object.destroy()
|
|
object = null
|
|
}
|
|
|
|
var component = undefined
|
|
status = SceneLoader.Loading
|
|
|
|
if (!Filepath.exists(source)) {
|
|
status = SceneLoader.None
|
|
return
|
|
}
|
|
|
|
switch (Filepath.extension(source)) {
|
|
case ".abc":
|
|
case ".json":
|
|
case ".sfm":
|
|
if (Viewer3DSettings.supportSfmData)
|
|
component = sfmDataLoaderEntityComponent
|
|
break
|
|
case ".exr":
|
|
if (Viewer3DSettings.supportDepthMap)
|
|
component = exrLoaderComponent
|
|
break
|
|
case ".obj":
|
|
case ".stl":
|
|
default:
|
|
component = sceneLoaderEntityComponent
|
|
break
|
|
}
|
|
|
|
// Media loader available
|
|
if (component) {
|
|
object = component.createObject(root, {"source": source})
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: sceneLoaderEntityComponent
|
|
MediaLoaderEntity {
|
|
id: sceneLoaderEntity
|
|
objectName: "SceneLoader"
|
|
|
|
components: [
|
|
SceneLoader {
|
|
source: parent.source
|
|
onStatusChanged: {
|
|
if (status == SceneLoader.Ready) {
|
|
textureCount = sceneLoaderPostProcess(sceneLoaderEntity)
|
|
faceCount = Scene3DHelper.faceCount(sceneLoaderEntity)
|
|
}
|
|
root.status = status;
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: sfmDataLoaderEntityComponent
|
|
MediaLoaderEntity {
|
|
id: sfmDataLoaderEntity
|
|
Component.onCompleted: {
|
|
var obj = Viewer3DSettings.sfmDataLoaderComp.createObject(sfmDataLoaderEntity, {
|
|
'source': source,
|
|
'pointSize': Qt.binding(function() { return 0.01 * Viewer3DSettings.pointSize }),
|
|
'locatorScale': Qt.binding(function() { return Viewer3DSettings.cameraScale }),
|
|
'cameraPickingEnabled': Qt.binding(function() { return root.enabled }),
|
|
'resectionId': Qt.binding(function() { return Viewer3DSettings.resectionId }),
|
|
'displayResections': Qt.binding(function() { return Viewer3DSettings.displayResectionIds })
|
|
});
|
|
|
|
obj.statusChanged.connect(function() {
|
|
if (obj.status === SceneLoader.Ready) {
|
|
for (var i = 0; i < obj.pointClouds.length; ++i) {
|
|
vertexCount += Scene3DHelper.vertexCount(obj.pointClouds[i]);
|
|
}
|
|
cameraCount = obj.spawnCameraSelectors();
|
|
}
|
|
Viewer3DSettings.resectionIdCount = obj.countResectionIds();
|
|
Viewer3DSettings.resectionGroups = obj.countResectionGroups(Viewer3DSettings.resectionIdCount + 1);
|
|
resectionIdCount = Viewer3DSettings.resectionIdCount
|
|
resectionGroups = Viewer3DSettings.resectionGroups
|
|
resectionId = Viewer3DSettings.resectionIdCount
|
|
root.status = obj.status;
|
|
})
|
|
|
|
obj.cameraSelected.connect(
|
|
function(viewId) {
|
|
obj.selectedViewId = viewId
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: exrLoaderComponent
|
|
MediaLoaderEntity {
|
|
id: exrLoaderEntity
|
|
Component.onCompleted: {
|
|
var fSize = Filepath.fileSizeMB(source)
|
|
if (fSize > 500) {
|
|
// Do not load images that are larger than 500MB
|
|
console.warn("Viewer3D: Do not load the EXR in 3D as the file size is too large: " + fSize + "MB")
|
|
root.status = SceneLoader.Error
|
|
return
|
|
}
|
|
|
|
// EXR loading strategy:
|
|
// - [1] as a depth map
|
|
var obj = Viewer3DSettings.depthMapLoaderComp.createObject(
|
|
exrLoaderEntity, {
|
|
'source': source
|
|
})
|
|
|
|
if (obj.status === SceneLoader.Ready) {
|
|
faceCount = Scene3DHelper.faceCount(obj)
|
|
root.status = SceneLoader.Ready
|
|
return
|
|
}
|
|
|
|
// - [2] as an environment map
|
|
obj.destroy()
|
|
root.status = SceneLoader.Loading
|
|
obj = Qt.createComponent("EnvironmentMapEntity.qml").createObject(
|
|
exrLoaderEntity, {
|
|
'source': source,
|
|
'position': Qt.binding(function() { return root.camera.position })
|
|
})
|
|
obj.statusChanged.connect(function() {
|
|
root.status = obj.status;
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: materialSwitcherComponent
|
|
MaterialSwitcher { }
|
|
}
|
|
|
|
// Remove automatically created DiffuseMapMaterial and
|
|
// instantiate a MaterialSwitcher instead. Returns the faceCount
|
|
function sceneLoaderPostProcess(rootEntity)
|
|
{
|
|
var materials = Scene3DHelper.findChildrenByProperty(rootEntity, "diffuse")
|
|
var entities = []
|
|
var texCount = 0
|
|
materials.forEach(function(mat) {
|
|
entities.push(mat.parent)
|
|
})
|
|
|
|
entities.forEach(function(entity) {
|
|
var mats = []
|
|
var componentsToRemove = []
|
|
// Create as many MaterialSwitcher as individual materials for this entity
|
|
// NOTE: we let each MaterialSwitcher modify the components of the entity
|
|
// and therefore remove the default material spawned by the sceneLoader
|
|
for (var i = 0; i < entity.components.length; ++i)
|
|
{
|
|
var comp = entity.components[i]
|
|
|
|
// handle DiffuseMapMaterials created by SceneLoader
|
|
if (comp.toString().indexOf("QDiffuseMapMaterial") > -1) {
|
|
// store material definition
|
|
var m = {
|
|
"diffuseMap": comp.diffuse.data[0].source,
|
|
"shininess": comp.shininess,
|
|
"specular": comp.specular,
|
|
"ambient": comp.ambient,
|
|
"mode": root.renderMode
|
|
}
|
|
texCount++
|
|
mats.push(m)
|
|
componentsToRemove.push(comp)
|
|
}
|
|
|
|
if (comp.toString().indexOf("QPhongMaterial") > -1) {
|
|
// create MaterialSwitcher with default colors
|
|
mats.push({})
|
|
componentsToRemove.push(comp)
|
|
}
|
|
}
|
|
|
|
mats.forEach(function(m) {
|
|
// create a material switcher for each material definition
|
|
var matSwitcher = materialSwitcherComponent.createObject(entity, m)
|
|
matSwitcher.mode = Qt.binding(function(){ return root.renderMode })
|
|
})
|
|
|
|
// remove replaced components
|
|
componentsToRemove.forEach(function(comp) {
|
|
Scene3DHelper.removeComponent(entity, comp)
|
|
})
|
|
})
|
|
return texCount
|
|
}
|
|
}
|