summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2018-05-23 17:54:26 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2018-05-23 17:54:33 +0200
commit41ccb47065b9ba4418d792644415a424270b256f (patch)
tree7a1ae164efc44b4cd74344fb88d13fe1158576c4
parent8bb3378d0d7c82eb1896ac043570ddab7c2edae9 (diff)
parentb81bba4795eea06d4dcbf39c99f986de2654077d (diff)
Merge remote-tracking branch 'origin/2.0'v2.0.0-beta2
-rw-r--r--res/effectlib/Fxaa3_8.glsllib2
-rw-r--r--res/effectlib/average.glsllib2
-rw-r--r--res/effectlib/calculateRoughness.glsllib4
-rw-r--r--res/effectlib/customMaterial.glsllib10
-rw-r--r--res/effectlib/customMaterialFragBody.glsllib8
-rw-r--r--res/effectlib/customMaterialFragBodyAO.glsllib8
-rw-r--r--res/effectlib/diffuseReflectionBSDF.glsllib6
-rw-r--r--res/effectlib/diffuseTransmissionBSDF.glsllib6
-rw-r--r--res/effectlib/fileBumpTexture.glsllib2
-rw-r--r--res/effectlib/flakeNoiseBumpTexture.glsllib2
-rw-r--r--res/effectlib/flakeNoiseTexture.glsllib8
-rw-r--r--res/effectlib/fresnelLayer.glsllib18
-rw-r--r--res/effectlib/gradient3Recolor.glsllib14
-rw-r--r--res/effectlib/gradientGetPosition.glsllib14
-rw-r--r--res/effectlib/miNoise.glsllib22
-rw-r--r--res/effectlib/microfacetBSDF.glsllib14
-rw-r--r--res/effectlib/normalizedMix.glsllib2
-rw-r--r--res/effectlib/perlinNoise.glsllib68
-rw-r--r--res/effectlib/physGlossyBSDF.glsllib4
-rw-r--r--res/effectlib/sampleArea.glsllib8
-rw-r--r--res/effectlib/sampleLight.glsllib12
-rw-r--r--res/effectlib/simpleGlossyBSDF.glsllib18
-rw-r--r--res/effectlib/specularBSDF.glsllib6
-rw-r--r--res/effectlib/spotEdf.glsllib2
-rw-r--r--src/3rdparty/imgui/qt_attribution.json2
-rw-r--r--src/imports/studio3d/q3dsstudio3ditem.cpp54
-rw-r--r--src/imports/studio3d/q3dssubpresentationsettings.cpp50
-rw-r--r--src/runtime/api/q3dsdatainput.cpp79
-rw-r--r--src/runtime/api/q3dselement.cpp65
-rw-r--r--src/runtime/api/q3dspresentation.cpp403
-rw-r--r--src/runtime/api/q3dssceneelement.cpp44
-rw-r--r--src/runtime/api/q3dssurfaceviewer.cpp35
-rw-r--r--src/runtime/api/q3dsviewersettings.cpp60
-rw-r--r--src/runtime/api/q3dswidget.cpp56
-rw-r--r--src/runtime/behaviorapi/q3dsbehaviorobject.cpp124
-rw-r--r--src/runtime/behaviorapi/q3dsbehaviorobject_p.h2
-rw-r--r--src/runtime/doc/src/copyright.qdoc2
-rw-r--r--src/runtime/doc/src/images/customsignal.pngbin0 -> 28206 bytes
-rw-r--r--src/runtime/doc/src/images/profileui-example.pngbin0 -> 427508 bytes
-rw-r--r--src/runtime/doc/src/images/profileui-tooltips.pngbin0 -> 261025 bytes
-rw-r--r--src/runtime/doc/src/index.qdoc5
-rw-r--r--src/runtime/doc/src/module.qdoc56
-rw-r--r--src/runtime/doc/src/profileui.qdoc133
-rw-r--r--src/runtime/q3dsanimationmanager.cpp30
-rw-r--r--src/runtime/q3dsengine.cpp30
-rw-r--r--src/runtime/q3dsgraphicslimits_p.h7
-rw-r--r--src/runtime/q3dsscenemanager.cpp508
-rw-r--r--src/runtime/q3dsscenemanager_p.h26
-rw-r--r--src/runtime/q3dsslideplayer.cpp97
-rw-r--r--src/runtime/q3dsslideplayer_p.h5
-rw-r--r--src/runtime/q3dsuippresentation.cpp11
-rw-r--r--src/runtime/q3dsuippresentation_p.h7
-rw-r--r--src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp3
-rw-r--r--src/runtime/shaders/compositor_ms2.frag5
-rw-r--r--src/runtime/shaders/compositor_ms4.frag5
-rw-r--r--tests/auto/q3dslancelot/data/cameras/componentCamera.uip2
56 files changed, 1536 insertions, 630 deletions
diff --git a/res/effectlib/Fxaa3_8.glsllib b/res/effectlib/Fxaa3_8.glsllib
index 7e76ecd..620f565 100644
--- a/res/effectlib/Fxaa3_8.glsllib
+++ b/res/effectlib/Fxaa3_8.glsllib
@@ -1370,7 +1370,7 @@ float4 FxaaPixelShader(
float2 posP = posN;
float2 offNP = horzSpan ?
FxaaFloat2(rcpFrame.x, 0.0) :
- FxaaFloat2(0.0f, rcpFrame.y);
+ FxaaFloat2(0.0, rcpFrame.y);
float lumaEndN;
float lumaEndP;
bool doneN = false;
diff --git a/res/effectlib/average.glsllib b/res/effectlib/average.glsllib
index 8c3f3fc..082eec0 100644
--- a/res/effectlib/average.glsllib
+++ b/res/effectlib/average.glsllib
@@ -30,6 +30,6 @@
float average( in vec3 v )
{
- return( ( v.x + v.y + v.z ) / 3.0f );
+ return( ( v.x + v.y + v.z ) / 3.0 );
}
diff --git a/res/effectlib/calculateRoughness.glsllib b/res/effectlib/calculateRoughness.glsllib
index d1e099b..a14083d 100644
--- a/res/effectlib/calculateRoughness.glsllib
+++ b/res/effectlib/calculateRoughness.glsllib
@@ -55,8 +55,8 @@ float calculateRoughness( in vec3 N, in float roughnessU, in float roughnessV, i
float cosPhi = dot( po, minorAxis );
// determine the polar coordinate of viewDir, take that radius as the roughness
- float excentricitySquare = 1.0f - square( b / a );
- roughness = b / sqrt( 1.0f - excentricitySquare * square( cosPhi ) );
+ float excentricitySquare = 1.0 - square( b / a );
+ roughness = b / sqrt( 1.0 - excentricitySquare * square( cosPhi ) );
}
return( roughness );
}
diff --git a/res/effectlib/customMaterial.glsllib b/res/effectlib/customMaterial.glsllib
index e99fa6e..0a4d88b 100644
--- a/res/effectlib/customMaterial.glsllib
+++ b/res/effectlib/customMaterial.glsllib
@@ -36,11 +36,11 @@ uniform sampler2D samplerName;
// some useful defines
#ifndef PI
-#define PI 3.14159265358979f
-#define PI_HALF ( 0.5f * PI )
-#define PI_TWO ( 2.0f * PI )
-#define ONE_OVER_PI ( 1.0f / PI )
-#define TWO_OVER_PI ( 2.0f / PI )
+#define PI 3.14159265358979
+#define PI_HALF ( 0.5 * PI )
+#define PI_TWO ( 2.0 * PI )
+#define ONE_OVER_PI ( 1.0 / PI )
+#define TWO_OVER_PI ( 2.0 / PI )
#define PI_SQUARE ( PI * PI )
#endif
diff --git a/res/effectlib/customMaterialFragBody.glsllib b/res/effectlib/customMaterialFragBody.glsllib
index 7a1b09a..c20c3e0 100644
--- a/res/effectlib/customMaterialFragBody.glsllib
+++ b/res/effectlib/customMaterialFragBody.glsllib
@@ -32,7 +32,7 @@
#define CUSTOM_MATERIAL_FRAG_BODY_GLSLLIB
bool twoSided = false;
- vec3 materialEmissive = vec3( 0.0f, 0.0f, 0.0f );
+ vec3 materialEmissive = vec3( 0.0, 0.0, 0.0 );
float materialIOR = computeIOR();
@@ -42,7 +42,7 @@
}
else
{
- materialIOR = 1.0f / materialIOR;
+ materialIOR = 1.0 / materialIOR;
twoSided = evalTwoSided();
if ( twoSided )
{
@@ -51,7 +51,7 @@
}
}
- vec4 rgba = vec4( materialEmissive, 0.0f );
+ vec4 rgba = vec4( materialEmissive, 0.0 );
vec3 lightAmbient, lightDiffuse, lightSpecular, L;
for ( int i=0 ; i<uNumLights ; i++ )
@@ -71,7 +71,7 @@
computeBackAreaColor( i, arealights[i].diffuse, arealights[i].specular );
}
- if ( 0.0f < alpha )
+ if ( 0.0 < alpha )
{
if (gl_FrontFacing)
computeFrontLayerEnvironment( normal, viewDir, 1.0 );
diff --git a/res/effectlib/customMaterialFragBodyAO.glsllib b/res/effectlib/customMaterialFragBodyAO.glsllib
index 4f98e09..4c79d8d 100644
--- a/res/effectlib/customMaterialFragBodyAO.glsllib
+++ b/res/effectlib/customMaterialFragBodyAO.glsllib
@@ -32,7 +32,7 @@
#define CUSTOM_MATERIAL_FRAG_BODY_AO_GLSLLIB
bool twoSided = false;
- vec3 materialEmissive = vec3( 0.0f, 0.0f, 0.0f );
+ vec3 materialEmissive = vec3( 0.0, 0.0, 0.0 );
float materialIOR = computeIOR();
@@ -42,7 +42,7 @@
}
else
{
- materialIOR = 1.0f / materialIOR;
+ materialIOR = 1.0 / materialIOR;
twoSided = evalTwoSided();
if ( twoSided )
{
@@ -51,7 +51,7 @@
}
}
- vec4 rgba = vec4( materialEmissive, 0.0f );
+ vec4 rgba = vec4( materialEmissive, 0.0 );
// compute ambient occlusion
float aoFactor = customMaterialAO( );
@@ -77,7 +77,7 @@
computeBackAreaColor( i, arealights[i].diffuse, arealights[i].specular );
}
- if ( 0.0f < alpha )
+ if ( 0.0 < alpha )
{
if (gl_FrontFacing)
computeFrontLayerEnvironment( normal, viewDir, aoFactor );
diff --git a/res/effectlib/diffuseReflectionBSDF.glsllib b/res/effectlib/diffuseReflectionBSDF.glsllib
index 9a66aef..a98509d 100644
--- a/res/effectlib/diffuseReflectionBSDF.glsllib
+++ b/res/effectlib/diffuseReflectionBSDF.glsllib
@@ -35,14 +35,14 @@ vec4 lambertReflectionBSDF( in vec3 N, in vec3 L, in vec3 lightDiffuse )
{
// If we're not going to use the roughness on the diffuse, there's no point
// in wasting the cycles for the branching.
- float cosThetaI = max( 0.0f, dot( N, L ) );
- return vec4( cosThetaI * lightDiffuse, 1.0f );
+ float cosThetaI = max( 0.0, dot( N, L ) );
+ return vec4( cosThetaI * lightDiffuse, 1.0 );
}
vec4 diffuseReflectionBSDFEnvironment( in vec3 N, in float roughness )
{
- return( vec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
+ return( vec4( 0.0, 0.0, 0.0, 1.0 ) );
}
// RNM radiosity normal maps
diff --git a/res/effectlib/diffuseTransmissionBSDF.glsllib b/res/effectlib/diffuseTransmissionBSDF.glsllib
index 09d9a7e..c588f14 100644
--- a/res/effectlib/diffuseTransmissionBSDF.glsllib
+++ b/res/effectlib/diffuseTransmissionBSDF.glsllib
@@ -30,13 +30,13 @@
vec4 diffuseTransmissionBSDF( in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightDiffuse, in vec4 transmissiveColor, in float translucentFalloff, float lightWrap )
{
- float cosThetaI = max( 0.0f, (dot( N, L ) + lightWrap) / (1.0 + lightWrap) );
+ float cosThetaI = max( 0.0, (dot( N, L ) + lightWrap) / (1.0 + lightWrap) );
float factor = cosThetaI;
- float l = 0.2126f * transmissiveColor.r + 0.7152f * transmissiveColor.g + 0.0722f * transmissiveColor.b;
+ float l = 0.2126 * transmissiveColor.r + 0.7152 * transmissiveColor.g + 0.0722 * transmissiveColor.b;
float translucent_thickness = l * l;
float translucent_thickness_exp = exp( translucent_thickness * translucentFalloff);
- return( translucent_thickness_exp * vec4( factor * lightDiffuse, 1.0f ) );
+ return( translucent_thickness_exp * vec4( factor * lightDiffuse, 1.0 ) );
}
diff --git a/res/effectlib/fileBumpTexture.glsllib b/res/effectlib/fileBumpTexture.glsllib
index 0f27fd8..d0129a8 100644
--- a/res/effectlib/fileBumpTexture.glsllib
+++ b/res/effectlib/fileBumpTexture.glsllib
@@ -83,7 +83,7 @@ vec3 fileBumpTexture( in sampler2D sampler, in float factor, in int bumpSource
// currently no lod supported we use 3.3 GL
//float lod = textureQueryLod( sampler, uvw.position.xy ).x;
vec2 size = mix( vec2( textureSize( sampler, int( floor( lod ) ) ) ), vec2( textureSize( sampler, int( ceil( lod ) ) ) ), fract( lod ) );
- vec2 unitStep = 1.0f / size;
+ vec2 unitStep = 1.0 / size;
// Add an inveres scale to keep the original gradient values
// this makes the bumps a lot smoother.
diff --git a/res/effectlib/flakeNoiseBumpTexture.glsllib b/res/effectlib/flakeNoiseBumpTexture.glsllib
index 6bd5f7e..e8e427c 100644
--- a/res/effectlib/flakeNoiseBumpTexture.glsllib
+++ b/res/effectlib/flakeNoiseBumpTexture.glsllib
@@ -34,7 +34,7 @@ vec3 flakeNoiseBumpTexture( in texture_coordinate_info uvw, in float scale, in f
vec3 grad = miNoise( tex ).xyz;
// displace coordinate according to noise value
- tex += 2.0f * grad;
+ tex += 2.0 * grad;
// then use only integer coordinates, to make flakes transients harder and not wobbly
grad = miNoise( round( tex ) ).xyz;
diff --git a/res/effectlib/flakeNoiseTexture.glsllib b/res/effectlib/flakeNoiseTexture.glsllib
index 7a73968..92f15d3 100644
--- a/res/effectlib/flakeNoiseTexture.glsllib
+++ b/res/effectlib/flakeNoiseTexture.glsllib
@@ -34,11 +34,11 @@ texture_return flakeNoiseTexture( in texture_coordinate_info uvw, in float inten
vec3 grad = miNoise( tex ).xyz;
// displace coordinate according to noise value
- tex += 2.0f * grad;
+ tex += 2.0 * grad;
// then use only integer coordinates, to make flakes transients harder and not wobbly
vec4 noise = miNoise( floor( tex ) );
- float s = pow( noise.w, 1.0f / density ) * intensity;
+ float s = pow( noise.w, 1.0 / density ) * intensity;
texture_return tr;
tr.tint = vec3( noise.x, noise.y, noise.z );
@@ -53,11 +53,11 @@ texture_return flakeNoiseAndBumpTexture( in texture_coordinate_info uvw, in floa
vec3 grad = miNoise( tex ).xyz;
// displace coordinate according to noise value
- tex += 2.0f * grad;
+ tex += 2.0 * grad;
// then use only integer coordinates, to make flakes transients harder and not wobbly
vec4 noise = miNoise( round( tex ) );
- float s = pow( noise.w, 1.0f / density ) * intensity;
+ float s = pow( noise.w, 1.0 / density ) * intensity;
texture_return tr;
tr.tint = normalize( normal/strength + ( uvw.tangent_u * grad.x + uvw.tangent_v * grad.y + normal * abs( grad.z ) ) );
diff --git a/res/effectlib/fresnelLayer.glsllib b/res/effectlib/fresnelLayer.glsllib
index a9b4087..60d7176 100644
--- a/res/effectlib/fresnelLayer.glsllib
+++ b/res/effectlib/fresnelLayer.glsllib
@@ -61,8 +61,8 @@ vec3 pseudoFresnel( in vec3 N, in vec3 ior, float fresnelPower )
float fresnel( in float eta1, in float eta2, in float cosTheta1 )
{
float etaInv = eta1 / eta2;
- float cosTheta2 = 1.0f - ( 1.0f - cosTheta1 * cosTheta1 ) * ( etaInv * etaInv );
- if ( 0.0f <= cosTheta2 )
+ float cosTheta2 = 1.0 - ( 1.0 - cosTheta1 * cosTheta1 ) * ( etaInv * etaInv );
+ if ( 0.0 <= cosTheta2 )
{
cosTheta2 = sqrt( cosTheta2 );
float n1t1 = eta1 * cosTheta1;
@@ -71,29 +71,29 @@ float fresnel( in float eta1, in float eta2, in float cosTheta1 )
float n2t2 = eta2 * cosTheta2;
float rs = ( n1t1 - n2t2 ) / ( n1t1 + n2t2 );
float rp = ( n1t2 - n2t1 ) / ( n1t2 + n2t1 );
- float f = 0.5f * ( rs * rs + rp * rp );
+ float f = 0.5 * ( rs * rs + rp * rp );
return( clamp( f, 0.0, 1.0 ) );
}
else
{
- return( 1.0f );
+ return( 1.0 );
}
}
-// we assume, light rays run through air with ior == 1.0f
+// we assume, light rays run through air with ior == 1.0
// with eta = eta2 / eta1, we have
-// - when hitting a front face: eta2 == ior, eta1 == 1.0f => eta = ior
-// - when hitting a back face : eta2 == 1.0f, eta1 == ior => eta = 1.0f / ior
+// - when hitting a front face: eta2 == ior, eta1 == 1.0 => eta = ior
+// - when hitting a back face : eta2 == 1.0, eta1 == ior => eta = 1.0 / ior
vec3 fresnel( in vec3 N, in vec3 ior )
{
float cosTheta1 = dot( N, viewDir );
if ( gl_FrontFacing )
{
- return( vec3( fresnel( 1.0f, ior[0], cosTheta1 ), fresnel( 1.0f, ior[1], cosTheta1 ), fresnel( 1.0f, ior[2], cosTheta1 ) ) );
+ return( vec3( fresnel( 1.0, ior[0], cosTheta1 ), fresnel( 1.0, ior[1], cosTheta1 ), fresnel( 1.0, ior[2], cosTheta1 ) ) );
}
else
{
- return( vec3( fresnel( ior[0], 1.0f, cosTheta1 ), fresnel( ior[1], 1.0f, cosTheta1 ), fresnel( ior[2], 1.0f, cosTheta1 ) ) );
+ return( vec3( fresnel( ior[0], 1.0, cosTheta1 ), fresnel( ior[1], 1.0, cosTheta1 ), fresnel( ior[2], 1.0, cosTheta1 ) ) );
}
}
diff --git a/res/effectlib/gradient3Recolor.glsllib b/res/effectlib/gradient3Recolor.glsllib
index 18556f3..ba7d593 100644
--- a/res/effectlib/gradient3Recolor.glsllib
+++ b/res/effectlib/gradient3Recolor.glsllib
@@ -35,15 +35,15 @@ float gradientInterpolate( in int interpolationMode, in float value )
case gradient_interpolation_linear :
return( value );
case gradient_interpolation_off :
- return( 0.0f );
+ return( 0.0 );
case gradient_interpolation_ease_in :
- return( 1.0f - pow( 1.0f - value, 2.0f/3.0f ) );
+ return( 1.0 - pow( 1.0 - value, 2.0/3.0 ) );
case gradient_interpolation_ease_out :
- return( pow( value, 2.0f/3.0f ) );
+ return( pow( value, 2.0/3.0 ) );
case gradient_interpolation_ease_in_out :
- return( ( value <= 0.5f )
- ? 0.5f * pow( 2.0f * value, 2.0f/3.0f )
- : 0.5f + 0.5f * ( 1.0f - pow( 2.0f * ( 1.0f - value ), 2.0f/3.0f ) ) );
+ return( ( value <= 0.5 )
+ ? 0.5 * pow( 2.0 * value, 2.0/3.0 )
+ : 0.5 + 0.5 * ( 1.0 - pow( 2.0 * ( 1.0 - value ), 2.0/3.0 ) ) );
default:
return( value ); // default is linear
}
@@ -67,7 +67,7 @@ texture_return gradient3Recolor( in float gradientPositions[3], in vec3 gradient
float relPos = gradientInterpolate( interpolationModes[index], ( pos - gradientPositions[index] ) / ( gradientPositions[index+1] - gradientPositions[index] ) );
tr.tint = mix( gradientColors[index], gradientColors[index+1], relPos );
}
- tr.mono = 0.0f;
+ tr.mono = 0.0;
return( tr );
}
diff --git a/res/effectlib/gradientGetPosition.glsllib b/res/effectlib/gradientGetPosition.glsllib
index 26b687d..4ceece0 100644
--- a/res/effectlib/gradientGetPosition.glsllib
+++ b/res/effectlib/gradientGetPosition.glsllib
@@ -39,7 +39,7 @@ float hypot( in float x, in float y )
float t = min( x, y );
x = max( x, y );
t = t/x;
- return( x * sqrt( 1.0f + ( t * t ) ) );
+ return( x * sqrt( 1.0 + ( t * t ) ) );
}
float gradientGetPosition( in int gradientMode, in vec2 xy )
@@ -55,22 +55,22 @@ float gradientGetPosition( in int gradientMode, in vec2 xy )
return( tex.x * tex.x );
case gradient_box :
// gradient is based on the distance from the center
- return( max( abs( tex.x - 0.5f ), abs( tex.y - 0.5f ) ) );
+ return( max( abs( tex.x - 0.5 ), abs( tex.y - 0.5 ) ) );
case gradient_diagonal :
// gradient is based on the distance from the diagonal
- return( sqrt(2.0f) * abs( tex.x - tex.y ) );
+ return( sqrt(2.0) * abs( tex.x - tex.y ) );
case gradient_90_degree :
// Need to check
- return( 0.0f );
+ return( 0.0 );
case gradient_symmetric_90_degree :
// Need to check
- return( 0.0f );
+ return( 0.0 );
case gradient_radial :
// Distance from center
- return( 2.0f * hypot( tex.x - 0.5f, tex.y - 0.5f ) );
+ return( 2.0 * hypot( tex.x - 0.5, tex.y - 0.5 ) );
case gradient_360_degree :
// fall through need to check
default :
- return( 0.0f );
+ return( 0.0 );
}
}
diff --git a/res/effectlib/miNoise.glsllib b/res/effectlib/miNoise.glsllib
index f2daa81..5fbff37 100644
--- a/res/effectlib/miNoise.glsllib
+++ b/res/effectlib/miNoise.glsllib
@@ -30,7 +30,7 @@
vec4 miNoise( in vec3 xyz )
{
- const float div = 1.0f / 256.0f;
+ const float div = 1.0 / 256.0;
ivec3 itmp = ivec3( xyz );
ivec3 ixyz[3] = ivec3[]( itmp & 0xFF, itmp+1 & 0xFF, itmp+2 & 0xFF );
@@ -38,19 +38,19 @@ vec4 miNoise( in vec3 xyz )
vec3 dux, ux;
dux.z = fxyz.x * div;
- dux.y = div - 2.0f * dux.z;
+ dux.y = div - 2.0 * dux.z;
dux.x = dux.z - div;
- ux.z = 0.5f * fxyz.x * dux.z;
- ux.y = dux.z + 0.5f * ( div - fxyz.x * dux.z );
- ux.x = ux.z - dux.z + 0.5f * div;
+ ux.z = 0.5 * fxyz.x * dux.z;
+ ux.y = dux.z + 0.5 * ( div - fxyz.x * dux.z );
+ ux.x = ux.z - dux.z + 0.5 * div;
vec3 duy, uy;
duy.z = fxyz.y;
- duy.y = 1.0f - 2.0f * duy.z;
- duy.x = duy.z - 1.0f;
- uy.z = 0.5f * square( duy.z );
- uy.y = duy.z + 0.5f - square( duy.z );
- uy.x = uy.z - duy.z + 0.5f;
+ duy.y = 1.0 - 2.0 * duy.z;
+ duy.x = duy.z - 1.0;
+ uy.z = 0.5 * square( duy.z );
+ uy.y = duy.z + 0.5 - square( duy.z );
+ uy.x = uy.z - duy.z + 0.5;
float duz[3] = float[]( fxyz.z - 1.0, 1.0 - 2.0 * fxyz.z, fxyz.z );
float uz[3] = float[]( 0.5 * square( fxyz.z ) - fxyz.z + 0.5, fxyz.z + 0.5 - square( fxyz.z ), 0.5 * square( fxyz.z ) );
@@ -83,7 +83,7 @@ vec4 miNoise( in vec3 xyz )
int ixyzzz = ixyz[0].z ^ ixyz[1].z;
- vec4 ret = vec4( 0.0f, 0.0f, 0.0f, 0.0f );
+ vec4 ret = vec4( 0.0, 0.0, 0.0, 0.0 );
for ( int i=0 ; i<3 ; i++ )
{
diff --git a/res/effectlib/microfacetBSDF.glsllib b/res/effectlib/microfacetBSDF.glsllib
index e164fca..8e48910 100644
--- a/res/effectlib/microfacetBSDF.glsllib
+++ b/res/effectlib/microfacetBSDF.glsllib
@@ -93,7 +93,7 @@ float DtermGGXAniso( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughnessU
vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior,
in float roughnessU, in float roughnessV, int mode )
{
- vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
vec3 H = normalize(L + V);
float HdotL = clamp(dot(H, L), 0.0, 1.0);
float NdotL = dot(tanFrame[2], L);
@@ -123,17 +123,17 @@ vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecul
vec4 microfacetBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
{
- vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
#if !QT3DS_ENABLE_LIGHT_PROBE
if ( uEnvironmentMappingEnabled )
{
float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
vec3 R = reflect( -viewDir, tanFrame[2] );
rgb = 0.01 * evalEnvironmentMap( R, roughness );
- rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0f, roughnessU, roughnessV, scatter_reflect ).rgb;
+ rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV, scatter_reflect ).rgb;
}
#endif
- return( vec4( rgb, 1.0f ) );
+ return( vec4( rgb, 1.0 ) );
}
@@ -211,7 +211,7 @@ vec3 sampleEnv(in vec3 L, float pdf, uint sampleCount, float roughness )
float b = 0.5*log2( pdf * d );
// convert coord to 2D
- vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0f * PI ), acos( -L.y ) / PI );
+ vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0 * PI ), acos( -L.y ) / PI );
float weight = step( 0.0001, roughness );
float lod = max( 0.0, min( (a - b)*weight, envMapLevels ));
@@ -221,7 +221,7 @@ vec3 sampleEnv(in vec3 L, float pdf, uint sampleCount, float roughness )
vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
{
- vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
float roughness = clamp( calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ), 0.0, 1.0 );
@@ -253,7 +253,7 @@ vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnes
rgb /= float(NumSamples);
- return( vec4( rgb, 1.0f ) );
+ return( vec4( rgb, 1.0 ) );
}
#endif
diff --git a/res/effectlib/normalizedMix.glsllib b/res/effectlib/normalizedMix.glsllib
index 7a44022..fc90b46 100644
--- a/res/effectlib/normalizedMix.glsllib
+++ b/res/effectlib/normalizedMix.glsllib
@@ -36,7 +36,7 @@ vec4 normalizedMix( in bsdf_component components[1] )
vec4 normalizedMix( in bsdf_component components[2] )
{
float sum = components[0].weight + components[1].weight;
- float invSum = ( sum <= 1.0f ) ? 1.0f : 1.0f / sum;
+ float invSum = ( sum <= 1.0 ) ? 1.0 : 1.0 / sum;
return( invSum * ( components[0].weight * components[0].component + components[1].weight * components[1].component ) );
}
diff --git a/res/effectlib/perlinNoise.glsllib b/res/effectlib/perlinNoise.glsllib
index 1fef880..347386c 100644
--- a/res/effectlib/perlinNoise.glsllib
+++ b/res/effectlib/perlinNoise.glsllib
@@ -45,13 +45,13 @@ vec2 fade( in vec2 x )
vec3 fade( in vec3 x )
{
return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
- //return( x * x * ( 3.0f - 2.0f * x ) );
+ //return( x * x * ( 3.0 - 2.0 * x ) );
}
vec4 fade( in vec4 x )
{
return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
- //return( x * x * ( 3.0f - 2.0f * x ) );
+ //return( x * x * ( 3.0 - 2.0 * x ) );
}
float influence( in int hash, in float x )
@@ -80,7 +80,7 @@ float perlinNoise( in float pos )
int intPos = int( floorPos );
float fracPos = pos - floorPos;
- return( mix( influence( random255X( intPos ), fracPos ), influence( random255X( intPos+1 ), fracPos - 1.0f ), fade( fracPos ) ) );
+ return( mix( influence( random255X( intPos ), fracPos ), influence( random255X( intPos+1 ), fracPos - 1.0 ), fade( fracPos ) ) );
}
float perlinNoise( in vec2 pos )
@@ -95,9 +95,9 @@ float perlinNoise( in vec2 pos )
int by = random255Y( int(floorPos.y) + 1 );
return( mix( mix( influence( ax^ay, fracPos.x, fracPos.y )
- , influence( bx^ay, fracPos.x - 1.0f, fracPos.y ), fadedPos.x )
- , mix( influence( ax^by, fracPos.x, fracPos.y - 1.0f )
- , influence( bx^by, fracPos.x - 1.0f, fracPos.y - 1.0f ), fadedPos.x ), fadedPos.y ) );
+ , influence( bx^ay, fracPos.x - 1.0, fracPos.y ), fadedPos.x )
+ , mix( influence( ax^by, fracPos.x, fracPos.y - 1.0 )
+ , influence( bx^by, fracPos.x - 1.0, fracPos.y - 1.0 ), fadedPos.x ), fadedPos.y ) );
}
float perlinNoise( in vec3 pos )
@@ -119,13 +119,13 @@ float perlinNoise( in vec3 pos )
int bxby = bx ^ by;
return( mix( mix( mix( influence( axay^az, fracPos.x, fracPos.y, fracPos.z )
- , influence( bxay^az, fracPos.x - 1.0f, fracPos.y, fracPos.z ), fadedPos.x )
- , mix( influence( axby^az, fracPos.x, fracPos.y - 1.0f, fracPos.z )
- , influence( bxby^az, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z ), fadedPos.x ), fadedPos.y )
- , mix( mix( influence( axay^bz, fracPos.x, fracPos.y , fracPos.z - 1.0f )
- , influence( bxay^bz, fracPos.x - 1.0f, fracPos.y , fracPos.z - 1.0f ), fadedPos.x )
- , mix( influence( axby^bz, fracPos.x, fracPos.y - 1.0f, fracPos.z - 1.0f )
- , influence( bxby^bz, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z - 1.0f ), fadedPos.x ), fadedPos.y ), fadedPos.z ) );
+ , influence( bxay^az, fracPos.x - 1.0, fracPos.y, fracPos.z ), fadedPos.x )
+ , mix( influence( axby^az, fracPos.x, fracPos.y - 1.0, fracPos.z )
+ , influence( bxby^az, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z ), fadedPos.x ), fadedPos.y )
+ , mix( mix( influence( axay^bz, fracPos.x, fracPos.y , fracPos.z - 1.0 )
+ , influence( bxay^bz, fracPos.x - 1.0, fracPos.y , fracPos.z - 1.0 ), fadedPos.x )
+ , mix( influence( axby^bz, fracPos.x, fracPos.y - 1.0, fracPos.z - 1.0 )
+ , influence( bxby^bz, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z - 1.0 ), fadedPos.x ), fadedPos.y ), fadedPos.z ) );
}
float perlinNoise( in vec4 pos )
@@ -154,45 +154,45 @@ float perlinNoise( in vec4 pos )
int bzaw = bz ^ aw;
result[i] = mix( mix( mix( influence( axay^azaw, fracPos.x, fracPos.y, fracPos.z, fracPos.w )
- , influence( bxay^azaw, fracPos.x - 1.0f, fracPos.y, fracPos.z, fracPos.w ), fadedPos.x )
- , mix( influence( axby^azaw, fracPos.x, fracPos.y - 1.0f, fracPos.z, fracPos.w )
- , influence( bxby^azaw, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z, fracPos.w ), fadedPos.x ), fadedPos.y )
- , mix( mix( influence( axay^bzaw, fracPos.x, fracPos.y, fracPos.z - 1.0f, fracPos.w )
- , influence( bxay^bzaw, fracPos.x - 1.0f, fracPos.y, fracPos.z - 1.0f, fracPos.w ), fadedPos.x )
- , mix( influence( axby^bzaw, fracPos.x, fracPos.y - 1.0f, fracPos.z - 1.0f, fracPos.w )
- , influence( bxby^bzaw, fracPos.x - 1.0f, fracPos.y - 1.0f, fracPos.z - 1.0f, fracPos.w ), fadedPos.x ), fadedPos.y ), fadedPos.z );
+ , influence( bxay^azaw, fracPos.x - 1.0, fracPos.y, fracPos.z, fracPos.w ), fadedPos.x )
+ , mix( influence( axby^azaw, fracPos.x, fracPos.y - 1.0, fracPos.z, fracPos.w )
+ , influence( bxby^azaw, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z, fracPos.w ), fadedPos.x ), fadedPos.y )
+ , mix( mix( influence( axay^bzaw, fracPos.x, fracPos.y, fracPos.z - 1.0, fracPos.w )
+ , influence( bxay^bzaw, fracPos.x - 1.0, fracPos.y, fracPos.z - 1.0, fracPos.w ), fadedPos.x )
+ , mix( influence( axby^bzaw, fracPos.x, fracPos.y - 1.0, fracPos.z - 1.0, fracPos.w )
+ , influence( bxby^bzaw, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z - 1.0, fracPos.w ), fadedPos.x ), fadedPos.y ), fadedPos.z );
aw = random255W( int(floorPos.w) + 1 );
- fracPos.w -= 1.0f;
+ fracPos.w -= 1.0;
}
return( mix( result[0], result[1], fadedPos.w ) );
}
float summedPerlinNoise( in vec3 pos, in int terms, in bool absNoise )
{
- float sum = 0.0f;
- float weight = 1.0f;
+ float sum = 0.0;
+ float weight = 1.0;
vec3 p = pos;
while ( terms-- != 0 )
{
float noise = perlinNoise( p );
sum += weight * ( absNoise ? abs(noise) : noise );
p += p;
- weight *= 0.5f;
+ weight *= 0.5;
}
return( sum );
}
float summedPerlinNoise( in vec4 pos, in int terms, in bool absNoise )
{
- float sum = 0.0f;
- float weight = 1.0f;
+ float sum = 0.0;
+ float weight = 1.0;
vec4 p = pos;
while ( terms-- != 0 )
{
float noise = perlinNoise( p );
sum += weight * ( absNoise ? abs(noise) : noise );
p += p;
- weight *= 0.5f;
+ weight *= 0.5;
}
return( sum );
}
@@ -200,34 +200,34 @@ float summedPerlinNoise( in vec4 pos, in int terms, in bool absNoise )
float perlinNoise( in vec3 pos, in float time, in int terms, in vec3 turbulenceWeight, in bool absoluteNoise, in bool applyMarble
, in bool applyDent, in float noiseBands, in float noiseThresholdHigh, in float noiseThresholdLow )
{
- float noise = ( time == 0.0f ) ? summedPerlinNoise( pos, terms, absoluteNoise ) : summedPerlinNoise( vec4( pos, time ), terms, absoluteNoise );
- if ( turbulenceWeight != vec3( 0.0f, 0.0f, 0.0f ) )
+ float noise = ( time == 0.0 ) ? summedPerlinNoise( pos, terms, absoluteNoise ) : summedPerlinNoise( vec4( pos, time ), terms, absoluteNoise );
+ if ( turbulenceWeight != vec3( 0.0, 0.0, 0.0 ) )
{
noise = sin( dot( pos, turbulenceWeight ) + noise );
}
if ( ! absoluteNoise )
{
- noise = 0.5f * noise + 0.5f; // scale [-1,1] to [0,1]
+ noise = 0.5 * noise + 0.5; // scale [-1,1] to [0,1]
}
if ( applyMarble )
{
- noise = cos( pos.x + 5.0f * noise ); // classic Perlin marble function, with magic 5.0f
+ noise = cos( pos.x + 5.0 * noise ); // classic Perlin marble function, with magic 5.0
}
if ( applyDent )
{
noise = cube( noise );
}
- if ( noiseBands != 1.0f )
+ if ( noiseBands != 1.0 )
{
// Create banding/stripes by using the fraction component only
noise *= noiseBands;
noise -= floor( noise );
- noise += pow( 1.0f - noise, 20.0f );
+ noise += pow( 1.0 - noise, 20.0 );
}
if ( noiseThresholdLow < noiseThresholdHigh )
{
// clamp the noise
- noise = clamp( ( noise - noiseThresholdLow ) / ( noiseThresholdHigh - noiseThresholdLow ), 0.0f, 1.0f );
+ noise = clamp( ( noise - noiseThresholdLow ) / ( noiseThresholdHigh - noiseThresholdLow ), 0.0, 1.0 );
}
return( noise );
}
diff --git a/res/effectlib/physGlossyBSDF.glsllib b/res/effectlib/physGlossyBSDF.glsllib
index ff0eb8c..ece836b 100644
--- a/res/effectlib/physGlossyBSDF.glsllib
+++ b/res/effectlib/physGlossyBSDF.glsllib
@@ -66,7 +66,7 @@ vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecul
float NdotL = dot(tanFrame[2], L);
float HdotL = clamp(dot(H, L), 0.0, 1.0);
- // if (0.0f < NdotL)
+ // if (0.0 < NdotL)
// {
vec3 Haf = L + V;
@@ -123,7 +123,7 @@ vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecul
float NdotL = dot(tanFrame[2], L);
float HdotL = clamp(dot(H, L), 0.0, 1.0);
-// if (0.0f < NdotL)
+// if (0.0 < NdotL)
// {
vec3 Haf = L + V;
diff --git a/res/effectlib/sampleArea.glsllib b/res/effectlib/sampleArea.glsllib
index 70c7ae0..01f3a74 100644
--- a/res/effectlib/sampleArea.glsllib
+++ b/res/effectlib/sampleArea.glsllib
@@ -113,7 +113,7 @@ vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 v
float sigmaV = clamp( 0.5 * roughV, 0.005, 0.5 );
vec2 UVset[5];
- mat3 lightFrame = mat3( arealights[lightIdx].right.xyz, arealights[lightIdx].up.xyz, arealights[lightIdx].direction.xyz );
+ mat3 lightFrame = mat3( arealights[lightIdx].right.xyz, arealights[lightIdx].up.xyz, -arealights[lightIdx].direction.xyz );
float thetaI = acos( dot(viewDir, lightFrame[2]) );
vec2 minMaxThetaH = vec2( (thetaI - 1.5707) * 0.5,
@@ -154,7 +154,7 @@ vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx )
{
float intensity = 0.0;
vec3 finalDir;
- intensity = calculateDiffuseAreaOld( -arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
+ intensity = calculateDiffuseAreaOld( arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir );
intensity *= clamp( dot(finalDir, tanFrame[2]), 0.0, 1.0 );
return vec4( intensity );
@@ -164,11 +164,11 @@ vec4 sampleAreaDiffuseTransmissive( in mat3 tanFrame, in vec3 pos, in int lightI
{
float intensity = 0.0;
vec3 finalDir;
- intensity = calculateDiffuseAreaOld( -arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
+ intensity = calculateDiffuseAreaOld( arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir );
intensity *= clamp( dot(finalDir, -tanFrame[2]), 0.0, 1.0 );
- float l = 0.2126f * transmissiveColor.r + 0.7152f * transmissiveColor.g + 0.0722f * transmissiveColor.b;
+ float l = 0.2126 * transmissiveColor.r + 0.7152 * transmissiveColor.g + 0.0722 * transmissiveColor.b;
float I = max( 0.0, ((dot(finalDir, -tanFrame[2]) + lightWrap)/ (1.0 + lightWrap)) );
float translucent_thickness = l * l;
diff --git a/res/effectlib/sampleLight.glsllib b/res/effectlib/sampleLight.glsllib
index 3218cdf..8afd8e2 100644
--- a/res/effectlib/sampleLight.glsllib
+++ b/res/effectlib/sampleLight.glsllib
@@ -59,7 +59,7 @@ void sampleLight(in LightSource light,
out vec3 opSpecular)
{
float att = 1.0;
- if (light.position.w == 0.0f) // directional light
+ if (light.position.w == 0.0) // directional light
{
wi = normalize(light.position.xyz);
#if QT3DS_ENABLE_SSM
@@ -67,7 +67,7 @@ void sampleLight(in LightSource light,
att *= sampleOrthographic( shadowMaps[light.shadowIdx], light.shadowControls, light.shadowView, pos, vec2(1.0, light.shadowControls.z) );
#endif
}
- else if (light.width > 0.01f && light.height > 0.01f) // area light
+ else if (light.width > 0.01 && light.height > 0.01) // area light
{
// This approach is based on the 1994 Tech Report by James Arvo --
// The Irradiance Jacobian for Partially Occluded Polyhedral Sources
@@ -106,12 +106,12 @@ void sampleLight(in LightSource light,
wi = light.position.xyz - pos;
float dist = length(wi);
wi = wi / dist; // == normalize(wi);
- att = 1.0f / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist);
+ att = 1.0 / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist);
/*
- if (light.spotCutoff < 180.0f) // spot light
+ if (light.spotCutoff < 180.0) // spot light
{
- float spot = max(0.0f, dot(wi, -light.direction.xyz));
- att *= (spot >= cos(light.spotCutoff * PI / 180.0f)) ? pow(spot, light.spotExponent) : 0.0f;
+ float spot = max(0.0, dot(wi, -light.direction.xyz));
+ att *= (spot >= cos(light.spotCutoff * PI / 180.0)) ? pow(spot, light.spotExponent) : 0.0;
}
*/
#if QT3DS_ENABLE_SSM
diff --git a/res/effectlib/simpleGlossyBSDF.glsllib b/res/effectlib/simpleGlossyBSDF.glsllib
index 31a9ac5..be6024c 100644
--- a/res/effectlib/simpleGlossyBSDF.glsllib
+++ b/res/effectlib/simpleGlossyBSDF.glsllib
@@ -31,10 +31,10 @@
vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecular, in float ior
, in float roughnessU, in float roughnessV, int mode )
{
- vec4 rgba = vec4( 0.0f, 0.0f, 0.0f, 1.0f );
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
float cosTheta = dot( tanFrame[2], L );
- if ( 0.0f < cosTheta )
+ if ( 0.0 < cosTheta )
{
float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
@@ -42,7 +42,7 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecula
{
vec3 R = reflect( -L, tanFrame[2] );
float cosine = dot( R, V );
- float shine = ( 0.0f < cosine ) ? ( ( 0.0f < roughness ) ? pow( cosine, 1.0f / roughness ) : ( 0.9999f <= cosine ) ? 1.0f : 0.0f ) : 0.0f;
+ float shine = ( 0.0 < cosine ) ? ( ( 0.0 < roughness ) ? pow( cosine, 1.0 / roughness ) : ( 0.9999 <= cosine ) ? 1.0 : 0.0 ) : 0.0;
rgba.rgb = shine * lightSpecular;
}
}
@@ -50,13 +50,13 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecula
{
// check against total reflection
vec3 R = refract( -V, tanFrame[2], ior );
- if ( R == vec3( 0.0f, 0.0f, 0.0f ) )
+ if ( R == vec3( 0.0, 0.0, 0.0 ) )
{
- rgba.a = 1.0f;
+ rgba.a = 1.0;
}
else
{
- rgba.a = 0.0f;
+ rgba.a = 0.0;
}
}
@@ -65,17 +65,17 @@ vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecula
vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
{
- vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
#if !QT3DS_ENABLE_LIGHT_PROBE
if ( uEnvironmentMappingEnabled )
{
float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
vec3 R = reflect( -viewDir, tanFrame[2] );
rgb = evalEnvironmentMap( R, roughness );
- rgb = simpleGlossyBSDF( tanFrame, R, viewDir, rgb, 1.0f, roughnessU, roughnessV, scatter_reflect ).rgb;
+ rgb = simpleGlossyBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV, scatter_reflect ).rgb;
}
#endif
- return( vec4( rgb, 1.0f ) );
+ return( vec4( rgb, 1.0 ) );
}
// RNM radiosity normal maps
diff --git a/res/effectlib/specularBSDF.glsllib b/res/effectlib/specularBSDF.glsllib
index 9e31544..78e541a 100644
--- a/res/effectlib/specularBSDF.glsllib
+++ b/res/effectlib/specularBSDF.glsllib
@@ -34,14 +34,14 @@
vec4 specularBSDFEnvironment( in vec3 N, in vec3 viewDir, in vec3 tint, int mode )
{
- vec3 rgb = vec3( 0.0f, 0.0f, 0.0f );
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
if ( uEnvironmentMappingEnabled )
{
vec3 R = reflect( -viewDir, N );
- rgb = evalEnvironmentMap( R, 0.0f );
+ rgb = evalEnvironmentMap( R, 0.0 );
rgb = specularBSDF( N, R, viewDir, rgb, 1.0, 256.0, tint, scatter_reflect ).rgb;
}
- return( vec4( rgb, 1.0f ) );
+ return( vec4( rgb, 1.0 ) );
}
#endif
diff --git a/res/effectlib/spotEdf.glsllib b/res/effectlib/spotEdf.glsllib
index 663bd8f..2abe194 100644
--- a/res/effectlib/spotEdf.glsllib
+++ b/res/effectlib/spotEdf.glsllib
@@ -35,7 +35,7 @@ float spotEdf( float exponent )
float dist = length(viewDir);
vec3 spotDir = viewDir / dist;
- float spot = max(0.0f, dot(spotDir, normal));
+ float spot = max(0.0, dot(spotDir, normal));
att = pow(spot, exponent);
return att;
diff --git a/src/3rdparty/imgui/qt_attribution.json b/src/3rdparty/imgui/qt_attribution.json
index d3b4381..fd789fc 100644
--- a/src/3rdparty/imgui/qt_attribution.json
+++ b/src/3rdparty/imgui/qt_attribution.json
@@ -2,7 +2,7 @@
{
"Id": "imgui",
"Name": "Dear ImGui",
- "QDocModule": "Qt3DStudioRuntime2",
+ "QDocModule": "qt3dstudioruntime2",
"Description": "Dear ImGui",
"QtUsage": "Bloat-free GUI library for in-scene visualization of profiling and debugging data",
diff --git a/src/imports/studio3d/q3dsstudio3ditem.cpp b/src/imports/studio3d/q3dsstudio3ditem.cpp
index b585122..1c16b89 100644
--- a/src/imports/studio3d/q3dsstudio3ditem.cpp
+++ b/src/imports/studio3d/q3dsstudio3ditem.cpp
@@ -89,36 +89,42 @@ QT_BEGIN_NAMESPACE
}
}
\endqml
-*/
-/*!
- \qmlsignal Studio3D::frameUpdate()
+ \section2 Controlling the presentation
- This signal is emitted each time a frame has been updated regardless of
- visibility. This allows a hidden Studio3D element to still process
- information every frame, even though the renderer is not rendering.
+ Like the example above suggests, Studio3D and the other types under the
+ QtStudio3D import offer more than simply rendering the animated Qt 3D
+ Studio presentation. They also offer scene manipulation, including
- The corresponding handler is \c onFrameUpdate.
+ \list
- To prevent expensive handlers from being processed when hidden, add an
- early return to the top like:
+ \li querying and changing scene object properties (for example, the
+ transform of a model, colors and other settings of a material, etc.) via
+ Presentation::getAttribute(), Presentation::setAttribute(), \l Element, and
+ \l DataInput,
- \qml
- onFrameUpdate: {
- if (!visible) return;
- ...
- }
- \endqml
+ \li changing slides (and thus starting the relevant animations and applying
+ the scene object property changes associated with the new slide) via
+ Presentation::goToSlide(), \l SceneElement, and \l DataInput,
+
+ \li and controlling the timeline (the current playback position for the
+ key-frame based animations) both on the main scene and on individual
+ Component nodes via Presentation::goToTime(), \l SceneElement, and \l DataInput.
+
+ \endlist
+*/
+
+/*!
+ \qmlsignal Studio3D::frameUpdate()
+
+ This signal is emitted each time a frame has been rendered.
*/
/*!
\qmlsignal Studio3D::presentationReady()
This signal is emitted when the viewer has been initialized and the
- presentation is ready to be shown. The difference to \c running property is
- that the viewer has to be visible for \c running to get \c{true}. This
- signal is useful for displaying splash screen while viewer is getting
- initialized.
+ presentation is ready to be shown.
*/
static bool engineCleanerRegistered = false;
@@ -181,6 +187,16 @@ bool Q3DSStudio3DItem::isRunning() const
return m_running;
}
+/*!
+ \qmlproperty string Studio3D::error
+
+ Contains the text for the error message that was generated during the
+ loading of the presentation. When no error occurred or there is no
+ presentation loaded, the value is an empty string.
+
+ This property is read-only.
+*/
+
QString Q3DSStudio3DItem::error() const
{
return m_error;
diff --git a/src/imports/studio3d/q3dssubpresentationsettings.cpp b/src/imports/studio3d/q3dssubpresentationsettings.cpp
index e8ffcea..44d9e43 100644
--- a/src/imports/studio3d/q3dssubpresentationsettings.cpp
+++ b/src/imports/studio3d/q3dssubpresentationsettings.cpp
@@ -83,6 +83,27 @@ QQmlListProperty<Q3DSInlineQmlSubPresentation> Q3DSSubPresentationSettings::qmlS
}
}
\endqml
+
+ \section2 Linking to the Presentation via presentationId
+
+ In Qt 3D Studio presentations QML sub-presentations are specified in the \e
+ assets element of the presentation's \c{.uia} file. This is important also
+ when using SubPresentationSettings and QmlStream.
+
+ \badcode
+ <assets ...>
+ <presentation-qml id="presentation-id" args="preview-presentation.qml" />
+ </assets>
+ \endcode
+
+ \note the Qt 3D Studio application takes care of generating the \c{.uia}
+ file based on what the designers have set in the Sub-presentations dialog.
+
+ The \c presentation-id attribute must contain a unique ID for the
+ sub-presentation. The corresponding \l QmlStream must provide the same
+ value in its presentationId property. The \c args attribute may contain an
+ optional preview version of the item, which is only used in the Viewer
+ application.
*/
/*!
@@ -97,36 +118,27 @@ QQmlListProperty<Q3DSInlineQmlSubPresentation> Q3DSSubPresentationSettings::qmlS
\ingroup 3dstudioruntime2
\brief QML stream.
- This type allows attaching QML sub-presentation with a quick item. The item is rendered to a
- texture and used as a part of a Qt 3D Studio presentation.
-
- The sub-presentation element must be specified in the \e assets element of the presentation
- .uia file:
-
- \badcode
- <assets ...>
- <presentation-qml id="presentation-id" args="preview-presentation.qml" />
- </assets>
- \endcode
+ This type allows specifying the contents of a QML sub-presentation within
+ the Studio3D item. QmlStream must be used in combination with
+ \l SubPresentationSettings.
- The \c presentation-id attribute must contain a unique ID of the sub-presentation.
- The \c args attribute may contain an optional preview version of the item, which is only
- used in the Viewer application.
+ \sa SubPresentationSettings
*/
/*!
\qmlproperty string QmlStream::presentationId
- Holds the string ID of the sub-presentation the item is attached to. The id must be one of
- the \c presentation-qml IDs specified in the .uia file.
+ Holds the string ID of the sub-presentation the contents of which is
+ specified by \l item. The id must be one of the \c presentation-qml IDs
+ specified in the \c{.uia} file.
*/
/*!
\qmlproperty Item QmlStream::item
- Holds the item attached to the sub-presentation. The item size is used as the the size of the
- texture the item is rendered to. Default values \c{(256, 256)} are used if the item doesn't
- specify a size.
+ Holds the item attached to the sub-presentation. The item size is used as
+ the the size of the texture the item is rendered to. A default value of
+ \c{(128, 128)} is used when the item does not specify a size.
*/
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dsdatainput.cpp b/src/runtime/api/q3dsdatainput.cpp
index 69cafe3..77b999a 100644
--- a/src/runtime/api/q3dsdatainput.cpp
+++ b/src/runtime/api/q3dsdatainput.cpp
@@ -111,10 +111,11 @@ void Q3DSDataInput::setName(const QString &name)
The value of this property only accounts for changes done via the same
Q3DSDataInput instance. If the value of the same data input in the
- presentation is changed elsewhere, for example via presentation scripting,
- those changes are not reflected in the value of this property. Due to this
- uncertainty, this property treats all value sets as changes even if the
- newly set value is the same value as the previous value.
+ presentation is changed elsewhere, for example via animations or
+ Q3DSPresentation::setAttribute(), those changes are not reflected in the
+ value of this property. Due to this uncertainty, this property treats all
+ value sets as changes even if the newly set value is the same value as the
+ previous value.
*/
QVariant Q3DSDataInput::value() const
{
@@ -149,9 +150,54 @@ void Q3DSDataInputPrivate::sendValue()
\instantiates Q3DSDataInput
\inqmlmodule QtStudio3D
\ingroup 3dstudioruntime2
- \brief Control type for data inputs in a Qt 3D Studio presentation.
- This type is a convenience type for controlling a data input in a presentation.
+ \brief Controls a data input entry in a Qt 3D Studio presentation.
+
+ This type is a convenience for controlling a data input in a presentation.
+ Its functionality is equivalent to Presentation::setDataInputValue(),
+ however it has a big advantage of being able to use QML property bindings,
+ thus avoiding the need to having to resort to a JavaScript function call
+ for every value change.
+
+ As an example, compare the following two approaches:
+
+ \qml
+ Studio3D {
+ ...
+ Presentation {
+ id: presentation
+ ...
+ }
+ }
+
+ Button {
+ onClicked: presentation.setAttribute("SomeTextNode", "textstring", "Hello World")
+ }
+ \endqml
+
+ \qml
+ Studio3D {
+ ...
+ Presentation {
+ id: presentation
+ ...
+ property string text: ""
+ DataInput {
+ name: "inputForSomeTextNode"
+ value: presentation.text
+ }
+ }
+ }
+
+ Button {
+ onClicked: presentation.text = "Hello World"
+ }
+ \endqml
+
+ The latter assumes that a data input connection was made in Qt 3D Studio
+ between the \c textstring property of \c SomeTextNode and a data input name
+ \c inputForSomeTextNode. As the value is now set via a property, the full
+ set of QML property bindings techniques are available.
\sa Studio3D, Presentation
*/
@@ -159,22 +205,23 @@ void Q3DSDataInputPrivate::sendValue()
/*!
\qmlproperty string DataInput::name
- Specifies the name of the controlled data input element in the presentation.
- This property must be set as part of DataInput declaration.
+ Specifies the name of the controlled data input element in the
+ presentation. This property must be set as part of DataInput declaration,
+ although it is changeable afterwards, if desired.
*/
/*!
\qmlproperty variant DataInput::value
Specifies the value of the controlled data input element in the presentation.
- The changes to the value property are queued and handled asynchronously before the
- next frame is displayed.
-
- The value of this property only accounts for changes done via the same DataInput instance.
- If the value of the same data input in the presentation is changed elsewhere,
- for example via presentation scripting, those changes are not reflected in
- the value of this property. Due to this uncertainty, this property treats all value sets as
- changes even if the newly set value is the same value as the previous value.
+
+ The value of this property only accounts for changes done via the same
+ DataInput instance. If the value of the underlying attribute in the
+ presentation is changed elsewhere, for example via animations or
+ Presentation::setAttribute(), those changes are not reflected in the value
+ of this property. Due to this uncertainty, this property treats all value
+ sets as changes even if the newly set value is the same value as the
+ previous value.
*/
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dselement.cpp b/src/runtime/api/q3dselement.cpp
index 3e72e83..a09d21e 100644
--- a/src/runtime/api/q3dselement.cpp
+++ b/src/runtime/api/q3dselement.cpp
@@ -37,7 +37,7 @@ QT_BEGIN_NAMESPACE
\inmodule 3dstudioruntime2
\since Qt 3D Studio 2.0
- \brief Controls a scene object in a Qt 3D Studio presentation.
+ \brief Controls a scene object (node) in a Qt 3D Studio presentation.
This class is a convenience class for controlling the properties of a scene
object (such as, model, material, camera, layer) in a Qt 3D Studio
@@ -183,10 +183,12 @@ void Q3DSElementPrivate::setPresentation(Q3DSPresentation *pres)
\ingroup 3dstudioruntime2
\brief Control type for elements in a Qt 3D Studio presentation.
- This type is a convenience type for managing a presentation element.
+ This type is a convenience for controlling the properties of a scene object
+ (such as, model, material, camera, layer) in a Qt 3D Studio presentation.
- All methods provided by this type are queued and handled asynchronously before the next
- frame is displayed.
+ \note The functionality of Element is equivalent to
+ Presentation::setAttribute(), Presentation::getAttribute() and
+ Presentation::fireEvent().
\sa Studio3D, Presentation, SceneElement
*/
@@ -195,37 +197,54 @@ void Q3DSElementPrivate::setPresentation(Q3DSPresentation *pres)
\qmlproperty string Element::elementPath
Holds the element path of the presentation element.
- This property must be set as part of Element declaration.
- You can specify an element of a sub-presentation by adding "SubPresentationId:"
- in front of the element path, for example \c{"SubPresentationOne:Scene"}.
-*/
-/*!
- \qmlmethod void Element::setAttribute(string attributeName, variant value)
+ An element path refers to an object in the scene either by name or id. The
+ latter is rarely used in application code since the unique IDs are not
+ exposed in the Qt 3D Studio application. To refer to an object by id,
+ prepend \c{#} to the name. Applications will typically refer to objects by
+ name.
- Sets the \a value of an attribute on an element specified by this instance.
- The \a attributeName is the \l{Attribute Names}{scripting name} of the attribute.
+ Names are not necessarily unique, however. To access an object with a
+ non-unique name, the path can be specified, for example,
+ \c{Scene.Layer.Camera}. Here the right camera object gets chosen even if
+ the scene contains other layers with the default camera names (for instance
+ \c{Scene.Layer2.Camera}).
- The attribute must be preserved for scripting to be set by this function, or else it will fail.
- An attribute is preserved if it is either \e{animated}, or
- \e{an attribute on a master element that is unlinked and changed per-slide}.
+ If the object is renamed to a unique name in the Qt 3D Studio application's
+ Timeline view, the path can be omitted. For example, if the camera in
+ question was renamed to \c MyCamera, applications can then simply pass \c
+ MyCamera as the element path.
+
+ To access an object in a sub-presentation, prepend the name of the
+ sub-presentation followed by a colon, for example,
+ \c{SubPresentationOne:Scene.Layer.Camera}.
*/
/*!
- \qmlmethod void Element::fireEvent(string eventName)
+ \qmlmethod variant Element::getAttribute(string attributeName)
+
+ Returns the current value of an attribute (property) of the scene object
+ specified by this Element instance. The \a attributeName is the
+ \l{Attribute Names}{scripting name} of the attribute.
+ */
- Dispatches an event with \a eventName on the element specified by this instance.
- Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
- method in attached scripts will be executed in response to the event.
+/*!
+ \qmlmethod void Element::setAttribute(string attributeName, variant value)
+
+ Sets the \a value of an attribute (property) of the scene object specified
+ by this Element instance. The \a attributeName is the \l{Attribute
+ Names}{scripting name} of the attribute.
*/
/*!
- \qmlsignal Element::elementPathChanged(string elementPath)
+ \qmlmethod void Element::fireEvent(string eventName)
- This signal is emitted when the element path property changes.
- The new value is provided in the \a elementPath parameter.
+ Dispatches an event with \a eventName on the scene object
+ specified by elementPath.
- The corresponding handler is \c onElementPathChanged.
+ Appropriate actions created in Qt 3D Studio or callbacks registered using
+ the registerForEvent() method in attached \c{behavior scripts} will be
+ executed in response to the event.
*/
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dspresentation.cpp b/src/runtime/api/q3dspresentation.cpp
index 0a797b2..3a8a055 100644
--- a/src/runtime/api/q3dspresentation.cpp
+++ b/src/runtime/api/q3dspresentation.cpp
@@ -128,6 +128,25 @@ void Q3DSPresentation::setSource(const QUrl &source)
emit sourceChanged();
}
+/*!
+ \property Q3DSPresentation::profilingEnabled
+
+ When enabled, Qt 3D objects managed by the runtime get tracked,
+ and various statistics get collected internally. These are then
+ exposed in the views that can be toggled by profileUiVisible.
+
+ The default value is \c false.
+
+ \note Changing the value after the presentation has been loaded
+ has no effect for the already loaded presentation. Therefore the
+ changing of this property must happen before calling setSource().
+
+ \note In the Qt 3D Studio Viewer application presentations are
+ opened with profiling enabled by default. Therefore, applications
+ wishing to have an experience comparable to the Viewer, when it
+ comes to the debug and profile views, should set this property to
+ \c true.
+*/
bool Q3DSPresentation::isProfilingEnabled() const
{
Q_D(const Q3DSPresentation);
@@ -149,6 +168,17 @@ void Q3DSPresentation::setProfilingEnabled(bool enable)
}
}
+/*!
+ \property Q3DSPresentation::profileUiVisible
+
+ When this property is \c{true}, the interactive statistics and profile
+ view is displayed in-scene, on top of the 3D content.
+
+ \note This feature can be disabled at build time, in which case this
+ property has no effect.
+
+ Default value is \c{false}.
+*/
bool Q3DSPresentation::isProfileUiVisible() const
{
Q_D(const Q3DSPresentation);
@@ -166,6 +196,13 @@ void Q3DSPresentation::setProfileUiVisible(bool visible)
}
}
+/*!
+ \property Q3DSPresentation::profileUiScale
+
+ Controls the scale factor of the in-scene debug and profile views.
+
+ The default value is 1.0.
+*/
float Q3DSPresentation::profileUiScale() const
{
Q_D(const Q3DSPresentation);
@@ -216,10 +253,11 @@ void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &va
}
/*!
- Dispatches an event with \a eventName on a specific element found in \a
- elementPath. Appropriate actions created in Qt 3D Studio or callbacks
- registered using the registerForEvent() method in attached (behavior)
- scripts will be executed in response to the event.
+ Dispatches a Qt 3D Studio presentation event with \a eventName on
+ scene object specified by \a elementPath. These events provide a
+ way to communicate with the \c .qml based \c{behavior scripts}
+ attached to scene objects since they can register to be notified
+ via Behavior::registerForEvent().
See setAttribute() for a description of \a elementPath.
*/
@@ -371,10 +409,54 @@ void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &a
d->controller->handleSetAttribute(elementPath, attributeName, value);
}
+/*!
+ \fn void Q3DSPresentation::customSignalEmitted(const QString &elementPath, const QString &name)
+
+ This signal is emitted when an action with the \c{Emit Signal}
+ handler is executed in the Qt 3D Studio presentation. \a
+ elementPath specifies the scene object on which the (Qt 3D Studio)
+ "signal" \a name was triggered.
+
+ Connecting to this signal offers a way of reacting upon certain
+ events in the Qt 3D Studio presentation.
+
+ \image customsignal.png
+
+ In this example, pressing or tapping on the Cluster object will result in
+ emitting \c{customSignalEmitted("Cluster", "clusterPressed")}.
+*/
+
+/*!
+ \fn Q3DSPresentation::slideEntered(const QString &elementPath, int index, const QString &name)
+
+ This signal is emitted when a slide is entered in the presentation. The \a
+ elementPath specifies the time context (a Scene or a Component element)
+ owning the entered slide. The \a index and \a name contain the index and
+ the name of the entered slide.
+*/
+
+/*!
+ \fn Q3DSPresentation::slideExited(const QString &elementPath, int index, const QString &name)
+
+ This signal is emitted when a slide is exited in the presentation. The \a
+ elementPath specifies the time context (a Scene or a Component element)
+ owning the exited slide. The \a index and \a name contain the index and the
+ name of the exited slide.
+*/
+
// These event forwarders are not stricly needed, Studio3D et al are fine
// without them. However, they are there in 3DS1 and can become handy to feed
// arbitrary, application-generated events into the engine.
+/*!
+ Passes a key press event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::keyPressEvent(QKeyEvent *e)
{
Q_D(Q3DSPresentation);
@@ -382,6 +464,15 @@ void Q3DSPresentation::keyPressEvent(QKeyEvent *e)
d->controller->handlePresentationKeyPressEvent(e);
}
+/*!
+ Passes a key release event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
{
Q_D(Q3DSPresentation);
@@ -389,6 +480,15 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
d->controller->handlePresentationKeyReleaseEvent(e);
}
+/*!
+ Passes a mouse press event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::mousePressEvent(QMouseEvent *e)
{
Q_D(Q3DSPresentation);
@@ -396,6 +496,15 @@ void Q3DSPresentation::mousePressEvent(QMouseEvent *e)
d->controller->handlePresentationMousePressEvent(e);
}
+/*!
+ Passes a mouse move event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e)
{
Q_D(Q3DSPresentation);
@@ -403,6 +512,15 @@ void Q3DSPresentation::mouseMoveEvent(QMouseEvent *e)
d->controller->handlePresentationMouseMoveEvent(e);
}
+/*!
+ Passes a mouse release event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(Q3DSPresentation);
@@ -410,6 +528,15 @@ void Q3DSPresentation::mouseReleaseEvent(QMouseEvent *e)
d->controller->handlePresentationMouseReleaseEvent(e);
}
+/*!
+ Passes a mouse double click event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::mouseDoubleClickEvent(QMouseEvent *e)
{
Q_D(Q3DSPresentation);
@@ -418,6 +545,15 @@ void Q3DSPresentation::mouseDoubleClickEvent(QMouseEvent *e)
}
#if QT_CONFIG(wheelevent)
+/*!
+ Passes a mouse wheel event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::wheelEvent(QWheelEvent *e)
{
Q_D(Q3DSPresentation);
@@ -426,6 +562,15 @@ void Q3DSPresentation::wheelEvent(QWheelEvent *e)
}
#endif
+/*!
+ Passes a touch event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::touchEvent(QTouchEvent *e)
{
Q_D(Q3DSPresentation);
@@ -434,6 +579,15 @@ void Q3DSPresentation::touchEvent(QTouchEvent *e)
}
#if QT_CONFIG(tabletevent)
+/*!
+ Passes a tablet (pen) event \a e to the presentation.
+
+ \note The event forwarders in Q3DSPresentation are not normally
+ needed since Q3DSWidget and Studio3D both pass mouse, keyboard and
+ touch input on to the Qt 3D Studio engine. They may become useful
+ however with Q3DSSurfaceViewer, or in special situations, in order
+ to inject input events.
+*/
void Q3DSPresentation::tabletEvent(QTabletEvent *e)
{
Q_D(Q3DSPresentation);
@@ -476,12 +630,76 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
\inqmlmodule QtStudio3D
\ingroup 3dstudioruntime2
- \brief Control type for Qt 3D Studio presentations.
+ \brief Represents a Qt 3D Studio presentation.
+
+ This class provides properties and methods for controlling a
+ presentation.
+
+ Qt 3D Studio supports multiple presentations in one project. There is
+ always a main presentation and zero or more sub-presentations. The
+ sub-presentations are composed into the main presentations either as
+ contents of Qt 3D Studio layers or as texture maps.
- This type provides properties and methods for controlling a presentation.
+ In the filesystem each presentation corresponds to one \c{.uip}
+ file. When present, the \c{.uia} file ties these together by
+ specifying a name for each of the (sub-)presentations and
+ specifies which one is the main one.
- All methods provided by this type are queued and handled asynchronously before the next
- frame is displayed.
+ From the API point of view Presentation corresponds to the main
+ presentation. The source property can refer either to a \c{.uia} or
+ \c{.uip} file. When specifying a file with \c{.uip} extension and a
+ \c{.uia} is present with the same name, the \c{.uia} is loaded
+ automatically and thus sub-presentation information is available
+ regardless.
+
+ The Presentation type handles child objects of the types \l Element, \l
+ SceneElement, \l DataInput, and \l SubPresentationSettings specially. These
+ will get automatically associated with the presentation and can control
+ certain aspects of it from that point on.
+
+ \section2 Example usage
+
+ \qml
+ Studio3D {
+ Presentation {
+ id: presentation
+
+ source: "qrc:/presentation/barrel.uip"
+ profilingEnabled: true
+
+ onSlideEntered: console.log("Entered slide " + name + "(index " + index + ") on " + elementPath)
+ onSlideExited: console.log("Exited slide " + name + "(index " + index + ") on " + elementPath)
+ onCustomSignalEmitted: console.log("Got custom signal " + name)
+
+ DataInput {
+ name: "di_text"
+ value: "hello world"
+ }
+
+ SceneElement {
+ elementPath: "SomeComponentNode"
+ onCurrentSlideIndexChanged: console.log("Current slide index for component: " + currentSlideIndex)
+ onCurrentSlideNameChanged: console.log("Current slide name for component: " + currentSlideName)
+ }
+
+ SubPresentationSettings {
+ qmlStreams: [
+ QmlStream {
+ presentationId: "sub-presentation-id"
+ Rectangle {
+ width: 1024
+ height: 1024
+ color: "red"
+ }
+ }
+ ]
+ }
+ }
+ }
+ Button {
+ onClicked: presentation.setAttribute("SomeMaterial", "diffuse", "0 1 0");
+ }
+ \endqml
\sa Studio3D
*/
@@ -489,22 +707,53 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
/*!
\qmlproperty url Presentation::source
- Holds the presentation source (\c{*.uia} or \c{*.uip}) file location.
+ Holds the main presentation source (\c{*.uia} or \c{*.uip}) file location.
May be either a file URL or a qrc URL.
*/
/*!
- \qmlproperty SubPresentationSettings Presentation::subPresentationSettings
+ \qmlproperty bool Presentation::profilingEnabled
+
+ When enabled, Qt 3D objects managed by the runtime get tracked,
+ and various statistics get collected internally. These are then
+ exposed in the views that can be toggled by profileUiVisible.
+
+ The default value is \c false.
+
+ \note Changing the value after the presentation has been loaded
+ has no effect for the already loaded presentation.
+
+ \note In the Qt 3D Studio Viewer application presentations are
+ opened with profiling enabled by default. Therefore, applications
+ wishing to have an experience comparable to the Viewer, when it
+ comes to the debug and profile views, should set this property to
+ \c true.
+*/
+
+/*!
+ \qmlproperty bool Presentation::profileUiVisible
+
+ When this property is \c{true}, the interactive statistics and profile
+ view is displayed in-scene, on top of the 3D content.
+
+ \note This feature can be disabled at build time, in which case this
+ property has no effect.
+
+ Default value is \c{false}.
+*/
+
+/*!
+ \qmlproperty real Presentation::profileUiScale
- Holds the settings for the subpresentations in the Qt 3D Studio presentation.
+ Controls the scale factor of the in-scene debug and profile views.
- This property is read-only.
+ The default value is 1.0.
*/
/*!
\qmlmethod void Presentation::goToSlide(string elementPath, string name)
- Requests a time context (a Scene or a Component element) to change to a specific slide
+ Requests a time context (a Scene or a Component node) to change to a specific slide
by \a name. If the context is already on that slide playback will start over.
If \a elementPath points to a time context, that element is controlled. For
@@ -516,7 +765,7 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
/*!
\qmlmethod void Presentation::goToSlide(string elementPath, int index)
- Requests a time context (a Scene or a Component element) to change to a specific slide by
+ Requests a time context (a Scene or a Component node) to change to a specific slide by
index \a index. If the context is already on that slide playback will start over.
If \a elementPath points to a time context, that element is controlled. For
@@ -528,7 +777,7 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
/*!
\qmlmethod void Presentation::goToSlide(string elementPath, bool next, bool wrap)
- Requests a time context (a Scene or a Component element) to change to the next or the
+ Requests a time context (a Scene or a Component node) to change to the next or the
previous slide, depending on the value of \a next. If the context is already at the
last or first slide, \a wrap defines if change occurs to the opposite end.
@@ -541,7 +790,7 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
/*!
\qmlmethod void Presentation::goToTime(string elementPath, real time)
- Sets a time context (a Scene or a Component element) to a specific playback \a time in seconds.
+ Sets a time context (a Scene or a Component node) to a specific playback \a time in seconds.
If \a elementPath points to a time context, that element is controlled. For
all other element types the time context owning that element is controlled instead.
@@ -564,88 +813,108 @@ void Q3DSPresentationPrivate::registerInlineQmlSubPresentations(const QVector<Q3
*/
/*!
- \qmlmethod void Presentation::setAttribute(string elementPath, string attributeName,
- variant value)
-
- Sets the \a value of an attribute on an element found at \a elementPath. The \a attributeName is
- the \l{Attribute Names}{scripting name} of the attribute.
+ \qmlmethod variant Presentation::getAttribute(string elementPath, string attributeName)
- You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
- front of the element path, for example \c{"SubPresentationOne:Scene.Mesh.Material"}.
-
- The attribute must be preserved for scripting to be set by this function, or else it will fail.
- An attribute is preserved if it is either \e{animated}, or
- \e{an attribute on a master element that is unlinked and changed per-slide}.
+ Returns the value of an attribute (property) on the object specified by \a
+ elementPath. The \a attributeName is the \l{Attribute Names}{scripting
+ name} of the attribute.
*/
/*!
- \qmlmethod void Presentation::setPresentationActive(string id, bool active)
-
- Stops or starts updates to a sub-presentation based on the \a active flag. The presentation is
- referenced to by the \a id, which is the name of the presentation without the \c{.uip}.
+ \qmlmethod void Presentation::setAttribute(string elementPath, string attributeName,
+ variant value)
- Making a presentation inactive prevents any elements, behaviors, and animations within it from
- updating. It also prevents any events within that presentation from being processed. It does
- not, however, prevent the presentation from rendering. An inactive presentation will continue
- to render using its last-updated information.
+ Sets the \a value of an attribute (property) on the Qt 3D Studio scene
+ object specified by \a elementPath. The \a attributeName is the
+ \l{Attribute Names}{scripting name} of the attribute.
- Explicitly inactivating presentations can provide a significant performance increase, depending
- on the number and size of the presentations that are inactive. Inactive presentations are not
- ‘paused’. When the presentation is re-activated, animations will resume at the time they should
- be had they been running, not where they were when the presentation was made inactive.
-*/
+ An element path refers to an object in the scene either by name or id. The
+ latter is rarely used in application code since the unique IDs are not
+ exposed in the Qt 3D Studio application. To refer to an object by id,
+ prepend \c{#} to the name. Applications will typically refer to objects by
+ name.
-/*!
- \qmlmethod void Presentation::fireEvent(string elementPath, string eventName)
+ Names are not necessarily unique, however. To access an object with a
+ non-unique name, the path can be specified, for example,
+ \c{Scene.Layer.Camera}. Here the right camera object gets chosen even if
+ the scene contains other layers with the default camera names (for instance
+ \c{Scene.Layer2.Camera}).
- Dispatches an event with \a eventName on a specific element found in \a elementPath. Appropriate
- Appropriate actions created in Qt 3D Studio or callbacks registered using the registerForEvent()
- method in attached scripts will be executed in response to the event.
+ If the object is renamed to a unique name in the Qt 3D Studio application's
+ Timeline view, the path can be omitted. For example, if the camera in
+ question was renamed to \c MyCamera, applications can then simply pass \c
+ MyCamera as the element path.
- You can target the command to a specific sub-presentation by adding "SubPresentationId:" in
- front of the element path, for example \c{"SubPresentationOne:Scene.Mesh"}.
+ To access an object in a sub-presentation, prepend the name of the
+ sub-presentation followed by a colon, for example,
+ \c{SubPresentationOne:Scene.Layer.Camera}.
*/
/*!
- \qmlmethod void Presentation::setGlobalAnimationTime(int64 milliseconds)
+ \qmlmethod void Presentation::fireEvent(string elementPath, string eventName)
- Sets the global animation time to \a milliseconds. Setting the global animation time to a
- non-zero value will disable the automatic animation timer. Setting the value to zero
- resumes automatic animation timer.
+ Dispatches a Qt 3D Studio presentation event with \a eventName on
+ scene object specified by \a elementPath. These events provide a
+ way to communicate with the \c .qml based \c{behavior scripts}
+ attached to scene objects since they can register to be notified
+ via Behavior::registerForEvent().
*/
/*!
\qmlmethod void Presentation::setDataInputValue(string name, variant value)
- \since QtStudio3D 1.1
Sets the \a value of a data input element \a name in the presentation.
+
+ Data input provides a higher level, designer-driven alternative to
+ setAttribute or Element. Instead of exposing a large set of properties with
+ their intenal engine names, data input allows designers to decide which
+ properties should be writable by the application, and can assign custom
+ names to these data input entries, thus forming a well-defined contract
+ between the designer and the developer.
+
+ In addition, data input also allows controlling the time line and the
+ current slide for time context objects (Scene or Component). Therefore it
+ is also an alternative to the goToSlide, goToTime, and SceneElement.
+
+ As an alternative to this method, the \l DataInput type can be used. That
+ approach has the advantage of being able to use QML property bindings for
+ the value, instead of having to resort to JavaScript function calls for
+ every value change.
*/
/*!
- \qmlsignal Presentation::slideEntered(string elementPath, int index, string name)
+ \qmlsignal Presentation::customSignalEmitted(string elementPath, string name)
+
+ This signal is emitted when an action with the \c{Emit Signal}
+ handler is executed in the Qt 3D Studio presentation. \a
+ elementPath specifies the scene object on which the (Qt 3D Studio)
+ "signal" \a name was triggered.
+
+ Connecting to this signal offers a way of reacting upon certain
+ events in the Qt 3D Studio presentation.
+
+ \image customsignal.png
- This signal is emitted when a slide is entered in the presentation.
- The \a elementPath specifies the time context (a Scene or a Component element) owning the
- entered slide.
- The \a index and \a name contain the index and the name of the entered slide.
+ In this example, pressing or tapping on the Cluster object will result in
+ emitting \c{customSignalEmitted("Cluster", "clusterPressed")}.
*/
/*!
- \qmlsignal Presentation::slideExited(string elementPath, int index, string name)
+ \qmlsignal Presentation::slideEntered(string elementPath, int index, string name)
- This signal is emitted when a slide is exited in the presentation.
- The \a elementPath specifies the time context (a Scene or a Component element) owning the
- exited slide.
- The \a index and \a name contain the index and the name of the exited slide.
+ This signal is emitted when a slide is entered in the presentation. The \a
+ elementPath specifies the time context (a Scene or a Component element)
+ owning the entered slide. The \a index and \a name contain the index and
+ the name of the entered slide.
*/
/*!
- \qmlsignal Presentation::sourceChanged(url source)
-
- This signal is emitted when the source property has changed.
- The new value is provided in the \a source parameter.
+ \qmlsignal Presentation::slideExited(string elementPath, int index, string name)
- The corresponding handler is \c onSourceChanged.
+ This signal is emitted when a slide is exited in the presentation. The \a
+ elementPath specifies the time context (a Scene or a Component element)
+ owning the exited slide. The \a index and \a name contain the index and the
+ name of the exited slide.
*/
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dssceneelement.cpp b/src/runtime/api/q3dssceneelement.cpp
index 6b3c161..cb7482b 100644
--- a/src/runtime/api/q3dssceneelement.cpp
+++ b/src/runtime/api/q3dssceneelement.cpp
@@ -95,7 +95,7 @@ Q3DSSceneElement::~Q3DSSceneElement()
\note If this property is set to something else than the default slide for
the scene at the initial declaration of SceneElement, a changed signal for
- the default slide may stil be emitted before the slide changes to the
+ the default slide may still be emitted before the slide changes to the
desired one. This happens in order to ensure we end up with the index of
the slide that is actually shown even if the slide specified in the initial
declaration is invalid.
@@ -126,7 +126,7 @@ int Q3DSSceneElement::previousSlideIndex() const
\note If this property is set to something else than the default slide for
the scene at the initial declaration of SceneElement, a changed signal for
- the default slide may stil be emitted before the slide changes to the
+ the default slide may still be emitted before the slide changes to the
desired one. This happens in order to ensure we end up with the index of
the slide that is actually shown even if the slide specified in the initial
declaration is invalid.
@@ -252,13 +252,14 @@ void Q3DSSceneElementPrivate::setPresentation(Q3DSPresentation *pres)
\inherits Element
\inqmlmodule QtStudio3D
\ingroup 3dstudioruntime2
- \brief Control type for scene and component elements in a Qt 3D Studio presentation.
- This type is a convenience type for managing the slides of a single
- time context (a Scene or a Component element) of a presentation.
+ \brief Controls the special Scene or Component scene objects in a Qt 3D
+ Studio presentation.
- All methods provided by this type are queued and handled asynchronously before the next
- frame is displayed.
+ This type is a convenience for controlling the properties of Scene
+ and Component objects in the scene. These are special since they have a
+ time context, meaning they control a timline and a set of associated
+ slides.
\sa Studio3D, Presentation, Element
*/
@@ -272,11 +273,12 @@ void Q3DSSceneElementPrivate::setPresentation(Q3DSPresentation *pres)
value will not actually change until the next frame has been processed, and
even then only if the new slide was valid.
- \note If this property is set to something else than the default slide for the scene at the
- initial declaration of SceneElement, you will still get an extra changed signal for the
- default slide before the slide changes to the desired one. This happens in order to ensure
- we end up with the index of the slide that is actually shown even if the slide specified in the
- initial declaration is invalid.
+ \note If this property is set to something else than the default slide for
+ the scene at the initial declaration of SceneElement, a changed signal for
+ the default slide may still be emitted before the slide changes to the
+ desired one. This happens in order to ensure we end up with the index of
+ the slide that is actually shown even if the slide specified in the initial
+ declaration is invalid.
*/
/*!
@@ -296,11 +298,12 @@ void Q3DSSceneElementPrivate::setPresentation(Q3DSPresentation *pres)
value will not actually change until the next frame has been processed, and
even then only if the new slide was valid.
- \note If this property is set to something else than the default slide for the scene at the
- initial declaration of SceneElement, you will still get an extra changed signal for the
- default slide before the slide changes to the desired one. This happens in order to ensure
- we end up with the name of the slide that is actually shown even if the slide specified in the
- initial declaration is invalid.
+ \note If this property is set to something else than the default slide for
+ the scene at the initial declaration of SceneElement, a changed signal for
+ the default slide may still be emitted before the slide changes to the
+ desired one. This happens in order to ensure we end up with the index of
+ the slide that is actually shown even if the slide specified in the initial
+ declaration is invalid.
*/
/*!
@@ -358,9 +361,10 @@ void Q3DSSceneElementPrivate::setPresentation(Q3DSPresentation *pres)
/*!
\qmlmethod void SceneElement::goToSlide(bool next, bool wrap)
- Requests a time context (a Scene or a Component element) to change to the next or the
- previous slide, depending on the value of \a next. If the context is already at the
- last or first slide, \a wrap defines if change occurs to the opposite end.
+ Requests a time context (a Scene or a Component object) to change to the
+ next or previous slide, depending on the value of \a next. If the context
+ is already at the last or first slide, \a wrap defines if wrapping over to
+ the first or last slide, respectively, occurs.
*/
/*!
diff --git a/src/runtime/api/q3dssurfaceviewer.cpp b/src/runtime/api/q3dssurfaceviewer.cpp
index 8ecb6c3..bbe6344 100644
--- a/src/runtime/api/q3dssurfaceviewer.cpp
+++ b/src/runtime/api/q3dssurfaceviewer.cpp
@@ -176,6 +176,11 @@ bool Q3DSSurfaceViewerPrivate::doCreate(QSurface *s, QOpenGLContext *c, uint id,
return createEngine();
}
+/*!
+ Releases the presentation and all related resources.
+
+ The Q3DSSurfaceViewer instance can be reused by calling create() again.
+ */
void Q3DSSurfaceViewer::destroy()
{
Q_D(Q3DSSurfaceViewer);
@@ -188,6 +193,19 @@ void Q3DSSurfaceViewer::destroy()
}
/*!
+ \fn Q3DSSurfaceViewer::frameUpdate()
+
+ This signal is emitted each time a frame has been rendered.
+*/
+
+/*!
+ \fn Q3DSSurfaceViewer::presentationLoaded()
+
+ This signal is emitted when the viewer has been initialized and the
+ presentation is ready to be shown.
+*/
+
+/*!
Returns the presentation object used by the Q3DSSurfaceViewer.
*/
Q3DSPresentation *Q3DSSurfaceViewer::presentation() const
@@ -205,6 +223,15 @@ Q3DSViewerSettings *Q3DSSurfaceViewer::settings() const
return d->viewerSettings;
}
+/*!
+ \property Q3DSSurfaceViewer::error
+
+ Contains the text for the error message that was generated during the
+ loading of the presentation. When no error occurred or there is no
+ presentation loaded, the value is an empty string.
+
+ This property is read-only.
+ */
QString Q3DSSurfaceViewer::error() const
{
Q_D(const Q3DSSurfaceViewer);
@@ -225,6 +252,14 @@ bool Q3DSSurfaceViewer::isRunning() const
return d->engine && d->sourceLoaded;
}
+/*!
+ \property Q3DSSurfaceViewer::size
+
+ Holds the desired size of the presentation. Relevant only when
+ autoSize is set to \c false.
+
+ \sa autoSize
+*/
QSize Q3DSSurfaceViewer::size() const
{
Q_D(const Q3DSSurfaceViewer);
diff --git a/src/runtime/api/q3dsviewersettings.cpp b/src/runtime/api/q3dsviewersettings.cpp
index a0d91ea..c6c65fd 100644
--- a/src/runtime/api/q3dsviewersettings.cpp
+++ b/src/runtime/api/q3dsviewersettings.cpp
@@ -66,6 +66,32 @@ Q3DSViewerSettings::~Q3DSViewerSettings()
{
}
+/*!
+ \enum Q3DSViewerSettings::ShadeMode
+
+ This enumeration specifies the possible shading modes.
+
+ \value ShadeModeShaded The objects in the presentation are shaded normally.
+ \value ShadeModeShadedWireframe The objects in the presentation are shaded
+ with a super-imposed wireframe on top of the normal shading. Only objects that specify
+ a tesselation mode will display this wireframe.
+*/
+
+/*!
+ \enum Q3DSViewerSettings::ScaleMode
+
+ This enumeration specifies the possible scaling modes.
+
+ \value ScaleModeFit Scales the presentation to fit the viewer.
+ \value ScaleModeFill Scales the presentation to fill the viewer.
+ \value ScaleModeCenter Centers the presentation into the viewer without scaling it.
+*/
+
+/*!
+ \property Q3DSViewerSettings::matteColor
+
+ \note This property is currently ignored.
+ */
QColor Q3DSViewerSettings::matteColor() const
{
Q_D(const Q3DSViewerSettings);
@@ -75,7 +101,7 @@ QColor Q3DSViewerSettings::matteColor() const
/*!
\property Q3DSViewerSettings::showRenderStats
- If this property is set to \c{true}, the interactive statistics and profile
+ When this property is \c{true}, the interactive statistics and profile
view is displayed in-scene, on top of the 3D content.
\note This feature can be disabled at build time, in which case this
@@ -89,12 +115,22 @@ bool Q3DSViewerSettings::isShowingRenderStats() const
return d->showRenderStats;
}
+/*!
+ \property Q3DSViewerSettings::shadeMode
+
+ \note This property is currently ignored.
+ */
Q3DSViewerSettings::ShadeMode Q3DSViewerSettings::shadeMode() const
{
Q_D(const Q3DSViewerSettings);
return d->shadeMode;
}
+/*!
+ \property Q3DSViewerSettings::scaleMode
+
+ \note This property is currently ignored.
+ */
Q3DSViewerSettings::ScaleMode Q3DSViewerSettings::scaleMode() const
{
Q_D(const Q3DSViewerSettings);
@@ -140,6 +176,12 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode)
}
}
+/*!
+ Persistently saves the viewer \l{QSettings}{settings} using \a group, \a organization and
+ \a application.
+
+ \note This function is not currently implemented.
+ */
void Q3DSViewerSettings::save(const QString &group,
const QString &organization,
const QString &application)
@@ -150,6 +192,12 @@ void Q3DSViewerSettings::save(const QString &group,
qWarning() << Q_FUNC_INFO << "not implemented";
}
+/*!
+ Loads previously saved viewer \l{QSettings}{settings} using \a group, \a organization and
+ \a application.
+
+ \note This function is not currently implemented.
+ */
void Q3DSViewerSettings::load(const QString &group,
const QString &organization,
const QString &application)
@@ -175,9 +223,13 @@ void Q3DSViewerSettings::load(const QString &group,
/*!
\qmlproperty bool ViewerSettings::showRenderStats
- If this property is set to \c{true}, render statistics are displayed on the upper part
- of the viewer.
- Default value is \c{false}.
+ If this property is set to \c true, the interactive statistics and profile
+ view is displayed in-scene, on top of the 3D content.
+
+ \note this feature can be disabled at build time, in which case this
+ property has no effect.
+
+ The default value is \c{false}.
*/
QT_END_NAMESPACE
diff --git a/src/runtime/api/q3dswidget.cpp b/src/runtime/api/q3dswidget.cpp
index 8cdd898..56d65d5 100644
--- a/src/runtime/api/q3dswidget.cpp
+++ b/src/runtime/api/q3dswidget.cpp
@@ -89,7 +89,24 @@ Q3DSWidget::~Q3DSWidget()
}
/*!
+ \fn Q3DSWidget::frameUpdate()
+
+ This signal is emitted each time a frame has been rendered.
+*/
+
+/*!
+ \fn Q3DSWidget::presentationLoaded()
+
+ This signal is emitted when the viewer has been initialized and the
+ presentation is ready to be shown.
+*/
+
+/*!
+ \property Q3DSWidget::presentation
+
Returns the presentation object used by the Q3DSWidget.
+
+ This property is read-only.
*/
Q3DSPresentation *Q3DSWidget::presentation() const
{
@@ -106,6 +123,15 @@ Q3DSViewerSettings *Q3DSWidget::settings() const
return d->viewerSettings;
}
+/*!
+ \property Q3DSWidget::error
+
+ Contains the text for the error message that was generated during the
+ loading of the presentation. When no error occurred or there is no
+ presentation loaded, the value is an empty string.
+
+ This property is read-only.
+ */
QString Q3DSWidget::error() const
{
Q_D(const Q3DSWidget);
@@ -159,6 +185,9 @@ void Q3DSWidget::setUpdateInterval(int interval)
}
}
+/*!
+ \internal
+ */
void Q3DSWidget::keyPressEvent(QKeyEvent *event)
{
Q_D(Q3DSWidget);
@@ -166,6 +195,9 @@ void Q3DSWidget::keyPressEvent(QKeyEvent *event)
d->engine->handleKeyPressEvent(event);
}
+/*!
+ \internal
+ */
void Q3DSWidget::keyReleaseEvent(QKeyEvent *event)
{
Q_D(Q3DSWidget);
@@ -173,6 +205,9 @@ void Q3DSWidget::keyReleaseEvent(QKeyEvent *event)
d->engine->handleKeyReleaseEvent(event);
}
+/*!
+ \internal
+ */
void Q3DSWidget::mousePressEvent(QMouseEvent *event)
{
Q_D(Q3DSWidget);
@@ -180,6 +215,9 @@ void Q3DSWidget::mousePressEvent(QMouseEvent *event)
d->engine->handleMousePressEvent(event);
}
+/*!
+ \internal
+ */
void Q3DSWidget::mouseMoveEvent(QMouseEvent *event)
{
Q_D(Q3DSWidget);
@@ -187,6 +225,9 @@ void Q3DSWidget::mouseMoveEvent(QMouseEvent *event)
d->engine->handleMouseMoveEvent(event);
}
+/*!
+ \internal
+ */
void Q3DSWidget::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(Q3DSWidget);
@@ -194,6 +235,9 @@ void Q3DSWidget::mouseReleaseEvent(QMouseEvent *event)
d->engine->handleMouseReleaseEvent(event);
}
+/*!
+ \internal
+ */
void Q3DSWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_D(Q3DSWidget);
@@ -202,6 +246,9 @@ void Q3DSWidget::mouseDoubleClickEvent(QMouseEvent *event)
}
#if QT_CONFIG(wheelevent)
+/*!
+ \internal
+ */
void Q3DSWidget::wheelEvent(QWheelEvent *event)
{
Q_D(Q3DSWidget);
@@ -210,10 +257,16 @@ void Q3DSWidget::wheelEvent(QWheelEvent *event)
}
#endif
+/*!
+ \internal
+ */
void Q3DSWidget::initializeGL()
{
}
+/*!
+ \internal
+ */
void Q3DSWidget::resizeGL(int w, int h)
{
Q_D(Q3DSWidget);
@@ -224,6 +277,9 @@ void Q3DSWidget::resizeGL(int w, int h)
}
}
+/*!
+ \internal
+ */
void Q3DSWidget::paintGL()
{
Q_D(Q3DSWidget);
diff --git a/src/runtime/behaviorapi/q3dsbehaviorobject.cpp b/src/runtime/behaviorapi/q3dsbehaviorobject.cpp
index 9a31ce8..761ac2a 100644
--- a/src/runtime/behaviorapi/q3dsbehaviorobject.cpp
+++ b/src/runtime/behaviorapi/q3dsbehaviorobject.cpp
@@ -145,47 +145,45 @@ void Q3DSBehaviorObject::setAttribute(const QString &handle, const QString &attr
const QStringList vecCompRef = attribute.split(QLatin1Char('.'), QString::SkipEmptyParts);
if (vecCompRef.count() == 2) {
QVariant newValue = obj->propertyValue(vecCompRef[0]);
- if (!newValue.isNull()) {
- switch (newValue.type()) {
- case QVariant::Vector2D:
- {
- QVector2D v = newValue.value<QVector2D>();
- if (vecCompRef[1] == QStringLiteral("x"))
- v.setX(value.toFloat());
- else if (vecCompRef[1] == QStringLiteral("y"))
- v.setY(value.toFloat());
- newValue = v;
- }
- break;
- case QVariant::Vector3D:
- {
- QVector3D v = newValue.value<QVector3D>();
- if (vecCompRef[1] == QStringLiteral("x"))
- v.setX(value.toFloat());
- else if (vecCompRef[1] == QStringLiteral("y"))
- v.setY(value.toFloat());
- else if (vecCompRef[1] == QStringLiteral("z"))
- v.setZ(value.toFloat());
- newValue = v;
- }
- break;
- case QVariant::Color:
- {
- QColor v = newValue.value<QColor>();
- if (vecCompRef[1] == QStringLiteral("x") || vecCompRef[1] == QStringLiteral("r"))
- v.setRedF(value.toFloat());
- else if (vecCompRef[1] == QStringLiteral("y") || vecCompRef[1] == QStringLiteral("g"))
- v.setGreenF(value.toFloat());
- else if (vecCompRef[1] == QStringLiteral("z") || vecCompRef[1] == QStringLiteral("b"))
- v.setBlueF(value.toFloat());
- newValue = v;
- }
- break;
- default:
- break;
- }
- cl.append(Q3DSPropertyChange::fromVariant(vecCompRef[0], newValue));
+ switch (newValue.type()) {
+ case QVariant::Vector2D:
+ {
+ QVector2D v = newValue.value<QVector2D>();
+ if (vecCompRef[1] == QStringLiteral("x"))
+ v.setX(value.toFloat());
+ else if (vecCompRef[1] == QStringLiteral("y"))
+ v.setY(value.toFloat());
+ newValue = v;
}
+ break;
+ case QVariant::Vector3D:
+ {
+ QVector3D v = newValue.value<QVector3D>();
+ if (vecCompRef[1] == QStringLiteral("x"))
+ v.setX(value.toFloat());
+ else if (vecCompRef[1] == QStringLiteral("y"))
+ v.setY(value.toFloat());
+ else if (vecCompRef[1] == QStringLiteral("z"))
+ v.setZ(value.toFloat());
+ newValue = v;
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor v = newValue.value<QColor>();
+ if (vecCompRef[1] == QStringLiteral("x") || vecCompRef[1] == QStringLiteral("r"))
+ v.setRedF(value.toFloat());
+ else if (vecCompRef[1] == QStringLiteral("y") || vecCompRef[1] == QStringLiteral("g"))
+ v.setGreenF(value.toFloat());
+ else if (vecCompRef[1] == QStringLiteral("z") || vecCompRef[1] == QStringLiteral("b"))
+ v.setBlueF(value.toFloat());
+ newValue = v;
+ }
+ break;
+ default:
+ break;
+ }
+ cl.append(Q3DSPropertyChange::fromVariant(vecCompRef[0], newValue));
}
} else {
// for example, setAttribute("rotation", "0 45 0")
@@ -265,6 +263,35 @@ void Q3DSBehaviorObject::setDataInputValue(const QString &name, const QVariant &
m_engine->setDataInputValue(name, value);
}
+QMatrix4x4 Q3DSBehaviorObject::calculateGlobalTransform(const QString &handle)
+{
+ Q3DSGraphObject *obj = m_engine->findObjectByHashIdOrNameOrPath(m_behaviorInstance->parent(), m_presentation, handle);
+ if (!obj) {
+ qWarning("calculateGlobalTransform: Invalid object reference %s", qPrintable(handle));
+ return QMatrix4x4();
+ }
+
+ if (obj->isNode()) {
+ Q3DSNodeAttached *attached = static_cast<Q3DSNodeAttached *>(obj->attached());
+ const float *m = attached->globalTransform.constData();
+ QMatrix4x4 correctedMatrix(m[0], m[1], -m[2], m[3],
+ m[4], m[5], -m[6], m[7],
+ -m[8], -m[9], m[10], m[11],
+ m[12], m[13], -m[14], m[15]);
+ return correctedMatrix;
+ }
+ return QMatrix4x4();
+}
+
+QVector3D Q3DSBehaviorObject::lookAt(const QVector3D &target)
+{
+ float mag = qSqrt(target.x() * target.x() + target.z() * target.z());
+ float pitch = -qAtan2(target.y(), mag);
+ float yaw = qAtan2(target.x(), target.z());
+
+ return QVector3D(qRadiansToDegrees(pitch), qRadiansToDegrees(yaw), 0.0f);
+}
+
/*!
\qmltype Behavior
\inqmlmodule QtStudio3D
@@ -277,6 +304,11 @@ void Q3DSBehaviorObject::setDataInputValue(const QString &name, const QVariant &
JavaScript. It enables interacting with the runtime using the Behavior
QML class exposed to each behavior script.
+ \note the Behavior type has its own import and is only available in
+ \c{behavior scripts} that are attached to scene objects during the design
+ phase in Qt 3D Studio. It is not usable in ordinary QML
+ application code.
+
In QML behavior script, the integration to Qt 3D Studio is established by using
the metadata tag system similar to the \l {file-formats-effects.html}{effect}
and \l {file-formats-material.html}{material} files.
@@ -393,6 +425,18 @@ Behavior {
*/
/*!
+ \qmlmethod matrix4x4 Behavior::calculateGlobalTransform(string handle)
+
+ Returns the transformation matrix of the object identified with the \a handle.
+*/
+
+/*!
+ \qmlmethod vector3d Behavior::lookAt(vector3d target)
+
+ Returns the euler angles for looking at the \a target.
+*/
+
+/*!
\qmlsignal void Behavior::onInitialize()
This signal is emitted when the script becomes active the first time.
diff --git a/src/runtime/behaviorapi/q3dsbehaviorobject_p.h b/src/runtime/behaviorapi/q3dsbehaviorobject_p.h
index 661e09f..b0bd965 100644
--- a/src/runtime/behaviorapi/q3dsbehaviorobject_p.h
+++ b/src/runtime/behaviorapi/q3dsbehaviorobject_p.h
@@ -80,6 +80,8 @@ public:
Q_INVOKABLE void unregisterForEvent(const QString &event);
Q_INVOKABLE void unregisterForEvent(const QString &handle, const QString &event);
Q_REVISION(1) Q_INVOKABLE void setDataInputValue(const QString &name, const QVariant &value);
+ Q_INVOKABLE QMatrix4x4 calculateGlobalTransform(const QString &handle = QString());
+ Q_INVOKABLE QVector3D lookAt(const QVector3D &target);
signals:
void initialize();
diff --git a/src/runtime/doc/src/copyright.qdoc b/src/runtime/doc/src/copyright.qdoc
index 01275f1..f0574a5 100644
--- a/src/runtime/doc/src/copyright.qdoc
+++ b/src/runtime/doc/src/copyright.qdoc
@@ -33,5 +33,5 @@
The following table lists parts (modules) of Qt 3D Studio Runtime that
incorporate code licensed under third-party open-source licenses:
-\annotatedlist attributions-Qt3DStudioRuntime2
+\annotatedlist attributions-qt3dstudioruntime2
*/
diff --git a/src/runtime/doc/src/images/customsignal.png b/src/runtime/doc/src/images/customsignal.png
new file mode 100644
index 0000000..eb0e0ba
--- /dev/null
+++ b/src/runtime/doc/src/images/customsignal.png
Binary files differ
diff --git a/src/runtime/doc/src/images/profileui-example.png b/src/runtime/doc/src/images/profileui-example.png
new file mode 100644
index 0000000..27c38bd
--- /dev/null
+++ b/src/runtime/doc/src/images/profileui-example.png
Binary files differ
diff --git a/src/runtime/doc/src/images/profileui-tooltips.png b/src/runtime/doc/src/images/profileui-tooltips.png
new file mode 100644
index 0000000..1828ad6
--- /dev/null
+++ b/src/runtime/doc/src/images/profileui-tooltips.png
Binary files differ
diff --git a/src/runtime/doc/src/index.qdoc b/src/runtime/doc/src/index.qdoc
index 43d8b18..387e86f 100644
--- a/src/runtime/doc/src/index.qdoc
+++ b/src/runtime/doc/src/index.qdoc
@@ -34,11 +34,10 @@
\list
\li \l {Getting Started}
\li \l {System and Application Requirements}
- \li \l {Using the Runtime on Android/iOS Devices}
- \li \l {Using the Runtime on Embedded Devices}
\li \l {Qt 3D Studio Runtime C++ Classes}
\li \l {Qt 3D Studio Runtime QML Types}
- \li \l {Attribute Names}{Scene object attribute list}
+ \li \l {Attribute Names}{Scene Object Attribute List}
+ \li \l {Using the In-Scene Debug and Profile views}
\li \l {Examples}
\li \l {Copyright Notices}
\endlist
diff --git a/src/runtime/doc/src/module.qdoc b/src/runtime/doc/src/module.qdoc
index d37417f..ba6068f 100644
--- a/src/runtime/doc/src/module.qdoc
+++ b/src/runtime/doc/src/module.qdoc
@@ -31,7 +31,8 @@
\keyword C++ API
\ingroup modules
- \brief Qt 3D Studio provides a number of C++ classes to view and control the presentation.
+ \brief The Qt 3D Studio Runtime provides a number of C++ classes to
+ integrate and control Qt 3D Studio presentations in Qt applications.
To include the definitions of the module's classes, use the following directive:
@@ -45,6 +46,36 @@
QT += 3dstudioruntime2
\endcode
+ \section1 Integrating
+
+ The two main classes are \l Q3DSWidget and \l Q3DSSurfaceViewer. Q3DSWidget
+ is a QWidget that can be used to show presentations inside a widget-based
+ user interface. Q3DSSurfaceViewer allows targeting a QWindow or an
+ offscreen render target (an OpenGL texture).
+
+ \note Qt applications based on QML and Qt Quick will rather want to use the
+ \l Studio3D type from \l{Qt 3D Studio Runtime QML Types}.
+
+ \section1 Controlling
+
+ Each \l Q3DSWidget and \l Q3DSSurfaceViewer instance exposes a \l
+ Q3DSPresentation. This, possibly in combination with \l Q3DSDataInput or
+ \l Q3DSElement objects, allows
+
+ \list
+
+ \li changing scene object properties (for example, the transform of a
+ model, colors and other settings of a material, etc.),
+
+ \li changing slides (thus starting the relevant animations and applying the
+ scene object property changes associated with the new slide),
+
+ \li and controlling the timeline (the current playback position for the
+ key-frame based animations) both on the main scene and on individual
+ Component nodes.
+
+ \endlist
+
\section1 Classes
\generatelist {classesbymodule 3dstudioruntime2}
@@ -59,14 +90,31 @@
\brief QML Types for the Qt 3D Studio Runtime module.
- Qt 3D Studio provides a number of QML types to view and control the
- presentation. These types can be imported into your application using the
- following import statement in your .qml file:
+ The Qt 3D Studio Runtime provides a number of QML types to integrate and
+ control Qt 3D Studio presentations in Qt Quick applications. These types
+ can be imported into your application using the following import statement
+ in your \c{.qml} file:
\badcode
import QtStudio3D 2.0
\endcode
+ The main type for embedding a Qt 3D Studio presentations into a Qt Quick
+ scene is \l Studio3D. Many of the other types correspond to a C++ class in
+ the API offered to non-QML based applications, providing the same level of
+ control described in \l{Qt 3D Studio Runtime C++ Classes}{the C++
+ reference}.
+
+ There are also QML types that offer functionality not available via the C++
+ classes. The \l SubPresentationSettings type allows defining \c{QML
+ sub-presentations} (live Qt Quick scenes composed into the 3D scene either
+ as Qt 3D Studio layers or as texture maps) in-line, inside a Studio3D
+ element, without having to deploy them as separate \c .qml files.
+
+ \note the \l Behavior type is to be used by \c{behavior scripts} (\c .qml
+ snippets associated with scene objects during the design phase in Qt 3D
+ Studio) and is not available in the main application code.
+
\section1 QML Types
\generatelist {qmltypesbymodule QtStudio3D}
diff --git a/src/runtime/doc/src/profileui.qdoc b/src/runtime/doc/src/profileui.qdoc
new file mode 100644
index 0000000..91df0a2
--- /dev/null
+++ b/src/runtime/doc/src/profileui.qdoc
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \page qt3d-runtime-profileui.html
+ \title Using the In-Scene Debug and Profile views
+
+ The Qt 3D Studio Runtime includes a set of built-in views that can be
+ brought up on top of the scene at any time. These panes are rendered
+ completely inside the 3D scene and are therefore available on any platform,
+ even when running on mobile or embedded systems without a windowing system
+ (for example, via the \c eglfs platform plugin), with the Qt 3D Studio
+ presentation and the Qt Quick user interface occupying the entire scren.
+
+ \image profileui-example.png
+
+ \section1 Activation
+
+ In the Viewer application, toggle with \c F10 or the \uicontrol{Profile and
+ Debug} submenu under \uicontrol View.
+
+ In applications these views have no built-in shortcuts. It is up to the
+ application to toggle visibility. From C++ this is done via \l
+ Q3DSPresentation::profileUiVisible or \l
+ Q3DSViewerSettings::showRenderStats. From QML the corresponding properties
+ are \l Presentation::profileUiVisible and \l ViewerSettings::showRenderStats.
+
+ In order to enable all features in the debug and profile views, presentations
+ must be loaded with profiling enabled. In this mode the Qt 3D objects
+ managed by the runtime get tracked, and various statistics get collected
+ internally. This is enabled by default in the Viewer application, whereas
+ applications have to opt-in explicitly via \l
+ Q3DSPresentation::profilingEnabled or \l Presentation::profilingEnabled.
+
+ As an example, the following is how the \l{Qt 3D Studio Runtime: Simple QML
+ Example} enables and connects the toggling of these views to a Qt Quick
+ Controls button:
+
+ \badcode
+ Studio3D {
+ Presentation {
+ id: presentation
+ source: "qrc:/presentation/barrel.uip"
+ profilingEnabled: true
+ }
+ }
+
+ Button {
+ text: "Toggle profile UI"
+ onClicked: presentation.profileUiVisible = !s3dpres.profileUiVisible
+ ...
+ }
+ }
+ \endcode
+
+ \section1 Features
+
+ \list
+
+ \li CPU and memory usage of the application process (available on Windows, Linux, and Android)
+
+ \li OpenGL context information
+
+ \li Frame rate, with a visualization of its history during the last 100 frames (configurable)
+
+ \li Various timings from the loading of the scene
+
+ \li Qt 3D object list - showing the active list of mesh and texture objects
+ can give an approximate understanding of the graphics resource usage and
+ can also uncover sub-optimal asset situations that lead to degraded
+ performance. For example, having a large number of meshes in the list for a
+ seemingly simple scene should warrant an investigation of the assets as
+ they may be overly complex. Similarly, large textures are often not ideal,
+ yet they may be overlooked during the design phase of the presentation.
+ Here it becomes immediately obvious if some texture map is unncessarily
+ large.
+
+ \li Layer list - showing the list of active and inactive \c layers in the
+ presentation. A Qt 3D Studio presentations consists of one or more layers
+ which are backed by OpenGL textures each. These are composed together with
+ the appropriate blending mode (and optionally with post-postprocessing
+ effects applied) to get the final output. It is important to understand
+ that each layer corresponds to a separate render target (e.g. an OpenGL
+ texture and the corresponding framebuffer setup) in the engine and is using
+ graphics resources like any other texture map. The performance of the
+ composition is also important, especially on mobile and embedded where the
+ fragment processing power can be more limited.
+
+ \li A filterable log view (with the debug messages that are also printed on
+ the default qDebug output of the platform)
+
+ \li A number of other, experimental views
+
+ \endlist
+
+ The views and their contents are live at any time, meaning they always
+ reflect the Qt 3D Studio Runtime's state for the current frame.
+
+ Watch out for the tooltips marked with \c{(?)}. Moving the mouse cursor
+ over these results in showing additional information about the item in
+ question which can be useful in understanding the implications of certain
+ statistics.
+
+ \image profileui-tooltips.png
+
+ \note the feature set may get extended or changed in future versions. It is
+ also possible that certain information gets folded into the Qt 3D Studio
+ application itself in the future.
+*/
diff --git a/src/runtime/q3dsanimationmanager.cpp b/src/runtime/q3dsanimationmanager.cpp
index 9c8eadb..a7cc96b 100644
--- a/src/runtime/q3dsanimationmanager.cpp
+++ b/src/runtime/q3dsanimationmanager.cpp
@@ -217,6 +217,8 @@ public:
void valueChanged(const QVariant &value) override;
private:
+ QVariant stabilizeAnimatedValue(const QVariant &value, Q3DS::PropertyType type);
+
Q3DSGraphObject *m_target;
Q3DSAnimationManager::Animatable m_animMeta;
Q3DSAnimationManager *m_animationManager;
@@ -229,12 +231,27 @@ void Q3DSAnimationCallback::valueChanged(const QVariant &value)
// invoked once per frame.
Q3DSAnimationManager::AnimationValueChange change;
- change.value = value;
+ change.value = stabilizeAnimatedValue(value, m_animMeta.type);
change.name = m_animMeta.name;
change.setter = m_animMeta.setter;
m_animationManager->queueChange(m_target, change);
}
+QVariant Q3DSAnimationCallback::stabilizeAnimatedValue(const QVariant &value, Q3DS::PropertyType type)
+{
+ if (type == Q3DS::Color && value.type() == QVariant::Vector3D) {
+ const QVector3D v = value.value<QVector3D>();
+ // rgb is already in range [0, 1] but let's make sure the 0 and 1 are really 0 and 1.
+ // This avoids confusing QColor when qFuzzyCompare(r, 1.0f) && r > 1.0f
+ const float r = qBound(0.0f, v.x(), 1.0f);
+ const float g = qBound(0.0f, v.y(), 1.0f);
+ const float b = qBound(0.0f, v.z(), 1.0f);
+ return QVariant::fromValue(QColor::fromRgbF(qreal(r), qreal(g), qreal(b)));
+ }
+
+ return value;
+}
+
static int componentSuffixToIndex(const QString &s)
{
if (s == QStringLiteral("x"))
@@ -483,12 +500,21 @@ void Q3DSAnimationManager::updateAnimationHelper(const AnimationTrackListMap<T *
clipData.appendChannel(chIt->channel);
// Figure out the QVariant/QMetaType type enum value.
- const int type = Q3DS::animatablePropertyTypeToMetaType(chIt->meta.type);
+ int type = Q3DS::animatablePropertyTypeToMetaType(chIt->meta.type);
if (type == QVariant::Invalid) {
qWarning("Cannot map channel type for animated property %s", qPrintable(channelName));
continue;
}
+ // Workaround for QColor::fromRgbF() warning and generating invalid
+ // colors when some component is very slightly over 1.0. Due to the
+ // Qt 3D animation fw or QVariant or something else, we get
+ // sometimes such results. We can handle this in our side but we
+ // cannot let Qt 3D do the QColor creation. So pretend we have a
+ // QVector3D instead. This will be 'reversed' in stabilizeAnimatedValue().
+ if (type == QVariant::Color)
+ type = QVariant::Vector3D;
+
// Create a mapping with a custom callback.
QScopedPointer<Qt3DAnimation::QCallbackMapping> mapping(new Qt3DAnimation::QCallbackMapping);
mapping->setChannelName(channelName);
diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp
index 5faae2c..45d9c67 100644
--- a/src/runtime/q3dsengine.cpp
+++ b/src/runtime/q3dsengine.cpp
@@ -193,22 +193,24 @@ static void initGraphicsLimits(QOpenGLContext *ctx)
qDebug(" multisample textures: %s", gfxLimits.multisampleTextureSupported ? "true" : "false");
auto extensions = ctx->extensions();
- if (!extensions.isEmpty()) {
- gfxLimits.extensions = extensions;
+ gfxLimits.extensions = extensions;
- if (ctx->isOpenGLES() && ctx->format().majorVersion() == 2) {
- gfxLimits.shaderTextureLodSupported = false;
- gfxLimits.shaderUniformBufferSupported = false;
- gfxLimits.packedDepthStencilBufferSupported = false;
- }
- if (extensions.contains("GL_EXT_shader_texture_lod"))
- gfxLimits.shaderTextureLodSupported = true;
- qDebug(" texture lod: %s", gfxLimits.shaderTextureLodSupported ? "true" : "false");
-
- if (extensions.contains("GL_EXT_packed_depth_stencil"))
- gfxLimits.packedDepthStencilBufferSupported = true;
- qDebug(" packed depth-stencil: %s", gfxLimits.packedDepthStencilBufferSupported ? "true" : "false");
+ if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3) {
+ gfxLimits.shaderUniformBufferSupported = false;
+ gfxLimits.shaderTextureLodSupported = extensions.contains("GL_EXT_shader_texture_lod");
+ gfxLimits.packedDepthStencilBufferSupported = extensions.contains("GL_EXT_packed_depth_stencil");
+ } else {
+ gfxLimits.shaderUniformBufferSupported = true;
+ gfxLimits.shaderTextureLodSupported = true;
+ gfxLimits.packedDepthStencilBufferSupported = true;
}
+ qDebug(" uniform buffers: %s", gfxLimits.shaderUniformBufferSupported ? "true" : "false");
+ qDebug(" texture lod: %s", gfxLimits.shaderTextureLodSupported ? "true" : "false");
+ qDebug(" packed depth-stencil: %s", gfxLimits.packedDepthStencilBufferSupported ? "true" : "false");
+
+ gfxLimits.norm16TexturesSupported = ctx->isOpenGLES() ? extensions.contains("GL_EXT_texture_norm16") : true;
+ qDebug(" norm16 textures: %s", gfxLimits.norm16TexturesSupported ? "true" : "false");
+
qDebug() << " extensions: " << extensions;
// version string bonanza for the profiler
diff --git a/src/runtime/q3dsgraphicslimits_p.h b/src/runtime/q3dsgraphicslimits_p.h
index 2e624cf..6314c7b 100644
--- a/src/runtime/q3dsgraphicslimits_p.h
+++ b/src/runtime/q3dsgraphicslimits_p.h
@@ -52,9 +52,10 @@ struct Q3DSGraphicsLimits {
bool versionedContextFailed = false;
int maxDrawBuffers = 4;
bool multisampleTextureSupported = false;
- bool shaderTextureLodSupported = true;
- bool shaderUniformBufferSupported = true;
- bool packedDepthStencilBufferSupported = true;
+ bool shaderTextureLodSupported = false;
+ bool shaderUniformBufferSupported = false;
+ bool packedDepthStencilBufferSupported = false;
+ bool norm16TexturesSupported = false;
QByteArray renderer;
QByteArray vendor;
QByteArray version;
diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp
index 877a733..b39795d 100644
--- a/src/runtime/q3dsscenemanager.cpp
+++ b/src/runtime/q3dsscenemanager.cpp
@@ -611,8 +611,7 @@ Q3DSSceneManager::Scene Q3DSSceneManager::buildScene(Q3DSUipPresentation *presen
m_scene = m_presentation->scene();
m_masterSlide = m_presentation->masterSlide();
m_currentSlide = nullptr;
- m_pendingNodeShow.clear();
- m_pendingNodeHide.clear();
+ m_pendingNodeVisibility.clear();
m_pendingSubPresLayers.clear();
m_pendingSubPresImages.clear();
m_subPresentations.clear();
@@ -866,7 +865,7 @@ static Qt3DRender::QAbstractTexture *newColorBuffer(const QSize &layerPixelSize,
return colorTex;
}
-static Qt3DRender::QAbstractTexture *newDepthStencilBuffer(const QSize &layerPixelSize, int msaaSampleCount, Qt3DRender::QAbstractTexture::TextureFormat format = Qt3DRender::QAbstractTexture::D24S8)
+static Qt3DRender::QAbstractTexture *newDepthStencilBuffer(const QSize &layerPixelSize, int msaaSampleCount, Qt3DRender::QAbstractTexture::TextureFormat format)
{
// GLES <= 3.1 does not have glFramebufferTexture and support for combined
// depth-stencil textures. Here we rely on the fact the Qt3D will
@@ -876,9 +875,10 @@ static Qt3DRender::QAbstractTexture *newDepthStencilBuffer(const QSize &layerPix
//
// The internal difference (renderbuffer vs. texture) won't matter as long
// as a custom material or other thing does not need the depth texture.
- // When that happens, we will be in trouble when running on GLES < 3.2 ...
- // An option then would be to get rid of stencil since plain depth textures
- // work in GLES >= 3.0.
+ // When that happens, we will be in trouble when running on GLES < 3.2.
+ //
+ // Therefore, on GLES 2.0, 3.0 and 3.1 we expect to get called with D16 (or
+ // D24 or D32) and no stencil. (whereas GLES 3.2 or desktop GL will use D24S8)
Qt3DRender::QAbstractTexture *dsTexOrRb;
if (msaaSampleCount > 1) {
@@ -912,28 +912,25 @@ Qt3DRender::QRenderTarget *Q3DSSceneManager::newLayerRenderTarget(const QSize &l
rt->addOutput(color);
Qt3DRender::QRenderTargetOutput *ds = new Qt3DRender::QRenderTargetOutput;
- if (m_gfxLimits.packedDepthStencilBufferSupported) {
- ds->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil);
- if (!existingDS) {
- *dsTexOrRb = newDepthStencilBuffer(layerPixelSize, msaaSampleCount);
- m_profiler->trackNewObject(*dsTexOrRb, Q3DSProfiler::Texture2DObject,
- "Depth-stencil buffer for layer %s", layer3DS->id().constData());
- (*dsTexOrRb)->setParent(textureParentNode);
- } else {
- *dsTexOrRb = existingDS;
- }
+ bool noStencil = !m_gfxLimits.packedDepthStencilBufferSupported; // GLES 2.0
+ // see newDepthStencilBuffer for a detailed description of this mess
+ noStencil |= m_gfxLimits.format.renderableType() == QSurfaceFormat::OpenGLES
+ && Q3DS::graphicsLimits().format.version() <= qMakePair(3, 1);
+ Qt3DRender::QAbstractTexture::TextureFormat textureFormat =
+ noStencil ? Qt3DRender::QAbstractTexture::D16 : Qt3DRender::QAbstractTexture::D24S8;
+ ds->setAttachmentPoint(noStencil ? Qt3DRender::QRenderTargetOutput::Depth
+ : Qt3DRender::QRenderTargetOutput::DepthStencil);
+ if (!existingDS) {
+ if (noStencil)
+ qCDebug(lcScene, "Render target depth-stencil attachment uses D16 (no stencil)");
+ else
+ qCDebug(lcScene, "Render target depth-stencil attachment uses D24S8");
+ *dsTexOrRb = newDepthStencilBuffer(layerPixelSize, msaaSampleCount, textureFormat);
+ m_profiler->trackNewObject(*dsTexOrRb, Q3DSProfiler::Texture2DObject,
+ "Depth-stencil buffer for layer %s", layer3DS->id().constData());
+ (*dsTexOrRb)->setParent(textureParentNode);
} else {
- // This is for ES2 case without support for packed depth-stencil buffers
- // Depth
- ds->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth);
- if (!existingDS) {
- *dsTexOrRb = newDepthStencilBuffer(layerPixelSize, msaaSampleCount, Qt3DRender::QAbstractTexture::D16);
- m_profiler->trackNewObject(*dsTexOrRb, Q3DSProfiler::Texture2DObject,
- "Depth buffer for layer %s", layer3DS->id().constData());
- (*dsTexOrRb)->setParent(textureParentNode);
- } else {
- *dsTexOrRb = existingDS;
- }
+ *dsTexOrRb = existingDS;
}
ds->setTexture(*dsTexOrRb);
@@ -1644,16 +1641,21 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS)
data->iblProbeData.lightProbeProperties = new Qt3DRender::QParameter;
data->iblProbeData.lightProbeProperties->setName(QLatin1String("light_probe_props"));
}
+ data->iblProbeData.lightProbeProperties->setValue(QVector4D(0.0f, 0.0f, layer3DS->probehorizon(), layer3DS->probebright() * 0.01f));
+
if (!data->iblProbeData.lightProbe2Properties) {
data->iblProbeData.lightProbe2Properties = new Qt3DRender::QParameter;
data->iblProbeData.lightProbe2Properties->setName(QLatin1String("light_probe2_props"));
}
+ data->iblProbeData.lightProbe2Properties->setValue(QVector4D(0.0f, 0.0f, 0.0f, 0.0f));
+
if (!data->iblProbeData.lightProbeOptions) {
data->iblProbeData.lightProbeOptions = new Qt3DRender::QParameter;
data->iblProbeData.lightProbeOptions->setName(QLatin1String("light_probe_opts"));
}
data->iblProbeData.lightProbeOptions->setValue(QVector4D(0.01745329251994329547f * layer3DS->probefov(), 0.0f, 0.0f, 0.0f));
+
if (layer3DS->lightProbe()) {
// initialize light probe parameters if necessary
if (!data->iblProbeData.lightProbeTexture) {
@@ -1746,12 +1748,6 @@ void Q3DSSceneManager::setLayerProperties(Q3DSLayerNode *layer3DS)
data->iblProbeData.lightProbe2Properties->setValue(QVector4D(0.0f, 0.0f, 0.0f, 0.0f));
data->iblProbeData.lightProbeProperties->setValue(QVector4D(0.0f, 0.0f, layer3DS->probehorizon(), layer3DS->probebright() * 0.01f));
}
- } else {
- // No light probes set
- // Still need to setup some defaults since light probes can be set on
- // individual materials
- data->iblProbeData.lightProbeProperties->setValue(QVector4D(0.0f, 0.0f, -1.0f, 0.0f));
- data->iblProbeData.lightProbe2Properties->setValue(QVector4D(0.0f, 0.0f, 0.0f, 0.0f));
}
}
@@ -2470,7 +2466,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
auto createDepthStencil = [size, this]() {
Qt3DRender::QTexture2D *dsTexOrRb = new Qt3DRender::QTexture2D;
m_profiler->trackNewObject(dsTexOrRb, Q3DSProfiler::Texture2DObject, "Shadow map depth");
- dsTexOrRb->setFormat(Qt3DRender::QAbstractTexture::D24S8);
+ dsTexOrRb->setFormat(Qt3DRender::QAbstractTexture::D16);
dsTexOrRb->setWidth(size);
dsTexOrRb->setHeight(size);
dsTexOrRb->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
@@ -2519,8 +2515,15 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
"Shadow map temp buffer for light %s", light3DS->id().constData());
}
- d->shadowMapTexture->setFormat(Qt3DRender::QAbstractTexture::R16_UNorm);
- d->shadowMapTextureTemp->setFormat(Qt3DRender::QAbstractTexture::R16_UNorm);
+ Qt3DRender::QAbstractTexture::TextureFormat format = Qt3DRender::QAbstractTexture::R16_UNorm;
+ // GL_R16 does not seem to exist in OpenGL ES unless GL_EXT_texture_norm16
+ // is present. Fall back to the GL_R8 when not supported (but this leads
+ // to uglier output with more artifacts).
+ if (!m_gfxLimits.norm16TexturesSupported)
+ format = Qt3DRender::QAbstractTexture::R8_UNorm;
+
+ d->shadowMapTexture->setFormat(format);
+ d->shadowMapTextureTemp->setFormat(format);
d->shadowMapTexture->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
d->shadowMapTextureTemp->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
@@ -2571,7 +2574,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
shadowRt->addOutput(shadowRtOutput);
shadowRtOutput = new Qt3DRender::QRenderTargetOutput;
- shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil);
+ shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth);
shadowRtOutput->setTexture(d->shadowDS);
shadowRt->addOutput(shadowRtOutput);
@@ -2632,7 +2635,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
shadowRt->addOutput(shadowRtOutput);
shadowRtOutput = new Qt3DRender::QRenderTargetOutput;
- shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::DepthStencil);
+ shadowRtOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::Depth);
shadowRtOutput->setTexture(d->shadowDS);
shadowRt->addOutput(shadowRtOutput);
@@ -3711,6 +3714,15 @@ QMatrix4x4 generateRotationMatrix(const QVector3D &nodeRotation, Q3DSNode::Rotat
}
return rotationMatrix;
}
+
+float clampOpacity(float f)
+{
+ f = qBound(0.0f, f, 1.0f);
+ // make sure 1 is 1 so we won't end up with opacity < 1 == false
+ if (qFuzzyCompare(f, 1.0f))
+ f = 1.0f;
+ return f;
+}
}
void Q3DSSceneManager::setNodeProperties(Q3DSNode *node, Qt3DCore::QEntity *entity,
@@ -3781,13 +3793,13 @@ void Q3DSSceneManager::updateGlobals(Q3DSNode *node, UpdateGlobalFlags flags)
globalTransform = parentData->globalTransform * data->transform->matrix();
}
// update the global, inherited opacity
- globalOpacity = parentData->globalOpacity * (node->localOpacity() / 100.0f);
+ globalOpacity = clampOpacity(parentData->globalOpacity * (node->localOpacity() / 100.0f));
// update inherited visibility
globalVisibility = node->flags().testFlag(Q3DSNode::Active) && parentData->globalVisibility;
} else {
if (!flags.testFlag(UpdateGlobalsSkipTransform))
globalTransform = data->transform->matrix();
- globalOpacity = node->localOpacity() / 100.0f;
+ globalOpacity = clampOpacity(node->localOpacity() / 100.0f);
globalVisibility = node->flags().testFlag(Q3DSNode::Active);
}
@@ -4182,7 +4194,7 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildModel(Q3DSModelNode *model3DS, Q3DSLay
// follow the reference for ReferencedMaterial
if (sm.material->type() == Q3DSGraphObject::ReferencedMaterial) {
Q3DSReferencedMaterial *matRef = static_cast<Q3DSReferencedMaterial *>(sm.material);
- sm.referencedMaterial = matRef;
+ sm.referencingMaterial = matRef;
if (matRef->referencedMaterial())
sm.resolvedMaterial = matRef->referencedMaterial();
}
@@ -4254,11 +4266,13 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
Q3DSDefaultMaterial *defaultMaterial = static_cast<Q3DSDefaultMaterial *>(sm.resolvedMaterial);
// Create parameters to the shader.
- QVector<Qt3DRender::QParameter *> params = prepareDefaultMaterial(defaultMaterial, sm.referencedMaterial, model3DS);
+ QVector<Qt3DRender::QParameter *> params = prepareDefaultMaterial(defaultMaterial, sm.referencingMaterial, model3DS);
+
// Update parameter values.
Q3DSDefaultMaterialAttached *defMatData = static_cast<Q3DSDefaultMaterialAttached *>(defaultMaterial->attached());
- defMatData->opacity = modelData->globalOpacity * (defaultMaterial->opacity() / 100.0f);
- updateDefaultMaterial(defaultMaterial, sm.referencedMaterial);
+ const float opacity = clampOpacity(modelData->globalOpacity * (defaultMaterial->opacity() / 100.0f));
+ defMatData->perModelData[model3DS].combinedOpacity = opacity;
+ updateDefaultMaterial(defaultMaterial, sm.referencingMaterial, model3DS);
// Setup camera properties
if (layerData->cameraPropertiesParam != nullptr)
@@ -4317,6 +4331,10 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
params.append(layerData->iblProbeData.lightProbeSampler);
params.append(layerData->iblProbeData.lightProbeOffset);
params.append(layerData->iblProbeData.lightProbeRotation);
+ } else {
+ params.append(defMatData->lightProbeSampler);
+ params.append(defMatData->lightProbeOffset);
+ params.append(defMatData->lightProbeRotation);
}
if (modelData->layer3DS->lightProbe2()) {
@@ -4333,14 +4351,14 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
param->setParent(layerData->entity);
}
- sm.materialComponent = m_matGen->generateMaterial(defaultMaterial, sm.referencedMaterial, params, lightNodes, modelData->layer3DS);
+ sm.materialComponent = m_matGen->generateMaterial(defaultMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS);
sm.entity->addComponent(sm.materialComponent);
} else if (sm.resolvedMaterial->type() == Q3DSGraphObject::CustomMaterial) {
Q3DSCustomMaterialInstance *customMaterial = static_cast<Q3DSCustomMaterialInstance *>(sm.resolvedMaterial);
- QVector<Qt3DRender::QParameter *> params = prepareCustomMaterial(customMaterial, sm.referencedMaterial, model3DS);
+ QVector<Qt3DRender::QParameter *> params = prepareCustomMaterial(customMaterial, sm.referencingMaterial, model3DS);
Q3DSCustomMaterialAttached *custMatData = static_cast<Q3DSCustomMaterialAttached *>(customMaterial->attached());
- custMatData->opacity = modelData->globalOpacity;
- updateCustomMaterial(customMaterial, sm.referencedMaterial);
+ custMatData->perModelData[model3DS].combinedOpacity = modelData->globalOpacity;
+ updateCustomMaterial(customMaterial, sm.referencingMaterial, model3DS);
if (lightsData) {
if (m_gfxLimits.shaderUniformBufferSupported) {
@@ -4393,6 +4411,10 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
params.append(layerData->iblProbeData.lightProbeSampler);
params.append(layerData->iblProbeData.lightProbeOffset);
params.append(layerData->iblProbeData.lightProbeRotation);
+ } else {
+ params.append(custMatData->lightProbeSampler);
+ params.append(custMatData->lightProbeOffset);
+ params.append(custMatData->lightProbeRotation);
}
if (modelData->layer3DS->lightProbe2()) {
@@ -4408,7 +4430,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
// ### TODO support more than one pass
auto pass = customMaterial->material()->passes().first();
- sm.materialComponent = m_customMaterialGen->generateMaterial(customMaterial, sm.referencedMaterial, params, lightNodes, modelData->layer3DS, pass);
+ sm.materialComponent = m_customMaterialGen->generateMaterial(customMaterial, sm.referencingMaterial, params, lightNodes, modelData->layer3DS, pass);
sm.entity->addComponent(sm.materialComponent);
}
}
@@ -4448,7 +4470,7 @@ void Q3DSSceneManager::retagSubMeshes(Q3DSModelNode *model3DS)
// not yet be created. This is not a problem in practice.
if (sm.resolvedMaterial->type() == Q3DSGraphObject::DefaultMaterial) {
auto defaultMaterial = static_cast<Q3DSDefaultMaterial *>(sm.resolvedMaterial);
- opacity *= defaultMaterial->opacity() / 100.0f;
+ opacity = clampOpacity(opacity * defaultMaterial->opacity() / 100.0f);
// Check maps for transparency as well
hasTransparency = ((defaultMaterial->diffuseMap() && defaultMaterial->diffuseMap()->hasTransparency(m_presentation)) ||
(defaultMaterial->diffuseMap2() && defaultMaterial->diffuseMap2()->hasTransparency(m_presentation)) ||
@@ -4464,11 +4486,13 @@ void Q3DSSceneManager::retagSubMeshes(Q3DSModelNode *model3DS)
sm.hasTransparency = opacity < 1.0f || matDesc->materialHasTransparency() || matDesc->materialHasRefraction();
}
- Qt3DRender::QLayer *newTag = sm.hasTransparency ? layerData->transparentTag : layerData->opaqueTag;
- if (!sm.entity->components().contains(newTag)) {
- Qt3DRender::QLayer *prevTag = newTag == layerData->transparentTag ? layerData->opaqueTag : layerData->transparentTag;
- sm.entity->removeComponent(prevTag);
- sm.entity->addComponent(newTag);
+ if (data->globalVisibility) {
+ Qt3DRender::QLayer *newTag = sm.hasTransparency ? layerData->transparentTag : layerData->opaqueTag;
+ if (!sm.entity->components().contains(newTag)) {
+ Qt3DRender::QLayer *prevTag = newTag == layerData->transparentTag ? layerData->opaqueTag : layerData->transparentTag;
+ sm.entity->removeComponent(prevTag);
+ sm.entity->addComponent(newTag);
+ }
}
profData.needsBlending = sm.hasTransparency;
@@ -4578,159 +4602,196 @@ void Q3DSSceneManager::setImageTextureFromSubPresentation(Qt3DRender::QParameter
QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS)
{
- QVector<Qt3DRender::QParameter *> params;
+ // This function can be called more than once for the same 'm' (with a
+ // different 'model3DS' each time). The returned QParameter list must be
+ // complete in any case, but returning QParameters that were returned
+ // before for a different model3DS is fine.
- if (!m->attached())
+ const bool firstRun = !m->attached();
+ if (firstRun)
m->setAttached(new Q3DSDefaultMaterialAttached);
Q3DSDefaultMaterialAttached *data = static_cast<Q3DSDefaultMaterialAttached *>(m->attached());
Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(model3DS->attached());
- data->entity = modelData->entity;
- data->model3DS = model3DS;
+ QVector<Qt3DRender::QParameter *> params;
+
+ if (firstRun)
+ data->entity = modelData->entity;
- if (!data->diffuseParam) {
+ if (firstRun) {
data->diffuseParam = new Qt3DRender::QParameter;
data->diffuseParam->setName(QLatin1String("diffuse_color"));
}
params.append(data->diffuseParam);
- if (!data->materialDiffuseParam) {
- data->materialDiffuseParam = new Qt3DRender::QParameter;
- data->materialDiffuseParam->setName(QLatin1String("material_diffuse"));
- }
- params.append(data->materialDiffuseParam);
+ Q3DSMaterialAttached::PerModelData md;
+ md.materialDiffuseParam = new Qt3DRender::QParameter;
+ md.materialDiffuseParam->setName(QLatin1String("material_diffuse"));
+ data->perModelData.insert(model3DS, md);
+ params.append(md.materialDiffuseParam);
+ data->perModelData.insert(model3DS, md);
- if (!data->specularParam) {
+ if (firstRun) {
data->specularParam = new Qt3DRender::QParameter;
data->specularParam->setName(QLatin1String("material_specular"));
}
params.append(data->specularParam);
- if (!data->fresnelPowerParam) {
+ if (firstRun) {
data->fresnelPowerParam = new Qt3DRender::QParameter;
data->fresnelPowerParam->setName(QLatin1String("fresnelPower"));
}
params.append(data->fresnelPowerParam);
- if (!data->bumpAmountParam) {
+ if (firstRun) {
data->bumpAmountParam = new Qt3DRender::QParameter;
data->bumpAmountParam->setName(QLatin1String("bumpAmount"));
}
params.append(data->bumpAmountParam);
- if (!data->materialPropertiesParam) {
+ if (firstRun) {
data->materialPropertiesParam = new Qt3DRender::QParameter;
data->materialPropertiesParam->setName(QLatin1String("material_properties"));
}
params.append(data->materialPropertiesParam);
- if (!data->translucentFalloffParam) {
+ if (firstRun) {
data->translucentFalloffParam = new Qt3DRender::QParameter;
data->translucentFalloffParam->setName(QLatin1String("translucentFalloff"));
}
params.append(data->translucentFalloffParam);
- if (!data->diffuseLightWrapParam) {
+ if (firstRun) {
data->diffuseLightWrapParam = new Qt3DRender::QParameter;
data->diffuseLightWrapParam->setName(QLatin1String("diffuseLightWrap"));
}
params.append(data->diffuseLightWrapParam);
- if (!data->displaceAmountParam) {
+ if (firstRun) {
data->displaceAmountParam = new Qt3DRender::QParameter;
data->displaceAmountParam->setName(QLatin1String("displaceAmount"));
}
params.append(data->displaceAmountParam);
if (m->diffuseMap()) {
- prepareTextureParameters(data->diffuseMapParams, QLatin1String("diffuseMap"), m->diffuseMap());
+ if (firstRun) {
+ prepareTextureParameters(data->diffuseMapParams, QLatin1String("diffuseMap"), m->diffuseMap());
+ static_cast<Q3DSImageAttached *>(m->diffuseMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->diffuseMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->diffuseMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->diffuseMap2()) {
- prepareTextureParameters(data->diffuseMap2Params, QLatin1String("diffuseMap2"), m->diffuseMap2());
+ if (firstRun) {
+ prepareTextureParameters(data->diffuseMap2Params, QLatin1String("diffuseMap2"), m->diffuseMap2());
+ static_cast<Q3DSImageAttached *>(m->diffuseMap2()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->diffuseMap2Params.parameters());
- static_cast<Q3DSImageAttached *>(m->diffuseMap2()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->diffuseMap3()) {
- prepareTextureParameters(data->diffuseMap3Params, QLatin1String("diffuseMap3"), m->diffuseMap3());
+ if (firstRun) {
+ prepareTextureParameters(data->diffuseMap3Params, QLatin1String("diffuseMap3"), m->diffuseMap3());
+ static_cast<Q3DSImageAttached *>(m->diffuseMap3()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->diffuseMap3Params.parameters());
- static_cast<Q3DSImageAttached *>(m->diffuseMap3()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->specularReflection()) {
- prepareTextureParameters(data->specularReflectionParams, QLatin1String("specularreflection"), m->specularReflection());
+ if (firstRun) {
+ prepareTextureParameters(data->specularReflectionParams, QLatin1String("specularreflection"), m->specularReflection());
+ static_cast<Q3DSImageAttached *>(m->specularReflection()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->specularReflectionParams.parameters());
- static_cast<Q3DSImageAttached *>(m->specularReflection()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->specularMap()) {
- prepareTextureParameters(data->specularMapParams, QLatin1String("specularMap"), m->specularMap());
+ if (firstRun) {
+ prepareTextureParameters(data->specularMapParams, QLatin1String("specularMap"), m->specularMap());
+ static_cast<Q3DSImageAttached *>(m->specularMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->specularMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->specularMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->roughnessMap()) {
- prepareTextureParameters(data->roughnessMapParams, QLatin1String("roughnessMap"), m->roughnessMap());
+ if (firstRun) {
+ prepareTextureParameters(data->roughnessMapParams, QLatin1String("roughnessMap"), m->roughnessMap());
+ static_cast<Q3DSImageAttached *>(m->roughnessMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->roughnessMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->roughnessMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->bumpMap()) {
- prepareTextureParameters(data->bumpMapParams, QLatin1String("bumpMap"), m->bumpMap());
+ if (firstRun) {
+ prepareTextureParameters(data->bumpMapParams, QLatin1String("bumpMap"), m->bumpMap());
+ static_cast<Q3DSImageAttached *>(m->bumpMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->bumpMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->bumpMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->normalMap()) {
- prepareTextureParameters(data->normalMapParams, QLatin1String("normalMap"), m->normalMap());
+ if (firstRun) {
+ prepareTextureParameters(data->normalMapParams, QLatin1String("normalMap"), m->normalMap());
+ static_cast<Q3DSImageAttached *>(m->normalMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->normalMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->normalMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->displacementmap()) {
- prepareTextureParameters(data->displacementMapParams, QLatin1String("displacementMap"), m->displacementmap());
+ if (firstRun) {
+ prepareTextureParameters(data->displacementMapParams, QLatin1String("displacementMap"), m->displacementmap());
+ static_cast<Q3DSImageAttached *>(m->displacementmap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->displacementMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->displacementmap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->opacityMap()) {
- prepareTextureParameters(data->opacityMapParams, QLatin1String("opacityMap"), m->opacityMap());
+ if (firstRun) {
+ prepareTextureParameters(data->opacityMapParams, QLatin1String("opacityMap"), m->opacityMap());
+ static_cast<Q3DSImageAttached *>(m->opacityMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->opacityMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->opacityMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->emissiveMap()) {
- prepareTextureParameters(data->emissiveMapParams, QLatin1String("emissiveMap"), m->emissiveMap());
+ if (firstRun) {
+ prepareTextureParameters(data->emissiveMapParams, QLatin1String("emissiveMap"), m->emissiveMap());
+ static_cast<Q3DSImageAttached *>(m->emissiveMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->emissiveMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->emissiveMap()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->emissiveMap2()) {
- prepareTextureParameters(data->emissiveMap2Params, QLatin1String("emissiveMap2"), m->emissiveMap2());
+ if (firstRun) {
+ prepareTextureParameters(data->emissiveMap2Params, QLatin1String("emissiveMap2"), m->emissiveMap2());
+ static_cast<Q3DSImageAttached *>(m->emissiveMap2()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->emissiveMap2Params.parameters());
- static_cast<Q3DSImageAttached *>(m->emissiveMap2()->attached())->referencingDefaultMaterials.insert(m);
}
if (m->translucencyMap()) {
- prepareTextureParameters(data->translucencyMapParams, QLatin1String("translucencyMap"), m->translucencyMap());
+ if (firstRun) {
+ prepareTextureParameters(data->translucencyMapParams, QLatin1String("translucencyMap"), m->translucencyMap());
+ static_cast<Q3DSImageAttached *>(m->translucencyMap()->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->translucencyMapParams.parameters());
- static_cast<Q3DSImageAttached *>(m->translucencyMap()->attached())->referencingDefaultMaterials.insert(m);
}
// Lightmaps
// check for referencedMaterial Overrides
+ // Note all the below must ignore firstRun since there's nothing saying the
+ // first call for a certain 'm' is the one with rm != null.
Q3DSImage *lightmapIndirect = nullptr;
if (rm && rm->lightmapIndirectMap())
lightmapIndirect = rm->lightmapIndirectMap();
else if (m->lightmapIndirectMap())
lightmapIndirect = m->lightmapIndirectMap();
if (lightmapIndirect) {
- prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect);
+ if (!data->lightmapIndirectParams.sampler) {
+ prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect);
+ static_cast<Q3DSImageAttached *>(lightmapIndirect->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->lightmapIndirectParams.parameters());
- static_cast<Q3DSImageAttached *>(lightmapIndirect->attached())->referencingDefaultMaterials.insert(m);
}
Q3DSImage *lightmapRadiosity = nullptr;
@@ -4739,9 +4800,11 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareDefaultMaterial(Q3DSD
else if (m->lightmapRadiosityMap())
lightmapRadiosity = m->lightmapRadiosityMap();
if (lightmapRadiosity) {
- prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity);
+ if (!data->lightmapRadiosityParams.sampler) {
+ prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity);
+ static_cast<Q3DSImageAttached *>(lightmapRadiosity->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->lightmapRadiosityParams.parameters());
- static_cast<Q3DSImageAttached *>(lightmapRadiosity->attached())->referencingDefaultMaterials.insert(m);
}
Q3DSImage *lightmapShadow = nullptr;
@@ -4750,9 +4813,11 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareDefaultMaterial(Q3DSD
else if (m->lightmapShadowMap())
lightmapShadow = m->lightmapShadowMap();
if (lightmapShadow) {
- prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow);
+ if (!data->lightmapShadowParams.sampler) {
+ prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow);
+ static_cast<Q3DSImageAttached *>(lightmapShadow->attached())->referencingDefaultMaterials.insert(m);
+ }
params.append(data->lightmapShadowParams.parameters());
- static_cast<Q3DSImageAttached *>(lightmapShadow->attached())->referencingDefaultMaterials.insert(m);
}
// IBL
@@ -4762,27 +4827,36 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareDefaultMaterial(Q3DSD
else if (m->lightProbe())
iblOverrideImage = m->lightProbe();
if (iblOverrideImage) {
- data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile(
- m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
- m_profiler, "Texture for image %s", iblOverrideImage->id().constData());
- data->lightProbeSampler = new Qt3DRender::QParameter;
- data->lightProbeSampler->setName(QLatin1String("light_probe"));
- params.append(data->lightProbeSampler);
+ if (!data->lightProbeOverrideTexture) {
+ data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile(
+ m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
+ m_profiler, "Texture for image %s", iblOverrideImage->id().constData());
+ data->lightProbeSampler = new Qt3DRender::QParameter;
+ data->lightProbeSampler->setName(QLatin1String("light_probe"));
- data->lightProbeRotation = new Qt3DRender::QParameter;
- data->lightProbeRotation->setName(QLatin1String("light_probe_rotation"));
- params.append(data->lightProbeRotation);
+ data->lightProbeRotation = new Qt3DRender::QParameter;
+ data->lightProbeRotation->setName(QLatin1String("light_probe_rotation"));
- data->lightProbeOffset = new Qt3DRender::QParameter;
- data->lightProbeOffset->setName(QLatin1String("light_probe_offset"));
+ data->lightProbeOffset = new Qt3DRender::QParameter;
+ data->lightProbeOffset->setName(QLatin1String("light_probe_offset"));
+ }
+ params.append(data->lightProbeSampler);
+ params.append(data->lightProbeRotation);
params.append(data->lightProbeOffset);
}
return params;
}
-void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm)
+void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS)
{
+ // This function is typically called in a loop for each Q3DSModelNode that
+ // shares the same Q3DSDefaultMaterial. Having more than one model can only
+ // happen when a ReferencedMaterial is used. Currently we are somewhat
+ // wasteful in this case since setting the QParameter values over and over
+ // again is not really needed, with the exception of the one model-specific
+ // one. We'll live with this for the time being.
+
Q3DSDefaultMaterialAttached *data = static_cast<Q3DSDefaultMaterialAttached *>(m->attached());
Q_ASSERT(data && data->diffuseParam);
@@ -4793,11 +4867,15 @@ void Q3DSSceneManager::updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferen
if (hasLighting)
emissivePower = m->emissivePower() / 100.0f;
+ // This one depends on the combinedOpacity which depends on the
+ // localOpacity from the model. Hence its placement in the perModelData map.
+ auto perModelDataIt = data->perModelData.find(model3DS);
+ Q_ASSERT(perModelDataIt != data->perModelData.end());
QVector4D material_diffuse(m->emissiveColor().redF() * emissivePower,
m->emissiveColor().greenF() * emissivePower,
m->emissiveColor().blueF() * emissivePower,
- data->opacity);
- data->materialDiffuseParam->setValue(material_diffuse);
+ perModelDataIt->combinedOpacity);
+ perModelDataIt->materialDiffuseParam->setValue(material_diffuse);
QVector4D material_specular(m->specularTint().redF(),
m->specularTint().greenF(),
@@ -5020,39 +5098,54 @@ Qt3DRender::QAbstractTexture *Q3DSSceneManager::createCustomPropertyTexture(cons
QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS)
{
- if (!m->attached())
+ // this function can be called more than once for the same 'm' (with a different 'model3DS' each time)
+
+ const bool firstRun = !m->attached();
+ if (firstRun)
m->setAttached(new Q3DSCustomMaterialAttached);
Q3DSCustomMaterialAttached *data = static_cast<Q3DSCustomMaterialAttached *>(m->attached());
Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(model3DS->attached());
- data->entity = modelData->entity;
- data->model3DS = model3DS;
+
+ if (firstRun)
+ data->entity = modelData->entity;
// Generate QParameters
QVector<Qt3DRender::QParameter *> paramList;
- forAllCustomProperties(m, [&paramList, data](const QString &propKey, const QVariant &, const Q3DSMaterial::PropertyElement &propMeta) {
- QVariant v(0); // initial value is something dummy, ignore propValue for now
- Qt3DRender::QParameter *param = new Qt3DRender::QParameter;
- param->setName(propKey);
- param->setValue(v);
- paramList.append(param);
- data->params.insert(propKey, Q3DSCustomPropertyParameter(param, v, propMeta));
- });
+ if (firstRun) {
+ forAllCustomProperties(m, [&paramList, data](const QString &propKey, const QVariant &, const Q3DSMaterial::PropertyElement &propMeta) {
+ QVariant v(0); // initial value is something dummy, ignore propValue for now
+ Qt3DRender::QParameter *param = new Qt3DRender::QParameter;
+ param->setName(propKey);
+ param->setValue(v);
+ paramList.append(param);
+ data->params.insert(propKey, Q3DSCustomPropertyParameter(param, v, propMeta));
+ });
+ } else {
+ for (auto it = data->params.cbegin(), itEnd = data->params.cend(); it != itEnd; ++it)
+ paramList.append(it->param);
+ }
- data->objectOpacityParam = new Qt3DRender::QParameter;
- data->objectOpacityParam->setName(QLatin1String("object_opacity"));
- paramList.append(data->objectOpacityParam);
+ Q3DSMaterialAttached::PerModelData md;
+ md.objectOpacityParam = new Qt3DRender::QParameter;
+ md.objectOpacityParam->setName(QLatin1String("object_opacity"));
+ data->perModelData.insert(model3DS, md);
+ paramList.append(md.objectOpacityParam);
+ data->perModelData.insert(model3DS, md);
// Lightmaps
// check for referencedMaterial Overrides
+ // Note all the below must ignore firstRun since there's nothing saying the
+ // first call for a certain 'm' is the one with rm != null.
Q3DSImage *lightmapIndirect = nullptr;
if (rm && rm->lightmapIndirectMap())
lightmapIndirect = rm->lightmapIndirectMap();
else if (m->lightmapIndirectMap())
lightmapIndirect = m->lightmapIndirectMap();
if (lightmapIndirect) {
- prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect);
+ if (!data->lightmapIndirectParams.sampler)
+ prepareTextureParameters(data->lightmapIndirectParams, QLatin1String("lightmapIndirect"), lightmapIndirect);
paramList.append(data->lightmapIndirectParams.parameters());
}
@@ -5062,7 +5155,8 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareCustomMaterial(Q3DSCu
else if (m->lightmapRadiosityMap())
lightmapRadiosity = m->lightmapRadiosityMap();
if (lightmapRadiosity) {
- prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity);
+ if (!data->lightmapRadiosityParams.sampler)
+ prepareTextureParameters(data->lightmapRadiosityParams, QLatin1String("lightmapRadiosity"), lightmapRadiosity);
paramList.append(data->lightmapRadiosityParams.parameters());
}
@@ -5072,7 +5166,8 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareCustomMaterial(Q3DSCu
else if (m->lightmapShadowMap())
lightmapShadow = m->lightmapShadowMap();
if (lightmapShadow) {
- prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow);
+ if (!data->lightmapShadowParams.sampler)
+ prepareTextureParameters(data->lightmapShadowParams, QLatin1String("lightmapShadow"), lightmapShadow);
paramList.append(data->lightmapShadowParams.parameters());
}
@@ -5083,27 +5178,36 @@ QVector<Qt3DRender::QParameter *> Q3DSSceneManager::prepareCustomMaterial(Q3DSCu
else if (m->lightProbe())
iblOverrideImage = m->lightProbe();
if (iblOverrideImage) {
- data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile(
- m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
- m_profiler, "Texture for image %s", iblOverrideImage->id().constData());
- data->lightProbeSampler = new Qt3DRender::QParameter;
- data->lightProbeSampler->setName(QLatin1String("light_probe"));
- paramList.append(data->lightProbeSampler);
+ if (!data->lightProbeOverrideTexture) {
+ data->lightProbeOverrideTexture = Q3DSImageManager::instance().newTextureForImageFile(
+ m_rootEntity, Q3DSImageManager::GenerateMipMapsForIBL,
+ m_profiler, "Texture for image %s", iblOverrideImage->id().constData());
+ data->lightProbeSampler = new Qt3DRender::QParameter;
+ data->lightProbeSampler->setName(QLatin1String("light_probe"));
- data->lightProbeRotation = new Qt3DRender::QParameter;
- data->lightProbeRotation->setName(QLatin1String("light_probe_rotation"));
- paramList.append(data->lightProbeRotation);
+ data->lightProbeRotation = new Qt3DRender::QParameter;
+ data->lightProbeRotation->setName(QLatin1String("light_probe_rotation"));
- data->lightProbeOffset = new Qt3DRender::QParameter;
- data->lightProbeOffset->setName(QLatin1String("light_probe_offset"));
+ data->lightProbeOffset = new Qt3DRender::QParameter;
+ data->lightProbeOffset->setName(QLatin1String("light_probe_offset"));
+ }
+ paramList.append(data->lightProbeSampler);
+ paramList.append(data->lightProbeRotation);
paramList.append(data->lightProbeOffset);
}
return paramList;
}
-void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm)
+void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS)
{
+ // This function is typically called in a loop for each Q3DSModelNode that
+ // shares the same Q3DSCustomMaterial(Instance). Having more than one model
+ // can only happen when a ReferencedMaterial is used. Currently we are
+ // somewhat wasteful in this case since setting the QParameter values over
+ // and over again is not really needed, with the exception of the one
+ // model-specific one. We'll live with this for the time being.
+
Q3DSCustomMaterialAttached *data = static_cast<Q3DSCustomMaterialAttached *>(m->attached());
// set all dynamic property values to the corresponding QParameters
@@ -5133,7 +5237,9 @@ void Q3DSSceneManager::updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSR
}
});
- data->objectOpacityParam->setValue(data->opacity);
+ auto perModelDataIt = data->perModelData.find(model3DS);
+ Q_ASSERT(perModelDataIt != data->perModelData.end());
+ perModelDataIt->objectOpacityParam->setValue(perModelDataIt->combinedOpacity);
// Lightmaps
Q3DSImage *lightmapIndirect = nullptr;
@@ -6371,11 +6477,14 @@ void Q3DSSceneManager::updateModel(Q3DSModelNode *model3DS)
if (sm.resolvedMaterial->type() == Q3DSGraphObject::DefaultMaterial) {
auto m = static_cast<Q3DSDefaultMaterial *>(sm.resolvedMaterial);
auto d = static_cast<Q3DSDefaultMaterialAttached *>(m->attached());
- if (d && d->materialDiffuseParam) {
- const float opacity = data->globalOpacity * (m->opacity() / 100.0f);
- QVector4D c = d->materialDiffuseParam->value().value<QVector4D>();
- c.setW(opacity);
- d->materialDiffuseParam->setValue(c);
+ if (d) {
+ auto perModelDataIt = d->perModelData.find(model3DS);
+ if (perModelDataIt != d->perModelData.end()) {
+ perModelDataIt->combinedOpacity = clampOpacity(data->globalOpacity * (m->opacity() / 100.0f));
+ QVector4D c = perModelDataIt->materialDiffuseParam->value().value<QVector4D>();
+ c.setW(perModelDataIt->combinedOpacity);
+ perModelDataIt->materialDiffuseParam->setValue(c);
+ }
}
}
}
@@ -6535,20 +6644,15 @@ void Q3DSSceneManager::updateSubTree(Q3DSGraphObject *obj)
}
for (Q3DSDefaultMaterial *mat3DS : m_pendingDefMatRebuild) {
- if (Q3DSDefaultMaterialAttached *matData = static_cast<Q3DSDefaultMaterialAttached *>(mat3DS->attached()))
- rebuildModelMaterial(matData->model3DS);
+ if (Q3DSDefaultMaterialAttached *matData = static_cast<Q3DSDefaultMaterialAttached *>(mat3DS->attached())) {
+ for (auto it = matData->perModelData.cbegin(), itEnd = matData->perModelData.cend(); it != itEnd; ++it)
+ rebuildModelMaterial(it.key());
+ }
}
- if (!m_pendingNodeHide.isEmpty()) {
- for (Q3DSNode *node : m_pendingNodeHide)
- setNodeVisibility(node, false);
- m_pendingNodeHide.clear();
- }
- if (!m_pendingNodeShow.isEmpty()) {
- for (Q3DSNode *node : m_pendingNodeShow)
- setNodeVisibility(node, true);
- m_pendingNodeShow.clear();
- }
+ for (auto it = m_pendingNodeVisibility.constBegin(); it != m_pendingNodeVisibility.constEnd(); ++it)
+ setNodeVisibility(it.key(), it.value());
+ m_pendingNodeVisibility.clear();
}
static Q3DSComponentNode *findNextComponentParent(Q3DSComponentNode *component)
@@ -6661,14 +6765,17 @@ void Q3DSSceneManager::prepareNextFrame()
static void markLayerForObjectDirty(Q3DSGraphObject *obj)
{
- auto findLayerForMat = [](Q3DSGraphObject *obj) {
- Q3DSLayerNode *layer3DS = nullptr;
+ auto findLayersForMat = [](Q3DSGraphObject *obj) {
+ QVector<Q3DSLayerNode *> layers;
Q3DSMaterialAttached *data = static_cast<Q3DSMaterialAttached *>(obj->attached());
- if (data && data->model3DS) {
- Q3DSNodeAttached *ndata = static_cast<Q3DSNodeAttached *>(data->model3DS->attached());
- layer3DS = ndata->layer3DS;
+ if (data) {
+ for (auto it = data->perModelData.cbegin(), itEnd = data->perModelData.cend(); it != itEnd; ++it) {
+ Q3DSModelNode *model3DS = it.key();
+ Q3DSNodeAttached *ndata = static_cast<Q3DSNodeAttached *>(model3DS->attached());
+ layers.append(ndata->layer3DS);
+ }
}
- return layer3DS;
+ return layers;
};
auto markLayerDirty = [](Q3DSLayerNode *layer3DS) {
static_cast<Q3DSLayerAttached *>(layer3DS->attached())->wasDirty = true;
@@ -6683,13 +6790,11 @@ static void markLayerForObjectDirty(Q3DSGraphObject *obj)
} else if (obj->type() == Q3DSGraphObject::Image) {
Q3DSImageAttached *data = static_cast<Q3DSImageAttached *>(obj->attached());
for (Q3DSDefaultMaterial *mat3DS : qAsConst(data->referencingDefaultMaterials)) {
- Q3DSLayerNode *layer3DS = findLayerForMat(mat3DS);
- if (layer3DS)
+ for (Q3DSLayerNode *layer3DS : findLayersForMat(mat3DS))
markLayerDirty(layer3DS);
}
} else if (obj->type() == Q3DSGraphObject::DefaultMaterial || obj->type() == Q3DSGraphObject::CustomMaterial) {
- Q3DSLayerNode *layer3DS = findLayerForMat(obj);
- if (layer3DS)
+ for (Q3DSLayerNode *layer3DS : findLayersForMat(obj))
markLayerDirty(layer3DS);
} else if (obj->type() == Q3DSGraphObject::Effect) {
Q3DSEffectAttached *data = static_cast<Q3DSEffectAttached *>(obj->attached());
@@ -6808,10 +6913,13 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj)
Q3DSDefaultMaterial *mat3DS = static_cast<Q3DSDefaultMaterial *>(obj);
Q3DSDefaultMaterialAttached *data = static_cast<Q3DSDefaultMaterialAttached *>(mat3DS->attached());
if (data && (data->frameDirty & Q3DSGraphObjectAttached::DefaultMaterialDirty)) {
- Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(data->model3DS->attached());
- data->opacity = modelData->globalOpacity * (mat3DS->opacity() / 100.0f);
- updateDefaultMaterial(mat3DS);
- retagSubMeshes(data->model3DS);
+ for (auto it = data->perModelData.begin(), itEnd = data->perModelData.end(); it != itEnd; ++it) {
+ Q3DSModelNode *model3DS = it.key();
+ Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(model3DS->attached());
+ it->combinedOpacity = clampOpacity(modelData->globalOpacity * (mat3DS->opacity() / 100.0f));
+ updateDefaultMaterial(mat3DS, nullptr, model3DS);
+ retagSubMeshes(model3DS);
+ }
m_wasDirty = true;
markLayerForObjectDirty(mat3DS);
if (data->frameChangeFlags & Q3DSDefaultMaterial::BlendModeChanges)
@@ -6824,10 +6932,13 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj)
Q3DSCustomMaterialInstance *mat3DS = static_cast<Q3DSCustomMaterialInstance *>(obj);
Q3DSCustomMaterialAttached *data = static_cast<Q3DSCustomMaterialAttached *>(mat3DS->attached());
if (data && (data->frameDirty & Q3DSGraphObjectAttached::CustomMaterialDirty)) {
- Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(data->model3DS->attached());
- data->opacity = modelData->globalOpacity;
- updateCustomMaterial(mat3DS);
- retagSubMeshes(data->model3DS);
+ for (auto it = data->perModelData.begin(), itEnd = data->perModelData.end(); it != itEnd; ++it) {
+ Q3DSModelNode *model3DS = it.key();
+ Q3DSModelAttached *modelData = static_cast<Q3DSModelAttached *>(model3DS->attached());
+ it->combinedOpacity = modelData->globalOpacity;
+ updateCustomMaterial(mat3DS, nullptr, model3DS);
+ retagSubMeshes(model3DS);
+ }
m_wasDirty = true;
markLayerForObjectDirty(mat3DS);
}
@@ -6870,8 +6981,11 @@ void Q3DSSceneManager::updateSubTreeRecursive(Q3DSGraphObject *obj)
Q3DSImageAttached *data = static_cast<Q3DSImageAttached *>(image3DS->attached());
if (data && (data->frameDirty & Q3DSGraphObjectAttached::ImageDirty)) {
image3DS->calculateTextureTransform();
- for (Q3DSDefaultMaterial *m : data->referencingDefaultMaterials)
- updateDefaultMaterial(m);
+ for (Q3DSDefaultMaterial *m : data->referencingDefaultMaterials) {
+ Q3DSDefaultMaterialAttached *matData = m->attached<Q3DSDefaultMaterialAttached>();
+ for (auto it = matData->perModelData.cbegin(), itEnd = matData->perModelData.cend(); it != itEnd; ++it)
+ updateDefaultMaterial(m, nullptr, it.key());
+ }
m_wasDirty = true;
markLayerForObjectDirty(image3DS);
}
@@ -6906,19 +7020,6 @@ void Q3DSSceneManager::updateNodeFromChangeFlags(Q3DSNode *node, Qt3DCore::QTran
}
if (changeFlags & Q3DSNode::EyeballChanges) {
- // Special case: objects on master slide that get an eyeball change in
- // a subslide. These must be tracked so that obj->masterRollbackList()
- // can be applied since otherwise there's nothing ensuring the
- // visibility is reset when moving to another slide afterwards.
- auto nodeData = static_cast<Q3DSNodeAttached*>(node->attached());
- auto currentSlide = nodeData->component ? nodeData->component->currentSlide() : m_currentSlide;
- auto masterSlide = nodeData->component ? nodeData->component->masterSlide() : m_masterSlide;
- if (currentSlide && masterSlide->objects().contains(node)) {
- Q3DSSlideAttached *data = static_cast<Q3DSSlideAttached *>(currentSlide->attached());
- Q_ASSERT(data);
- data->needsMasterRollback.insert(node);
- }
-
if (node->type() == Q3DSGraphObject::Light) {
Q3DSLightAttached *lightData = static_cast<Q3DSLightAttached *>(node->attached());
Q3DSGraphObject *rootObject = lightData->layer3DS;
@@ -6932,8 +7033,7 @@ void Q3DSSceneManager::updateNodeFromChangeFlags(Q3DSNode *node, Qt3DCore::QTran
// Drop whatever is queued since that was based on now-invalid
// input. (important when entering slides, where eyball property
// changes get processed after an initial visit of all objects)
- m_pendingNodeShow.remove(node);
- m_pendingNodeHide.remove(node);
+ m_pendingNodeVisibility.remove(node);
const bool active = node->flags().testFlag(Q3DSNode::Active);
setNodeVisibility(node, active);
@@ -6976,10 +7076,12 @@ void Q3DSSceneManager::setNodeVisibility(Q3DSNode *node, bool visible)
Q3DSModelAttached *mdata = static_cast<Q3DSModelAttached *>(node->attached());
for (Q3DSModelAttached::SubMesh &sm : mdata->subMeshes) {
Qt3DRender::QLayer *tag = sm.hasTransparency ? layerData->transparentTag : layerData->opaqueTag;
- if (!visible)
- sm.entity->removeComponent(tag);
- else
+ if (!visible) {
+ sm.entity->removeComponent(layerData->opaqueTag);
+ sm.entity->removeComponent(layerData->transparentTag);
+ } else {
sm.entity->addComponent(tag);
+ }
}
}
diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h
index d569284..25f91c8 100644
--- a/src/runtime/q3dsscenemanager_p.h
+++ b/src/runtime/q3dsscenemanager_p.h
@@ -434,7 +434,7 @@ public:
Qt3DRender::QMaterial *materialComponent = nullptr;
Q3DSGraphObject *material = nullptr; // Default, Custom, Referenced
Q3DSGraphObject *resolvedMaterial = nullptr; // Default, Custom normally, but can still be Referenced for invalid refs
- Q3DSReferencedMaterial *referencedMaterial = nullptr; // When valid, there are some overrides possible by referenced material
+ Q3DSReferencedMaterial *referencingMaterial = nullptr; // When valid, there are some overrides possible by referenced material
Qt3DCore::QEntity *entity = nullptr;
bool hasTransparency = false;
};
@@ -460,15 +460,24 @@ struct Q3DSTextureParameters
class Q3DSMaterialAttached : public Q3DSGraphObjectAttached
{
public:
- Q3DSModelNode *model3DS = nullptr;
- float opacity = 1.0f;
+ // One default or custom material may be associated with multiple models
+ // when a ReferencedMaterial is used.
+ struct PerModelData {
+ float combinedOpacity = 1.0f;
+ union {
+ Qt3DRender::QParameter *materialDiffuseParam;
+ Qt3DRender::QParameter *objectOpacityParam;
+ };
+ };
+ QHash<Q3DSModelNode *, PerModelData> perModelData;
};
+Q_DECLARE_TYPEINFO(Q3DSMaterialAttached::PerModelData, Q_MOVABLE_TYPE);
+
class Q3DSDefaultMaterialAttached : public Q3DSMaterialAttached
{
public:
Qt3DRender::QParameter *diffuseParam = nullptr;
- Qt3DRender::QParameter *materialDiffuseParam = nullptr;
Qt3DRender::QParameter *materialPropertiesParam = nullptr;
Qt3DRender::QParameter *specularParam = nullptr;
Qt3DRender::QParameter *fresnelPowerParam = nullptr;
@@ -522,7 +531,6 @@ class Q3DSCustomMaterialAttached : public Q3DSMaterialAttached
{
public:
QHash<QString, Q3DSCustomPropertyParameter> params;
- Qt3DRender::QParameter *objectOpacityParam = nullptr;
// Lightmaps
Q3DSTextureParameters lightmapIndirectParams;
Q3DSTextureParameters lightmapRadiosityParams;
@@ -573,7 +581,6 @@ public:
Q3DSSlidePlayer *slidePlayer = nullptr;
Qt3DAnimation::QClipAnimator *animator = nullptr;
QVector<Qt3DAnimation::QClipAnimator *> animators;
- QSet<Q3DSNode *> needsMasterRollback;
};
class Q3DSImageAttached : public Q3DSGraphObjectAttached
@@ -778,8 +785,8 @@ private:
QVector<Qt3DRender::QParameter *> prepareCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS);
void setImageTextureFromSubPresentation(Qt3DRender::QParameter *sampler, Q3DSImage *image);
void updateTextureParameters(Q3DSTextureParameters &textureParameters, Q3DSImage *image);
- void updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm = nullptr);
- void updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm = nullptr);
+ void updateDefaultMaterial(Q3DSDefaultMaterial *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS);
+ void updateCustomMaterial(Q3DSCustomMaterialInstance *m, Q3DSReferencedMaterial *rm, Q3DSModelNode *model3DS);
void buildEffect(Q3DSEffectInstance *eff3DS, Q3DSLayerNode *layer3DS);
void updateEffectStatus(Q3DSLayerNode *layer3DS);
void ensureEffectSource(Q3DSLayerNode *layer3DS);
@@ -846,8 +853,7 @@ private:
Q3DSTextRenderer *m_textRenderer;
QSet<Q3DSGraphObject *> m_subTreeWithDirtyLights;
QSet<Q3DSDefaultMaterial *> m_pendingDefMatRebuild;
- QSet<Q3DSNode *> m_pendingNodeShow;
- QSet<Q3DSNode *> m_pendingNodeHide;
+ QHash<Q3DSNode *, bool> m_pendingNodeVisibility;
Qt3DRender::QLayer *m_fsQuadTag = nullptr;
QStack<Q3DSComponentNode *> m_componentNodeStack;
QSet<Q3DSLayerNode *> m_pendingSubPresLayers;
diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp
index f7c2ee2..9c7b03e 100644
--- a/src/runtime/q3dsslideplayer.cpp
+++ b/src/runtime/q3dsslideplayer.cpp
@@ -597,7 +597,7 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide,
}
if (slide && slideDidChange && isSlideVisible(slide)) {
- processPropertyChanges(slide, previousSlide);
+ processPropertyChanges(slide);
m_animationManager->updateAnimations(slide, (m_mode == PlayerMode::Editor));
if (parentChanged)
setSlideTime(static_cast<Q3DSSlide *>(slide->parent()), 0.0f);
@@ -665,17 +665,18 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide,
Q_EMIT slideChanged(slide);
}
-static bool nodeHasVisibilityTag(Q3DSNode *node)
+static bool objectHasVisibilityTag(Q3DSGraphObject *object)
{
- Q_ASSERT(node);
- Q_ASSERT(node->attached());
+ Q_ASSERT(object);
+ Q_ASSERT(object->attached());
+ Q_ASSERT(object->isNode() || object->type() == Q3DSGraphObject::Effect);
- auto nodeAttached = static_cast<Q3DSNodeAttached *>(node->attached());
- auto entity = nodeAttached->entity;
+ auto entity = object->attached()->entity;
if (!entity)
return false;
- auto layerAttached = static_cast<Q3DSLayerAttached *>(nodeAttached->layer3DS->attached());
+ auto layerAttached = static_cast<Q3DSLayerAttached *>(object->isNode() ? object->attached<Q3DSNodeAttached>()->layer3DS->attached()
+ : object->attached<Q3DSEffectAttached>()->layer3DS->attached());
if (entity->components().contains(layerAttached->opaqueTag) || entity->components().contains(layerAttached->transparentTag))
return true;
@@ -690,20 +691,23 @@ void Q3DSSlidePlayer::setSlideTime(Q3DSSlide *slide, float time, bool parentVisi
const bool forceUpdate = parentVisible &&
(qFuzzyCompare(time, 0.0f) || qFuzzyCompare(time, -1.0f));
for (Q3DSGraphObject *obj : slide->objects()) {
- if (!obj->isNode() || obj->type() == Q3DSGraphObject::Camera || obj->type() == Q3DSGraphObject::Layer)
+ const bool isEffect = (obj->type() == Q3DSGraphObject::Effect);
+ if ((!obj->isNode() && !isEffect) || obj->type() == Q3DSGraphObject::Camera || obj->type() == Q3DSGraphObject::Layer)
continue;
- Q3DSNode *node = static_cast<Q3DSNode *>(obj);
- if (!node->attached())
+ Q3DSNode *node = obj->isNode() ? static_cast<Q3DSNode *>(obj) : nullptr;
+ if (node && !node->attached())
continue;
+ const bool nodeActive = (node && node->flags().testFlag(Q3DSNode::Active) && node->attached<Q3DSNodeAttached>()->globalVisibility);
+ const bool effectActive = isEffect && static_cast<Q3DSEffectInstance *>(obj)->active();
+
const bool shouldBeVisible = parentVisible
&& time >= obj->startTime() && time <= obj->endTime()
- && node->flags().testFlag(Q3DSNode::Active)
- && static_cast<Q3DSNodeAttached *>(node->attached())->globalVisibility;
+ && (nodeActive || effectActive);
- if (forceUpdate || shouldBeVisible != nodeHasVisibilityTag(node))
- updateNodeVisibility(node, shouldBeVisible);
+ if (forceUpdate || shouldBeVisible != objectHasVisibilityTag(obj))
+ updateObjectVisibility(obj, shouldBeVisible);
}
// This method is called for all slides, but we only want to update the
@@ -729,14 +733,29 @@ void Q3DSSlidePlayer::sendPositionChanged(Q3DSSlide *slide, float pos)
onSlideFinished(slide);
}
-void Q3DSSlidePlayer::updateNodeVisibility(Q3DSNode *node, bool shouldBeVisible)
+void Q3DSSlidePlayer::updateObjectVisibility(Q3DSGraphObject *obj, bool shouldBeVisible)
{
- if (shouldBeVisible) {
- qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be shown", node->id().constData());
- m_sceneManager->m_pendingNodeShow.insert(node);
+ Q_ASSERT(obj->isNode() || obj->type() == Q3DSGraphObject::Effect);
+ if (obj->isNode()) {
+ Q3DSNode *node = static_cast<Q3DSNode *>(obj);
+ auto foundIt = m_sceneManager->m_pendingNodeVisibility.find(node);
+ const bool insertValue = (foundIt == m_sceneManager->m_pendingNodeVisibility.end());
+ const bool updateValue = (!insertValue && foundIt.value() != shouldBeVisible);
+
+ if (insertValue || updateValue) {
+ qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be %s", obj->id().constData(), shouldBeVisible ? "shown" : "hidden");
+ if (updateValue)
+ *foundIt = shouldBeVisible;
+ else if (insertValue)
+ m_sceneManager->m_pendingNodeVisibility.insert(node, shouldBeVisible);
+ }
} else {
- qCDebug(lcSlidePlayer, "Scheduling node \"%s\" to be hidden", node->id().constData());
- m_sceneManager->m_pendingNodeHide.insert(node);
+ Q3DSEffectInstance *effect = static_cast<Q3DSEffectInstance *>(obj);
+ if (effect->active() != shouldBeVisible) {
+ qCDebug(lcSlidePlayer, "Scheduling effect \"%s\" to be %s", obj->id().constData(), shouldBeVisible ? "shown" : "hidden");
+ obj->applyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))}));
+ obj->notifyPropertyChanges(Q3DSPropertyChangeList({Q3DSPropertyChange::fromVariant(QLatin1String("eyeball"), QVariant::fromValue(shouldBeVisible))}));
+ }
}
}
@@ -768,32 +787,17 @@ bool Q3DSSlidePlayer::isSlideVisible(Q3DSSlide *slide)
return visible;
}
-void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide,
- Q3DSSlide *previousSlide)
+void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide)
{
Q_ASSERT(currentSlide->attached());
- if (previousSlide) {
- auto slideData = static_cast<Q3DSSlideAttached *>(previousSlide->attached());
- for (Q3DSNode *node : qAsConst(slideData->needsMasterRollback)) {
- const Q3DSPropertyChangeList *changeList = node->masterRollbackList();
- if (changeList) {
- qCDebug(lcScene, "Rolling back %d changes to master for %s", changeList->count(), node->id().constData());
- node->applyPropertyChanges(*changeList);
- node->notifyPropertyChanges(*changeList);
- m_sceneManager->updateSubTreeRecursive(node);
- }
- }
- slideData->needsMasterRollback.clear();
- }
-
// Find properties on targets that has dynamic properties.
// TODO: Find a better solution (e.g., there can be duplicate updates for e.g., xyz here).
QHash<Q3DSGraphObject *, Q3DSPropertyChangeList> dynamicPropertyChanges;
const auto &tracks = currentSlide->animations();
std::find_if(tracks.cbegin(), tracks.cend(), [&dynamicPropertyChanges](const Q3DSAnimationTrack &track) {
if (track.isDynamic()) {
- auto foundIt = dynamicPropertyChanges.constFind(track.target());
+ const auto foundIt = dynamicPropertyChanges.constFind(track.target());
Q3DSPropertyChangeList changeList;
if (foundIt != dynamicPropertyChanges.constEnd())
changeList = *foundIt;
@@ -805,6 +809,25 @@ void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide,
return false;
});
+ // Rollback master slide properties
+ if (currentSlide->parent()) {
+ Q3DSSlide *parent = static_cast<Q3DSSlide *>(currentSlide->parent());
+ const auto &objects = parent->objects();
+ std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *object){
+ if (!object->isNode() && object->type() != Q3DSGraphObject::Effect)
+ return false;
+
+ const Q3DSPropertyChangeList &masterRollbackList = object->isNode() ? static_cast<Q3DSNode *>(object)->masterRollbackList()
+ : static_cast<Q3DSEffectInstance *>(object)->masterRollbackList();
+ if (masterRollbackList.isEmpty())
+ return false;
+
+ object->applyPropertyChanges(masterRollbackList);
+ object->notifyPropertyChanges(masterRollbackList);
+ return false;
+ });
+ }
+
// Filter out properties that we needs to be marked dirty, i.e., eyeball changes.
const auto &propertyChanges = currentSlide->propertyChanges();
for (auto it = propertyChanges.cbegin(); it != propertyChanges.cend(); ++it) {
diff --git a/src/runtime/q3dsslideplayer_p.h b/src/runtime/q3dsslideplayer_p.h
index 01020e2..7441bb5 100644
--- a/src/runtime/q3dsslideplayer_p.h
+++ b/src/runtime/q3dsslideplayer_p.h
@@ -144,10 +144,9 @@ private:
// TODO: Move out to a "slide manager"?
void setSlideTime(Q3DSSlide *slide, float time, bool parentVisible = true);
void sendPositionChanged(Q3DSSlide *slide, float pos);
- void updateNodeVisibility(Q3DSNode *node, bool visible);
+ void updateObjectVisibility(Q3DSGraphObject *obj, bool visible);
bool isSlideVisible(Q3DSSlide *slide);
- void processPropertyChanges(Q3DSSlide *currentSlide,
- Q3DSSlide *previousSlide);
+ void processPropertyChanges(Q3DSSlide *currentSlide);
struct Data {
Q3DSSlideDeck *slideDeck = nullptr;
diff --git a/src/runtime/q3dsuippresentation.cpp b/src/runtime/q3dsuippresentation.cpp
index 3633a2a..75bef24 100644
--- a/src/runtime/q3dsuippresentation.cpp
+++ b/src/runtime/q3dsuippresentation.cpp
@@ -2323,6 +2323,13 @@ void Q3DSEffectInstance::setProperties(const QXmlStreamAttributes &attrs, PropSe
// refer to custom properties defined in the effect.
for (const QXmlStreamAttribute &attr : attrs)
m_pendingCustomProperties.append(Q3DSPropertyChange(attr.name().toString(), attr.value().toString()));
+
+ // If this is on the master slide, store some rollback info.
+ if (flags.testFlag(PropSetOnMaster)) {
+ m_masterRollbackList.append(Q3DSPropertyChange(QLatin1String("eyeball"), m_active ? QLatin1String("True")
+ : QLatin1String("False")));
+
+ }
}
void Q3DSEffectInstance::applyPropertyChanges(const Q3DSPropertyChangeList &changeList)
@@ -2532,9 +2539,7 @@ void Q3DSNode::setProperties(const QXmlStreamAttributes &attrs, PropSetFlags fla
// If this is on the master slide, store some rollback info.
if (flags.testFlag(PropSetOnMaster)) {
- if (m_masterRollbackList.isNull())
- m_masterRollbackList.reset(new Q3DSPropertyChangeList);
- m_masterRollbackList->append(Q3DSPropertyChange(QLatin1String("eyeball"),
+ m_masterRollbackList.append(Q3DSPropertyChange(QLatin1String("eyeball"),
m_flags.testFlag(Q3DSNode::Active)
? QLatin1String("True") : QLatin1String("False")));
diff --git a/src/runtime/q3dsuippresentation_p.h b/src/runtime/q3dsuippresentation_p.h
index bc4bec3..6345db2 100644
--- a/src/runtime/q3dsuippresentation_p.h
+++ b/src/runtime/q3dsuippresentation_p.h
@@ -834,7 +834,7 @@ public:
void applyPropertyChanges(const Q3DSPropertyChangeList &changeList) override;
int mapChangeFlags(const Q3DSPropertyChangeList &changeList) override;
- const Q3DSPropertyChangeList *masterRollbackList() const { return m_masterRollbackList.data(); }
+ const Q3DSPropertyChangeList &masterRollbackList() const { return m_masterRollbackList; }
QStringList propertyNames() const override;
QVariantList propertyValues() const override;
@@ -870,7 +870,7 @@ protected:
qint32 m_skeletonId = -1;
RotationOrder m_rotationOrder = YXZ;
Orientation m_orientation = LeftHanded;
- QScopedPointer<Q3DSPropertyChangeList> m_masterRollbackList;
+ Q3DSPropertyChangeList m_masterRollbackList;
private:
Q_DISABLE_COPY(Q3DSNode)
@@ -1842,6 +1842,8 @@ public:
QVariant customProperty(const QString &name) const { return m_effectPropertyVals.value(name); }
Q3DSPropertyChange setCustomProperty(const QString &name, const QVariant &value);
+ const Q3DSPropertyChangeList &masterRollbackList() const { return m_masterRollbackList; }
+
private:
Q_DISABLE_COPY(Q3DSEffectInstance)
template<typename V> void setProps(const V &attrs, PropSetFlags flags);
@@ -1852,6 +1854,7 @@ private:
bool m_active = true;
QVariantMap m_effectPropertyVals;
Q3DSPropertyChangeList m_pendingCustomProperties;
+ Q3DSPropertyChangeList m_masterRollbackList;
};
class Q3DSV_PRIVATE_EXPORT Q3DSBehaviorInstance : public Q3DSGraphObject
diff --git a/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp b/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp
index 6d646da..e95aa33 100644
--- a/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp
+++ b/src/runtime/shadergenerator/q3dscustommaterialvertexpipeline.cpp
@@ -408,7 +408,8 @@ struct ShaderGenerator : public Q3DSCustomMaterialShaderGenerator
fragmentShader << "#include \"customMaterialFragBodyAO.glsllib\"\n";
// for us right now transparency means we render a glass style material
- if (m_currentMaterial->shaderHasTransparency() && !m_currentMaterial->shaderIsTransmissive())
+ if (m_currentMaterial->materialHasTransparency()
+ && !m_currentMaterial->shaderIsTransmissive())
fragmentShader << " rgba = computeGlass( normal, materialIOR, alpha, rgba );\n";
if (m_currentMaterial->shaderIsTransmissive())
fragmentShader << " rgba = computeOpacity( rgba );\n";
diff --git a/src/runtime/shaders/compositor_ms2.frag b/src/runtime/shaders/compositor_ms2.frag
index 40b50d4..f920a7b 100644
--- a/src/runtime/shaders/compositor_ms2.frag
+++ b/src/runtime/shaders/compositor_ms2.frag
@@ -1,14 +1,15 @@
#version 310 es
+precision highp float;
in vec2 texCoord;
-uniform sampler2DMS tex;
+uniform highp sampler2DMS tex;
out vec4 fragColor;
void main()
{
- ivec2 tc = ivec2(floor(textureSize(tex) * texCoord));
+ ivec2 tc = ivec2(floor(vec2(textureSize(tex)) * texCoord));
vec4 c = texelFetch(tex, tc, 0) + texelFetch(tex, tc, 1);
c /= 2.0;
// This discard, while not necessarily ideal for some GPUs, is necessary to
diff --git a/src/runtime/shaders/compositor_ms4.frag b/src/runtime/shaders/compositor_ms4.frag
index 12dc470..1bbf3d8 100644
--- a/src/runtime/shaders/compositor_ms4.frag
+++ b/src/runtime/shaders/compositor_ms4.frag
@@ -1,14 +1,15 @@
#version 310 es
+precision highp float;
in vec2 texCoord;
-uniform sampler2DMS tex;
+uniform highp sampler2DMS tex;
out vec4 fragColor;
void main()
{
- ivec2 tc = ivec2(floor(textureSize(tex) * texCoord));
+ ivec2 tc = ivec2(floor(vec2(textureSize(tex)) * texCoord));
vec4 c = texelFetch(tex, tc, 0) + texelFetch(tex, tc, 1) + texelFetch(tex, tc, 2) + texelFetch(tex, tc, 3);
c /= 4.0;
// This discard, while not necessarily ideal for some GPUs, is necessary to
diff --git a/tests/auto/q3dslancelot/data/cameras/componentCamera.uip b/tests/auto/q3dslancelot/data/cameras/componentCamera.uip
index f8ca4fd..f0ae750 100644
--- a/tests/auto/q3dslancelot/data/cameras/componentCamera.uip
+++ b/tests/auto/q3dslancelot/data/cameras/componentCamera.uip
@@ -84,7 +84,7 @@
</State>
<State name="Master Slide" component="#Component" >
<State id="Component-Slide1" name="Slide1" >
- <Add ref="#Camera_004" name="Camera" position="2.3094 -2.3094 2.3094" rotation="12 -291 0" scale="1 1 -0.6" />
+ <Add ref="#Camera_004" name="Camera" position="2.3094 -2.3094 2.3094" rotation="12 249 0" scale="1 1 0.6" />
</State>
</State>
</Logic>