def setup_selector_views():
    selector_views = []
    for aVariant in Puzzle_variant:
        selector_view = scn.View(None, superView=data.main_view)
        selector_view.preferredFramesPerSecond = 30
        selector_view.rendersContinuously = False
        selector_view.autoenablesDefaultLighting = True
        selector_view.allowsCameraControl = False

        selector_view.scene = scn.Scene()
        selector_view.scene.background.contents = 'beige'

        title_geometry = scn.Text(str(aVariant.name).replace('_', ' '), 0.3)
        title_geometry.font = ('Chalkboard SE', 4.)
        title_geometry.firstMaterial.contents = (.48, .14, .14)
        title_geometry.flatness = 0.1
        title_geometry.chamferRadius = 0.08
        bbox_min, bbox_max = title_geometry.boundingBox
        title_size = bbox_max.x - bbox_min.x
        title_node = scn.Node.nodeWithGeometry(title_geometry)
        title_node.position = (-title_size / 2, -1., -25.)
        selector_view.scene.rootNode.addChildNode(title_node)

        puzzle_node = scn.Node()

        table_geometry = scn.Cylinder(6., 0.5)
        table_geometry.firstMaterial.diffuse.contents = 'resources/marble.jpg'
        table_node = scn.Node.nodeWithGeometry(table_geometry)
        table_node.position = (0., -0.75, 0.)
        puzzle_node.addChildNode(table_node)

        puzzle_node.position = (0., -0.25, 0.)
        piece_set = Piece_set(aVariant)
        pieces = len(piece_set.pieces)
        for index, aPiece in enumerate(piece_set.pieces):
            show_piece = aPiece.drawer_handle_node
            show_piece.rotation = (0, 1, 0,
                                   index / pieces * 2 * math.pi - math.pi / 4.)
            show_piece.position = scn.Vector3(
                4. * math.sin(index / pieces * 2 * math.pi), 0.,
                4. * math.cos(index / pieces * 2 * math.pi))
            puzzle_node.addChildNode(show_piece)

        puzzle_node.runAction(rotate_action)
        selector_view.scene.rootNode.addChildNode(puzzle_node)

        camera_node = scn.Node()
        camera_node.name = 'selector_camera'
        camera_node.position = (0., 7., 11.)
        camera_node.lookAt((0., 0., 0.))
        camera_node.camera = scn.Camera()
        selector_view.scene.rootNode.addChildNode(camera_node)

        selector_views.append(selector_view)
    return selector_views
