diff options
Diffstat (limited to 'doc/src/tutorials')
-rw-r--r-- | doc/src/tutorials/penguin.qdoc | 106 | ||||
-rw-r--r-- | doc/src/tutorials/sceneformat.qdoc | 116 | ||||
-rw-r--r-- | doc/src/tutorials/shaders.qdoc | 388 | ||||
-rw-r--r-- | doc/src/tutorials/simpleobject.qdoc | 106 |
4 files changed, 0 insertions, 716 deletions
diff --git a/doc/src/tutorials/penguin.qdoc b/doc/src/tutorials/penguin.qdoc deleted file mode 100644 index e973090d..00000000 --- a/doc/src/tutorials/penguin.qdoc +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation ([email protected]) -** -** This file is part of the QtQuick3D documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example qt3d/penguin - \title Loading a 3DS model with Qt3D - - This tutorial shows how Qt3D can be used to load a simple - model object in 3D Studio Max (3DS) format with a perspective - camera view. - - We start by defining a class that inherits from QGLView, which - provides some basic scene setup logic and 3D camera navigation: - - \snippet qt3d/penguin/modelview.h class-defn - - Refer first to the \l{Teapot Example} for the basics of using - the QGLView class, lighting and so on. - - When the application starts up, we load the scene from its - resource file, and store the result in a member variable, so - we can refer to it in the paint function: - - \snippet qt3d/penguin/modelview.cpp initialize - - In the teapot example we had to specify appropriate effects but - the model loader sets appropriate effects on the scene for us. - - \snippet qt3d/penguin/modelview.cpp paint - - Here in the paint function we call the \c{draw()} function of - the scene's main object, in order to display the fully - loaded model. - - This was really just two lines of code: one to load the model - (once off, when the application initialized) and another line to - display the model (every time the paint function is called). - - \image penguin-0-screenshot.png - - The result is pretty good for two lines of code, but it could - stand some improvements. - - Here we are looking down onto the top of our penguin's head, and - even when we stand him on his feet, he is too close to the camera - to all fit in the frame. - - Let's make a few changes to have our penguin display nicely - when the application opens. - - \snippet qt3d/penguin_advanced/modelview.cpp initialize - - First of all, let move the camera away from the penguin and up - so he fits in the frame and we can get a better angle on him, - when the application loads. - - If use dragging and so on in the QGLView this will change the - camera from these intial settings, but this setup means the camera - will be well positioned at the moment the application opens. - - We don't want to position the camera in the paintGL function, - because that would defeat QGLViews camera dragging features and - we would not be able to interact with the view properly. - - We'll also save the main object away in a member variable so that - the overhead of searching the scene is not incurred every paint. - - Finally a pose for our penguin is calculated - its a turn around the - x axis, so he is standing up on his feet; and a turn around the y - axis, so he shows a bit more of his profile. The pose is - calculated and stored as a quaternion - we want the x twist first - so that goes last in the product of the two quaternions. - - \snippet qt3d/penguin_advanced/modelview.cpp paint - - Now all that remains in the updated paint function is to apply the - new pose, and then paint the penguin. - - \image penguin-screenshot.png - - \l{qt3d-examples.html}{Return to Tutorials}. -*/ diff --git a/doc/src/tutorials/sceneformat.qdoc b/doc/src/tutorials/sceneformat.qdoc deleted file mode 100644 index 3774b6a1..00000000 --- a/doc/src/tutorials/sceneformat.qdoc +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation ([email protected]) -** -** This file is part of the QtQuick3D documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \title Writing a scene format plug-in for Qt3D - \keyword Scene Format Plugin - \example sceneformats/obj - - Scene format plugins are used to load external 3D model file - formats like \bold 3DS, \bold obj, and so on. In this tutorial we will - do a walk-through of the \bold obj scene format plugin to - demonstrate what is required to add a new format to Qt3D. - - Models are loaded by QGLAbstractScene::loadScene(), which locates - a suitable plug-in for the format, and then asks the plug-in to - parse the data and create a QGLAbstractScene object that describes - the 3D objects in the scene. - - We start by declaring an instance of QGLSceneFormatPlugin and - arranging for it to be registered with the Qt plug-in system: - - \snippet sceneformats/obj/main.cpp 1 - \snippet sceneformats/obj/main.cpp 4 - - The two functions we need to implement are - \l{QGLSceneFormatPlugin::keys()}{keys()} and - \l{QGLSceneFormatPlugin::create()}{create()}. The first of these - returns a lower-case list of the file extensions and MIME types - that are supported by the plug-in: - - \snippet sceneformats/obj/main.cpp 2 - - The create function is called to create the QGLSceneFormatHandler - which is used to load the model data: - - \snippet sceneformats/obj/main.cpp 3 - - The create function is passed the QIODevice for the data, - the URL of where the data was found, and the chosen format. - These parameters can be used by the plug-in to decide which - handler to return if multiple formats are supported by - the plug-in. In the case of obj, we always return the same - handler so we don't need to inspect the passed parameters. - - QGLAbstractScene::loadScene() will set the parameters on - the QGLSceneFormatHandler object and then call - \l{QGLSceneFormatHandler::read()}{read()}: - - \snippet sceneformats/obj/qglobjscenehandler.h 1 - \dots - \snippet sceneformats/obj/qglobjscenehandler.h 2 - - The read function will typically construct a QGLBuilder - for the geometry in the scene and then parse all of the objects, - materials, textures, and so on. Ultimately, it needs to produce a - QGLAbstractScene object, populated with QGLSceneNode instances - for each of the objects in the model file. In our case, we create - an instance of \c QGLObjScene: - - \snippet sceneformats/obj/qglobjscene.h 1 - \dots - \snippet sceneformats/obj/qglobjscene.h 2 - \dots - \snippet sceneformats/obj/qglobjscene.h 3 - - The most important function is the override for - QGLAbstractScene::objects(), which allows the rest of Qt3D - to query the full list of objects in the model file. - The scene object can also override QGLAbstractScene::object() - if it has an efficient method to quickly look up an object by name. - - The scene should also override QGLAbstractScene::mainNode() - to return the main mesh node in the scene. Usually this is - the first element in the list returned by QGLAbstractScene::objects() - but doesn't have to be. - - Note: the plug-in does not need to use QGLBuilder and the - other Qt3D classes to load the model if it doesn't want to. - It can instantiate subclasses of QGLSceneNode that override - the draw() method and draws the object using whatever technique - the plug-in chooses. It just needs to leave the OpenGL state - in the condition that it found it so that other parts of Qt3D - will not be confused. - - Once you have written a plug-in for your new format, you should - install it into \c{$QTDIR/plugins/sceneformats}. You can test it - by running the \c{modelviewer} program and trying to load models - in your new format. When debugging, it can be useful to set the - \c{QT_DEBUG_PLUGINS} environment variable to 1. - - \l{qt3d-examples.html}{Return to the main Tutorials page}. -*/ diff --git a/doc/src/tutorials/shaders.qdoc b/doc/src/tutorials/shaders.qdoc deleted file mode 100644 index dc20099b..00000000 --- a/doc/src/tutorials/shaders.qdoc +++ /dev/null @@ -1,388 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation ([email protected]) -** -** This file is part of the QtQuick3D documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \title Using GLSL shaders in QtQuick3D - \example quick3d/shaders - - - In this tutorial, we will show how to apply QML property animations to - GLSL shaders in a QtQuick3D application. - - Starting with a relatively simple shader program, we are going to - manipulate various parameters to explain how both the shader and the QML - integration work (This is quite a lot to start a tutorial with, but we'll - focus on each small piece of it in turn): - - \raw HTML - <table align="left" width="100%"> - <tr class="qt-code"><td> - \endraw - \snippet quick3d/shaders/shader-tutorial.qml 1 - \raw HTML - </td><td align="right"> - \endraw - \inlineimage tutorials/shader-tutorial.png - \raw HTML - </td></tr> - </table> - \endraw - - At the highest level, shaders in QtQuick3D are created using the ShaderProgram - element. The ShaderProgram element in this example has the id \a program, - and applying it to the teapot is as simple as assigning it to the \c effect - property of an Item3D derived element. - - The two most important properties of the ShaderProgram element are the - \c vertexShader and \c fragmentShader properties, which are strings - containing the code for the respective shader programs. Broadly speaking, - the vertex shader is run on each vertex in a model (for example, the 8 - corners of a cube) to calculate the final position of each point, while the - fragment shader is run on each pixel visible onscreen to calculate it's - color. - - The other attribute we use in this tutorial is the \c texture property. - This property is connected to the \c qt_Texture0 attribute in our shader - programs, and we'll cover how it's used shortly. - - \section1 Texture Coordinates and Textures (shader-tutorial-1-textures.qml) - - To start with, there are a couple of obvious problems with our starting - point - the Qt is upside down and back to front, and it's also boring - (before you ask, the reasons for the image being the wrong way around are - also boring). - - First, let's get the logo the right way up. The key here is the texture - coordinates. Let's look at it's declaration in the vertex shader for a - moment: \code attribute highp vec4 qt_MultiTexCoord0; \endcode - - The \c attribute declaration indicates that this is a per-vertex value - that we get from our model. Our teapot has a position, a normal, and - texture coordinates for each vertex, and qt3d automatically provides - these to us through the \c qt_Vertex, \c qt_MultiTexCoord0, and \c - qt_Normal attributes. (we don't care about normals until we get to - lighting). - - The \c mediump tag indicates that we want pretty good accuracy on this - attribute, but it doesn't need double precision. It's a hint for - embedded systems to save bandwidth (highp is usually used for positions, - and lowp is generally only suitable for colors, and the rule of thumb is - to use as little memory as you can get away with). - - \c vec4 indicates that the value is a 4-element vector. Our texture is - 2D, so we only care about the first two elements, but there are 3D - textures and cube maps out there. - - To fix the image's orientation we can simply reverse the sign when we - pass the texture coordinate to our fragment shader because the default - behaviour is for texture coordinates wrap around if they are higher than - 1.0 or lower than 0.0: - \code texCoord = -qt_MultiTexCoord0; \endcode - - In order to fix the boring, we're going to have to add a bit more QML - first. We need to add a property to our ShaderProgram element, and a - matching variable to the shader program. The types match up exactly - between QML and GLSL, but if the variables have the same name they - should automatically be hooked up, so we just add this to the - ShaderProgram element: - \code property real textureOffsetX : 1.0 - NumberAnimation on textureOffsetX - { - running: true; loops: Animation.Infinite - from: 0.0; to: 1.0; - duration: 1000 - } - \endcode - and we add this to the vertex shader: - \code uniform mediump float textureOffsetX; \endcode - - The final step is to work our new variable into the program, by changing - the texCoord assignment. We'll add our animated variable to our horizontal - texture coordinate, which will effectively scroll our texture around our - teapot: - \code - texCoord = vec4(-qt_MultiTexCoord0.s - textureOffsetX, - -qt_MultiTexCoord0.t, - 0,0); - \endcode - - Adding an additional texture is done by adding another uniform. The - ShaderProgram element interprets string properties as URIs for texture - resources, so adding a second texture is as easy as: - \code - property string texture2: "textures/basket.jpg" - \endcode - In order to have a smooth transition back and forth, we'll add and animate - a second property to use to blend the two textures: - \code - property real interpolationFactor : 1.0 - SequentialAnimation on interpolationFactor - { - running: true; loops: Animation.Infinite - NumberAnimation { - from: 0.0; to: 1.0; - duration: 2000 - } - PauseAnimation { duration: 500 } - NumberAnimation { - from: 1.0; to: 0.0; - duration: 2000 - } - PauseAnimation { duration: 500 } - } - \endcode - - Next we need to use all of that information in the fragment shader: - \code - varying highp vec4 texCoord; - uniform sampler2D qt_Texture0; - uniform sampler2D texture2; - uniform mediump float interpolationFactor; - - void main(void) - { - mediump vec4 texture1Color = texture2D(qt_Texture0, texCoord.st); - mediump vec4 texture2Color = texture2D(texture2, texCoord.st); - mediump vec4 textureColor = mix(texture1Color, texture2Color, - interpolationFactor); - gl_FragColor = textureColor; - } - \endcode - - In general, textures needs to have the same name in the shaders as in the - ShaderProgram element in order to be automatically connected, but \c - qt_Texture0 is special cased and very slightly faster, so it's good to use - it first. - - \c mix() is another handy built in GLSL function that interpolates linearly - between two values or vectors. (You can find details of all the built in - functions in the official OpenGL Shader Language specification available at - http://www.khronos.org/opengl/ ) - - Finally, let's make one more change to make this example pop. If you're - a performance fanatic, it just might have rankled that we padded out our - texture coordinates with two zeros, and passed them in for processing - on every single pixel of our teapot. - - Let's make use of that space by putting a second set of co-ordinates in - there to use with our second texture. Let's change our texture assignment - to this: - \code - texCoord.st = vec2(-qt_MultiTexCoord0.s - textureOffsetX, - -qt_MultiTexCoord0.t); - texCoord.pq = vec2(-qt_MultiTexCoord0.s + textureOffsetX, - -qt_MultiTexCoord0.t); - \endcode - Now the top half of our vector contains co-ordianates spinning in the - opposite direction. Back in the fragment shader, we just need use these - instead for our second texture color, so let's change the \c texture2Color - assignment to this, and really fix that boring: - \code - mediump vec4 texture2Color = texture2D(texture2, texCoord.pq); - \endcode - - \section1 Varying values (shader-tutorial-varying.qml) - - The left hand side value is our \c varying attribute \c texCoord. - \c varying values are how the vertex shader communicates with the - fragment shader, and the declaration has to be identical in both shaders. - \c varying values are calculated once for each - vertex, but the values are interpolated across the shapes. The - shader-tutorial-varying.qml shows this visually using the Pane - class and a neat debugging trick - using the texture coordinates as - a color. Even with only 4 vertexes the texture coordinates are smeared - smoothly across the shape: - \table - \row - \o \code gl_FragColor = vec4(mod(texCoord.x, 1.0), - mod(texCoord.y, 1.0), 0.0, 1.0); \endcode - \o - \o \image tutorials/shader-tutorial-varying.png - \endtable - - - \section1 Vertexes and Matrices (shader-tutorial-2-vertex-shader.qml) - - Let's go back to the vertex shader. As already mentioned, the - vertex shader's primary function is to generate the final position of a - vertex. - - First, let's look at \c qt_Vertex. This is the value we're getting out - of our model, the actual points on our shape. Manipulating this value - will lets us change the position of the points somewhat independantly. - - For this tutorial, we'll create a squashing effect that might work for - something rising out of water, or something rubbery being squashed down. - - What we need to do is create a floor, where vertexes above the floor - retain their position, and vertexes below it are clamped to (nearly) that - value. Then we move the model relative to this floor to create a nice - effect. - - We need to use some knowledge that we have about the model for this to - work - most notably it's height, and it's bottom. A bit of experimenting - suggests that 2.0 for height and -1.0 for bottom are close enough. - - We need to introduce a couple more GLSL things here. \c max() is one of - the GL SL built in functions, selecting the higher of the two arguments as - you might expect. - - The \c foo.xyzw are called \i twiddles, and are - convenient and efficient ways to pull out specific elements of vector - areguments. You can see in this example, that we use twiddles to get out - the x, z, and w values from our original vector and substitute in our own - y value. For convenience, there are 3 different sets of twiddles that are - all equivalent: foo.xyzw (co-ordinates), foo.rgba (colors), and - foo.stpq (texture coordinates). As far as GLSL is concerned, though, - they're just vectors, and effectively just commenting your code. - - The \c vec4() function will accept whatever combination of values and - twiddles you throw at it, and mold them back into a 4 element vector. - - What this function is doing is moving the model down the screen (which for - us, here, is along the y axis in the negative direction). - We draw an imaginary line where the bottom of the model used to be, and if - the vertex ends up below that line, we move it back to just past the line. - - "Just past" is important. Graphics cards get confused if vertexes are too - close together, and the result is ugly. Try taking out the - "\c {qt_Vertex.y * 0.01}" if you'd like to see what it looks like. - - \code - float newY = max(qt_Vertex.y - squashFactor * modelSize, - qt_Vertex.y * 0.01 + modelBottom); - \endcode - - - \code - const float modelSize = 2.0; - const float modelBottom = -1.0; - float newY = max(qt_Vertex.y - squashFactor * modelSize, - qt_Vertex.y * 0.01 + modelBottom); - - gl_Position = qt_ModelViewProjectionMatrix * - vec4(qt_Vertex.x, newY, qt_Vertex.zw); - \endcode - - Hopefully, that makes the function of the \c qt_Vertex attribute clear, so - next we'll look at the Model/View/Projection matrices. - - The model matrix is generally used to place an object in a scene. In the - simplest case, this might just be "up and to the left a bit", but it's - often inherited from a parent. It's very easy mathematically to combine - the matrices in such a way that one object is always in the same relative - position to another ("The hip bones connected to the thigh bone"). - - The view matrix is generally used much like a camera is in a movie, for - panning around a whole scene at once. Manipulating the view matrix is also - commonly used for effects like mirrors. - - The projection matrix (\c qt_ProjectionMatrix) functions much like a - camera does when you take a - picture, converting all the 3d points in a scene into the 2d points on the - screen. - - We won't be exploring the matrices individually, but let's explore what - happens if we use the same effect that we just used on the vertex after - the transformation matrices are applied. - - Firstly, we're going to need multiple teapots to see the difference, so - let's add those in. We want to move them all together, so we'll wrap - them in an Item3D, and apply our animations to that item instead of - the teapots directly. - \code - - Item3D { - z: -8.0 - transform: [ - Rotation3D { - NumberAnimation on angle { - running: true; loops: Animation.Infinite - from: 0; to: 360; duration: 5000 - } - axis: Qt.vector3d(0, 0, 1.0) - } - ] - - TutorialTeapot {id: teapot1; effect: program; y:2.0; x:0.0} - TutorialTeapot {id: teapot2; effect: program; y:-1.0; x:-1.732} - TutorialTeapot {id: teapot3; effect: program; y:-1.0; x:1.732} - } - \endcode - - In order to show the difference, what we want to do now is the same sort - of effect as the previous example, only applied to the positions after - the matrices have been applied, so our new vertex shader looks like this: - \code - attribute highp vec4 qt_Vertex; - uniform mediump mat4 qt_ModelViewProjectionMatrix; - - attribute mediump vec4 qt_MultiTexCoord0; - varying mediump vec4 texCoord; - - void main(void) - { - const float modelBottom = -4.0; - - vec4 workingPosition = qt_ModelViewProjectionMatrix * qt_Vertex; - float newY = max(workingPosition.y, - workingPosition.y * 0.15 + modelBottom); - workingPosition.y = newY; - gl_Position = workingPosition; - - texCoord = -qt_MultiTexCoord0; - } - \endcode - - There's nothing new here, we're just tweaking a few numbers for the new - effect and manipulating the vertexes after the matrices have been applied. - The result is an imaginary line across the whole scene, and when any part - of any teapot dips below that line we deform it as though it's being - squished or refracted. - - The obvious difference is that when you're manipulating \c qt_Vertex, - the inputs, outputs, and changes are relative to the model. After the - matrices are applied, - - We'll leave adding a pretty watery surface as an exercise for the reader. - - - - \section1 Lighting - - Finally, we'll add lighting. We've left lighting till last because it - requires a lot of additional variables, and it is not within the scope of - this tutorial to explore them all individually. There are many better - resources readily available, and the techniques already covered can be - used to explore each element. - - - For further reading, the full specification for the OpenGL Shader Language - is available from the Khronos website at http://www.khronos.org/opengl/ - - \l{qt3d-examples.html}{Return to the main Tutorials page}. -*/ diff --git a/doc/src/tutorials/simpleobject.qdoc b/doc/src/tutorials/simpleobject.qdoc deleted file mode 100644 index db6c3be3..00000000 --- a/doc/src/tutorials/simpleobject.qdoc +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation ([email protected]) -** -** This file is part of the QtQuick3D documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \title Applying Transformations and Materials - \keyword Object Effects - \example qt3d/cube4 - - In this tutorial we will apply transformations and materials to a - simple cube object to demonstrate how to modify the QGLPainter - state to achieve different effects. - - \section2 Cube in QtQuick3D - - It is quite simple to achieve these effects in QtQuick3D: - - \snippet quick3d/cube/qml/cube.qml 1 - - \section2 Cube in Qt3D - - In the C++ world we start by declaring a view class to show our cube - on the screen: - - \snippet qt3d/cube1/cubeview.h 1 - - QGLView provides most of the logic for initializing the view, - setting the camera position, and handling navigation via - keyboard and mouse events. In the constructor we use - QGLBuilder to create the geometry for the cube object that - we will be using in later steps: - - \snippet qt3d/cube1/cubeview.cpp 1 - - Then it is a simple matter to draw the object in our \c{paintGL()} - method: - - \snippet qt3d/cube1/cubeview.cpp 2 - - If we run the program now, we get the following output, which isn't - very cube-like: - - \image tutorials/cube1-screenshot.png - - The problem is that we are looking at the cube straight onto its - front face. So the rest of the cube is hidden from our view and - it looks like a square. Let's modify the modelview transformation - matrix a little bit to apply a 45 degree rotation around the - axis (1, 1, 1): - - \snippet qt3d/cube2/cubeview.cpp 2 - - Now the results are a little better: - - \image tutorials/cube2-screenshot.png - - The cube is still a little odd-looking however. This is because - up until now we have been using the default flat color effect - in QGLPainter that colors the faces with a uniform color - (white in this case). So let's change to a lit material effect - with a nice green color: - - \snippet qt3d/cube3/cubeview.cpp 2 - - That's much better; now it looks like a cube: - - \image tutorials/cube3-screenshot.png - - To complete this tutorial, let's make the cube a little more - interesting by adding a texture to the side: - - \snippet qt3d/cube4/cubeview.h 1 - \dots - \snippet qt3d/cube4/cubeview.h 2 - \snippet qt3d/cube4/cubeview.cpp 1 - \dots - \snippet qt3d/cube4/cubeview.cpp 2 - \snippet qt3d/cube4/cubeview.cpp 3 - - \image tutorials/cube4-screenshot.png - - \l{qt3d-examples.html}{Return to the main Tutorials page}. -*/ |