mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-29 10:17:27 +02:00
`pointSize` was divided by 100 before being sent to the shader that rendered the programmable points, and was used as is to set the size of the "fixed size" points implicitly in the QML. Now that both cases are handled by the same shader, we do not need to perform this division here: it will be done directly in the shader (by opposition, keeping it here would have meant performing a x100 multiplication in the shader for the "fixed size" case).
246 lines
9 KiB
QML
246 lines
9 KiB
QML
import QtQuick
|
|
import Qt3D.Core 2.6
|
|
import Qt3D.Render 2.6
|
|
import Qt3D.Extras 2.15
|
|
import QtQuick.Scene3D 2.6
|
|
|
|
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
|
|
property bool cameraPickingEnabled: 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 ".ply":
|
|
if ((Filepath.extension(Filepath.removeExtension(source))) == ".pc") {
|
|
if (Viewer3DSettings.supportSfmData)
|
|
component = sfmDataLoaderEntityComponent
|
|
}
|
|
else {
|
|
component = sceneLoaderEntityComponent
|
|
}
|
|
break
|
|
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: function(status) {
|
|
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,
|
|
"fixedPointSize": Qt.binding(function() { return Viewer3DSettings.fixedPointSize }),
|
|
"pointSize": Qt.binding(function() { return Viewer3DSettings.pointSize }),
|
|
"locatorScale": Qt.binding(function() { return Viewer3DSettings.cameraScale }),
|
|
"cameraPickingEnabled": Qt.binding(function() { return root.enabled && root.cameraPickingEnabled }),
|
|
"resectionId": Qt.binding(function() { return Viewer3DSettings.resectionId }),
|
|
"displayResections": Qt.binding(function() { return Viewer3DSettings.displayResectionIds }),
|
|
"syncPickedViewId": Qt.binding(function() { return Viewer3DSettings.syncWithPickedViewId })
|
|
});
|
|
|
|
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
|
|
}
|
|
}
|