def createScene(): # Root entity. rootEntity = QEntity() # Material. material = QPhongMaterial(rootEntity) # Torus. torusEntity = QEntity(rootEntity) torusMesh = QTorusMesh() torusMesh.setRadius(5) torusMesh.setMinorRadius(1) torusMesh.setRings(100) torusMesh.setSlices(20) torusTransform = QTransform() torusTransform.setScale3D(QVector3D(1.5, 1.0, 0.5)) torusTransform.setRotation( QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0)) torusEntity.addComponent(torusMesh) torusEntity.addComponent(torusTransform) torusEntity.addComponent(material) # Sphere. sphereEntity = QEntity(rootEntity) sphereMesh = QSphereMesh() sphereMesh.setRadius(3) sphereTransform = QTransform() controller = OrbitTransformController(sphereTransform) controller.target = sphereTransform controller.radius = 20.0 sphereRotateTransformAnimation = QPropertyAnimation(sphereTransform) sphereRotateTransformAnimation.setTargetObject(controller) sphereRotateTransformAnimation.setPropertyName(b'angle') sphereRotateTransformAnimation.setStartValue(0) sphereRotateTransformAnimation.setEndValue(360) sphereRotateTransformAnimation.setDuration(10000) sphereRotateTransformAnimation.setLoopCount(-1) sphereRotateTransformAnimation.start() sphereEntity.addComponent(sphereMesh) sphereEntity.addComponent(sphereTransform) sphereEntity.addComponent(material) return rootEntity
def createScene(self): root = QEntity() # Material material = QPhongMaterial(root) material.setAmbient(QColor(100, 100, 0)) material.setDiffuse(QColor(100, 0, 100)) cube_E = QEntity(root) cube_mesh = QCuboidMesh() cube_mesh.setXExtent(2) cube_mesh.setYExtent(2) cube_mesh.setZExtent(2) cube_tr = QTransform() cube_tr.setScale3D(QVector3D(2, 2, 2)) cube_E.addComponent(cube_mesh) cube_E.addComponent(cube_tr) cube_E.addComponent(material) return root
diffuseMapMaterial = QDiffuseMapMaterial() diffuseMapMaterial.setSpecular(QColor.fromRgbF(0.2, 0.2, 0.2, 1.0)) diffuseMapMaterial.setShininess(2.0) chestDiffuseImage = QTextureImage() chestDiffuseImage.setSource(QUrl.fromLocalFile('assets/chest/diffuse.webp')) diffuseMapMaterial.diffuse().addTextureImage(chestDiffuseImage) chest.addComponent(diffuseMapMaterial) # Trefoil Knot. trefoil = RotatingTrefoilKnot(sceneRoot) trefoil.position = QVector3D(0.0, 3.5, 0.0) trefoil.scale = 0.5 phongMaterial = QPhongMaterial() phongMaterial.setDiffuse(QColor(204, 205, 75)) phongMaterial.setSpecular(Qt.white) trefoil.addComponent(phongMaterial) # Barrels. basicBarrel = Barrel(sceneRoot) basicBarrel.transform().setTranslation(QVector3D(8.0, 0.0, 0.0)) rustyBarrel = Barrel(sceneRoot) rustyBarrel.setDiffuse(Barrel.RustDiffuse) rustyBarrel.setSpecular(Barrel.RustSpecular) rustyBarrel.setBumps(Barrel.HardBumps) rustyBarrel.transform().setTranslation(QVector3D(10.0, 0.0, 0.0))
class Animation(object): """ Abstract class for setting up a 3D scene and animating it. """ def __init__(self, title, frame_rate, run_time): """ Create a new Animation. Arguments: title: str, the window title frame_rate: float, the number of frames to display per second run_time: float, the number of seconds to run the animation """ self.title = title assert 0 < frame_rate < 1000 self.frame_rate = frame_rate assert run_time > 0 self.run_time = run_time self.frame = 0 self.prev_update_time = None # import OpenGL so Qt can use it for rendering from OpenGL import GL # create the 3D window self.view = Qt3DWindow() self.view.setX(100) self.view.setY(100) self.view.setTitle(self.title) self.qml_engine = QQmlEngine(self.view) def load_qml(self, path, parent): """ Helper method to load an object using Qt's QML system. Arguments: path: str, a path to a QML file parent: QObject, the parent of the object to be loaded Returns: the loaded QObject """ component = QQmlComponent(self.qml_engine, path, parent) obj = component.create() if obj is None: print('Error loading {}'.format(path)) for error in component.errors(): print(error.toString()) exit() return obj def add_light(self, position, intensity=1.0, color=util.hsl(0, 0, 100)): """ Helper method to add a simple point light to the scene. Arguments: position: QVector3D, the position of the light in the scene intensity: float, the intensity of the light color: QColor, the color of the light """ light_entity = QEntity(self.scene) light = QPointLight(light_entity) light.setColor(color) light.setIntensity(intensity) light_transform = QTransform(self.scene) light_transform.setTranslation(position) light_entity.addComponent(light) light_entity.addComponent(light_transform) def add_rgb_cube(self, w, h, d): """ Helper method to add an RGB-textured cube to the scene. Arguments: w: float, the width of the cube h: float, the height of the cube d: float, the depth of the cube Returns: the QTransform of the cube """ cube_entity = QEntity(self.scene) cube_mesh = QCuboidMesh() cube_mesh.setXExtent(w) cube_mesh.setYExtent(h) cube_mesh.setZExtent(d) cube_entity.addComponent(cube_mesh) cube_transform = QTransform(self.scene) cube_entity.addComponent(cube_transform) if not hasattr(self, 'rgb_cube_material'): # load material definition from QML # this was the easiest way I could find to create a custom shader in Qt3D... self.rgb_cube_material = self.load_qml( os.path.join(os.path.dirname(__file__), 'RGBCubeMaterial.qml'), self.scene) cube_entity.addComponent(self.rgb_cube_material) return cube_transform def add_sphere(self, r): """ Helper method to add a sphere to the scene. Arguments: r: float, the radius of the sphere Returns: the QTransform of the sphere """ sphere_entity = QEntity(self.scene) sphere_mesh = QSphereMesh() sphere_mesh.setRadius(r) sphere_entity.addComponent(sphere_mesh) sphere_transform = QTransform(self.scene) sphere_entity.addComponent(sphere_transform) if not hasattr(self, 'sphere_material'): self.sphere_material = QPhongMaterial(self.scene) self.sphere_material.setAmbient(util.hsl(0, 0, 50)) sphere_entity.addComponent(self.sphere_material) return sphere_transform def add_path(self, *pts): """ Helper method to add a path to the scene. Arguments: pts: list of QVector3D's, the points in the path Returns: a list of the entities added to the scene """ # make a bunch of cylinder objects aligned along the path entities = [] prev_pt = None for pt in pts: if prev_pt is not None: if prev_pt != pt: # for each adjacent pair of points that are different # make a cylinder path_entity = QEntity(self.scene) path_mesh = QCylinderMesh() path_mesh.setRadius(0.05) # very thin path_mesh.setLength((prev_pt - pt).length( )) # length is the distance between the points path_entity.addComponent(path_mesh) path_transform = QTransform(self.scene) path_transform.setRotation( QQuaternion.fromDirection( QVector3D(0, 0, -1), prev_pt - pt)) # rotate to point along path path_transform.setTranslation( (pt + prev_pt) / 2) # center between points path_entity.addComponent(path_transform) if not hasattr(self, 'path_material'): self.path_material = QPhongMaterial(self.scene) self.path_material.setAmbient(util.hsl(0, 0, 50)) path_entity.addComponent(self.path_material) entities.append(path_entity) prev_pt = pt return entities def setup_scene(self, background_color, camera_position, camera_lookat): """ Sets up the scene. Should be called before running the animation. Arguments: background_color: QColor, background color of the scene camera_position: QVector3D, the position of the camera in the scene camera_lookat: QVector3D, the point that the camera should be pointing at in the scene """ # clear color is the background color self.view.defaultFrameGraph().setClearColor(background_color) self.scene = QEntity() # let subclass populate scene self.make_scene() # set up camera camera = self.view.camera() camera.setPosition(camera_position) camera.setViewCenter(camera_lookat) self.view.setRootEntity(self.scene) def make_scene(self): """ Abstract method. Populates the scene with objects. """ raise NotImplementedError() def _update(self): """ Updates the animation, rendering the next frame. """ # current animation time in seconds t = util.lerp(self.frame, 0, self.frame_rate, 0, 1) # change in time since the last frame dt = 1 / self.frame_rate if self.prev_update_time is None else t - self.prev_update_time # call subclass's frame update self.update(self.frame, t, dt) # stop the animation and close the window if run past run_time if t >= self.run_time: self.animation_timer.stop() self.view.close() self.prev_update_time = t self.frame += 1 def update(self, frame, t, dt): """ Abstract method. Updates one frame of the animation. Arguments: frame: int, the current frame number t: float, the current animation time in seconds dt: float, the number of seconds since the last update """ raise NotImplementedError() def run(self): """ Runs the animation asynchronously. The animation runs in the background for self.run_time seconds. """ self.animation_timer = QTimer(self.view) # timer interval in msecs self.animation_timer.setInterval(1000 / self.frame_rate) # call update on each timeout of the timer self.animation_timer.timeout.connect(self._update) self.animation_timer.start() # show the main window self.view.show()
def __init__(self, rootEntity): super(SceneModifier, self).__init__() self.m_rootEntity = rootEntity # Torus shape data. self.m_torus = QTorusMesh() self.m_torus.setRadius(1.0) self.m_torus.setMinorRadius(0.4) self.m_torus.setRings(100) self.m_torus.setSlices(20) # TorusMesh transform. torusTransform = QTransform() torusTransform.setScale(2.0) torusTransform.setRotation( QQuaternion.fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0), 25.0)) torusTransform.setTranslation(QVector3D(5.0, 4.0, 0.0)) torusMaterial = QPhongMaterial() torusMaterial.setDiffuse(QColor(0xbeb32b)) # Torus. self.m_torusEntity = QEntity(self.m_rootEntity) self.m_torusEntity.addComponent(self.m_torus) self.m_torusEntity.addComponent(torusMaterial) self.m_torusEntity.addComponent(torusTransform) # Cone shape data. cone = QConeMesh() cone.setTopRadius(0.5) cone.setBottomRadius(1) cone.setLength(3) cone.setRings(50) cone.setSlices(20) # ConeMesh transform. coneTransform = QTransform() coneTransform.setScale(1.5) coneTransform.setRotation( QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0)) coneTransform.setTranslation(QVector3D(0.0, 4.0, -1.5)) coneMaterial = QPhongMaterial() coneMaterial.setDiffuse(QColor(0x928327)) # Cone. self.m_coneEntity = QEntity(self.m_rootEntity) self.m_coneEntity.addComponent(cone) self.m_coneEntity.addComponent(coneMaterial) self.m_coneEntity.addComponent(coneTransform) # Cylinder shape data. cylinder = QCylinderMesh() cylinder.setRadius(1) cylinder.setLength(3) cylinder.setRings(100) cylinder.setSlices(20) # CylinderMesh transform. cylinderTransform = QTransform() cylinderTransform.setScale(1.5) cylinderTransform.setRotation( QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0)) cylinderTransform.setTranslation(QVector3D(-5.0, 4.0, -1.5)) cylinderMaterial = QPhongMaterial() cylinderMaterial.setDiffuse(QColor(0x928327)) # Cylinder. self.m_cylinderEntity = QEntity(self.m_rootEntity) self.m_cylinderEntity.addComponent(cylinder) self.m_cylinderEntity.addComponent(cylinderMaterial) self.m_cylinderEntity.addComponent(cylinderTransform) # Cuboid shape data. cuboid = QCuboidMesh() # CuboidMesh transform. cuboidTransform = QTransform() cuboidTransform.setScale(4.0) cuboidTransform.setTranslation(QVector3D(5.0, -4.0, 0.0)) cuboidMaterial = QPhongMaterial() cuboidMaterial.setDiffuse(QColor(0x665423)) # Cuboid. self.m_cuboidEntity = QEntity(self.m_rootEntity) self.m_cuboidEntity.addComponent(cuboid) self.m_cuboidEntity.addComponent(cuboidMaterial) self.m_cuboidEntity.addComponent(cuboidTransform) # Plane shape data. planeMesh = QPlaneMesh() planeMesh.setWidth(2) planeMesh.setHeight(2) # Plane mesh transform. planeTransform = QTransform() planeTransform.setScale(1.3) planeTransform.setRotation( QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0)) planeTransform.setTranslation(QVector3D(0.0, -4.0, 0.0)) planeMaterial = QPhongMaterial() planeMaterial.setDiffuse(QColor(0xa69929)) # Plane. self.m_planeEntity = QEntity(self.m_rootEntity) self.m_planeEntity.addComponent(planeMesh) self.m_planeEntity.addComponent(planeMaterial) self.m_planeEntity.addComponent(planeTransform) # Sphere shape data. sphereMesh = QSphereMesh() sphereMesh.setRings(20) sphereMesh.setSlices(20) sphereMesh.setRadius(2) # Sphere mesh transform. sphereTransform = QTransform() sphereTransform.setScale(1.3) sphereTransform.setTranslation(QVector3D(-5.0, -4.0, 0.0)) sphereMaterial = QPhongMaterial() sphereMaterial.setDiffuse(QColor(0xa69929)) # Sphere. self.m_sphereEntity = QEntity(self.m_rootEntity) self.m_sphereEntity.addComponent(sphereMesh) self.m_sphereEntity.addComponent(sphereMaterial) self.m_sphereEntity.addComponent(sphereTransform)