QQuick3D-Model的实例化
Model的实例化
- Model类继承于Node类;如果想让一个Model(模型)可以渲染,至少需要一个Mesh(网格)和material(材质)
- Mesh(网格):Qt内置了矩形(Rectangle)、Sphere(球)、立方体(Cube)、圆柱(Cylinder) 、圆锥( Cone);也可以通过Balsam 工具导入支持的其它格式,如obj,fbx之类格式
- Model可以通过实例化,通过一次调用绘制多个相同实例的技术。
Model的实例化相关属性介绍:
- 属性instanceRoot : QtQuick3D::Node:定义实例坐标系的原点
- 属性instancing : QtQuick3D::Instancing:定义实例化表
- 属性instancingLodMax : real定义显示此模型实例时与摄影机的最大距离
- 属性instancingLodMin : real定义显示此模型实例时与摄影机的最小距离
Instancing类的介绍
- Instancing 类是实例化表(instance tables)的基础类,有3个派生对象:FileInstancing, InstanceList, RandomInstancing
- 实例化类型定义了一个表,该表指定了如何相对于基础模型修改每个实例。该表为每个索引都有一个条目,其中包含一个变换矩阵、一种颜色和供自定义材质使用的通用数据。要使用实例化,请设置模型(Model)的实例化属性以引用实例化对象。
- 属性depthSortingEnabled : bool:保存实例表的深度排序启用值。启用后,实例将从离相机最远的实例到最近的实例进行排序和渲染,即从后到前。如果禁用(这是默认设置),则实例将按照在实例表中指定的顺序呈现。注意,排序仅实例间相互排序,不会与场景中其它对象排序;排序会增加帧准备时间,特别是在实例数量较大的情况下。
- 属性hasTransparency : bool:如果实例化表包含渲染模型时应使用的alpha值,此属性设置为true;如果模型具有透明材质或不透明度小于1,则无论如何都将使用实例化表中的alpha值
- 属性instanceCountOverride : int:此属性用于限制实例数量,而无需重新生成或重新上传实例表。
- 方法color instanceColor(int index):返回 index 对应的实例(instance)的颜色;
- 方法vector3d instanceCustomData(int index):返回 index 对应的实例(instance)的自定义数据;
- 方法vector3d instancePosition(int index):返回 index 对应的实例(instance)的位置;
- 方法quaternion instanceRotation(int index):返回 index 对应的实例(instance)的旋转角度;
- 方法vector3d instanceScale(int index):返回 index 对应的实例(instance)的缩放;
InstanceList类的介绍
-
InstanceList类型允许在QML中手动定义实例表(instance tables),由InstanceListEntry 组成
-
每个InstanceListEntry都是一个可以具有属性绑定和动画的对象。这提供了极大的灵活性,但也会导致内存开销。因此,不建议对包含数千(或数百万)个实例的程序生成表使用InstanceList。此外,对条目的任何属性更改都会导致整个实例表被重新计算并上传到GPU。
-
InstanceListEntry 包含每个实例的:color : vector3d、customData : vector4d、eulerRotation : vector3d、position : vector3d、rotation : quaternion、scale : vector3d 信息
Model实例化代码
- 实例化 Model + 实例化表(Instance Table); 实例化表(如 InstanceList) 由实例条目(InstanceListEntry)组成;
- 实例效果:会实例化两个Cube,两个Sphere, 其中Sphere 围绕Cube旋转
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D//摄像机Demo
Item {id: root//场景需要 Model(mesh + Material), Light, Camera, 3个元素Node{id: rootSceneNode //3D场景的根节点//平行光: 光源从无线远地方发射,类似于生活中太阳;平行光具有无限的范围,不会衰减;如果启用castsShadow,阴影将平行于灯光方向;//平行光实际上没有位置,因此移动它没有任何效果。光将始终沿光的Z轴方向发射。沿X或Y轴旋转灯光将改变发光方向。DirectionalLight {ambientColor: Qt.rgba(0.5, 0.5, 0.5, 1.0)brightness: 1.0}//实例化表InstanceList{id:instanceTableinstances: [InstanceListEntry{//position: Qt.vector3d(0, 0, 0)position: Qt.vector3d(-120, 0, 0)//eulerRotation: Qt.vector3d(-10, 0, 30)color: "red"},InstanceListEntry {// position: Qt.vector3d(120, 10, 100)position: Qt.vector3d(120, 0, 0)eulerRotation: Qt.vector3d(0, 180, 0)color: "yellow"}]}Model {id: cubeinstancing: instanceTable //使用实列表创建 2个实例source: "#Cube"scale:Qt.vector3d(0.5,0.5,0.5);materials: DefaultMaterial { diffuseColor: "lightgray" }}Node {Model {source: "#Sphere"instanceRoot: cubeinstancing: instanceTablex: 100materials: DefaultMaterial { diffuseColor: "lightgray" }}NumberAnimation on eulerRotation.y {from: 0to: 360duration: 4000loops: Animation.Infinite}}//Node {//使用节点给摄像机设置动画。//Camera 做为Node 的子节点,可以通过Node节点的属性来定义相机的位置、旋转 之类属性;也会继承父节点的变换//透视投影:主要涉及 近平面(clipNear),远平面(clipFar),视野角(fiedOfView)id: idCamPNodePerspectiveCamera {id: cameraPerspectiveOnez: 600}//将动画至于 eulerRotation 包含 x,y,z 轴的旋转值,顺序是 zxy// PropertyAnimation on eulerRotation.y {// loops: Animation.Infinite// duration: 5000// to: -360// from: 0// }Component.onCompleted: {console.log("forward = ",cameraPerspectiveOne.forward," up = ",cameraPerspectiveOne.up, " right = ",cameraPerspectiveOne.right);}}}View3D{id:idView3Danchors.fill: parentimportScene: rootSceneNodecamera: cameraPerspectiveOneMouseArea{anchors.fill: parentonClicked:(mouse)=> {var viewPos = Qt.vector3d(mouse.x /parent.width,mouse.y/parent.height,0);//同样的viewPos 因为Camera的位置在变化,造成映射到scene中值不一致var scenePos = cameraPerspectiveOne.mapFromViewport(viewPos);console.log("scenePos = ",scenePos, " viewPos = ",mouse.x,mouse.y);}}}
}