def setupScene(self): #create a new scene scene = scn.Scene() #global environment self.setupEnvironment(scene) #add elements self.setupSceneElements(scene) #setup vehicle self.myVehicleNode = self.setupVehicle(scene) #create a main camera self.myCameraNode = scn.Node() self.myCameraNode.camera = scn.Camera() self.myCameraNode.camera.xFov = 75 self.myCameraNode.camera.zFar = 500 self.myCameraNode.position = scn.Vector3(0, 60, 50) self.myCameraNode.rotation = scn.Vector4(1, 0, 0, -M_PI_4*0.75) scene.rootNode.addChildNode(self.myCameraNode) #add a secondary camera to the car frontCameraNode = scn.Node() frontCameraNode.position = scn.Vector3(0, 3.5, 2.5) frontCameraNode.rotation = scn.Vector4(0, 1, 0, M_PI) frontCameraNode.camera = scn.Camera() frontCameraNode.camera.xFov = 75 frontCameraNode.camera.zFar = 500 self.myVehicleNode.addChildNode(frontCameraNode) self.pointOfViews = [self.myCameraNode, frontCameraNode] return scene
def shift(self, axis, distance): pos = self.piece_handle_node.position if axis == 'x': new_shift = scn.Vector3(distance, 0, 0) elif axis == 'y': new_shift = scn.Vector3(0, distance, 0) elif axis == 'z': new_shift = scn.Vector3(0, 0, distance) self.piece_handle_node.position = (pos.x + new_shift.x, pos.y + new_shift.y, pos.z + new_shift.z) self.constraint()
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
def drop(self): tray_handle = self.tray_handle_node.parentNode starting_positions = [ self.piece_handle_node.convertPosition(aNode.position, toNode=tray_handle) for aNode in self.piece_handle_node.childNodes ] pieces_resting_set = set() for aPiece in (_ for _ in self.piece_set.pieces if _.location == Piece_location.Puzzle): for aNode in aPiece.piece_handle_node.childNodes: aPos = aPiece.piece_handle_node.convertPosition( aNode.position, toNode=tray_handle) pieces_resting_set.add( scn.Vector3(round(aPos.x), round(aPos.y), round(aPos.z))) for downShift in range(16): new_positions = { scn.Vector3(round(aStartPos.x), round(aStartPos.y - downShift), round(aStartPos.z)) for aStartPos in starting_positions } break_value = min(aPos.y for aPos in new_positions) if break_value < -6: break if not new_positions.isdisjoint(pieces_resting_set): break downShift -= 1 current_position = self.piece_handle_node.position self.piece_handle_node.position = scn.Vector3( current_position.x, current_position.y - downShift, current_position.z) top_value = max(aPos.y for aPos in new_positions) + 1 if top_value <= -4: self.location = Piece_location.Puzzle self.piece_set.previous_piece_in_tray.append(self) return True else: return False
def constraint(self, zero_align=False): pos = self.piece_handle_node.position min_box, max_box = self.tray_handle_node.boundingBox min_box = scn.Vector3(round(min_box.x + 0.5), round(min_box.y + 0.5), round(min_box.z + 0.5)) max_box = scn.Vector3(round(max_box.x - 0.5), round(max_box.y - 0.5), round(max_box.z - 0.5)) new_pos = [round(pos.x), round(pos.y), round(pos.z)] if not zero_align: if min_box.x < 0: new_pos[0] = pos.x - min_box.x if max_box.x > 2: new_pos[0] = pos.x - (max_box.x - 2) if min_box.y < -2: new_pos[1] = pos.y - (min_box.y + 2) if max_box.y > 0: new_pos[1] = pos.y - (max_box.y - 0) if min_box.z < -2: new_pos[2] = pos.z - (min_box.z + 2) if max_box.z > 0: new_pos[2] = pos.z - max_box.z else: new_pos[0] = pos.x - min_box.x new_pos[1] = pos.y - min_box.y new_pos[2] = pos.z - max_box.z self.piece_handle_node.position = new_pos
def addTrainToSceneBlock(child): if child.geometry is not None and child.geometry != scn.nil: node = child.clone() node.position = scn.Vector3(node.position.x + pos.x, node.position.y + pos.y, node.position.z + pos.z) min, max = node.getBoundingBox() body = scn.PhysicsBody.dynamicBody() boxShape = scn.Box(width=(max.x - min.x), height=(max.y - min.y), length=(max.z - min.z), chamferRadius=0.0) body.physicsShape = scn.PhysicsShape(geometry=boxShape, options=None) trans = list(scn.Matrix4Identity) trans[13] = -min.y node.pivot = trans node.physicsBody = body scene.rootNode.addChildNode(node) return False
def setupEnvironment(self, scene): #add an ambient light ambientLight = scn.Node() ambientLight.light = scn.Light() ambientLight.light.type = scn.LightTypeAmbient ambientLight.light.color = (0.3, 0.3, 0.3, 1.0) scene.rootNode.addChildNode(ambientLight) #add a key light to the scene #keep an ivar for later manipulation self.mySpotLightNode = scn.Node() self.mySpotLightNode.light = scn.Light() self.mySpotLightNode.light.type = scn.LightTypeSpot self.mySpotLightNode.light.castsShadow = True self.mySpotLightNode.light.color = (0.8, 0.8, 0.8, 1.0) self.mySpotLightNode.position = scn.Vector3(0, 80, 30) self.mySpotLightNode.rotation = scn.Vector4(1, 0, 0, -M_PI/2.8) self.mySpotLightNode.light.spotInnerAngle = 0 self.mySpotLightNode.light.spotOuterAngle = 50 self.mySpotLightNode.light.shadowColor = 'black' self.mySpotLightNode.light.zFar = 40 self.mySpotLightNode.light.zNear = 5 self.mySpotLightNode.shadowSampleCount = 16 scene.rootNode.addChildNode(self.mySpotLightNode) floor = scn.Node() floor.geometry = scn.Floor() floor.geometry.firstMaterial.diffuse.contents = "resources/wood.png" scale = list(scn.Matrix4Identity) scale[0], scale[5], scale[10] = 2., 2., 1. floor.geometry.firstMaterial.diffuse.contentsTransform = scale floor.geometry.firstMaterial.locksAmbientWithDiffuse = True floor.geometry.reflectionFalloffEnd = 10 staticBody = scn.PhysicsBody.staticBody() floor.physicsBody = staticBody scene.rootNode.addChildNode(floor)
def main(self): self.main_view = ui.View() w, h = ui.get_window_size() self.main_view.frame = (0, 0, w, h) self.main_view.name = 'vehicle demo' self.close_button = ui.Button() self.close_button.action = self.close self.close_button.frame = (20, 40, 40, 40) self.close_button.background_image = ui.Image.named('emj:No_Entry_2') if DEBUG: self.scene_view = scn.View((0,25,w,h-25), superView=self.main_view) self.scene_view.showsStatistics = True else: self.scene_view = scn.View((0, 0, w, h), superView=self.main_view) self.scene_view.preferredFramesPerSecond = 30 self.scene_view.autoresizingMask = scn.ViewAutoresizing.FlexibleHeight | scn.ViewAutoresizing.FlexibleWidth self.scene_view.allowsCameraControl = False self.scene_view.scene = scn.Scene() self.root_node = self.scene_view.scene.rootNode self.scene_view.backgroundColor = (.77, .97, 1.0) self.scene_view.delegate = self self.physics_world = self.scene_view.scene.physicsWorld self.physics_world.speed = 2. self.physics_world.contactDelegate = self if DEBUG: marker1 = scn.Sphere(0.1) marker1.firstMaterial.emission.contents = (1.0, .14, .14) marker1.firstMaterial.diffuse.contents = (.0, .0, .0) Demo.marker_node1 = scn.Node.nodeWithGeometry(marker1) Demo.marker_node1.name = 'marker1' self.root_node.addChildNode(Demo.marker_node1) marker2 = scn.Sphere(0.1) marker2.firstMaterial.emission.contents = (.17, .0, 1.0) marker2.firstMaterial.diffuse.contents = (.0, .0, .0) Demo.marker_node2 = scn.Node.nodeWithGeometry(marker2) Demo.marker_node2.name = 'marker2' self.root_node.addChildNode(Demo.marker_node2) floor_geometry = scn.Floor() floor_geometry.reflectivity = 0.05 tile_image = ui.Image.named('plf:Ground_DirtCenter') tile_number = 5 tile_factor = scn.Matrix4(tile_number, 0.0, 0.0, 0.0, 0.0, tile_number, 0.0, 0.0, 0.0, 0.0, tile_number, 0.0, 0.0, 0.0, 0.0, 1.0) floor_geometry.firstMaterial.diffuse.contents = tile_image floor_geometry.firstMaterial.diffuse.intensity = 0.8 floor_geometry.firstMaterial.diffuse.contentsTransform = tile_factor floor_geometry.firstMaterial.diffuse.wrapS, floor_geometry.firstMaterial.diffuse.wrapT = scn.WrapMode.Repeat, scn.WrapMode.Repeat floor_geometry.firstMaterial.locksAmbientWithDiffuse = True self.floor_node = scn.Node.nodeWithGeometry(floor_geometry) self.floor_node.name = 'Floor' self.floor_node.physicsBody = scn.PhysicsBody.staticBody() self.root_node.addChildNode(self.floor_node) cars = [dict(name='red', position=(5, 0, 0), volume=1.), dict(name='yellow', too_far=25, body_color=(1.0, .78, .0), position=(-5, 0, -2), sound='game:Pulley', volume=0.1), dict(name='blue', too_far=30, body_color=(.0, .61, 1.0), position=(-12, 0, -6), sound='game:Woosh_1', volume=0.5), dict(name='green', too_far=18, body_color=(.0, .82, .28), position=(10, 0, -10), sound='casino:DiceThrow3', volume=0.8), dict(name='pink', too_far=20, body_color=(.91, .52, .62), position=(5, 0, 10), sound='casino:DieThrow3', volume=0.5)] self.cars =[Car(world=self, props=cars[i]) for i in range(min(MAXCARS, len(cars)))] self.free_flags = [] for i in range(2*len(self.cars)): node = scn.Node() self.free_flags.append(node) self.root_node.addChildNode(node) self.used_flags = {} self.crash = Sparks().particleSystem self.crash_sound = scn.AudioSource('game:Crashing') self.crash_action = scn.Action.playAudioSource(self.crash_sound, False) self.road_blocks_node = scn.Node() self.road_blocks = [] self.road_blocks.append(RoadBlock(w=1.6, l=25, name='block 0', position=(28, 6))) self.road_blocks.append(RoadBlock(w=20, l=1.6, name='block 1', position=(-2, -12))) self.road_blocks.append(RoadBlock(w=8, l=1.6, name='block 2', position=(-10, 6), rotation=-math.pi/6)) self.road_blocks.append(RoadBlock(w=40, l=1.6, name='block 3', position=(-40, 0), rotation=-math.pi/3)) self.road_blocks.append(RoadBlock(w=0.8, h=3, l=0.8, name='start', position=(0, 0))) for aBlock in self.road_blocks: self.road_blocks_node.addChildNode(aBlock.block_node) self.root_node.addChildNode(self.road_blocks_node) self.camera_node = scn.Node() self.camera_node.camera = scn.Camera() self.camera_node.camera.zFar = 150 carPos = self.cars[0].node.position self.camera_node.position = scn.Vector3(carPos.x+5, 10, carPos.z+30) self.root_node.addChildNode(self.camera_node) self.light_node = scn.Node() self.light_node.position = (50, 50, 50) self.light_node.lookAt(self.root_node.position) self.light = scn.Light() self.light.type = scn.LightTypeDirectional self.light.castsShadow = True self.light.shadowSampleCount = 16 self.light.color = (.95, 1.0, .98) self.light_node.light = self.light self.root_node.addChildNode(self.light_node) self.ambient_node = scn.Node() self.ambient = scn.Light() self.ambient.type = scn.LightTypeAmbient self.ambient.color = (.38, .42, .45, .1) self.ambient_node.light = self.ambient self.root_node.addChildNode(self.ambient_node) self.scene_view.pointOfView = self.camera_node if DEBUG: self.main_view.add_subview(Demo.status_label) self.close = False self.shut_down = False self.main_view.add_subview(self.close_button) self.main_view.present(hide_title_bar=~DEBUG)
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 main(self): # actually you need only to preserve those properties that are needed after the main_view.present call, # in this case the self.morpher. All the other self. prefixes are not needed for the same functionality self.main_view = ui.View() w, h = ui.get_screen_size() self.main_view.frame = (0, 0, w, h) self.main_view.name = 'Morpher demo' self.scene_view = scn.View(self.main_view.frame, superView=self.main_view) self.scene_view.autoresizingMask = scn.ViewAutoresizing.FlexibleHeight | scn.ViewAutoresizing.FlexibleRightMargin self.scene_view.allowsCameraControl = True self.scene_view.scene = scn.Scene() self.scene_view.delegate = self self.root_node = self.scene_view.scene.rootNode self.camera_node = scn.Node() self.camera_node.camera = scn.Camera() self.camera_node.position = (0, 0, 5) self.root_node.addChildNode(self.camera_node) verts = [ scn.Vector3(0, 1, 0), scn.Vector3(-0.5, 0, 0.5), scn.Vector3(0.5, 0, 0.5), scn.Vector3(0.5, 0, -0.5), scn.Vector3(-0.5, 0, -0.5), scn.Vector3(0, -1, 0) ] verts_2 = [ scn.Vector3(0, 2.5, 0), scn.Vector3(-0.4, 0, 0.4), scn.Vector3(0.4, 0, 0.4), scn.Vector3(0.4, 0, -0.4), scn.Vector3(-0.4, 0, -0.4), scn.Vector3(0, -1.5, 0) ] self.source = scn.GeometrySource.geometrySourceWithVertices(verts) self.source_2 = scn.GeometrySource.geometrySourceWithVertices(verts_2) indexes = [ 0, 1, 2, 2, 3, 0, 3, 4, 0, 4, 1, 0, 1, 5, 2, 2, 5, 3, 3, 5, 4, 4, 5, 1 ] self.elements = scn.GeometryElement.geometryElementWithData( indexes, scn.GeometryPrimitiveType.Triangles) self.geometry = scn.Geometry.geometryWithSources( self.source, self.elements) self.geometry_2 = scn.Geometry.geometryWithSources( self.source_2, self.elements) self.material = scn.Material() self.material.contents = scn.RGBA(1, 0.9, 0.9, 1.0) self.geometry.materials = self.material self.morpher = scn.Morpher() self.morpher.targets = [self.geometry_2] self.morpher.setWeightForTargetAtIndex(0.0, 0) self.geometry_node = scn.Node.nodeWithGeometry(self.geometry) self.geometry_node.name = 'hero' self.geometry_node.morpher = self.morpher self.root_node.addChildNode(self.geometry_node) # Add a constraint to the camera to keep it pointing to the target geometry constraint = scn.LookAtConstraint.lookAtConstraintWithTarget( self.geometry_node) constraint.gimbalLockEnabled = True self.camera_node.constraints = constraint self.light_node = scn.Node() self.light_node.position = (100, 0, -10) self.light = scn.Light() self.light.type = scn.LightTypeDirectional self.light.castsShadow = True self.light.color = 'white' self.light_node.light = self.light self.root_node.addChildNode(self.light_node) self.rotate_action = scn.Action.repeatActionForever( scn.Action.rotateBy(0, math.pi * 2, 0, 10)) self.geometry_node.runAction(self.rotate_action) self.main_view.present(style='fullscreen', hide_title_bar=False)
def didSimulatePhysics(self, view, atTime): engineForce = 0 brakingForce = 0 accelerometer = motion.get_gravity() if accelerometer[0] > 0: self.myOrientation = accelerometer[1] * 1.3 else: self.myOrientation = -accelerometer[1] * 1.3 orientation = self.myOrientation #drive: 1 touch = accelerate, 2 touches = backward, 3 touches = brake if self.touchCount == 1: engineForce = self.defaultEngineForce self.myReactor.birthRate = self.myReactorDefaultBirthRate elif self.touchCount == 2: engineForce = -self.defaultEngineForce self.myReactor.birthRate = 0 elif self.touchCount == 3: brakingForce = 100 self.myReactor.birthRate = 0 else: brakingForce = self.defaultBrakingForce self.myReactor.birthRate = 0 myVehicleSteering = -orientation if orientation == 0: myVehicleSteering = myVehicleSteering * 0.9 if myVehicleSteering < -self.steeringClamp: myVehicleSteering = -self.steeringClamp elif myVehicleSteering > self.steeringClamp: myVehicleSteering = self.steeringClamp #update the vehicle steering and acceleration self.myVehicle.setSteeringAngle(myVehicleSteering, forWheelAtIndex=0) self.myVehicle.setSteeringAngle(myVehicleSteering, forWheelAtIndex=1) self.myVehicle.applyEngineForce(engineForce, forWheelAtIndex=2) self.myVehicle.applyEngineForce(engineForce, forWheelAtIndex=3) self.myVehicle.applyBrakingForce(brakingForce, forWheelAtIndex=2) self.myVehicle.applyBrakingForce(brakingForce, forWheelAtIndex=3) self.ReorientCarIfNeeded() if self.overlayScene.myCameraButton.clicked: #play a sound self.myCameraNode.runAction(self.overlayScene.myCameraButton.clickAction) #change the point of view self.changePointOfView() return #make camera follow the car node car = self.myVehicleNode.presentationNode carPos = car.position targetPos = scn.Vector3(carPos.x, 30.0, carPos.z + 25.0) cameraPos = self.myCameraNode.position cameraPos = scn.Vector3(cameraPos.x * (1.0 - self.cameraDamping) + targetPos.x * self.cameraDamping, cameraPos.y * (1.0 - self.cameraDamping) + targetPos.y * self.cameraDamping, cameraPos.z * (1.0 - self.cameraDamping) + targetPos.z * self.cameraDamping) self.myCameraNode.position = cameraPos if not self.inCarView: #move spot light in front of the camera frontPosition = self.scnView.pointOfView.presentationNode.convertPosition(scn.Vector3(0, 0, -30), toNode=scn.nil) self.mySpotLightNode.position = scn.Vector3(frontPosition.x, 80.0, frontPosition.z) self.mySpotLightNode.rotation = scn.Vector4(1,0,0, -M_PI/2) else: #move spot light on top of the car self.mySpotLightNode.position = scn.Vector3(carPos.x, 80.0, carPos.z + 30.0) self.mySpotLightNode.rotation = scn.Vector4(1,0,0, -M_PI/2.8) self.overlayScene.mySpeedNeedle.zRotation = -(abs(self.myVehicle.speedInKilometersPerHour) * M_PI / self.maxSpeed)
def setupVehicle(self, scene): chassisNode = scn.Node() carScene = scn.Scene(url="resources/rc_car_PY.scn") chassisNode = carScene.rootNode.childNodeWithName("rccarBody", recursively=False) #setup the chassis chassisNode.position = scn.Vector3(0, 10, 30) chassisNode.rotation = scn.Vector4(0, 1, 0, M_PI) body = scn.PhysicsBody.dynamicBody() body.allowsResting = False body.mass = 80 body.restitution = 0.1 body.friction = 0.5 body.rollingFriction = 0 chassisNode.physicsBody = body scene.rootNode.addChildNode(chassisNode) self.pipeNode = chassisNode.childNodeWithName("pipe", recursively=False) self.myReactor = scn.ParticleSystem() self.myReactor.birthRate = 1000 self.myReactor.birthLocation = scn.ParticleBirthLocation.SCNParticleBirthLocationSurface self.myReactor.loops = True self.myReactor.emissionDuration = 1 self.myReactor.emissionDurationVariation = 0 self.myReactor.idleDuration = 0 self.myReactor.idleDurationVariation = 0. self.myReactor.emittingDirection = (0, 1, 0) self.myReactor.spreadingAngle = 10 self.myReactor.particleAngleVariation = 180 self.myReactor.particleDiesOnCollision = False self.myReactor.particleLifeSpan = 0.15 self.myReactor.particleLifeSpanVariation = 0.05 self.myReactor.particleVelocity = 40. self.myReactor.particleVelocityVariation = 40. self.myReactor.particleImage = ui.Image.named('resources/spark.png') self.myReactor.particleSize = 1. self.myReactor.particleSizeVariation = 1. self.myReactor.particleIntensity = 1. self.myReactor.particleIntensityVariation = 0.4 self.myReactor.stretchFactor = 0.0 self.myReactor.particleColor = (.87, .45, .0) self.myReactor.blendMode = scn.ParticleBlendMode.SCNParticleBlendModeAdditive self.myReactorDefaultBirthRate = self.myReactor.birthRate self.myReactor.birthRate = 0 self.pipeNode.addParticleSystem(self.myReactor) #add wheels wheel0Node = chassisNode.childNodeWithName("wheelLocator_FL", recursively=True) wheel1Node = chassisNode.childNodeWithName("wheelLocator_FR", recursively=True) wheel2Node = chassisNode.childNodeWithName("wheelLocator_RL", recursively=True) wheel3Node = chassisNode.childNodeWithName("wheelLocator_RR", recursively=True) wheel0 = scn.PhysicsVehicleWheel(node=wheel0Node) wheel1 = scn.PhysicsVehicleWheel(node=wheel1Node) wheel2 = scn.PhysicsVehicleWheel(node=wheel2Node) wheel3 = scn.PhysicsVehicleWheel(node=wheel3Node) min, max = wheel0Node.getBoundingBox() wheelHalfWidth = 0.5 * (max.x - min.x) p = wheel0Node.convertPosition((0, 0, 0), toNode=chassisNode) p = (p.x+wheelHalfWidth, p.y, p.z) wheel0.connectionPosition = p p = wheel1Node.convertPosition((0, 0, 0), toNode=chassisNode) p = (p.x-wheelHalfWidth, p.y, p.z) wheel1.connectionPosition = p p = wheel2Node.convertPosition((0, 0, 0), toNode=chassisNode) p = (p.x+wheelHalfWidth, p.y, p.z) wheel2.connectionPosition = p p = wheel3Node.convertPosition((0, 0, 0), toNode=chassisNode) p = (p.x-wheelHalfWidth, p.y, p.z) wheel3.connectionPosition = p #create the physics vehicle vehicle = scn.PhysicsVehicle(chassisBody=chassisNode.physicsBody, wheels=[wheel0, wheel1, wheel2, wheel3]) scene.physicsWorld.addBehavior(vehicle) self.myVehicle = vehicle return chassisNode
def addTrainToScene(self, scene=None, pos=None): def addTrainToSceneBlock(child): if child.geometry is not None and child.geometry != scn.nil: node = child.clone() node.position = scn.Vector3(node.position.x + pos.x, node.position.y + pos.y, node.position.z + pos.z) min, max = node.getBoundingBox() body = scn.PhysicsBody.dynamicBody() boxShape = scn.Box(width=(max.x - min.x), height=(max.y - min.y), length=(max.z - min.z), chamferRadius=0.0) body.physicsShape = scn.PhysicsShape(geometry=boxShape, options=None) trans = list(scn.Matrix4Identity) trans[13] = -min.y node.pivot = trans node.physicsBody = body scene.rootNode.addChildNode(node) return False trainScene = scn.Scene(url="resources/train_flat_PY.scn") #physicalize the train with simple boxes trainScene.rootNode.enumerateChildNodesUsingBlock(addTrainToSceneBlock) #add smoke self.smokeHandle = scene.rootNode.childNodeWithName("Smoke", recursively=True) self.smoke = scn.ParticleSystem() self.smoke.birthRate = 30 self.smoke.birthLocation = scn.ParticleBirthLocation.SCNParticleBirthLocationSurface self.smoke.loops = True self.smoke.emissionDuration = 1 self.smoke.emissionDurationVariation = 0 self.smoke.idleDuration = 0 self.smoke.idleDurationVariation = 0. self.smoke.emittingDirection = (0, 1, 0) self.smoke.spreadingAngle = 10 self.smoke.particleAngleVariation = 180 self.smoke.particleDiesOnCollision = False self.smoke.particleLifeSpan = 5. self.smoke.particleLifeSpanVariation = 0. self.smoke.particleVelocity = 6. self.smoke.particleVelocityVariation = 1 self.smoke.particleImage = ui.Image.named('resources/tex_smoke.png') self.smoke.particleSize = 3. self.smoke.particleSizeVariation = 0.5 self.smoke.particleIntensity = 1. self.smoke.particleIntensityVariation = 0. self.smoke.stretchFactor = 0.0 self.smoke.particleColor = (.41, .42, .48) self.smoke.blendMode = scn.ParticleBlendMode.SCNParticleBlendModeScreen self.smokeHandle.addParticleSystem(self.smoke) #add physics constraints between engine and wagons engineCar = scene.rootNode.childNodeWithName("EngineCar", recursively=False) wagon1 = scene.rootNode.childNodeWithName("Wagon1", recursively=False) wagon2 = scene.rootNode.childNodeWithName("Wagon2", recursively=False) min, max = engineCar.getBoundingBox() wmin, wmax = wagon1.getBoundingBox() #Tie EngineCar & Wagon1 joint = scn.PhysicsBallSocketJoint(bodyA=engineCar.physicsBody, anchorA=scn.Vector3(max.x, min.y, 0), bodyB=wagon1.physicsBody, anchorB=scn.Vector3(wmin.x, wmin.y, 0)) scene.physicsWorld.addBehavior(joint) #Wagon1 & Wagon2 joint = scn.PhysicsBallSocketJoint(bodyA=wagon1.physicsBody, anchorA=scn.Vector3(wmax.x + 0.1, wmin.y, 0), bodyB=wagon2.physicsBody, anchorB=scn.Vector3(wmin.x - 0.1, wmin.y, 0)) scene.physicsWorld.addBehavior(joint)
def setupSceneElements(self, scene): #add walls wall = scn.Node(geometry=scn.Box(width=400, height=100, length=4, chamferRadius=0)) wall.geometry.firstMaterial.diffuse.contents = "resources/wall.jpg" scale = list(scn.Matrix4Identity) scale[0], scale[5], scale[13], scale[10] = 24., 2., 1., 1. wall.geometry.firstMaterial.diffuse.contentsTransform = scale wall.geometry.firstMaterial.diffuse.wrapS = scn.WrapMode.Repeat wall.geometry.firstMaterial.diffuse.wrapT = scn.WrapMode.Mirror wall.geometry.firstMaterial.doubleSided = False wall.castsShadow = False wall.geometry.firstMaterial.locksAmbientWithDiffuse = False wall.position = scn.Vector3(0, 50, -92) wall.physicsBody = scn.PhysicsBody.staticBody() scene.rootNode.addChildNode(wall) wall = wall.clone() wall.position = scn.Vector3(-202, 50, 0) wall.rotation = scn.Vector4(0, 1, 0, M_PI_2) scene.rootNode.addChildNode(wall) wall = wall.clone() wall.position = scn.Vector3(202, 50, 0) wall.rotation = scn.Vector4(0, 1, 0, -M_PI_2) scene.rootNode.addChildNode(wall) backWall = scn.Node(geometry=scn.Plane(width=400, height=100)) backWall.geometry.firstMaterial = wall.geometry.firstMaterial backWall.position = scn.Vector3(0, 50, 200) backWall.rotation = scn.Vector4(0, 1, 0, M_PI) backWall.castsShadow = False backWall.physicsBody = scn.PhysicsBody.staticBody() scene.rootNode.addChildNode(backWall) #add ceil ceilNode = scn.Node(geometry=scn.Plane(width=400, height=400)) ceilNode.position = scn.Vector3(0, 100, 0) ceilNode.rotation = scn.Vector4(1, 0, 0, M_PI_2) ceilNode.geometry.firstMaterial.doubleSided = False ceilNode.castsShadow = False ceilNode.geometry.firstMaterial.locksAmbientWithDiffuse = False scene.rootNode.addChildNode(ceilNode) #add a train self.addTrainToScene(scene, pos=scn.Vector3(-5, 20, -40)) #add wooden blocks self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeA.jpg", position=scn.Vector3(-10, 15, 10)) self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeB.jpg", position=scn.Vector3(-9, 10, 10)) self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeC.jpg", position=scn.Vector3(20, 15, -11)) self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeA.jpg", position=scn.Vector3(25, 5, -20)) #add more block for _ in range(4): self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeA.jpg", position=scn.Vector3(random.randint(-30, 30), 20, random.randint(-20, 20))) self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeB.jpg", position=scn.Vector3(random.randint(-30, 30), 20, random.randint(-20, 20))) self.addWoodenBlockToScene(scene, imageName="resources/WoodCubeC.jpg", position=scn.Vector3(random.randint(-30, 30), 20, random.randint(-20, 20))) #add cartoon book block = scn.Node() block.position = scn.Vector3(20, 10, -16) block.rotation = scn.Vector4(0, 1, 0, -M_PI_4) block.geometry = scn.Box(width=22, height=2., length=34, chamferRadius=0) frontMat = scn.Material() frontMat.locksAmbientWithDiffuse = True frontMat.diffuse.contents = "resources/book_front.jpg" frontMat.diffuse.mipFilter = scn.FilterMode.Linear backMat = scn.Material() backMat.locksAmbientWithDiffuse = True backMat.diffuse.contents = "resources/book_back.jpg" backMat.diffuse.mipFilter = scn.FilterMode.Linear edgeMat = scn.Material() edgeMat.locksAmbientWithDiffuse = True edgeMat.diffuse.contents = "resources/book_side_title.jpg" edgeMat.diffuse.mipFilter = scn.FilterMode.Linear edgeMatSide = scn.Material() edgeMatSide.locksAmbientWithDiffuse = True edgeMatSide.diffuse.contents = "resources/book_side.jpg" edgeMatSide.diffuse.mipFilter = scn.FilterMode.Linear block.geometry.materials = [edgeMatSide, edgeMatSide, edgeMatSide, edgeMat, frontMat, backMat] block.physicsBody = scn.PhysicsBody.dynamicBody() scene.rootNode.addChildNode(block) #add carpet path = ui.Path.rounded_rect(-50, -30, 100, 50, 2.5) rug_geometry = scn.Shape.shapeWithPath(path, extrusionDepth=0.05) rug = scn.Node.nodeWithGeometry(rug_geometry) rug.geometry.firstMaterial.locksAmbientWithDiffuse = True rug.geometry.firstMaterial.diffuse.contents = "resources/carpet.jpg" rug.position = scn.Vector3(0, 0.01, 0) rug.rotation = scn.Vector4(1, 0, 0, M_PI_2) scene.rootNode.addChildNode(rug) #add ball ball = scn.Node() ball.position = scn.Vector3(-5, 5, -18) ball.geometry = scn.Sphere(radius=5) ball.geometry.firstMaterial.locksAmbientWithDiffuse = True ball.geometry.firstMaterial.diffuse.contents = "resources/ball.jpg" scale = list(scn.Matrix4Identity) scale[0], scale[5], scale[10] = 2., 1., 1. ball.geometry.firstMaterial.diffuse.contentsTransform = scale ball.geometry.firstMaterial.diffuse.wrapS = scn.WrapMode.Mirror ball.physicsBody = scn.PhysicsBody.dynamicBody() ball.physicsBody.restitution = 0.9 scene.rootNode.addChildNode(ball)
def demo(): main_view = ui.View() w, h = ui.get_screen_size() main_view.frame = (0, 0, w, h) main_view.name = 'Tetrahedron' scene_view = scn.View(main_view.frame, superView=main_view) scene_view.autoresizingMask = scn.ViewAutoresizing.FlexibleHeight | scn.ViewAutoresizing.FlexibleRightMargin scene_view.allowsCameraControl = True scene_view.scene = scn.Scene() root_node = scene_view.scene.rootNode camera_node = scn.Node() camera_node.camera = scn.Camera() camera_node.position = (0, 0, 5) root_node.addChildNode(camera_node) verts = [ scn.Vector3(0, 1, 0), scn.Vector3(-0.5, 0, 0.5), scn.Vector3(0.5, 0, 0.5), scn.Vector3(0.5, 0, -0.5), scn.Vector3(-0.5, 0, -0.5), scn.Vector3(0, -1, 0) ] source = scn.GeometrySource.geometrySourceWithVertices(verts) indexes = [ 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 2, 2, 3, 0, 3, 4, 0, 4, 1, 0, 1, 5, 2, 2, 5, 3, 3, 5, 4, 4, 5, 1 ] elements = scn.GeometryElement.geometryElementWithData( indexes, scn.GeometryPrimitiveType.Polygon) geometry = scn.Geometry.geometryWithSources(source, elements) material = scn.Material() material.contents = scn.RGBA(1, 0.9, 0.9, 1.0) geometry.materials = material geometry_node = scn.Node.nodeWithGeometry(geometry) root_node.addChildNode(geometry_node) elements2 = [] materials = [] colors = [ 'red', 'blue', 'green', 'yellow', 'orange', 'pink', 'cyan', 'orchid' ] for i in range(8): j = 8 + i * 3 indexes2 = [indexes[j], indexes[j + 1], indexes[j + 2]] element = scn.GeometryElement.geometryElementWithData( indexes2, scn.GeometryPrimitiveType.Triangles) elements2.append(element) material = scn.Material() material.contents = colors[i] materials.append(material) geometry2 = scn.Geometry.geometryWithSources(source, elements2) geometry2.materials = materials geometry2_node = scn.Node.nodeWithGeometry(geometry2) tx, ty, tz = (-1.5, 0, 0) translation = (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1) geometry2_node.pivot = translation root_node.addChildNode(geometry2_node) constraint = scn.LookAtConstraint.lookAtConstraintWithTarget(geometry_node) constraint.gimbalLockEnabled = True camera_node.constraints = constraint light_node = scn.Node() light_node.position = (100, 0, -10) light = scn.Light() light.type = scn.LightTypeDirectional light.castsShadow = True light.color = 'white' light_node.light = light root_node.addChildNode(light_node) rotate_action = scn.Action.repeatActionForever( scn.Action.rotateBy(0, math.pi * 2, 0, 10)) geometry_node.runAction(rotate_action) geometry2_node.runAction(rotate_action) main_view.present(hide_title_bar=False)