Beispiel #2
0
  def buildCar(self, body_color=None, sound_file=None, sound_volume=1.0):
    self.chassis_node = scn.Node()
    self.chassis_node.categoryBitMask = 1 << 1
    
    self.camera_controller_node = scn.Node()

    self.camera_node = scn.Node()
    self.camera_node.position = (0, 1.6, 2.05)
    self.camera_node.lookAt((0, 0.9, 10))
    self.camera = scn.Camera()    
    self.camera.zNear = 0.25
    self.camera.zFar = 10
    self.camera.fieldOfView = 35
    self.camera_node.camera = self.camera
    
    self.camera_controller_node.addChildNode(self.camera_node)
    self.chassis_node.addChildNode(self.camera_controller_node)

    self.radar_p1L = scn.Vector3(1.2, 1.3, 2.05)
    self.radar_p2L = scn.Vector3(4.5, 0.8, 20)
    self.radar_pSL = scn.Vector3(10., 0.8, 2.4)
    self.radar_p1R = scn.Vector3(-1.2, 1.3, 2.05)
    self.radar_p2R = scn.Vector3(-4.5, 0.8, 20)
    self.radar_pSR = scn.Vector3(-10., 0.8, 2.4)
    
    self.body_material = scn.Material()
    self.body_material.diffuse.contents = body_color
    self.body_material.specular.contents = (.88, .88, .88)
    
    self.body = scn.Box(2, 1, 4, 0.2)
    self.body.firstMaterial = self.body_material

    self.body_node = scn.Node.nodeWithGeometry(self.body)
    self.body_node.position = (0, 0.75, 0)
    self.chassis_node.addChildNode(self.body_node)
    
    self.physicsBody = scn.PhysicsBody.dynamicBody()
    self.physicsBody.allowsResting = False
    self.physicsBody.mass = 1200
    self.physicsBody.restitution = 0.1
    self.physicsBody.damping = 0.3
    self.chassis_node.physicsBody = self.physicsBody
    
    self.top = scn.Box(1.6, 0.6, 1.8, 0.1)
    self.top.firstMaterial = self.body_material
    self.top_node = scn.Node.nodeWithGeometry(self.top)
    self.top_node.position = (0, 0.5+0.2, 0)
    self.body_node.addChildNode(self.top_node)
    
    self.door1 = scn.Box(2.02, 1-0.2, 1.8/2.2, 0.08)
    self.door1.firstMaterial = self.body_material
    self.door1_node = scn.Node.nodeWithGeometry(self.door1)
    self.door1_node.position = (0, 0.1, 1.8/4)
    self.body_node.addChildNode(self.door1_node)
    
    self.door2_node = scn.Node.nodeWithGeometry(self.door1)
    self.door2_node.position = (0, 0.1, -1.8/4+0.1)
    self.body_node.addChildNode(self.door2_node)
    
    self.window_material = scn.Material()
    self.window_material.diffuse.contents = (.64, .71, .75, 0.6)
    self.window_material.specular.contents = (.88, .88, .88, 0.8)
    
    self.sideW1 = scn.Box(1.61, 0.6-0.1, 1.8/2.2, 0.08)
    self.sideW1.firstMaterial = self.window_material
    self.sideW1_node = scn.Node.nodeWithGeometry(self.sideW1)
    self.sideW1_node.position = (0, 0.5+0.2, 1.8/4)
    self.body_node.addChildNode(self.sideW1_node)
    
    self.sideW2_node = scn.Node.nodeWithGeometry(self.sideW1)
    self.sideW2_node.position = (0, 0.5+0.2, -1.8/4+0.1)
    self.body_node.addChildNode(self.sideW2_node)
    
    self.window_materials = [scn.Material() for i in range(6)]
    self.window_materials[0] = self.window_material
    self.window_materials[2] = self.window_material
    for i in [1, 3, 4, 5]:
      self.window_materials[i] = self.body_material
    
    alpha = math.pi/5
    self.frontW = scn.Box(1.4, 0.6/math.cos(alpha), 0.1, 0.06)
    self.frontW.materials = self.window_materials
    self.frontW_node = scn.Node.nodeWithGeometry(self.frontW)
    self.frontW_node.position = (0, 0.5+0.2-0.05, 1.8/2+math.tan(alpha)*0.6/2-0.1)
    self.frontW_node.rotation = (1, 0, 0, -alpha)
    self.body_node.addChildNode(self.frontW_node)
    
    alpha = math.pi/5
    self.frontW2 = scn.Box(1.3, 0.6/math.cos(alpha), 0.3, 0.0)
    self.frontW2.firstMaterial = self.window_material
    self.frontW2_node = scn.Node.nodeWithGeometry(self.frontW2)
    self.frontW2_node.position = (0, 0.5+0.2-0.05-0.2, 1.8/2+math.tan(alpha)*0.6/2-0.08)
    self.frontW2_node.rotation = (1, 0, 0, -alpha)
    self.body_node.addChildNode(self.frontW2_node)
    
    alpha = math.pi/3.2
    self.rearW = scn.Box(1.4, 0.6/math.cos(alpha), 0.2, 0.2)
    self.rearW.materials = self.window_materials
    self.rearW_node = scn.Node.nodeWithGeometry(self.rearW)
    self.rearW_node.position = (0, 0.5+0.2-0.0417, -1.8/2-math.tan(alpha)*0.6/2+0.15)
    self.rearW_node.rotation = (1, 0, 0, alpha)
    self.body_node.addChildNode(self.rearW_node)
    
    alpha = math.pi/3.2
    self.rearW2 = scn.Box(1.3, 0.6/math.cos(alpha), 0.3, 0.05)
    self.rearW2.firstMaterial = self.window_material
    self.rearW2_node = scn.Node.nodeWithGeometry(self.rearW2)
    self.rearW2_node.position = (0, 0.5+0.2-0.05-0.2, -1.8/2-math.tan(alpha)*0.6/2+0.1)
    self.rearW2_node.rotation = (1, 0, 0, alpha)
    self.body_node.addChildNode(self.rearW2_node)
    
    self.nose = scn.Pyramid(2-0.4, 0.15, 1-0.2)
    self.nose.firstMaterial = self.body_material
    self.nose_node = scn.Node.nodeWithGeometry(self.nose)
    self.nose_node.position = (0, 0.75, 2-0.03)
    self.nose_node.rotation = (1, 0, 0, math.pi/2)
    self.chassis_node.addChildNode(self.nose_node)
    
    self.lampBack_colors = [(.6, .0, .0), (1.0, .0, .0)]
    
    self.front_spot = scn.Light()
    self.front_spot.type = scn.LightTypeSpot
    self.front_spot.castsShadow = False
    self.front_spot.color = (1.0, 1.0, .95)
    self.front_spot.spotInnerAngle = 20
    self.front_spot.spotOuterAngle = 25
    self.front_spot.attenuationEndDistance = 15
    
    self.exhaust = scn.Tube(0.05, 0.07, 0.08)
    self.exhaust.firstMaterial.metalness.contents = (.5, .5, .5)
    self.exhaust_node = scn.Node.nodeWithGeometry(self.exhaust)
    self.exhaust_node.position = (0.5, -0.42, -2.04)
    self.exhaust_node.rotation = (1, 0, 0, math.pi/2)
    self.body_node.addChildNode(self.exhaust_node)
    
    self.smoke = scn.ParticleSystem()
    self.smoke.emitterShape = scn.Sphere(0.01)
    self.smoke.birthLocation = scn.ParticleBirthLocation.SCNParticleBirthLocationSurface
    self.smoke.birthRate =6000
    self.smoke.loops = True
    self.smoke.emissionDuration = 0.08
    self.smoke.idleDuration = 0.4
    self.smoke.idleDurationVariation = 0.2
    self.smoke.particleLifeSpan = 0.3
    self.smoke.particleLifeSpanVariation = 1.2
    self.smoke.particleColor = (1., 1., 1., 1.)
    self.smoke.particleColorVariation = (.6, .0, .6, 0.)
    self.smoke.blendMode = scn.ParticleBlendMode.Multiply
    self.smoke.birthDirection = scn.ParticleBirthDirection.Random
    self.smoke.particleVelocity = 2.
    self.smoke.particleVelocityVariation = 3.5
    self.smoke.acceleration = (0., 15, 0.)
    self.sizeAnim = scn.CoreBasicAnimation()
    self.sizeAnim.fromValue = 0.1
    self.sizeAnim.toValue = 0.0
    self.size_con = scn.ParticlePropertyController.controllerWithAnimation(self.sizeAnim)    
    self.smoke.propertyControllers = {scn.SCNParticlePropertySize:self.size_con}

    self.smoker_node = scn.Node()
    self.smoker_node.position = (0., -0.15, 0.)
    self.smoker_node.addParticleSystem(self.smoke)
    self.exhaust_node.addChildNode(self.smoker_node)
    
    self.lamp = scn.Tube(0.12, 0.15, 4.07)
    self.lamp.firstMaterial.metalness.contents = (.93, .93, .93)
    self.lampGlasFront = scn.Sphere(0.13)
    self.lampGlasFront.firstMaterial.emission.contents = (.92, .93, .66)
    self.lampGlasBack = scn.Sphere(0.13)
    self.lampGlasBack.firstMaterial.diffuse.contents = 'black'
    self.lampGlasBack.firstMaterial.emission.contents = self.lampBack_colors[0]
    
    self.lamp_nodeR = scn.Node.nodeWithGeometry(self.lamp)
    self.lamp_nodeR.position = (-0.6, 0.75, 0.015)
    self.lamp_nodeR.rotation = (1, 0, 0, math.pi/2)
    self.chassis_node.addChildNode(self.lamp_nodeR)
    self.lamp_nodeL = scn.Node.nodeWithGeometry(self.lamp)
    self.lamp_nodeL.position = (0.6, 0.75, 0.015)
    self.lamp_nodeL.rotation = (1, 0, 0, math.pi/2)
    self.chassis_node.addChildNode(self.lamp_nodeL)
    
    self.lampGlasFront_nodeR = scn.Node.nodeWithGeometry(self.lampGlasFront)
    self.lampGlasFront_nodeR.position = (0, 1.95, 0)
    self.lampGlasFront_nodeR.lookAt((0, 45, 10))
    self.lampGlasFront_nodeR.light = self.front_spot
    self.lamp_nodeR.addChildNode(self.lampGlasFront_nodeR)    
    self.lampGlasBack_nodeR = scn.Node.nodeWithGeometry(self.lampGlasBack)
    self.lampGlasBack_nodeR.position = (0, -1.95, 0)
    self.lamp_nodeR.addChildNode(self.lampGlasBack_nodeR)
    
    self.lampGlasFront_nodeL = scn.Node.nodeWithGeometry(self.lampGlasFront)
    self.lampGlasFront_nodeL.position = (0, 1.95, 0)
    self.lampGlasFront_nodeL.lookAt((0, 45, 10))
    self.lampGlasFront_nodeL.light = self.front_spot
    self.lamp_nodeL.addChildNode(self.lampGlasFront_nodeL)    
    self.lampGlasBack_nodeL = scn.Node.nodeWithGeometry(self.lampGlasBack)
    self.lampGlasBack_nodeL.position = (0, -1.95, 0)
    self.lamp_nodeL.addChildNode(self.lampGlasBack_nodeL)
    
    self.wheel_nodes = [scn.Node()]
    self.tire = scn.Tube(0.12, 0.35, 0.25)
    self.tire.firstMaterial.diffuse.contents = 'black'
    self.wheel_nodes[0].position = (0.94, 0.4, 2-0.6)
    self.tire_node = scn.Node.nodeWithGeometry(self.tire)
    self.tire_node.rotation = (0, 0, 1, math.pi/2)
    self.wheel_nodes[0].addChildNode(self.tire_node)
    
    self.trace = scn.ParticleSystem()
    self.trace.birthRate = 750
    self.trace.loops = True
    self.trace.emissionDuration = 0.1
    self.trace.particleLifeSpan = 4.6
    self.trace.particleLifeSpanVariation = 5
    self.trace.particleSize = 0.02
    self.trace.particleColor = (.1, .1, .1, 1.)
    self.trace.particleColorVariation = (0.1, 0.1, 0.1, 0.1)
    self.trace.blendMode = scn.ParticleBlendMode.Replace
    self.trace.emitterShape = scn.Cylinder(0.02, 0.26)
    self.trace.birthLocation = scn.ParticleBirthLocation.SCNParticleBirthLocationVolume
    self.trace.handle(scn.ParticleEvent.Birth, [scn.ParticlePropertyPosition], self.traceParticleEventBlock)

    self.tire_node.addParticleSystem(self.trace)

    self.rim = scn.Cylinder(0.14, 0.1)
    self.rim.firstMaterial.diffuse.contents = 'gray' 
    self.rim.firstMaterial.specular.contents = (.88, .88, .88)
    self.rim_node = scn.Node.nodeWithGeometry(self.rim)
    self.rim_node.name = 'rim'
    self.rim_node.position = (0, 0.06, 0)
    self.tire_node.addChildNode(self.rim_node)
    self.rim_deco = scn.Text('Y', 0.05)
    self.rim_deco.font = ('Arial Rounded MT Bold', 0.3)
    self.rim_deco.firstMaterial.diffuse.contents = 'black' 
    self.rim_deco.firstMaterial.specular.contents = (.88, .88, .88)
    self.rim_deco_node = scn.Node.nodeWithGeometry(self.rim_deco)
    self.rim_deco_node.name = 'deco'
    self.rim_deco_node.position = (-0.1, 0.03, -1.12)
    self.rim_deco_node.rotation = (1, 0, 0, math.pi/2)
    self.rim_node.addChildNode(self.rim_deco_node)
    
    self.wheel_nodes.append(self.wheel_nodes[0].clone())
    self.wheel_nodes[1].position = (-0.94, 0.4, 2-0.6)
    self.wheel_nodes[1].childNodeWithName('rim', True).position = (0, -0.06, 0)
    self.wheel_nodes[1].childNodeWithName('deco', True).position = (-0.1, -0.03, -1.12)
    self.wheel_nodes[1].childNodeWithName('rim', True).rotation = (0, 1, 0, -math.pi/7)
    
    self.wheel_nodes.append(self.wheel_nodes[0].clone())
    self.wheel_nodes[2].position = (0.94, 0.4, -2+0.7)
    self.wheel_nodes[2].childNodeWithName('rim', True).rotation = (0, 1, 0, math.pi/7)
    
    self.wheel_nodes.append(self.wheel_nodes[0].clone())
    self.wheel_nodes[3].position = (-0.94, 0.4, -2+0.7)
    self.wheel_nodes[3].childNodeWithName('rim', True).position = (0, -0.06, 0)
    self.wheel_nodes[3].childNodeWithName('deco', True).position = (-0.1, -0.03, -1.12)
    self.wheel_nodes[3].childNodeWithName('rim', True).rotation = (0, 1, 0, math.pi/3)
    
    for aNode in self.wheel_nodes: self.chassis_node.addChildNode(aNode)
    
    self.wheels = [scn.PhysicsVehicleWheel(node=aNode) for aNode in self.wheel_nodes]    
    for i in [0, 1]: self.wheels[i].suspensionRestLength = 1.3     
    for i in [2, 3]: self.wheels[i].suspensionRestLength = 1.4
    for aWheel in self.wheels: aWheel.maximumSuspensionTravel = 150
    
    self.chassis_node.physicsBody.contactTestBitMask = scn.PhysicsCollisionCategory.Default.value
    self.chassis_node.physicsBody.continuousCollisionDetectionThreshold = 2.
    self.vehicle = scn.PhysicsVehicle(chassisBody=self.chassis_node.physicsBody, wheels=self.wheels)
    self.physics_world.addBehavior(self.vehicle)
    self.world.root_node.addChildNode(self.chassis_node)

    if ENGINESOUND:    
      self.sound = scn.AudioSource(sound_file)
      self.sound.load()
      self.sound.loops = True
      self.sound.volume = sound_volume
      self.sound_player = scn.AudioPlayer.audioPlayerWithSource(self.sound)
      self.chassis_node.addAudioPlayer(self.sound_player)
