def __init__(self): self.flag = scn.Sphere(0.05) self.particleSystem = scn.ParticleSystem() self.particleSystem.loops = True self.particleSystem.birthRate = 550 self.particleSystem.emissionDuration = 2 self.particleSystem.particleLifeSpan = 0.18 self.particleSystem.particleLifeSpanVariation = 0.29 self.particleSystem.particleVelocity = 8 self.particleSystem.particleVelocityVariation = 15 self.particleSystem.particleSize = 0.04 self.particleSystem.particleSizeVariation = 0.03 self.particleSystem.stretchFactor = 0.02 self.particleSystemColorAnim = scn.CoreKeyframeAnimation() self.particleSystemColorAnim.values = [(.99, 1.0, .71, 0.8), (1.0, .52, .0, 0.8), (1., .0, .1, 1.), (.78, .0, .0, 0.3)] self.particleSystemColorAnim.keyTimes = (0., 0.1, 0.8, 1.) self.particleSystemProp_con = scn.ParticlePropertyController.controllerWithAnimation( self.particleSystemColorAnim) self.particleSystem.propertyControllers = { scn.SCNParticlePropertyColor: self.particleSystemProp_con } self.particleSystem.emitterShape = self.flag self.particleSystem.birthLocation = scn.ParticleBirthLocation.SCNParticleBirthLocationSurface self.particleSystem.birthDirection = scn.ParticleBirthDirection.Random
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 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 demo(): main_view = ui.View() w, h = ui.get_screen_size() main_view.frame = (0, 0, w, h) main_view.name = 'particles demo' scene_view = scn.View(main_view.frame, superView=main_view) scene_view.autoresizingMask = scn.ViewAutoresizing.FlexibleHeight | scn.ViewAutoresizing.FlexibleWidth scene_view.antialiasingMode = scn.AntialiasingMode.Multisampling16X scene_view.allowsCameraControl = True scene_view.backgroundColor = 'black' scene_view.scene = scn.Scene() root_node = scene_view.scene.rootNode text_mesh = scn.Text.textWithString('Pythonista', 6.0) text_mesh.flatness = 0.2 text_mesh.chamferRadius = 0.4 text_mesh.font = ('HelveticaNeue-Bold', 18) bbox_min, bbox_max = text_mesh.boundingBox text_width = bbox_max.x - bbox_min.x text_node = scn.Node.nodeWithGeometry(text_mesh) text_node.castsShadow = False text_container = scn.Node.node() text_container.addChildNode(text_node) text_container.position = (0, 40, 0) text_node.position = (-text_width / 2, 0, 0) fire = scn.ParticleSystem() fire.birthRate = 300000 fire.loops = True fire.emissionDuration = 8 fire.emissionDurationVariation = 4 fire.idleDuration = 2 fire.idleDurationVariation = 0.5 fire.emittingDirection = (0, 1, 0) fire.spreadingAngle = 15 fire.particleDiesOnCollision = False fire.particleLifeSpan = 0.4 fire.particleLifeSpanVariation = 0.5 fire.particleVelocity = 20 fire.particleVelocityVariation = 30 fire.particleImage = ui.Image.named('shp:WhitePuff05') fire.particleSize = 0.4 fire.particleSizeVariation = 0.2 fire.particleIntensity = 1.5 fire.particleIntensityVariation = 2 fire.stretchFactor = 0.02 colorAnim = scn.CoreKeyframeAnimation() colorAnim.values = [(.99, 1.0, .71, 0.8), (1.0, .52, .0, 0.8), (1., .0, .1, 1.), (.78, .0, .0, 0.3)] colorAnim.keyTimes = (0., 0.1, 0.8, 1.) fire.timingFunctions = [ scn.CoreMediaTimingFunction.functionWithName(aFunc) for aFunc in [ scn.MediaTimingFunctionEaseOut, scn.MediaTimingFunctionEaseInEaseOut, scn.MediaTimingFunctionEaseIn ] ] prop_con = scn.ParticlePropertyController.controllerWithAnimation( colorAnim) fire.propertyControllers = {scn.SCNParticlePropertyColor: prop_con} fire.emitterShape = text_mesh fire.birthLocation = scn.ParticleBirthLocation.SCNParticleBirthLocationSurface text_node.addParticleSystem(fire) root_node.addChildNode(text_container) light_node = scn.Node.node() light_node.position = (0, 105, 5) light_node.rotation = (1, 0, 0, -math.pi / 2) light = scn.Light.light() light.type = 'spot' light.spotOuterAngle = 90 light.castsShadow = True light.shadowSampleCount = 16 light.color = 'white' light_node.light = light root_node.addChildNode(light_node) main_view.present(hide_title_bar=False)
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)