def onLoop(self): # get elapsed time t = sdl2.SDL_GetTicks() self.deltaTime = t - self.frames[-1] if not self.paused: # create new particle system with SPACE key if self.spacePressed >= 0.0: self.spacePressed += self.deltaTime if self.spacePressed >= 1000.0: position = spk.Vector3D(spk.random(-2.0, 2.0), spk.random(-2.0, 2.0), spk.random(-2.0, 2.0)) self.explosions.append(self.explosion.clone(position)) self.spacePressed = 0.0 # calclate camera position and distances with each explosion # so draw in the order: far -> near cosX = math.cos(self.angleX * math.pi / 180.0) sinX = math.sin(self.angleX * math.pi / 180.0) cosY = math.cos(self.angleY * math.pi / 180.0) sinY = math.sin(self.angleY * math.pi / 180.0) cz = self.camPosZ campos = spk.Vector3D(-cosX * sinY * cz, sinX * cz, cosX * cosY * cz) def compareDist(explosion): return -spk.getSqrDist(explosion.system.getWorldTransformPos(), campos) self.explosions.sort(key=compareDist) explosions = [] for explosion in self.explosions: # update time of particle system alive = explosion.system.update(self.deltaTime * 0.001) if alive: explosions.append(explosion) else: pass # remove dead systems from self.systems self.explosions = explosions # rendering self.onRender() # time logging self.frames.append(t) while self.frames[-1] - self.frames[0] > 1000 and len(self.frames) > 2: self.frames.pop(0) # update text nbParticles = sum([s.system.getNbParticles() for s in self.explosions]) self.nbParticles = "NB PARTICLES : " + str(nbParticles) fps = ((len(self.frames) - 1) * 1000.0) // (self.frames[-1] - self.frames[0]) self.fps = "FPS : " + str(fps) if notext and t - self.lasttime >= 1000: # output informations to console print(self.fps, ',', self.nbParticles) self.lasttime = t
def onLoop(self): # get elapsed time t = sdl2.SDL_GetTicks() self.deltaTime = t - self.frames[-1] if not self.paused: # update emitters angle = self.totalTime * 2.0 * math.pi / 15000.0 sinA = math.sin(angle) cosA = math.cos(angle) sinB = math.sin(angle * 10.0) for i in range(5): self.emitters[i].setForce(1.8 + 1.8 * sinB, 2.1 + 2.1 * sinB) if self.highGraphics: self.emitters[i].setFlow((self.flow[i] * 0.5) + (self.flow[i] * 0.5) * sinB) else: self.emitters[i].setFlow((self.flowLow[i] * 0.5) + (self.flowLow[i] * 0.5) * sinB) self.emitters[1].setDirection( spk.Vector3D(cosA - sinA, 3.0, sinA + cosA)) self.emitters[2].setDirection( spk.Vector3D(-cosA + sinA, 3.0, -sinA - cosA)) self.emitters[3].setDirection( spk.Vector3D(-cosA - sinA, 3.0, -sinA + cosA)) self.emitters[4].setDirection( spk.Vector3D(cosA + sinA, 3.0, sinA - cosA)) # update time of particle system self.system.update(self.deltaTime * 0.001) # normalize 1.0 as 1[sec] self.totalTime += self.deltaTime # rendering self.onRender() # time logging self.frames.append(t) while self.frames[-1] - self.frames[0] > 1000 and len(self.frames) > 2: self.frames.pop(0) # update text self.nbParticles = "NB PARTICLES : " + str( self.system.getNbParticles()) fps = ((len(self.frames) - 1) * 1000.0) // (self.frames[-1] - self.frames[0]) self.fps = "FPS : " + str(fps) if notext and t - self.lasttime >= 1000: # output informations to console print(self.fps, ',', self.nbParticles, ',', self.getGraphicsString()) self.lasttime = t
def onLoop(self): # get elapsed time t = sdl2.SDL_GetTicks() self.deltaTime = t - self.frames[-1] if not self.paused: # if space is pressed, a new system is added if self.spacePressed >= 0.0: self.spacePressed += self.deltaTime if self.spacePressed >= 200.0: color = spk.Vector3D(spk.random(0.0, 360.0), 0.8, 1.0) position = spk.Vector3D(spk.random(-2.0, 2.0), spk.random(-2.0, 2.0), spk.random(-2.0, 2.0)) newsystem = self.basesystem.createSystem(position, self.convertHSV2RGB(color)) self.systems.append(newsystem) self.spacePressed = 0.0 systems = [] for system in self.systems: # Updates the particle systems if system.update(self.deltaTime * 0.001): # the system is alive systems.append(system) else: # If a system is sleeping, destroys it and removes from list spk.destroySystem(system) self.systems = systems # rendering self.onRender() # time logging self.frames.append(t) while self.frames[-1] - self.frames[0] > 1000 and len(self.frames) > 2: self.frames.pop(0) # update text nbParticles = sum([s.getNbParticles() for s in self.systems]) self.nbParticles = "NB PARTICLES : " + str(nbParticles) fps = ((len(self.frames)-1) * 1000.0) // (self.frames[-1] - self.frames[0]) self.fps = "FPS : " + str(fps) if notext and t - self.lasttime >= 1000: # output informations to console print(self.fps, ',', self.nbParticles) self.lasttime = t
def onLoop(self): # get elapsed time t = sdl2.SDL_GetTicks() self.deltaTime = t - self.frames[-1] if not self.paused: # update time of particle system self.system.update(self.deltaTime * 0.001) # normalize 1.0 as 1[sec] # update gravity direction cosX = math.cos(self.angleX * math.pi / 180.0) sinX = math.sin(self.angleX * math.pi / 180.0) cosZ = math.cos(self.angleZ * math.pi / 180.0) sinZ = math.sin(self.angleZ * math.pi / 180.0) gx = -0.5 * sinZ * cosX gy = -0.5 * cosZ * cosX gz = 0.5 * sinX self.group.setGravity(spk.Vector3D(gx, gy, gz)) if self.system.getNbParticles() == 0: self.group.addParticles(self.NB_PARTICLES[self.particleIndex], zone=self.obstacle.getZone(), velocity=spk.Vector3D()) self.group.flushAddedParticles() # rendering self.onRender() # time logging self.frames.append(t) while self.frames[-1] - self.frames[0] > 1000 and len(self.frames) > 2: self.frames.pop(0) # update text self.nbParticles = "NB PARTICLES : " + str( self.system.getNbParticles()) fps = ((len(self.frames) - 1) * 1000.0) // (self.frames[-1] - self.frames[0]) self.fps = "FPS : " + str(fps) if notext and t - self.lasttime >= 1000: # output informations to console print(self.fps, ',', self.nbParticles) self.lasttime = t
def killRain(self, particle, deltatime): if particle.position().y <= 0.0: particle.position().set(particle.position().x, 0.01, particle.position().z) self.splashGroup.addParticles(1, position=particle.position(), velocity=spk.Vector3D()) self.dropGroup.addParticles(self.param_i(2, 8), position=particle.position(), emitter=self.dropEmitter) return True return False
def convertHSV2RGB(self, hsv): """ Converts a HSV color to RGB h E [0,360] s E [0,1] v E [0,1] :type hsv: Vector3D :rtype: Vector3D """ h, s, v = hsv.x, hsv.y, hsv.z hi = (h // 60.0) % 6 f = h / 60.0 - hi p = v * (1.0 - s) q = v * (1.0 - f * s) t = v * (1.0 - (1.0 - f) * s) if hi == 0: return spk.Vector3D(v, t, p) elif hi == 1: return spk.Vector3D(q, v, p) elif hi == 2: return spk.Vector3D(p, v, t) elif hi == 3: return spk.Vector3D(p, q, v) elif hi == 4: return spk.Vector3D(t, p, v) else: return spk.Vector3D(v, p, q)
def __init__(self, screenheight, texture): # create Model model_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA model_mutable = spk.FLAG_ALPHA model_random = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE model = spk.Model.create(model_enable, model_mutable, model_random) model.setParam(spk.PARAM_ALPHA, 1.0, 0.0) # This makes the particles fade out over time model.setLifeTime(1.0, 2.0) # create Renderer renderer = GLPointRenderer.create() renderer.setType(spk.POINT_SPRITE) renderer.enableWorldSize(True) GLPointRenderer.setPixelPerUnit(45.0 * math.pi / 180.0, screenheight) renderer.setSize(0.1) renderer.setTexture(texture) renderer.enableBlending(True) renderer.setBlendingFunctions(gl.GL_SRC_ALPHA, gl.GL_ONE) # additive blending renderer.setTextureBlending(gl.GL_MODULATE) # the texture is modulated with the particle's color renderer.enableRenderingHint(spk.DEPTH_TEST, False) # the depth test is disabled self.renderer = renderer # create Zone source = spk.Point.create() # create Emitter emitter = spk.RandomEmitter.create() emitter.setForce(2.8, 3.2) emitter.setZone(source) emitter.setTank(500) emitter.setFlow(-1) # Creates all the particles in the tank at the first frame # create Group group = spk.Group.create(model, 500) # 500 particles is the maximum capacity of the group group.addEmitter(emitter) group.setGravity(spk.Vector3D(0.0, -1.0, 0.0)) group.setFriction(2.0) group.setRenderer(renderer) # create System system = spk.System.create() system.addGroup(group) self.system = system # Defines which objects will be shared by all systems model.setShared(True) renderer.setShared(True)
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Flakes Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.0, 0.0, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # random seed initialization spk.setRandomSeed(int(time.time())) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useAdaptiveStep( 0.001, 0.01) # use an adaptive step from 1ms to 10ms (1000fps to 100fps) # create Renderer renderer = GLPointRenderer.create(1.0) # type: GLPointRenderer renderer.setBlending( spk.BLENDING_ADD ) # blending method between particles(additive blending) renderer.enableRenderingHint(spk.DEPTH_TEST, False) # notifying not to use depth info renderer.setAlphaTestThreshold(0.8) self.renderer = renderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model model_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA # use color channels(RGBA) model = spk.Model.create(model_enable) # type: spk.Model model.setParam(spk.PARAM_RED, 1.0) model.setParam(spk.PARAM_GREEN, 0.8) model.setParam(spk.PARAM_BLUE, 0.3) model.setParam(spk.PARAM_ALPHA, 0.4) model.setImmortal(True) # particle is immortal self.model = model # no Emitter # create Modifier self.sphere = spk.Sphere.create(spk.Vector3D(), 1.0) obstacle = spk.Obstacle.create(self.sphere) # type: spk.Obstacle obstacle.setFriction(0.9) obstacle.setBouncingRatio(0.9) self.obstacle = obstacle # create Group self.NB_PARTICLES = [10000, 25000, 50000, 100000, 200000, 500000] group = spk.Group.create(model, self.NB_PARTICLES[-1]) # type: spk.Group group.addModifier(obstacle) group.setRenderer(renderer) group.setGravity(spk.Vector3D(0.0, -0.5, 0.0)) group.setFriction(0.2) self.group = group # create System system = spk.System.create() # type: spk.System system.addGroup(group) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.angleX = 0.0 self.angleZ = 0.0 self.camPosZ = 2.75 self.particleIndex = 2 self.nbParticles = '' self.fps = '' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def onEvent(self, event): # interaction # quit with ESC or close button if event.type == sdl2.SDL_QUIT: self.running = False elif event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_ESCAPE: self.running = False # reset with DEL if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_DELETE: self.system.empty() # text switching with F1 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F1: self.text = (self.text - 1) % 3 # on/off Bounding Box with F2 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F2: self.group.enableAABBComputing( not self.group.isAABBComputingEnabled()) if self.paused: self.system.computeAABB() # renderer switching with F4 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F4: renderers = [self.renderer, self.basicRenderer, None] self.renderValue = (self.renderValue + 1) % 3 self.group.setRenderer(renderers[self.renderValue]) # PAUSE if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_PAUSE: self.paused = not self.paused # +/- numbers of particles with if not self.paused: if event.type == sdl2.SDL_KEYDOWN and \ (event.key.keysym.sym == sdl2.SDLK_PLUS or event.key.keysym.sym == sdl2.SDLK_KP_PLUS): if self.particleIndex < len(self.NB_PARTICLES) - 1: self.particleIndex += 1 nb_current = self.NB_PARTICLES[self.particleIndex] nb_before = self.NB_PARTICLES[self.particleIndex - 1] # update the upper limit and supply the deficiency self.group.addParticles(nb_current - nb_before, zone=self.sphere, velocity=spk.Vector3D()) elif event.type == sdl2.SDL_KEYDOWN and \ (event.key.keysym.sym == sdl2.SDLK_MINUS or event.key.keysym.sym == sdl2.SDLK_KP_MINUS): if self.particleIndex > 0: self.particleIndex -= 1 nb_current = self.NB_PARTICLES[self.particleIndex] nb_before = self.NB_PARTICLES[self.particleIndex + 1] # remove the excess for i in range(0, nb_before - nb_current): self.group.getParticle(i).kill() # reset particle's speed with SPACE if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_SPACE: for i in range(self.group.getNbParticles()): velocity = self.group.getParticle( i).velocity() # velocity() returns internal reference velocity.x = spk.random(-0.5, 0.5) velocity.y = spk.random(-0.5, 0.5) velocity.z = spk.random(-0.5, 0.5) # Camera rotation with mouse if event.type == sdl2.SDL_MOUSEMOTION: sensitive = 0.4 self.angleZ += event.motion.xrel * sensitive self.angleX += event.motion.yrel * sensitive # Camera zooming with mouse wheel if event.type == sdl2.SDL_MOUSEWHEEL: if event.wheel.y < 0: self.camPosZ = min(10.0, self.camPosZ + 0.5) elif event.wheel.y > 0: self.camPosZ = max(0.5, self.camPosZ - 0.5)
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Collision Demo2", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.0, 0.0, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) # load Texture texture = loadTexture(b'res/ball.bmp', gl.GL_RGBA, gl.GL_CLAMP) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useAdaptiveStep( 0.001, 0.01) # use an adaptive step from 1ms to 10ms (1000fps to 100fps) # create Renderer renderer = GLPointRenderer.create(1.0) # type: GLPointRenderer renderer.setType( spk.POINT_SPRITE) # using Point Sprite(require >=OpenGL2.0) renderer.setTexture(texture) # use the texture on drawing renderer.enableWorldSize( True ) # true: unit is adjusted with the screen, false: unit is pixel(fixed) GLPointRenderer.setPixelPerUnit(45.0 * math.pi / 180.0, self.height) renderer.setSize(0.15) renderer.setBlending( spk.BLENDING_NONE ) # blending method between particles(no blending) renderer.enableRenderingHint(spk.ALPHA_TEST, True) renderer.setAlphaTestThreshold(0.8) self.renderer = renderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model model_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA # use color channels(RGBA) model = spk.Model.create(model_enable) # type: spk.Model model.setImmortal(True) # particle is immortal self.model = model # no Emitter # create Modifier self.sphere = spk.Sphere.create(spk.Vector3D(), 1.0 - 0.15 / 2.0) self.cube = spk.AABox.create(spk.Vector3D(), spk.Vector3D(1.2, 1.2, 1.2)) self.obstacle = spk.Obstacle.create(self.sphere, spk.EXIT_ZONE, 0.9, 0.9) # type: spk.Obstacle self.obstacle.setZone(self.sphere) collision = spk.Collision.create(0.15, 0.9) # create Group self.NB_PARTICLES = 250 group = spk.Group.create(model, self.NB_PARTICLES) # type: spk.Group group.addModifier(self.obstacle) group.addModifier(collision) group.setRenderer(renderer) group.setGravity(spk.Vector3D()) group.setFriction(0.1) self.group = group # create System system = spk.System.create() # type: spk.System system.addGroup(group) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.angleX = 0.0 self.angleZ = 0.0 self.camPosZ = 2.75 self.nbParticles = '' self.fps = '' self.strZone = 'ZONE: SPHERE' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Fire Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.0, 0.0, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) # load textures txFire = loadTexture(b'res/fire2.bmp', gl.GL_ALPHA, gl.GL_CLAMP, mipmap=True) txSmoke = loadTexture(b'res/explosion.bmp', gl.GL_ALPHA, gl.GL_CLAMP) # lighting light_ambient = [0.15, 0.15, 0.25, 1.0] light_diffuse = [1.0, 0.75, 0.25, 1.0] gl.glLightfv(gl.GL_LIGHT0, gl.GL_AMBIENT, light_ambient) gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE, light_diffuse) gl.glLightf(gl.GL_LIGHT0, gl.GL_QUADRATIC_ATTENUATION, 20.0) mat_ambient = [0.2, 0.2, 0.2, 1.0] mat_diffuse = [1.0, 1.0, 1.0, 1.0] gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, mat_ambient) gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, mat_diffuse) gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT, light_ambient) gl.glLightModelf(gl.GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init PyWavefront self.scene = pywavefront.Wavefront('./res/SceneFireCamp.obj') # init SPARK(pyspk) # random seed initialization spk.setRandomSeed(int(time.time())) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useAdaptiveStep( 0.001, 0.01) # use an adaptive step from 1ms to 10ms (1000fps to 100fps) # create Renderer fireRenderer = GLQuadRenderer.create() # type: GLQuadRenderer fireRenderer.setScale(0.3, 0.3) fireRenderer.setTexturingMode(spk.TEXTURE_2D) fireRenderer.setTexture(txFire) fireRenderer.setTextureBlending(gl.GL_MODULATE) fireRenderer.setBlending(spk.BLENDING_ADD) fireRenderer.enableRenderingHint(spk.DEPTH_WRITE, False) fireRenderer.setAtlasDimensions(2, 2) self.fireRenderer = fireRenderer smokeRenderer = GLQuadRenderer.create() # type: GLQuadRenderer smokeRenderer.setScale(0.3, 0.3) smokeRenderer.setTexturingMode(spk.TEXTURE_2D) smokeRenderer.setTexture(txSmoke) smokeRenderer.setTextureBlending(gl.GL_MODULATE) smokeRenderer.setBlending(spk.BLENDING_ALPHA) smokeRenderer.enableRenderingHint(spk.DEPTH_WRITE, False) smokeRenderer.setAtlasDimensions(2, 2) self.smokeRenderer = smokeRenderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model fire_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | \ spk.FLAG_SIZE | spk.FLAG_ANGLE | spk.FLAG_TEXTURE_INDEX fire_mutable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_ALPHA | spk.FLAG_ANGLE fire_random = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_TEXTURE_INDEX | spk.FLAG_ANGLE fire_interpolated = spk.FLAG_SIZE fireModel = spk.Model.create(fire_enable, fire_mutable, fire_random, fire_interpolated) # type: spk.Model fireModel.setParam(spk.PARAM_RED, 0.8, 0.9, 0.8, 0.9) # [min,max]on birth, [min,max]on death fireModel.setParam(spk.PARAM_GREEN, 0.5, 0.6, 0.5, 0.6) fireModel.setParam(spk.PARAM_BLUE, 0.3) fireModel.setParam(spk.PARAM_ALPHA, 0.4, 0.0) # on birth, on death minAngle, maxAngle = 0.0, 2.0 * math.pi fireModel.setParam(spk.PARAM_ANGLE, minAngle, maxAngle, minAngle, maxAngle) fireModel.setParam(spk.PARAM_TEXTURE_INDEX, 0.0, 4.0) fireModel.setLifeTime(1.0, 1.5) ip_size = fireModel.getInterpolator(spk.PARAM_SIZE) ip_size.addEntry(0.5, 2.0, 5.0) ip_size.addEntry(1.0, 0.0) self.fireModel = fireModel smoke_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | \ spk.FLAG_SIZE | spk.FLAG_ANGLE | spk.FLAG_TEXTURE_INDEX smoke_mutable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_SIZE | spk.FLAG_ANGLE smoke_random = spk.FLAG_TEXTURE_INDEX | spk.FLAG_ANGLE smoke_interpolated = spk.FLAG_ALPHA smokeModel = spk.Model.create(smoke_enable, smoke_mutable, smoke_random, smoke_interpolated) # type: spk.Model smokeModel.setParam(spk.PARAM_RED, 0.3, 0.2) smokeModel.setParam(spk.PARAM_GREEN, 0.25, 0.2) smokeModel.setParam(spk.PARAM_BLUE, 0.2) smokeModel.setParam(spk.PARAM_ALPHA, 0.2, 0.0) smokeModel.setParam(spk.PARAM_SIZE, 5.0, 10.0) smokeModel.setParam(spk.PARAM_TEXTURE_INDEX, 0.0, 4.0) smokeModel.setParam(spk.PARAM_ANGLE, 0.0, 2.0 * math.pi, 0.0, 2.0 * math.pi) smokeModel.setLifeTime(5.0, 5.0) ip_alpha = smokeModel.getInterpolator(spk.PARAM_ALPHA) ip_alpha.addEntry(0.0, 0.0) ip_alpha.addEntry(0.2, 0.2) ip_alpha.addEntry(1.0, 0.0) self.smokeModel = smokeModel # create Emitter fireEmitter1 = spk.StraightEmitter.create(spk.Vector3D(0.0, 1.0, 0.0)) fireEmitter1.setZone( spk.Sphere.create(spk.Vector3D(0.0, -1.0, 0.0), 0.5)) fireEmitter1.setFlow(40) fireEmitter1.setForce(1.0, 2.5) fireEmitter2 = spk.StraightEmitter.create(spk.Vector3D(1.0, 0.6, 0.0)) fireEmitter2.setZone( spk.Sphere.create(spk.Vector3D(0.15, -1.2, 0.075), 0.1)) fireEmitter2.setFlow(15) fireEmitter2.setForce(0.5, 1.5) fireEmitter3 = spk.StraightEmitter.create(spk.Vector3D( -0.6, 0.8, -0.8)) fireEmitter3.setZone( spk.Sphere.create(spk.Vector3D(-0.375, -1.15, -0.375), 0.3)) fireEmitter3.setFlow(15) fireEmitter3.setForce(0.5, 1.5) fireEmitter4 = spk.StraightEmitter.create(spk.Vector3D(-0.8, 0.5, 0.2)) fireEmitter4.setZone( spk.Sphere.create(spk.Vector3D(-0.255, -1.2, 0.225), 0.2)) fireEmitter4.setFlow(10) fireEmitter4.setForce(0.5, 1.5) fireEmitter5 = spk.StraightEmitter.create(spk.Vector3D(0.1, 0.8, -1.0)) fireEmitter5.setZone( spk.Sphere.create(spk.Vector3D(-0.075, -1.2, -0.3), 0.2)) fireEmitter5.setFlow(10) fireEmitter5.setForce(0.5, 1.5) smokeEmitter = spk.SphericEmitter.create(spk.Vector3D(0.0, 1.0, 0.0), 0.0, 0.5 * math.pi) smokeEmitter.setZone(spk.Sphere.create(spk.Vector3D(), 1.2)) smokeEmitter.setFlow(25) smokeEmitter.setForce(0.5, 1.0) # no Modifier # create Group fireGroup = spk.Group.create(fireModel, 135) # type: spk.Group fireGroup.addEmitter(fireEmitter1) fireGroup.addEmitter(fireEmitter2) fireGroup.addEmitter(fireEmitter3) fireGroup.addEmitter(fireEmitter4) fireGroup.addEmitter(fireEmitter5) fireGroup.setRenderer(fireRenderer) fireGroup.setGravity(spk.Vector3D(0.0, 3.0, 0.0)) self.fireGroup = fireGroup smokeGroup = spk.Group.create(smokeModel, 135) # type: spk.Group smokeGroup.addEmitter(smokeEmitter) smokeGroup.setRenderer(smokeRenderer) smokeGroup.setGravity(spk.Vector3D(0.0, 0.4, 0.0)) self.smokeGroup = smokeGroup # create System system = spk.System.create() # type: spk.System system.addGroup(fireGroup) system.addGroup(smokeGroup) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.renderEnv = True self.angleY = 30.0 self.angleX = 25.0 self.camPosZ = 12.0 self.smoke = True self.lightTime = 0 self.nbParticles = '' self.fps = '' self.strSmoke = 'SMOKE: ON' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def __init__(self, system=None, screenheight=0): if system: # copy self.system = system return assert (screenheight != 0) # # Texture # # create textures for OpenGL txExplosion = loadTexture(b'res/explosion.bmp', gl.GL_ALPHA, gl.GL_CLAMP) txFlash = loadTexture(b'res/flash.bmp', gl.GL_RGB, gl.GL_CLAMP) txSpark1 = loadTexture(b'res/spark1.bmp', gl.GL_RGB, gl.GL_CLAMP) txSpark2 = loadTexture(b'res/point.bmp', gl.GL_ALPHA, gl.GL_CLAMP) txWave = loadTexture(b'res/wave.bmp', gl.GL_RGBA, gl.GL_CLAMP) # # Renderer # # common setting function def commonSettings(renderer, texture, txblending, ptblending): renderer.setTexturingMode(spk.TEXTURE_2D) renderer.setTexture(texture) renderer.setTextureBlending(txblending) renderer.setBlending(ptblending) renderer.enableRenderingHint( spk.DEPTH_WRITE, False) # bacause I'll sort particles later renderer.setShared( True ) # means that this resource is reused between particle systems # create Smoke renderer smokeRenderer = GLQuadRenderer.create() # type: spk.GL.GLQuadRenderer commonSettings(smokeRenderer, txExplosion, gl.GL_MODULATE, spk.BLENDING_ALPHA) smokeRenderer.setAtlasDimensions(2, 2) # texture is divided by four(2x2) # create Flame renderer flameRenderer = GLQuadRenderer.create() commonSettings(flameRenderer, txExplosion, gl.GL_MODULATE, spk.BLENDING_ADD) flameRenderer.setAtlasDimensions(2, 2) # create Flash renderer flashRenderer = GLQuadRenderer.create() commonSettings(flashRenderer, txFlash, gl.GL_REPLACE, spk.BLENDING_ADD) # create Spark(line) renderer spark1Renderer = GLQuadRenderer.create() commonSettings(spark1Renderer, txSpark1, gl.GL_REPLACE, spk.BLENDING_ADD) spark1Renderer.setOrientation( spk.DIRECTION_ALIGNED) # consideration about direction spark1Renderer.setScale(0.05, 1.0) # narrow rectangle # create Spark(point) renderer GLPointRenderer.setPixelPerUnit(45.0 * math.pi / 180.0, screenheight) spark2Renderer = GLPointRenderer.create( ) # type: spk.GL.GLPointRenderer spark2Renderer.setType(spk.POINT_SPRITE) spark2Renderer.setTexture(txSpark2) spark2Renderer.setTextureBlending(gl.GL_MODULATE) spark2Renderer.setBlending(spk.BLENDING_ADD) spark2Renderer.enableRenderingHint(spk.DEPTH_WRITE, False) spark2Renderer.enableWorldSize(True) spark2Renderer.setSize(0.02) spark2Renderer.setShared(True) # create Wave renderer waveRenderer = GLQuadRenderer.create() # type: spk.GL.GLQuadRenderer commonSettings(waveRenderer, txWave, gl.GL_MODULATE, spk.BLENDING_ALPHA) # enable alpha-test to cut center area of texture image waveRenderer.enableRenderingHint(spk.ALPHA_TEST, True) waveRenderer.setAlphaTestThreshold(0.0) waveRenderer.setOrientation(spk.FIXED_ORIENTATION) # fix direction waveRenderer.lookVector.set(0.0, 1.0, 0.0) # emit along Y axis waveRenderer.upVector.set(1.0, 0.0, 0.0) # # Model # # create Smoke model smoke_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | \ spk.FLAG_SIZE | spk.FLAG_ANGLE | spk.FLAG_TEXTURE_INDEX # parameters to use smoke_mutable = spk.FLAG_SIZE | spk.FLAG_ANGLE # paramters to be changed smoke_random = spk.FLAG_SIZE | spk.FLAG_ANGLE | spk.FLAG_TEXTURE_INDEX # paramters to be changed randomly smoke_interpolated = spk.FLAG_ALPHA # paramters applying interpolation smokeModel = spk.Model.create(smoke_enable, smoke_mutable, smoke_random, smoke_interpolated) # type: spk.Model smokeModel.setParam(spk.PARAM_RED, 0.2) # set color(RGB) smokeModel.setParam(spk.PARAM_GREEN, 0.2) smokeModel.setParam(spk.PARAM_BLUE, 0.2) smokeModel.setParam(spk.PARAM_SIZE, 0.6, 0.8, 1.0, 1.4) # [min,max]on birth, [min,max]on death smokeModel.setParam(spk.PARAM_TEXTURE_INDEX, 0.0, 4.0) # select a texture from divided by four smokeModel.setParam(spk.PARAM_ANGLE, 0.0, math.pi * 0.5, 0.0, math.pi * 0.5) # azimuth angle smokeModel.setLifeTime(2.5, 3.0) smokeModel.setShared(True) # interpolator is a utility to make parameter curve # if you provide (x1, y1),(x2, y2) ... (xn, yn) paramters (n>=2), # interpolator fills the intermediate. # x is the timeline. By default(spk.INTERPOLATOR_LIFETIME), domain of x is [0,1]. ip_alpha = smokeModel.getInterpolator( spk.PARAM_ALPHA) # type: spk.Interpolator ip_alpha.addEntry(0.0, 0.0) # (x1,y1) ip_alpha.addEntry( 0.4, 0.4, 0.6 ) # (x2, y2min, y2max) y is randomly selected from [y2min,y2max] ip_alpha.addEntry(0.6, 0.4, 0.6) # (x3, y3min, y3max) ip_alpha.addEntry(1.0, 0.0) # (x4, y4) # create Flame model flame_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | \ spk.FLAG_SIZE | spk.FLAG_ANGLE | spk.FLAG_TEXTURE_INDEX flame_mutable = spk.FLAG_ANGLE | spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE flame_random = spk.FLAG_ANGLE | spk.FLAG_TEXTURE_INDEX flame_interpolated = spk.FLAG_SIZE | spk.FLAG_ALPHA flameModel = spk.Model.create(flame_enable, flame_mutable, flame_random, flame_interpolated) flameModel.setParam(spk.PARAM_RED, 1.0, 0.2) flameModel.setParam(spk.PARAM_GREEN, 0.5, 0.2) flameModel.setParam(spk.PARAM_BLUE, 0.2, 0.2) flameModel.setParam(spk.PARAM_TEXTURE_INDEX, 0.0, 4.0) flameModel.setParam(spk.PARAM_ANGLE, 0.0, math.pi * 0.5, 0.0, math.pi * 0.5) flameModel.setLifeTime(1.5, 2.0) flameModel.setShared(True) ip_size = flameModel.getInterpolator(spk.PARAM_SIZE) ip_size.addEntry(0.0, 0.25) ip_size.addEntry(0.02, 0.6, 0.8) ip_size.addEntry(1.0, 1.0, 1.4) ip_alpha = flameModel.getInterpolator(spk.PARAM_ALPHA) ip_alpha.addEntry(0.5, 1.0) ip_alpha.addEntry(1.0, 0.0) # create Flash model flash_enable = spk.FLAG_ALPHA | spk.FLAG_SIZE | spk.FLAG_ANGLE flash_mutable = spk.FLAG_NONE flash_random = spk.FLAG_ANGLE flash_interpolated = spk.FLAG_ALPHA | spk.FLAG_SIZE flashModel = spk.Model.create(flash_enable, flash_mutable, flash_random, flash_interpolated) flashModel.setParam(spk.PARAM_ANGLE, 0.0, 2.0 * math.pi) flashModel.setLifeTime(0.5, 0.5) flashModel.setShared(True) ip_size = flashModel.getInterpolator(spk.PARAM_SIZE) ip_size.addEntry(0.0, 0.25) ip_size.addEntry(0.1, 1.0, 2.0) ip_alpha = flashModel.getInterpolator(spk.PARAM_ALPHA) ip_alpha.addEntry(0.0, 1.0) ip_alpha.addEntry(0.4, 0.0) # create Spark(line) model spark1Model = spk.Model.create(spk.FLAG_SIZE | spk.FLAG_ALPHA, spk.FLAG_ALPHA, spk.FLAG_SIZE) spark1Model.setParam(spk.PARAM_ALPHA, 1.0, 0.0) spark1Model.setParam(spk.PARAM_SIZE, 0.2, 0.4) spark1Model.setLifeTime(0.2, 1.0) spark1Model.setShared(True) # create Spark(point) model spark2Model = spk.Model.create( spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA, spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA, spk.FLAG_GREEN) spark2Model.setParam(spk.PARAM_ALPHA, 1.0, 0.0) spark2Model.setParam(spk.PARAM_RED, 1.0) spark2Model.setParam(spk.PARAM_GREEN, 1.0, 1.0, 0.3, 1.0) spark2Model.setParam(spk.PARAM_BLUE, 0.7, 0.3) spark2Model.setLifeTime(1.0, 3.0) spark2Model.setShared(True) # create Wave model waveModel = spk.Model.create(spk.FLAG_ALPHA | spk.FLAG_SIZE, spk.FLAG_SIZE | spk.FLAG_ALPHA) waveModel.setParam(spk.PARAM_SIZE, 0.0, 4.0) waveModel.setParam(spk.PARAM_ALPHA, 0.2, 0.0) waveModel.setLifeTime(0.8, 0.8) waveModel.setShared(True) # # Emitter # zero = spk.Vector3D() # center of explosion smokeSphere = spk.Sphere.create(zero, 0.6) # the range of smoke particles explosionSphere = spk.Sphere.create( zero, 0.4) # the range of flame,spark,wave particles flashSphere = spk.Sphere.create(zero, 0.1) # the range of flash particles # create Smoke emitter smokeEmitter = spk.RandomEmitter.create() smokeEmitter.setZone(smokeSphere, False) smokeEmitter.setFlow(-1) # infinite [particles/frame] smokeEmitter.setTank(15) # upper limit of particle creation smokeEmitter.setForce(0.02, 0.04) # create Flame emitter flameEmitter = spk.NormalEmitter.create() flameEmitter.setZone(explosionSphere) flameEmitter.setFlow(-1) flameEmitter.setTank(15) flameEmitter.setForce(0.06, 0.1) # create Flas emitter flashEmitter = spk.StaticEmitter.create() flashEmitter.setZone(flashSphere) flashEmitter.setFlow(-1) flashEmitter.setTank(3) # create Spark(line) emitter spark1Emitter = spk.NormalEmitter.create() spark1Emitter.setZone(explosionSphere) spark1Emitter.setFlow(-1) spark1Emitter.setTank(20) spark1Emitter.setForce(2.0, 3.0) # create Spark(point) emitter spark2Emitter = spk.NormalEmitter.create() spark2Emitter.setZone(explosionSphere) spark2Emitter.setFlow(-1) spark2Emitter.setTank(400) spark2Emitter.setForce(0.4, 0.8) # create Wave emitter waveEmitter = spk.StaticEmitter.create() waveEmitter.setZone(spk.Point.create(zero)) waveEmitter.setFlow(-1) waveEmitter.setTank(1) # no Modifier # # Group # # create Smoke group smokeGroup = spk.Group.create(smokeModel, 15) smokeGroup.addEmitter(smokeEmitter) smokeGroup.setRenderer(smokeRenderer) smokeGroup.setGravity(spk.Vector3D(0.0, 0.05, 0.0)) # create Flame group flameGroup = spk.Group.create(flameModel, 15) flameGroup.addEmitter(flameEmitter) flameGroup.setRenderer(flameRenderer) # create Flash group flashGroup = spk.Group.create(flashModel, 3) flashGroup.addEmitter(flashEmitter) flashGroup.setRenderer(flashRenderer) # create Spark(line) group spark1Group = spk.Group.create(spark1Model, 20) spark1Group.addEmitter(spark1Emitter) spark1Group.setRenderer(spark1Renderer) spark1Group.setGravity(spk.Vector3D(0.0, -1.5, 0.0)) # create Spark(point) group spark2Group = spk.Group.create(spark2Model, 400) spark2Group.addEmitter(spark2Emitter) spark2Group.setRenderer(spark2Renderer) spark2Group.setGravity(spk.Vector3D(0.0, -0.3, 0.0)) spark2Group.setFriction(0.4) # create Wave group waveGroup = spk.Group.create(waveModel, 1) waveGroup.addEmitter(waveEmitter) waveGroup.setRenderer(waveRenderer) # # System # system = spk.System.create() system.addGroup(waveGroup) system.addGroup(smokeGroup) system.addGroup(flameGroup) system.addGroup(flashGroup) system.addGroup(spark1Group) system.addGroup(spark2Group) self.system = system
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Collision Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.0, 0.0, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) # load Texture txParticle = loadTexture(b'res/ball2.bmp', gl.GL_RGBA, gl.GL_CLAMP) self.txCrate = loadTexture(b'res/crate.bmp', gl.GL_RGB, gl.GL_REPEAT) self.txFloor = loadTexture(b'res/floor.bmp', gl.GL_RGB, gl.GL_REPEAT) self.txWall = loadTexture(b'res/wall.bmp', gl.GL_RGB, gl.GL_REPEAT) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # create Renderer spk.setRandomSeed(int(time.time())) renderer = GLPointRenderer.create(1.0) # type: GLPointRenderer renderer.setType( spk.POINT_SPRITE) # using Point Sprite(require >=OpenGL2.0) renderer.setTexture(txParticle) # use the texture on drawing renderer.enableWorldSize( True ) # true: unit is adjusted with the screen, false: unit is pixel(fixed) GLPointRenderer.setPixelPerUnit(45.0 * math.pi / 180.0, self.height) renderer.setSize(0.05) renderer.setBlending( spk.BLENDING_NONE ) # blending method between particles(no blending) renderer.enableRenderingHint(spk.ALPHA_TEST, True) # notifying not to use depth info renderer.setAlphaTestThreshold(0.8) self.renderer = renderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model model_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE # use color channels(RGB) model = spk.Model.create(model_enable) # type: spk.Model model.setLifeTime(10.0, 10.0) # particle's life time is 10[sec] self.model = model # create Emitter emit_dir = spk.Vector3D(0.0, 0.0, -1.0) emit_center = spk.Vector3D(0.0, 2.0, 4.475) minangle = 0.0 * math.pi # zenith angle(min) maxangle = 0.5 * math.pi # zenith angle(max) emitter = spk.SphericEmitter.create( emit_dir, minangle, maxangle) # type: spk.SphericEmitter emitter.setZone( spk.Point.create(emit_center), True) # particles are randomly placed in the specified zone emitter.setFlow(300) # max number of particles emitter.setForce(1.5, 2.5) # emittion power # create Group maxparticle = 3100 # upper limit number of particles group = spk.Group.create(model, maxparticle) # type: spk.Group group.addEmitter(emitter) group.setRenderer(renderer) group.setCustomBirth(self.assignColor) group.setGravity(spk.Vector3D(0.0, -0.8, 0.0)) group.setFriction(0.2) self.group = group # create Room objects self.ROOM_X = 7.0 self.ROOM_Y = 3.0 self.ROOM_Z = 9.0 self.boxes = [] self.partitions = [] self.initRoom(group) # obstacles self.createDisplayLists() # display list for OpenGL drawing # create System system = spk.System.create() # type: spk.System system.addGroup(group) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.enableBoxDrawing = False self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.renderEnv = True self.angleY = 90.0 self.angleX = 45.0 self.camPosZ = 10.0 self.nbParticles = '' self.fps = '' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def initRoom(self, parent): # creating room objects and register it to system # structure tree of the room is below: # root # +-partition1(7) # | +-partition0(6) # | | +-box1(1) # | | +-box2(2) # | | +-box3(3) # | | +-box4(4) # | +-box5(5) # +-room(0) CRATE_DIM2 = 1.0 CRATE_DIM = CRATE_DIM2 * 0.5 obstacles = [] # room box = spk.AABox.create() # type: spk.AABox box.setPosition(spk.Vector3D(0.0, self.ROOM_Y * 0.5, 0.0)) box.setDimension( spk.Vector3D(self.ROOM_X - 0.05, self.ROOM_Y - 0.05, self.ROOM_Z - 0.05)) self.boxes.append(box) obstacle = spk.Obstacle.create() # type: spk.Obstacle obstacle.setZone(box) obstacle.setBouncingRatio(0.8) obstacle.setFriction(0.95) obstacles.append(obstacle) # crates centers = [] centers.append(spk.Vector3D(0.0, CRATE_DIM, 0.0)) centers.append(spk.Vector3D(CRATE_DIM2, CRATE_DIM, 0.2)) centers.append(spk.Vector3D(CRATE_DIM2, CRATE_DIM, 0.2 + CRATE_DIM2)) centers.append(spk.Vector3D(CRATE_DIM2, CRATE_DIM2 + CRATE_DIM, 0.5)) centers.append(spk.Vector3D(-1.6, CRATE_DIM, -0.8)) self.crate_positions = centers for pos in centers: box = spk.AABox.create() # type: spk.AABox box.setPosition(pos) box.setDimension( spk.Vector3D(CRATE_DIM2 + 0.05, CRATE_DIM2 + 0.05, CRATE_DIM2 + 0.05)) self.boxes.append(box) obstacle = spk.Obstacle.create() # type: spk.Obstacle obstacle.setZone(box) obstacle.setBouncingRatio(0.8) obstacle.setFriction(0.95) obstacles.append(obstacle) # partitioning(grouping) # 1. calculate min&max along each axis) vMin0 = spk.Vector3D(10000, 10000, 10000) # box1-4(nb:4) vMax0 = spk.Vector3D(-10000, -10000, -10000) vMin1 = spk.Vector3D(10000, 10000, 10000) # box1-5(nb:5) vMax1 = spk.Vector3D(-10000, -10000, -10000) # 1.1. calc vMin0 & vMax0 for pos in centers[:-1]: # exclude last box vMin0.x = min(vMin0.x, pos.x) vMin0.y = min(vMin0.y, pos.y) vMin0.z = min(vMin0.z, pos.z) vMax0.x = max(vMax0.x, pos.x) vMax0.y = max(vMax0.y, pos.y) vMax0.z = max(vMax0.z, pos.z) # 1.2 calc vMin1 & vMax1 lastboxpos = centers[-1] vMin1.x = min(vMin0.x, lastboxpos.x) vMin1.y = min(vMin0.y, lastboxpos.y) vMin1.z = min(vMin0.z, lastboxpos.z) vMax1.x = max(vMax0.x, lastboxpos.x) vMax1.y = max(vMax0.y, lastboxpos.y) vMax1.z = max(vMax0.z, lastboxpos.z) # 2. register {box1-4} as partition0 box0 = spk.AABox.create() # type: spk.AABox box0.setPosition((vMin0 + vMax0) / 2.0) box0.setDimension(vMax0 - vMin0 + CRATE_DIM2 + 0.05) self.partitions.append(box0) partition0 = spk.ModifierGroup.create( box0, spk.INSIDE_ZONE) # type: spk.ModifierGroup partition0.addModifier(obstacles[1]) partition0.addModifier(obstacles[2]) partition0.addModifier(obstacles[3]) partition0.addModifier(obstacles[4]) # 3. register {box1-5} as partition1 box1 = spk.AABox.create() # type: spk.AABox box1.setPosition((vMin1 + vMax1) / 2.0) box1.setDimension(vMax1 - vMin1 + CRATE_DIM2 + 0.05) self.partitions.append(box1) partition1 = spk.ModifierGroup.create( box1, spk.INSIDE_ZONE) # type: spk.ModifierGroup partition1.addModifier(partition0) partition1.addModifier(obstacles[5]) # 4. register all to root parent.addModifier(obstacles[0]) parent.addModifier(partition1)
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Basic Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.0, 0.0, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) # load Texture texture = loadTexture(b'res/point.bmp', gl.GL_ALPHA, gl.GL_CLAMP) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useAdaptiveStep( 0.001, 0.01) # use an adaptive step from 1ms to 10ms (1000fps to 100fps) # create Renderer renderer = GLPointRenderer.create(1.0) # type: GLPointRenderer renderer.setType( spk.POINT_SPRITE) # using Point Sprite(require >=OpenGL2.0) renderer.setTexture(texture) # use the texture on drawing renderer.setTextureBlending(gl.GL_MODULATE) renderer.enableWorldSize( True ) # true: unit is adjusted with the screen, false: unit is pixel(fixed) GLPointRenderer.setPixelPerUnit(45.0 * math.pi / 180.0, self.height) renderer.setSize(0.05) renderer.setBlending( spk.BLENDING_ADD ) # blending method between particles(additive blending) renderer.enableRenderingHint(spk.DEPTH_WRITE, False) # notifying not to use depth info self.renderer = renderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model model_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA # use color channels(RGBA) model = spk.Model.create(model_enable) # type: spk.Model model.setParam(spk.PARAM_ALPHA, 1.0) # alpha is fixed(RGB are changed later) model.setLifeTime(8.0, 8.0) # particle's life time is 8.0[sec] self.model = model # create Emitter emit_dir = spk.Vector3D(0.0, 1.0, 0.0) emit_center = spk.Vector3D(0.0, 0.015, 0.0) minangle = 0.1 * math.pi # zenith angle(min) maxangle = 0.1 * math.pi # zenith angle(max) emitter = spk.SphericEmitter.create( emit_dir, minangle, maxangle) # type: spk.SphericEmitter emitter.setZone( spk.Point.create(emit_center), True) # particles are randomly placed in the specified zone emitter.setFlow(1000) # max number of particles emitter.setForce(1.5, 1.5) # emittion power # create Modifier groundplane = spk.Plane.create() bouncing = 0.6 # bouncing ratio(coefficient of restitution) friction = 1.0 # coefficient of friction obstacle = spk.Obstacle.create(groundplane, spk.INTERSECT_ZONE, bouncing, friction) # create Group maxparticle = 5000 # upper limit number of particles group = spk.Group.create(model, maxparticle) # type: spk.Group group.addEmitter(emitter) group.addModifier(obstacle) group.setRenderer(renderer) group.setGravity(spk.Vector3D(0.0, -0.8, 0.0)) self.group = group # create System system = spk.System.create() # type: spk.System system.addGroup(group) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.angleY = 0.0 self.angleX = 45.0 self.camPosZ = 5.0 self.nbParticles = '' self.fps = '' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Galaxy Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.0, 0.0, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) gl.glEnable(gl.GL_DEPTH_TEST) # load Textures texture = loadTexture(b'res/flare.bmp', gl.GL_ALPHA, gl.GL_CLAMP) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useRealStep() # no adjustment # create Renderer renderer = GLQuadRenderer.create() # type: GLQuadRenderer renderer.setTexturingMode(spk.TEXTURE_2D) renderer.setTexture(texture) renderer.setTextureBlending(gl.GL_MODULATE) renderer.setScale(0.05, 0.05) renderer.setBlending(spk.BLENDING_ADD) renderer.enableRenderingHint(spk.DEPTH_WRITE, False) self.renderer = renderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model galaxy_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | spk.FLAG_SIZE galaxy_mutable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE galaxy_random = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_SIZE galaxy_interpolated = spk.FLAG_ALPHA galaxyModel = spk.Model.create(galaxy_enable, galaxy_mutable, galaxy_random, galaxy_interpolated) # type: spk.Model galaxyModel.setParam(spk.PARAM_RED, 0.0, 0.3, 0.5, 0.5) galaxyModel.setParam(spk.PARAM_GREEN, 0.0, 0.3, 0.5, 0.5) galaxyModel.setParam(spk.PARAM_BLUE, 1.0, 0.1) galaxyModel.setParam(spk.PARAM_SIZE, 0.1, 5.0) galaxyModel.setLifeTime(35.0, 40.0) ip_alpha = galaxyModel.getInterpolator(spk.PARAM_ALPHA) ip_alpha.addEntry(0.0, 0.0) ip_alpha.addEntry(0.95, 0.6, 1.0) ip_alpha.addEntry(1.0, 0.0) star_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | spk.FLAG_SIZE star_mutable = spk.FLAG_NONE star_random = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_ALPHA | spk.FLAG_SIZE starModel = spk.Model.create(star_enable, star_mutable, star_random) # type: spk.Model starModel.setParam(spk.PARAM_RED, 0.8, 1.0) starModel.setParam(spk.PARAM_GREEN, 0.4, 1.0) starModel.setParam(spk.PARAM_BLUE, 0.8, 1.0) starModel.setParam(spk.PARAM_ALPHA, 0.2, 1.0) starModel.setParam(spk.PARAM_SIZE, 0.1, 5.0) starModel.setImmortal(True) # create Emitter # 2 emitters in diagonal lines on Y=0 plane lineEmitter1 = spk.RandomEmitter.create() # type: spk.RandomEmitter lineEmitter1.setZone( spk.Line.create(spk.Vector3D(-2.5, 0.0, -2.5), spk.Vector3D(2.5, 0.0, 2.5))) lineEmitter1.setFlow(100) lineEmitter1.setForce(0.0, 0.01) lineEmitter2 = spk.RandomEmitter.create() lineEmitter2.setZone( spk.Line.create(spk.Vector3D(-2.5, 0.0, 2.5), spk.Vector3D(2.5, 0.0, -2.5))) lineEmitter2.setFlow(100) lineEmitter2.setForce(0.0, 0.01) # create Modifier vortex = spk.Vortex.create() # type: spk.Vortex vortex.setRotationSpeed(0.4, False) # True->[rad/sec], False->[unit/src] vortex.setAttractionSpeed(0.04, True) vortex.setEyeRadius(0.05) vortex.enableParticleKilling(True) # kill attracted particles # create Group galaxyGroup = spk.Group.create(galaxyModel, 8000) # type: spk.Group galaxyGroup.addEmitter(lineEmitter1) galaxyGroup.addEmitter(lineEmitter2) galaxyGroup.setRenderer(renderer) galaxyGroup.addModifier(vortex) self.galaxyGroup = galaxyGroup starGroup = spk.Group.create(starModel, 1000) starGroup.setRenderer(renderer) skySphere = spk.Sphere(spk.Vector3D(), 16.0) starGroup.addParticles(1000, zone=skySphere, velocity=spk.Vector3D(), full=False) starGroup.flushAddedParticles() # create System galaxySystem = spk.System.create() # type: spk.System galaxySystem.addGroup(galaxyGroup) self.galaxySystem = galaxySystem starSystem = spk.System.create() starSystem.addGroup(starGroup) self.starSystem = starSystem print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.renderEnv = True self.angleY = 0.0 self.angleX = 45.0 self.camPosZ = 5.0 self.nbParticles = '' self.fps = '' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def onEvent(self, event): # interaction # quit with ESC or close button if event.type == sdl2.SDL_QUIT: self.running = False elif event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_ESCAPE: self.running = False # reset with DEL if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_DELETE: self.galaxySystem.empty() # text switching with F1 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F1: self.text = (self.text - 1) % 3 # on/off Bounding Box with F2 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F2: self.galaxyGroup.enableAABBComputing( not self.galaxyGroup.isAABBComputingEnabled()) if self.paused: self.galaxySystem.computeAABB() # renderer switching with F4 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F4: rainRenderers = [self.rainRenderer, self.basicRenderer, None] dropRenderers = [self.dropRenderer, self.basicRenderer, None] splashRenderers = [self.splashRenderer, self.basicRenderer, None] self.renderValue = (self.renderValue + 1) % 3 self.rainGroup.setRenderer(rainRenderers[self.renderValue]) self.dropGroup.setRenderer(dropRenderers[self.renderValue]) self.splashGroup.setRenderer(splashRenderers[self.renderValue]) # on/off fog with F5 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F5: self.renderEnv = not self.renderEnv if self.renderEnv: color = self.param_f(0.8, 0.2) gl.glClearColor(color, color, color, 1.0) gl.glEnable(gl.GL_FOG) else: gl.glClearColor(0.0, 0.0, 0.0, 1.0) gl.glDisable(gl.GL_FOG) # PAUSE if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_PAUSE: self.paused = not self.paused # Camera rotation with mouse if event.type == sdl2.SDL_MOUSEMOTION: sensitive = 0.4 self.angleY += event.motion.xrel * sensitive self.angleX += event.motion.yrel * sensitive self.angleX = min(90.0, max(-90.0, self.angleX)) if event.type == sdl2.SDL_KEYDOWN: key = event.key.keysym.sym if key == sdl2.SDLK_PLUS or key == sdl2.SDLK_KP_PLUS: self.rainRatio += 0.01 self.rainRatio = min(1.0, self.rainRatio) self.recompute = True elif key == sdl2.SDLK_MINUS or key == sdl2.SDLK_KP_MINUS: self.rainRatio -= 0.01 self.rainRatio = max(0.0, self.rainRatio) self.recompute = True move = False moveRate = 0.01 if key == sdl2.SDLK_UP or key == sdl2.SDLK_w: self.posX += moveRate * self.deltaTime * math.sin( self.angleY * math.pi / 180.0) self.posZ += -moveRate * self.deltaTime * math.cos( self.angleY * math.pi / 180.0) move = True if key == sdl2.SDLK_DOWN or key == sdl2.SDLK_s: self.posX += -moveRate * self.deltaTime * math.sin( self.angleY * math.pi / 180.0) self.posZ += moveRate * self.deltaTime * math.cos( self.angleY * math.pi / 180.0) move = True if key == sdl2.SDLK_LEFT or key == sdl2.SDLK_a: self.posX += -moveRate * self.deltaTime * math.sin( self.angleY * math.pi / 180.0) self.posZ += -moveRate * self.deltaTime * math.cos( self.angleY * math.pi / 180.0) move = True if key == sdl2.SDLK_RIGHT or key == sdl2.SDLK_d: self.posX += moveRate * self.deltaTime * math.sin( self.angleY * math.pi / 180.0) self.posZ += moveRate * self.deltaTime * math.cos( self.angleY * math.pi / 180.0) move = True if move: self.rainZone.setPosition( spk.Vector3D(self.posX, 5.0, self.posZ))
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Fountain Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) gl.glClearColor(0.0, 0.68, 0.85, 1.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) # init fog gl.glEnable(gl.GL_FOG) gl.glFogi(gl.GL_FOG_MODE, gl.GL_EXP2) gl.glFogfv(gl.GL_FOG_COLOR, [0.0, 0.68, 0.85, 1.0]) gl.glFogf(gl.GL_FOG_DENSITY, 0.04) gl.glHint(gl.GL_PERSPECTIVE_CORRECTION_HINT, gl.GL_NICEST) # load Textures self.txGrass = loadTexture(b'res/grass.bmp', gl.GL_RGB, gl.GL_REPEAT, mipmap=True) self.txFountain = loadTexture(b'res/tile.bmp', gl.GL_RGB, gl.GL_REPEAT, mipmap=True) self.txWater = loadTexture(b'res/water.bmp', gl.GL_RGB, gl.GL_REPEAT, mipmap=True) txSplash = loadTexture(b'res/waterdrops.bmp', gl.GL_ALPHA, gl.GL_CLAMP) # create display lists self.createDisplayLists() # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # random seed initialization spk.setRandomSeed(int(time.time())) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useAdaptiveStep( 0.001, 0.01) # use an adaptive step from 1ms to 10ms (1000fps to 100fps) # create Renderer renderer = GLQuadRenderer.create(1.0) # type: GLQuadRenderer renderer.setScale(0.06, 0.06) renderer.setTexturingMode(spk.TEXTURE_2D) renderer.setTexture(txSplash) renderer.setBlending(spk.BLENDING_ALPHA) renderer.enableRenderingHint(spk.DEPTH_WRITE, False) self.renderer = renderer self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) # create Model model_enable = spk.FLAG_ALPHA | spk.FLAG_SIZE | spk.FLAG_ANGLE model_mutable = spk.FLAG_ALPHA | spk.FLAG_SIZE | spk.FLAG_ANGLE model_random = spk.FLAG_SIZE | spk.FLAG_ANGLE model = spk.Model.create(model_enable, model_mutable, model_random) # type: spk.Model model.setParam(spk.PARAM_ALPHA, 0.2, 0.0) model.setParam(spk.PARAM_SIZE, 1.0, 1.0, 2.0, 8.0) model.setParam(spk.PARAM_ANGLE, 0.0, 4.0 * math.pi, 0.0, 4.0 * math.pi) model.setLifeTime(1.6, 2.2) self.model = model # create Emitter self.emitterZones = [] self.emitters = [] # splash to just above(x1) self.emitterZones.append(spk.Point.create(spk.Vector3D(0.0, 0.1, 0.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(0.0, 1.0, 0.0))) # splash from center of fountain(x4) self.emitterZones.append(spk.Point.create(spk.Vector3D(0.0, 0.1, 0.0))) self.emitterZones.append(spk.Point.create(spk.Vector3D(0.0, 0.1, 0.0))) self.emitterZones.append(spk.Point.create(spk.Vector3D(0.0, 0.1, 0.0))) self.emitterZones.append(spk.Point.create(spk.Vector3D(0.0, 0.1, 0.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(1.0, 3.0, 1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(-1.0, 3.0, -1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(-1.0, 3.0, 1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(1.0, 3.0, -1.0))) # splash from the side of fountain(x8) self.emitterZones.append( spk.Point.create(spk.Vector3D(-1.6, 0.1, -1.6))) self.emitterZones.append(spk.Point.create(spk.Vector3D(1.6, 0.1, 1.6))) self.emitterZones.append(spk.Point.create(spk.Vector3D(1.6, 0.1, -1.6))) self.emitterZones.append(spk.Point.create(spk.Vector3D(-1.6, 0.1, 1.6))) self.emitterZones.append( spk.Point.create(spk.Vector3D(-2.26, 0.1, 0.0))) self.emitterZones.append(spk.Point.create(spk.Vector3D(2.26, 0.1, 0.0))) self.emitterZones.append( spk.Point.create(spk.Vector3D(0.0, 0.1, -2.26))) self.emitterZones.append(spk.Point.create(spk.Vector3D(0.0, 0.1, 2.26))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(1.0, 2.0, 1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(-1.0, 2.0, -1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(-1.0, 2.0, 1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(1.0, 2.0, -1.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(1.41, 2.0, 0.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(-1.41, 2.0, 0.0))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(0.0, 2.0, 1.41))) self.emitters.append( spk.StraightEmitter.create(spk.Vector3D(0.0, 2.0, -1.41))) self.flow = [ 500.0, 600.0, 600.0, 600.0, 600.0, 900.0, 900.0, 900.0, 900.0, 900.0, 900.0, 900.0, 900.0 ] self.flowLow = [ 150.0, 200.0, 200.0, 200.0, 200.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0, 250.0 ] for i in range(len(self.emitters)): self.emitters[i].setZone(self.emitterZones[i]) self.emitters[i].setFlow(self.flow[i]) self.emitters[i].setForce(2.5, 4.0) self.emitters[0].setForce(3.0, 3.5) # no Modifier # create Group group = spk.Group.create(model, 20000) # type: spk.Group for emitter in self.emitters: group.addEmitter(emitter) group.setRenderer(renderer) group.setCustomUpdate(self.splash) group.setGravity(spk.Vector3D(0.0, -2.2, 0.0)) group.setFriction(0.7) self.group = group # create System system = spk.System.create() # type: spk.System system.addGroup(group) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.totalTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.renderEnv = True self.highGraphics = True self.angleY = 25.0 self.angleX = 25.0 self.camPosZ = 8.0 self.nbParticles = '' self.fps = '' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def __init__(self, width, height): self.width = width self.height = height # init SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_DOUBLEBUFFER, 1) self.window = sdl2.SDL_CreateWindow( b"SPARK(&pyspk) Rain Demo", sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_OPENGL) sdl2.SDL_CaptureMouse(True) # init OpenGL self.context = sdl2.SDL_GL_CreateContext(self.window) sdl2.SDL_GL_SetSwapInterval(0) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_MULTISAMPLEBUFFERS, 1) sdl2.SDL_GL_SetAttribute(sdl2.SDL_GL_MULTISAMPLESAMPLES, 4) gl.glClearColor(0.8, 0.8, 0.8, 0.0) surface = sdl2.SDL_GetWindowSurface(self.window) gl.glViewport(0, 0, surface.contents.w, surface.contents.h) # gl.glDisable(gl.GL_DEPTH) gl.glDisable(gl.GL_DEPTH_TEST) # load Textures self.txPaving = loadTexture(b'res/paving.bmp', gl.GL_RGB, gl.GL_REPEAT, mipmap=True) txSplash = loadTexture(b'res/waterdrops.bmp', gl.GL_ALPHA, gl.GL_CLAMP) # init fog gl.glEnable(gl.GL_FOG) gl.glFogi(gl.GL_FOG_MODE, gl.GL_EXP2) # init FTGL if not notext: font = FTGL.TextureFont('res/font.ttf') font.FaceSize(24) self.font = font # init SPARK(pyspk) # random seed initialization spk.setRandomSeed(int(time.time())) # step configuration spk.System.setClampStep(True, 0.1) # clamp the step to 100 ms spk.System.useAdaptiveStep( 0.001, 0.01) # use an adaptive step from 1ms to 10ms (1000fps to 100fps) # create Renderer self.sizeRatio = self.width / 1440 self.basicRenderer = GLPointRenderer.create( 1.0) # bare renderer for comparison(F4) dropRenderer = GLPointRenderer.create() dropRenderer.setType(spk.POINT_CIRCLE) dropRenderer.setSize(2.0 * self.sizeRatio) dropRenderer.enableBlending(True) self.dropRenderer = dropRenderer rainRenderer = GLLineRenderer.create() rainRenderer.setLength(-0.1) rainRenderer.enableBlending(True) self.rainRenderer = rainRenderer splashRenderer = GLQuadRenderer.create() splashRenderer.setScale(0.05, 0.05) splashRenderer.setTexturingMode(spk.TEXTURE_2D) splashRenderer.setTexture(txSplash) splashRenderer.enableBlending(True) splashRenderer.enableRenderingHint(spk.DEPTH_WRITE, False) self.splashRenderer = splashRenderer # create Model rain_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | spk.FLAG_MASS rain_mutable = spk.FLAG_NONE rain_random = spk.FLAG_MASS rainModel = spk.Model.create(rain_enable, rain_mutable, rain_random) rainModel.setParam(spk.PARAM_ALPHA, 0.2) rainModel.setImmortal(True) self.rainModel = rainModel dropModel = spk.Model.create(rain_enable, rain_mutable, rain_random) # same as rain dropModel.setParam(spk.PARAM_ALPHA, 0.6) self.dropModel = dropModel splash_enable = spk.FLAG_RED | spk.FLAG_GREEN | spk.FLAG_BLUE | spk.FLAG_ALPHA | spk.FLAG_SIZE | spk.FLAG_ANGLE splash_mutable = spk.FLAG_SIZE | spk.FLAG_ALPHA splash_random = spk.FLAG_SIZE | spk.FLAG_ANGLE splashModel = spk.Model.create(splash_enable, splash_mutable, splash_random) splashModel.setParam(spk.PARAM_ANGLE, 0.0, 2.0 * math.pi) splashModel.setParam(spk.PARAM_ALPHA, 1.0, 0.0) self.splashModel = splashModel # create Emitter rainZone = spk.Ring.create(spk.Vector3D(0.0, 5.0, 0.0)) self.rainZone = rainZone rainEmitter = spk.SphericEmitter.create(spk.Vector3D(0.0, -1.0, 0.0), 0.0, 0.03 * math.pi) rainEmitter.setZone(rainZone) self.rainEmitter = rainEmitter self.dropEmitter = spk.SphericEmitter.create( spk.Vector3D(0.0, 1.0, 0.0), 0.0, 0.2 * math.pi) # create Group gravity = spk.Vector3D(0.0, -2.0, 0.0) rainGroup = spk.Group.create(rainModel, 8000) rainGroup.setCustomUpdate(lambda p, t: self.killRain(p, t)) rainGroup.setRenderer(rainRenderer) rainGroup.addEmitter(rainEmitter) rainGroup.setFriction(0.7) rainGroup.setGravity(gravity) self.rainGroup = rainGroup dropGroup = spk.Group.create(dropModel, 16000) dropGroup.setRenderer(dropRenderer) dropGroup.setFriction(0.7) dropGroup.setGravity(gravity) self.dropGroup = dropGroup splashGroup = spk.Group.create(splashModel, 2400) splashGroup.setRenderer(splashRenderer) self.splashGroup = splashGroup # create System system = spk.System.create() system.addGroup(splashGroup) system.addGroup(dropGroup) system.addGroup(rainGroup) self.system = system print('SPARK FACTORY AFTER INIT :') spk.Factory.getInstance().traceAll() # init Variables self.running = True self.paused = False self.deltaTime = 0 self.step = 0 self.text = 2 self.renderValue = 0 self.renderEnv = True self.angleY = 0.0 self.angleX = 12.0 self.posX = 0.0 self.posZ = 0.0 self.rainRatio = 0.5 self.recompute = True self.nbParticles = '' self.fps = '' self.strRainRate = '' self.frames = [sdl2.SDL_GetTicks() - 1] self.lasttime = self.frames[-1]
def onEvent(self, event): # interaction # quit with ESC or close button if event.type == sdl2.SDL_QUIT: self.running = False elif event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_ESCAPE: self.running = False # reset with DEL if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_DELETE: self.system.empty() # text switching with F1 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F1: self.text = (self.text - 1) % 3 # on/off Bounding Box with F2 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F2: self.group.enableAABBComputing( not self.group.isAABBComputingEnabled()) if self.paused: self.system.computeAABB() # renderer switching with F4 if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_F4: renderers = [self.renderer, self.basicRenderer, None] self.renderValue = (self.renderValue + 1) % 3 self.group.setRenderer(renderers[self.renderValue]) # PAUSE if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_PAUSE: self.paused = not self.paused # reset particle's speed with SPACE if event.type == sdl2.SDL_KEYDOWN and event.key.keysym.sym == sdl2.SDLK_SPACE: for i in range(self.group.getNbParticles()): velocity = self.group.getParticle( i).velocity() # velocity() returns internal reference velocity.x = spk.random(-0.5, 0.5) velocity.y = spk.random(-0.5, 0.5) velocity.z = spk.random(-0.5, 0.5) # Camera zooming with mouse wheel if event.type == sdl2.SDL_MOUSEWHEEL: if event.wheel.y < 0: self.camPosZ = min(10.0, self.camPosZ + 0.5) elif event.wheel.y > 0: self.camPosZ = max(0.5, self.camPosZ - 0.5) # Writing with MouseButtons self.oldZ = self.camPosZ if event.type == sdl2.SDL_MOUSEBUTTONDOWN: if event.button.button == sdl2.SDL_BUTTON_LEFT: self.add = True self.oldX = (event.motion.x - self.width * 0.5) * self.screenToUniverse self.oldY = -(event.motion.y - self.height * 0.5) * self.screenToUniverse if event.type == sdl2.SDL_MOUSEBUTTONUP: if event.button.button == sdl2.SDL_BUTTON_LEFT: self.add = False if self.add and not self.paused: x = (event.motion.x - self.width * 0.5) * self.screenToUniverse y = -(event.motion.y - self.height * 0.5) * self.screenToUniverse self.offset = self.group.addParticles( start=spk.Vector3D(self.oldX, self.oldY, self.oldZ - 5.0), end=spk.Vector3D(x, y, self.camPosZ - 5.0), emitter=self.emitter, step=0.025, offset=self.offset) self.oldX = x self.oldY = y self.group.flushAddedParticles()