[ui][3D] add EnvironmentMapEntity to display equirectangular images

Load EXR files in the 3D viewport as environment maps mapped on a sphere "attached"  to the camera.
* improve exr loading strategy by considering depthmaps and env maps
* update to DepthMapEntity 2.1 (required to get the loading status)
This commit is contained in:
Yann Lanthony 2019-12-12 19:10:08 +01:00
parent fbfb7d6143
commit 63ffb20819
No known key found for this signature in database
GPG key ID: 519FAE6DF7A70642
5 changed files with 82 additions and 9 deletions

View file

@ -1,4 +1,4 @@
import DepthMapEntity 2.0
import DepthMapEntity 2.1
/**
* Support for Depth Map files (EXR) in Qt3d.

View file

@ -0,0 +1,48 @@
import QtQuick 2.9
import Qt3D.Core 2.1
import Qt3D.Render 2.1
import Qt3D.Extras 2.10
/**
* EnvironmentMap maps an equirectangular image on a Sphere.
* The 'position' property can be used to virually attach it to a camera
* and get the impression of an environment at an infinite distance.
*/
Entity {
id: root
/// Source of the equirectangular image
property url source
/// Radius of the sphere
property alias radius: sphereMesh.radius
/// Number of slices of the sphere
property alias slices: sphereMesh.slices
/// Number of rings of the sphere
property alias rings: sphereMesh.rings
/// Position of the sphere
property alias position: transform.translation
components: [
SphereMesh {
id: sphereMesh
radius: 1000
slices: 50
rings: 50
},
Transform {
id: transform
translation: root.position
},
DiffuseMapMaterial {
ambient: "#FFF"
shininess: 0
specular: "#000"
diffuse: TextureLoader {
magnificationFilter: Texture.Linear
mirrored: true
source: root.source
}
}
]
}

View file

@ -16,6 +16,9 @@ Entity {
property bool pickingEnabled: false
readonly property alias count: instantiator.count // number of instantiated media delegates
/// Camera to consider for positionning
property Camera camera: null
/// True while at least one media is being loaded
readonly property bool loading: {
for(var i=0; i<m.mediaModel.count; ++i) {
@ -173,6 +176,7 @@ Entity {
// source based on currentSource + "requested" property
readonly property string finalSource: model.requested ? currentSource : ""
camera: root.camera
renderMode: root.renderMode
enabled: visible

View file

@ -1,7 +1,7 @@
import QtQuick 2.9
import Qt3D.Core 2.1
import Qt3D.Render 2.1
import Qt3D.Extras 2.1
import Qt3D.Extras 2.10
import QtQuick.Scene3D 2.0
import "Materials"
import Utils 1.0
@ -20,6 +20,9 @@ import Utils 1.0
property var object: null
property int renderMode
/// Scene's current camera
property Camera camera: null
property bool cached: false
onSourceChanged: {
@ -44,7 +47,7 @@ import Utils 1.0
switch(Filepath.extension(source)) {
case ".abc": if(Viewer3DSettings.supportAlembic) component = abcLoaderEntityComponent; break;
case ".exr": if(Viewer3DSettings.supportDepthMap) component = depthMapLoaderComponent; break;
case ".exr": if(Viewer3DSettings.supportDepthMap) component = exrLoaderComponent; break;
case ".obj":
default: component = sceneLoaderEntityComponent; break;
}
@ -103,15 +106,32 @@ import Utils 1.0
}
Component {
id: depthMapLoaderComponent
id: exrLoaderComponent
MediaLoaderEntity {
id: depthMapLoaderEntity
id: exrLoaderEntity
Component.onCompleted: {
var obj = Viewer3DSettings.depthMapLoaderComp.createObject(depthMapLoaderEntity, {
// 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()
obj = Qt.createComponent("EnvironmentMapEntity.qml").createObject(
exrLoaderEntity, {
'source': source,
'position': Qt.binding(function() { return root.camera.position })
});
root.status = SceneLoader.Ready;
}
}
}

View file

@ -221,6 +221,7 @@ FocusScope {
// Picking to set focus point (camera view center)
// Only activate it when a double click may happen or when the 'Control' key is pressed
pickingEnabled: cameraController.pickingActive || doubleClickTimer.running
camera: cameraSelector.camera
components: [
Transform {