def setup_axes():
    axis_rode = scn.Cylinder(0.015, 7.5)
    axis_rode.firstMaterial.contents = 'blue'

    vertical_axis_rode = scn.Cylinder(0.015, 11.)
    vertical_axis_rode.firstMaterial.contents = 'blue'

    rotate_control_geometry = scn.Sphere(0.35)
    rotate_control_geometry.firstMaterial.contents = 'red'

    cube_rotate_control_geometry = scn.Sphere(0.35)
    cube_rotate_control_geometry.firstMaterial.contents = 'green'

    shift_control_geometry = scn.Cone(0, 0.38, 0.7)
    shift_control_geometry.firstMaterial.contents = 'orange'

    axis_handle = scn.Node()
    axis_handle.name = 'origo'
    axis_handle.position = (-0.5, -0.5, 0.5)

    x_axis_node = scn.Node.nodeWithGeometry(axis_rode)
    x_axis_node.rotation = (0, 0, 1, math.pi / 2)
    x_axis_node.position = (1.5, 0, 0)

    x_axis_rotate_control_node_1 = scn.Node.nodeWithGeometry(
        rotate_control_geometry)
    x_axis_rotate_control_node_1.position = (0., -axis_rode.height / 2 + 1, 0.)
    x_axis_rotate_control_node_1.name = 'rx1'
    x_axis_rotate_control_node_1.categoryBitMask = 2
    x_axis_node.addChildNode(x_axis_rotate_control_node_1)
    x_axis_rotate_control_node_2 = scn.Node.nodeWithGeometry(
        rotate_control_geometry)
    x_axis_rotate_control_node_2.position = (0., axis_rode.height / 2 - 1, 0.)
    x_axis_rotate_control_node_2.name = 'rx2'
    x_axis_rotate_control_node_2.categoryBitMask = 2
    x_axis_node.addChildNode(x_axis_rotate_control_node_2)

    x_axis_shift_control_node_1 = scn.Node.nodeWithGeometry(
        shift_control_geometry)
    x_axis_shift_control_node_1.position = (0., -axis_rode.height / 2, 0.)
    x_axis_shift_control_node_1.rotation = (0., 0., 1., -math.pi)
    x_axis_shift_control_node_1.name = 'sx1'
    x_axis_shift_control_node_1.categoryBitMask = 2
    x_axis_node.addChildNode(x_axis_shift_control_node_1)
    x_axis_shift_control_node_2 = scn.Node.nodeWithGeometry(
        shift_control_geometry)
    x_axis_shift_control_node_2.position = (0., axis_rode.height / 2, 0.)
    x_axis_shift_control_node_2.name = 'sx2'
    x_axis_shift_control_node_2.categoryBitMask = 2
    x_axis_node.addChildNode(x_axis_shift_control_node_2)

    axis_handle.addChildNode(x_axis_node)

    y_axis_node = scn.Node.nodeWithGeometry(vertical_axis_rode)
    y_axis_node.rotation = (1, 0, 0, -math.pi)
    y_axis_node.position = (0, -3, 0)
    y_axis_rotate_control_node_1 = scn.Node.nodeWithGeometry(
        rotate_control_geometry)
    y_axis_rotate_control_node_1.position = (0.,
                                             -vertical_axis_rode.height / 2,
                                             0.)
    y_axis_rotate_control_node_1.name = 'ry1'
    y_axis_rotate_control_node_1.categoryBitMask = 2
    y_axis_node.addChildNode(y_axis_rotate_control_node_1)
    y_axis_rotate_control_node_2 = scn.Node.nodeWithGeometry(
        rotate_control_geometry)
    y_axis_rotate_control_node_2.position = (0., vertical_axis_rode.height / 2,
                                             0.)
    y_axis_rotate_control_node_2.name = 'ry2'
    y_axis_rotate_control_node_2.categoryBitMask = 2
    y_axis_node.addChildNode(y_axis_rotate_control_node_2)

    axis_handle.addChildNode(y_axis_node)

    z_axis_node = scn.Node.nodeWithGeometry(axis_rode)
    z_axis_node.rotation = (1, 0, 0, -math.pi / 2)
    z_axis_node.position = (0, 0, -1.5)
    z_axis_rotate_control_node_1 = scn.Node.nodeWithGeometry(
        rotate_control_geometry)
    z_axis_rotate_control_node_1.position = (0., -axis_rode.height / 2 + 1, 0.)
    z_axis_rotate_control_node_1.name = 'rz1'
    z_axis_rotate_control_node_1.categoryBitMask = 2
    z_axis_node.addChildNode(z_axis_rotate_control_node_1)
    z_axis_rotate_control_node_2 = scn.Node.nodeWithGeometry(
        rotate_control_geometry)
    z_axis_rotate_control_node_2.position = (0., axis_rode.height / 2 - 1, 0.)
    z_axis_rotate_control_node_2.name = 'rz2'
    z_axis_rotate_control_node_2.categoryBitMask = 2
    z_axis_node.addChildNode(z_axis_rotate_control_node_2)

    z_axis_shift_control_node_1 = scn.Node.nodeWithGeometry(
        shift_control_geometry)
    z_axis_shift_control_node_1.position = (0., -axis_rode.height / 2, 0.)
    z_axis_shift_control_node_1.rotation = (0., 0., 1., math.pi)
    z_axis_shift_control_node_1.name = 'sz1'
    z_axis_shift_control_node_1.categoryBitMask = 2
    z_axis_node.addChildNode(z_axis_shift_control_node_1)
    z_axis_shift_control_node_2 = scn.Node.nodeWithGeometry(
        shift_control_geometry)
    z_axis_shift_control_node_2.position = (0., axis_rode.height / 2, 0.)
    z_axis_shift_control_node_2.name = 'sz2'
    z_axis_shift_control_node_2.categoryBitMask = 2
    z_axis_node.addChildNode(z_axis_shift_control_node_2)

    axis_handle.addChildNode(z_axis_node)

    return axis_handle
    def main(self):
        main_view = ui.View()
        w, h = ui.get_screen_size()
        main_view.frame = (0, 0, w, h)
        main_view.name = 'Feisar_Ship demo'

        scene_view = scn.View(main_view.frame, superView=main_view)
        scene_view.autoresizingMask = scn.ViewAutoresizing.FlexibleHeight | scn.ViewAutoresizing.FlexibleWidth
        scene_view.allowsCameraControl = True

        scene_view.backgroundColor = 'black'

        scene_view.scene = scn.Scene.sceneWithURL(url='Feisar_Ship.scn')

        root_node = scene_view.scene.rootNode

        feisar_node = root_node.childNodes[0]

        feisar_node.light = scn.nil
        root_node.light = scn.nil

        feisar_geometry = feisar_node.geometry
        geometry_sources = feisar_geometry.geometrySources

        feisar_material = feisar_geometry.firstMaterial
        feisar_material.emission.intensity = 0.05
        feisar_material.roughness.contents = (.79, .79, .79)
        feisar_material.metalness.contents = (.11, .11, .11)

        pulse_action = scn.Action.repeatActionForever(
            scn.Action.sequence([
                scn.Action.fadeInWithDuration(1.2),
                scn.Action.fadeOutWithDuration(0.5)
            ]))

        blue_emitter = scn.Material()
        blue_emitter.diffuse.contents = 'black'
        blue_emitter.emission.contents = (.0, .35, 1.0)
        white_emitter = scn.Material()
        white_emitter.diffuse.contents = 'black'
        white_emitter.emission.contents = (.86, .98, 1.0)

        nose_geometry = scn.Sphere(radius=1.5)
        nose_geometry.firstMaterial = blue_emitter
        nose_node = scn.Node.nodeWithGeometry(nose_geometry)
        nose_node.position = (0., 4.35, 161.)
        nose_node.castsShadow = False
        nose_node.runAction(pulse_action)
        feisar_node.addChildNode(nose_node)

        front_grille_p0 = scn.vector3Make((0., 10., 137.6))
        front_grille_p1 = scn.vector3Make((0., 20., 153.5))
        front_grille_ds1 = scn.vector3Make((-0.25, 0.7, -0.25))
        grille_nr = 15
        dt = 0.8 / grille_nr
        front_grille_node = scn.Node()
        feisar_node.addChildNode(front_grille_node)

        front_grille_geometry = scn.Cylinder(0.45, 13.7)
        front_grille_geometry.firstMaterial = white_emitter

        for i in range(grille_nr):
            aNode = scn.Node.nodeWithGeometry(front_grille_geometry)
            aNode.position = (
                0., front_grille_p0.y +
                (front_grille_p1.y - front_grille_p0.y) * i / grille_nr,
                front_grille_p0.z +
                (front_grille_p1.z - front_grille_p0.z) * i / grille_nr)
            aNode.scale = (1. + front_grille_ds1.x * i / grille_nr,
                           1. + front_grille_ds1.y * i / grille_nr,
                           1. + front_grille_ds1.z * i / grille_nr)
            aNode.rotation = (0., 0., 1., math.pi / 2)
            grille_action = scn.Action.sequence([
                scn.Action.waitForDuration(i * dt),
                scn.Action.fadeOutWithDuration(0.7 * dt),
                scn.Action.waitForDuration(dt),
                scn.Action.fadeInWithDuration(0.3 * dt),
                scn.Action.waitForDuration((grille_nr - 2 - i) * dt)
            ])
            aNode.runAction(
                scn.Action.repeatActionForever(
                    scn.Action.sequence(
                        [grille_action,
                         grille_action.reversedAction()])))
            front_grille_node.addChildNode(aNode)

        constraint = scn.LookAtConstraint.lookAtConstraintWithTarget(
            feisar_node)
        constraint.gimbalLockEnabled = True

        light_node = scn.Node()
        light_node.position = (150, 60, -20)

        light = scn.Light()
        light.type = scn.LightTypeDirectional
        light.castsShadow = True
        light.color = (.99, 1.0, .86)
        light_node.light = light
        light_node.constraints = constraint
        root_node.addChildNode(light_node)

        main_view.present(hide_title_bar=False)