-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathparticlecandy.bmx
More file actions
769 lines (676 loc) · 30.2 KB
/
particlecandy.bmx
File metadata and controls
769 lines (676 loc) · 30.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
' This software is a port of Martin Liedel's (Xaron) Particle Candy for Monkey-X
'
' BlitzMax OpenB3DMax Port by RonTek
' https://www.blitzcoder.org
'
' ---------------------------------------------------------------------------------
'
' This software is a port of Mike Dogan's great ParticleCandy for BlitzBasic3d
'
' http://www.x-pressive.com
'
' Check his page if you're interested in his latest ParticleCandy Engine
' for Corona SDK!
'
' A BIG THANKS goes to him as he gave the permission to publish this as open source
'
' For any support or questions contact: martin.leidel@gmail.com
'
' This software is provided 'as-is', without any express or implied
' warranty. In no event will the authors be held liable for any damages
' arising from the use of this software.
'
' Permission is granted to anyone to use this software for any purpose,
' including commercial applications, and to alter it and redistribute it
' freely, subject to the following restrictions:
'
' 1. The origin of this software must not be misrepresented; you must not
' claim that you wrote the original software. If you use this software
' in a product, an acknowledgment in the product documentation would be
' appreciated but is not required.
' 2. Altered source versions must be plainly marked as such, and must not be
' misrepresented as being the original software.
' 3. This notice may not be removed or altered from any source distribution.
Strict
'Import sidesign.minib3d
'Framework Openb3d.B3dglgraphics
Import "emitter.bmx"
'Import "particle.bmx"
Import "particletype.bmx"
Type ParticleCandy
Field _gravity:Float
Field _numParticleTypes:Int
Field _maxNumParticleTypes:Int
Field _useTriangles
Field _entityFX:Int
Field _emitterList:TList
Field _particleTypes:ParticleType[]
Field _particleTypeList:TList
Field _numParticles:Int
Field _particlesRendered:Int
Field _camera:TCamera
Field _screenW:Int
Field _screenH:Int
Field _mesh:TMesh[2]
Field _surface:TSurface[2]
Field _ptmsh:TMesh
Field _ptsrf:TSurface
Field _dummyPivot:TEntity
Field _dummyMesh:TMesh
Field _dummySurface:TSurface
Field _particleTexture:TTexture
Field _textureFrames:Int
Field _textureFrameSize:Int
Field _textureNumFrames:Int
Field _uvUnit:Float
Field _updatespeed:Int
Field _wind:Float
Field _cycles:Int
Field _prev:Int = MilliSecs()
Field _now:Int = MilliSecs()
Field _diff:Float ' MILLISEC-DIFFERENCE BETWEEN LAST TWO FRAMES
Method Create:ParticleCandy( gravity:Float = 0.01, numParticleTypes:Int = 100, useTriangles = False, EntityFX:Int = 1+2+8+16+32 )
Local pc:ParticleCandy = New ParticleCandy
pc._gravity = gravity
pc._maxNumParticleTypes = numParticleTypes
pc._numParticleTypes = 0
pc._useTriangles = useTriangles
pc._entityFX = EntityFX
pc._emitterList = New TList
pc._particleTypes = New ParticleType[numParticleTypes]
pc._particleTypeList = New TList
DebugLog "Creating Particle..."
Return pc
End Method
Method init( cam:TCamera , texFile:String , texFrames:Int , viewportW:Int = 0 , viewportH:Int = 0 )
DebugLog "Init..."
_camera = cam
_screenW = viewportW
_screenH = viewportH
If( _screenW = 0 ) _screenW = GraphicsWidth()
If( _screenH = 0 ) _screenH = GraphicsHeight()
_mesh[0] = CreateMesh()
_surface[0] = CreateSurface( _mesh[0] )
_mesh[1] = CreateMesh()
_surface[1] = CreateSurface( _mesh[1] )
EntityBlend( _mesh[0], 1 )
EntityBlend( _mesh[1], 3 )
EntityFX ( _mesh[0], _entityFX )
EntityFX ( _mesh[1], _entityFX )
' DUMMY PIVOT
_dummyPivot = CreatePivot()
' DUMMY QUAD (CAMERA FACING + ROTATION)
_dummyMesh = CreateMesh()
_dummySurface = CreateSurface( _dummyMesh )
HideEntity( _dummyMesh )
AddVertex ( _dummySurface, -1.0, 1.0, 0.0, 0.0, 0.0 )
AddVertex ( _dummySurface, 1.0, 1.0, 0.0, 1.0, 0.0 )
AddVertex ( _dummySurface, -1.0, -1.0, 0.0, 0.0, 1.0 )
If( Not _useTriangles ) AddVertex( _dummySurface, 1.0, -1.0, 0.0, 1.0, 1.0 )
DebugLog texFile
loadParticleTexture( texFile, texFrames )
End Method
Method loadParticleTexture( texFile:String, texFrames:Int )
If( _particleTexture ) FreeTexture( _particleTexture )
_particleTexture = LoadTexture( texFile, 2+16+32 )
If( Not _particleTexture ) RuntimeError "COULD NOT LOAD PARTICLE TEXTURE: " + texFile
_textureFrames = texFrames
_textureFrameSize = TextureWidth( _particleTexture ) / _textureFrames
_textureNumFrames = TextureWidth( _particleTexture ) / _textureFrameSize
_uvUnit = 1.0 / Float( _textureNumFrames )
EntityTexture( _mesh[0], _particleTexture )
EntityTexture( _mesh[1], _particleTexture )
End Method
Method changeParticleCamera( cam:TCamera, viewportW:Int, viewportH:Int )
If( Not cam ) RuntimeError "changeParticleCamera(): INVALID CAMERA HANDLE."
_camera = cam
_screenW = viewportW
_screenH = viewportH
End Method
Method setParticleUpdateCycle( i:Int )
_updatespeed = i
End Method
Method setParticleWind( i:Float = 0.0 )
_wind = i / 1000.0
End Method
Method CreateEmitter:Emitter( parent:TEntity = Null, scale:Float = 1.0 )
' CAMERA SET?
If( Not _camera ) RuntimeError "YOU DID NOT SET A REFERENCE TO YOUR CAMERA. USE InitParticles(...) FIRST !"
' TEXTURE LOADED?
If( Not _particleTexture ) RuntimeError "YOU DID NOT SET A PARTICLE TEXTURE. USE InitParticles(...) FIRST !"
Local emitter:Emitter = New Emitter.Create( parent, scale, _dummyPivot, _dummyMesh, _dummySurface )
_emitterList.AddLast( emitter )
Return emitter
End Method
Method stopEmitters()
For Local emitter:Emitter = EachIn _emitterList
emitter._active = False
'TODO If xChannelPlaying(Emitter.Sch) xStopChannel Emitter.Sch
Next
End Method
Method freeEmitter( emitter:Emitter )
emitter.freeEmitter()
_emitterList.Remove( emitter )
End Method
Method freeEmitters()
For Local emitter:Emitter = EachIn _emitterList
freeEmitter( emitter )
Next
End Method
Method clearParticles()
stopEmitters()
For Local emitter:Emitter = EachIn _emitterList
emitter.clearParticles()
Next
DebugLog "clearing..."
End Method
Method free()
' clearParticles()
' freeEmitters ()
' For Local ParticleType:TParticleType = EachIn ParticleTypeList
' ParticleTypeList.Remove( ParticleType )
' Next
' _numParticleTypes = 0
' FreeTexture( _particleTexture )
' FreeEntity PTDummy
' FreeEntity PTDummyPiv
' FreeEntity PTMesh[0]
' FreeEntity PTMesh[1]
' PTTex = Null
' PTMesh[0] = Null
' PTMesh[1] = Null
' PTDummy = Null
' PTDummyPiv= Null
End Method
Method createParticleType:Int()
_numParticleTypes = _numParticleTypes + 1
If( _numParticleTypes > _maxNumParticleTypes ) RuntimeError "TOO MANY PARTICLE TYPES USED. SET '_maxNumParticleTypes' TO A HIGHER VALUE!"
Local id:Int = _numParticleTypes
_particleTypes[id] = New ParticleType
' SET Default VALUES WHEN CREATED
setPTImage( id )
setPTSpeed( id )
setPTRandomSpeed( id )
setPTSize( id )
setPTAlpha( id )
setPTWeight( id )
setPTRotation( id )
setPTColor( id )
setPTEmissionAngle( id )
setPTInnerAngle( id )
setPTStartOffsets( id )
setPTLifeTime( id )
setPTBounce( id )
setPTPulsation( id )
horizontalPTAlign( id )
setPTAddedBlend( id )
setPTCircularMotion( id )
setPTEmissionShape( id )
_particleTypeList.AddLast( _particleTypes[id] )
Return id
End Method
Method setPTNearCameraFade( id:Int, radius:Float )
_particleTypes[id]._cfa = radius
End Method
Method setPTImage( id:Int, frm:Int = 1 )
'VALID IMAGE FRAME?
If( frm > _textureFrames * _textureFrames ) RuntimeError "COULD NOT SET PARTICLE IMAGE -IMAGE FRAME " + frm + " DOES NOT EXIST IN TEXTURE!"
' PARTICLE Type'S UV COORDS
Local row:Int = 1
While frm > _textureFrames
frm = frm - _textureFrames
row = row + 1
Wend
_particleTypes[id]._u = (frm-1) * _uvUnit
_particleTypes[id]._v = (row-1) * _uvUnit
End Method
Method setPTSpeed( id:Int, spd:Float = 10.0, spv:Float = 1.0, slo:Float = 0.0 )
_particleTypes[id]._spd = spd / 1000.0
_particleTypes[id]._spv = spv / 1000.0
_particleTypes[id]._slo = slo / 1000.0
End Method
Method setPTRandomSpeed( id:Int, srx:Float = 0.0, sry:Float = 0.0, srz:Float = 0.0 )
_particleTypes[id]._srx = srx / 1000.0
_particleTypes[id]._sry = sry / 1000.0
_particleTypes[id]._srz = srz / 1000.0
End Method
Method setPTSize( id:Int, sze:Float = 1.0, szv:Float = 0.0, szc:Float = 0.0, szm:Float = 10.0 )
If( _useTriangles )
_particleTypes[id]._sze = sze * 1.5
_particleTypes[id]._szv = szv * 1.5
_particleTypes[id]._szc = ( szc / 1000.0 ) * 1.5
_particleTypes[id]._szm = szm * 1.5
Else
_particleTypes[id]._sze = sze
_particleTypes[id]._szv = szv
_particleTypes[id]._szc = szc / 1000.0
_particleTypes[id]._szm = szm
End If
End Method
Method setPTAlpha( id:Int, alp:Float = 1.0, alv:Float = 0.0, alc:Float = 0.0 )
_particleTypes[id]._alp = alp
_particleTypes[id]._alv = alv
_particleTypes[id]._alc = alc / 1000.0
End Method
Method setPTWeight( id:Int, wgt:Float = 1.0, wgv:Float = 0.0 )
_particleTypes[id]._wgt = wgt / 1000.0
_particleTypes[id]._wgv = wgv / 1000.0
End Method
Method setPTRotation( id:Int, rom:Int = 0, roc:Float = 0.0 )
_particleTypes[id]._rom = rom
If( rom = 1 )
_particleTypes[id]._roc = roc / 1000.0
Else
_particleTypes[id]._roc = roc
End If
End Method
Method setPTColor( id:Int, r:Int = 100, g:Int = 100, b:Int = 100, bv:Int = 0, rc:Float = 0.0, gc:Float = 0.0, bc:Float = 0.0 )
_particleTypes[id]._r = Float( r )
_particleTypes[id]._g = Float( g )
_particleTypes[id]._b = Float( b )
_particleTypes[id]._bv = bv
_particleTypes[id]._rc = rc / 1000.0
_particleTypes[id]._gc = gc / 1000.0
_particleTypes[id]._bc = bc / 1000.0
End Method
Method setPTBounce( id:Int, flh:Float = 0.0, bnc:Float = 0.0, bnm:Int = 0 )
_particleTypes[id]._flh = flh
_particleTypes[id]._bnc = bnc
_particleTypes[id]._bnm = bnm
End Method
Method setPTInnerAngle( id:Int, ian:Float = 0.0 )
If( ian < 0.0 ) ian = 0.0
_particleTypes[id]._ian = ian / 2.0
End Method
Method setPTOuterAngle( id:Int, emr:Float = 0.0 )
If( emr < _particleTypes[id]._ian ) emr = _particleTypes[id]._ian
If( emr > 360.0 ) emr = 360.0
_particleTypes[id]._emr = emr / 2.0
End Method
Method setPTEmissionAngle( id:Int, emx:Int = 3, emr:Float = 15.0 )
If( emx < 0 Or emx > 3 ) RuntimeError "PARTICLE EMISSION ANGLE INVALID -USE AXIS VALUES 0-3 ONLY!"
_particleTypes[id]._emr = emr / 2.0
' ParticleTypes[id].emx = emx
End Method
Method setPTStartOffsets( id:Int, ox1:Float = 0.0, ox2:Float = 0.0, oy1:Float = 0.0, oy2:Float = 0.0, oz1:Float = 0.0, oz2:Float = 0.0 )
_particleTypes[id]._ox1 = ox1
_particleTypes[id]._ox2 = ox2
_particleTypes[id]._oy1 = oy1
_particleTypes[id]._oy2 = oy2
_particleTypes[id]._oz1 = oz1
_particleTypes[id]._oz2 = oz2
End Method
Method setPTLifeTime( id:Int, lft:Int = 1000 )
_particleTypes[id]._lft = lft
End Method
Method setPTPulsation( id:Int, pls:Float = 0.0 )
_particleTypes[id]._pls = pls
End Method
Method horizontalPTAlign( id:Int, hor:Int = 0 )
_particleTypes[id]._hor = hor
End Method
Method setPTAddedBlend( id:Int, msh:Int = 0 )
If( msh > 1 ) RuntimeError "SET PARTICLE BLEND MODE FAILED: USE ONLY 0 (NORMAL) OR 1 (ADDED BLEND)!"
_particleTypes[id]._msh = msh
End Method
Method setPTTrail( id:Int, trl:Int, tst:Int = 0, tlt:Int = 1000, ter:Float = 15.0 )
If( trl = 0 ) RuntimeError "SET PARTICLE TRAIL FAILED. YOU DID NOT SPECIFY A TRAIL PARTICLE ID."
If( trl > _maxNumParticleTypes ) RuntimeError "SET PARTICLE TRAIL FAILED. THE SPECIFIED PARTICLE TYPE DOES NOT EXIST."
_particleTypes[id]._trl = trl
_particleTypes[id]._tst = tst
_particleTypes[id]._tlt = tlt
_particleTypes[id]._ter = ter / 1000.0
End Method
Method removePTTrail( id:Int )
_particleTypes[id]._trl = 0
_particleTypes[id]._tst = 0
_particleTypes[id]._tlt = 0
_particleTypes[id]._ter = 0
End Method
Method setPTCircularMotion( id:Int, cms:Float = 0.0 )
_particleTypes[id]._cms = cms / 1000.0
End Method
Method setPTEmissionShape( id:Int, esh:Int = 0 )
_particleTypes[id]._esh = esh
End Method
Method copyParticleType:Int( id2:Int )
_numParticleTypes = _numParticleTypes + 1
If( _numParticleTypes > _maxNumParticleTypes ) RuntimeError "TOO MANY PARTICLE TYPES USED. SET '_maxNumParticleTypes' TO A HIGHER VALUE!"
Local id:Int = _numParticleTypes
_particleTypes[id] = New ParticleType
' COPY VALUES FROM SOURCE Type
_particleTypes[id]._u = _particleTypes[id2]._u
_particleTypes[id]._v = _particleTypes[id2]._v
_particleTypes[id]._spd = _particleTypes[id2]._spd
_particleTypes[id]._spv = _particleTypes[id2]._spv
_particleTypes[id]._slo = _particleTypes[id2]._slo
_particleTypes[id]._srx = _particleTypes[id2]._srx
_particleTypes[id]._sry = _particleTypes[id2]._sry
_particleTypes[id]._srz = _particleTypes[id2]._srz
_particleTypes[id]._sze = _particleTypes[id2]._sze
_particleTypes[id]._szv = _particleTypes[id2]._szv
_particleTypes[id]._szc = _particleTypes[id2]._szc
_particleTypes[id]._szm = _particleTypes[id2]._szm
_particleTypes[id]._alp = _particleTypes[id2]._alp
_particleTypes[id]._alv = _particleTypes[id2]._alv
_particleTypes[id]._alc = _particleTypes[id2]._alc
_particleTypes[id]._wgt = _particleTypes[id2]._wgt
_particleTypes[id]._wgv = _particleTypes[id2]._wgv
_particleTypes[id]._rom = _particleTypes[id2]._rom
_particleTypes[id]._hor = _particleTypes[id2]._hor
_particleTypes[id]._roc = _particleTypes[id2]._roc
_particleTypes[id]._ian = _particleTypes[id2]._ian
_particleTypes[id]._emr = _particleTypes[id2]._emr
_particleTypes[id]._flh = _particleTypes[id2]._flh
_particleTypes[id]._bnc = _particleTypes[id2]._bnc
_particleTypes[id]._bnm = _particleTypes[id2]._bnm
_particleTypes[id]._pls = _particleTypes[id2]._pls
_particleTypes[id]._ox1 = _particleTypes[id2]._ox1
_particleTypes[id]._ox2 = _particleTypes[id2]._ox2
_particleTypes[id]._oy1 = _particleTypes[id2]._oy1
_particleTypes[id]._oy2 = _particleTypes[id2]._oy2
_particleTypes[id]._oz1 = _particleTypes[id2]._oz1
_particleTypes[id]._oz2 = _particleTypes[id2]._oz2
_particleTypes[id]._r = _particleTypes[id2]._r
_particleTypes[id]._g = _particleTypes[id2]._g
_particleTypes[id]._b = _particleTypes[id2]._b
_particleTypes[id]._bv = _particleTypes[id2]._bv
_particleTypes[id]._rc = _particleTypes[id2]._rc
_particleTypes[id]._gc = _particleTypes[id2]._gc
_particleTypes[id]._bc = _particleTypes[id2]._bc
_particleTypes[id]._lft = _particleTypes[id2]._lft
_particleTypes[id]._msh = _particleTypes[id2]._msh
_particleTypes[id]._trl = _particleTypes[id2]._trl
_particleTypes[id]._tst = _particleTypes[id2]._tst
_particleTypes[id]._tlt = _particleTypes[id2]._tlt
_particleTypes[id]._ter = _particleTypes[id2]._ter
_particleTypes[id]._cms = _particleTypes[id2]._cms
_particleTypes[id]._esh = _particleTypes[id2]._esh
_particleTypeList.AddLast( _particleTypes[id] )
Return id
End Method
Method render()
Local r1:Float, r2:Float, i:Int, j:Int, k:Int, typ:Int, typ2:Int
' UPDATE EVERY ..th CYCLE ONLY
_cycles = _cycles + 1
If( _cycles < _updatespeed ) Return
_cycles = 0
' CALCULATE TIME CHANGE
_now = MilliSecs()
_diff = _now - _prev
If( _diff > 500 ) _diff = 500
_prev = _now
_numParticles = 0
_particlesRendered = 0
_surface[0].ClearSurface()
_surface[1].ClearSurface()
For Local emitter:Emitter = EachIn _emitterList
' EMITTER ACTIVE?
If( emitter._active )
Local x:Float = EntityX ( emitter._piv, True )
Local y:Float = EntityY ( emitter._piv, True )
Local z:Float = EntityZ ( emitter._piv, True )
Local xr:Float = EntityPitch( emitter._piv, True )
Local yr:Float = EntityYaw ( emitter._piv, True )
Local zr:Float = EntityRoll ( emitter._piv, True )
' LOOP THROUGH EMITTER'S PARTICLE TYPES
For Local i:Int = 1 To emitter._npt
typ = emitter._pty[i]
Local spv:Float = _particleTypes[typ]._spv
Local emr:Float = _particleTypes[typ]._emr
Local ian:Float = _particleTypes[typ]._ian
' EMITTER FINISHED?
If( _now - emitter._est > emitter._mlt )
emitter._active = False
'TODO If Emitter.slp And xChannelPlaying(Emitter.Sch) xStopChannel Emitter.Sch
' EMIT THIS PARTICLE Type?
Else If( _now - emitter._est > emitter._pst[i] And _now - emitter._est < emitter._plt[i] And emitter._pta[i] = True )
emitter._pea[i] = emitter._pea[i] + _diff * emitter._per[i]
While emitter._pea[i] > 1.0
Local particle:Particle = New Particle
particle._typ = typ
particle._piv = emitter._piv
' PARTICLE ANGLE
RotateEntity ( emitter._piv, xr, yr, zr, True )
PositionEntity( emitter._piv, x, y, z, True )
' START POSITION
If( _particleTypes[typ]._esh = 0 )
' EMISSION SHAPE AREA
TurnEntity( emitter._piv, Rnd( ian, emr ), Rnd( 0, 359 ), Rnd( ian, emr ), False )
MoveEntity( emitter._piv, ( _particleTypes[typ]._ox1 + Rnd( 0, _particleTypes[typ]._ox2 ) ) * emitter._scl, ( _particleTypes[typ]._oy1 + Rnd( 0, _particleTypes[typ]._oy2 ) ) * emitter._scl, ( _particleTypes[typ]._oz1 + Rnd( 0, _particleTypes[typ]._oz2) ) * emitter._scl )
Else If( _particleTypes[typ]._esh = 1 )
' EMISSION SHAPE POINT
TurnEntity( emitter._piv, Rnd( ian, emr ), Rnd( 0, 359 ), Rnd( ian, emr ), False )
Else If( _particleTypes[typ]._esh = 2 )
' EMISSION SHAPE RING
TurnEntity( emitter._piv, Rnd( ian, emr ), Rnd( 0, 359 ), Rnd( ian, emr ), False )
MoveEntity( emitter._piv, ( _particleTypes[typ]._ox1 + _particleTypes[typ]._ox2) * emitter._scl, ( _particleTypes[typ]._oy1 + Rnd( 0, _particleTypes[typ]._oy2 ) ) * emitter._scl, ( _particleTypes[typ]._oz1 + _particleTypes[typ]._oz2 ) * emitter._scl )
Else If( _particleTypes[typ]._esh = 3 )
' EMISSION SHAPE xLine
MoveEntity( emitter._piv, ( _particleTypes[typ]._ox1 + Rnd( 0, _particleTypes[typ]._ox2 ) ) * emitter._scl, ( _particleTypes[typ]._oy1 + Rnd( 0, _particleTypes[typ]._oy2 ) ) * emitter._scl, ( _particleTypes[typ]._oz1 + Rnd( 0, _particleTypes[typ]._oz2 ) ) * emitter._scl )
End If
particle._x = EntityX( emitter._piv, True )
particle._y = EntityY( emitter._piv, True )
particle._z = EntityZ( emitter._piv, True )
particle._lx = x
particle._ly = y
particle._lz = z
' SET SPEED
TFormVector( 0,( _particleTypes[typ]._spd + Rnd( -spv, spv ) ) * emitter._scl, 0, emitter._piv, Null )
particle._vx = TFormedX()
particle._vy = TFormedY()
particle._vz = TFormedZ()
' RANDOM PARTICLE ROTATION?
If( _particleTypes[typ]._rom = 1 )
particle._rot = Rnd( 0.0, 359.0 )
Else If( _particleTypes[typ]._rom = 0 )
' FIXED PARTICLE ROTATION?
particle._rot = _particleTypes[typ]._roc
End If
particle._scl = emitter._scl
particle._sze = ( _particleTypes[typ]._sze + Rnd( -_particleTypes[typ]._szv, _particleTypes[typ]._szv ) ) * emitter._scl
particle._alp = _particleTypes[typ]._alp + Rnd( -_particleTypes[typ]._alv, _particleTypes[typ]._alv )
k = Rnd( -_particleTypes[typ]._bv, _particleTypes[typ]._bv )
particle._r = _particleTypes[typ]._r + k
particle._g = _particleTypes[typ]._g + k
particle._b = _particleTypes[typ]._b + k
particle._stt = _now
emitter._particleList.AddLast( particle )
emitter._pea[i] = emitter._pea[i] - 1.0
Wend
' CHANGE PARTICLE'S EMISSION RATE
emitter._per[i] = emitter._per[i] + emitter._pec[i]
End If ' End If EMIT THIS PARTICLE Type
Next
' RESTORE EMITTER'S POSITION
RotateEntity ( emitter._piv, xr, yr, zr, True )
PositionEntity( emitter._piv, x, y, z, True )
End If
' UPDATE ALL PARTICLES
For Local particle:Particle = EachIn emitter._particleList
' COUNT PARTICLE
_numParticles = _numParticles + 1
' UPDATE PARTICLE
typ = particle._typ
_ptmsh = _mesh[_particleTypes[typ]._msh]
_ptsrf = _surface[_particleTypes[typ]._msh]
particle._lx = particle._x
particle._ly = particle._y
particle._lz = particle._z
particle._x = particle._x + ( _diff * particle._vx ) + ( _diff * _wind )
particle._y = particle._y + _diff * particle._vy
particle._z = particle._z + _diff * particle._vz
particle._vx = particle._vx + _diff * Rnd( -_particleTypes[typ]._srx, _particleTypes[typ]._srx )
particle._vy = particle._vy + _diff * Rnd( -_particleTypes[typ]._sry, _particleTypes[typ]._sry )
particle._vz = particle._vz + _diff * Rnd( -_particleTypes[typ]._srz, _particleTypes[typ]._srz )
' SLOW DOWN
particle._vx = particle._vx + _diff * ( particle._vx * _particleTypes[typ]._slo )
particle._vy = particle._vy + _diff * ( particle._vy * _particleTypes[typ]._slo )
particle._vz = particle._vz + _diff * ( particle._vz * _particleTypes[typ]._slo )
'
particle._vy = particle._vy - _diff * ( ( ( particle._scl * _particleTypes[typ]._wgt ) + Rnd( -_particleTypes[typ]._wgv, _particleTypes[typ]._wgv ) ) * _gravity )
particle._alp = particle._alp + _diff * _particleTypes[typ]._alc
particle._r = particle._r + _diff * _particleTypes[typ]._rc
particle._g = particle._g + _diff * _particleTypes[typ]._gc
particle._b = particle._b + _diff * _particleTypes[typ]._bc
particle._sze = particle._sze + _diff * ( _particleTypes[typ]._szc * particle._scl )
' SIZE CHANGE
If( particle._sze > _particleTypes[typ]._szm * particle._scl ) particle._sze = _particleTypes[typ]._szm * particle._scl
' ROTATION
If( _particleTypes[typ]._rom = 1 )
If( particle._vx > 0 )
particle._rot = particle._rot + _diff * _particleTypes[typ]._roc
Else
particle._rot = particle._rot - _diff * _particleTypes[typ]._roc
End If
End If
' Floor BOUNCE?
If( _particleTypes[typ]._flh <> 0.0 )
If( particle._y < _particleTypes[typ]._flh )
particle._bnc = particle._bnc + 1
particle._y = _particleTypes[typ]._flh
particle._vy = -( particle._vy * _particleTypes[typ]._bnc )
End If
End If
' EMIT TRAIL PARTICLE?
If( _particleTypes[typ]._trl )
If( _now - particle._stt > _particleTypes[typ]._tst And _now - particle._stt < _particleTypes[typ]._tlt )
particle._tea = particle._tea + _diff * _particleTypes[typ]._ter
While particle._tea > 1.0
typ2 = _particleTypes[typ]._trl
Local trail:Particle = New Particle
trail._typ = typ2
trail._x = particle._x
trail._y = particle._y
trail._z = particle._z
trail._rot = Rnd( 0.0, 359.0 )
trail._scl = particle._scl
trail._sze = ( particle._sze + Rnd( -_particleTypes[typ2]._szv, _particleTypes[typ2]._szv ) ) * particle._scl
trail._alp = _particleTypes[typ2]._alp + Rnd( -_particleTypes[typ2]._alv, _particleTypes[typ2]._alv )
k = Rnd( -_particleTypes[typ2]._bv, _particleTypes[typ2]._bv )
trail._r = _particleTypes[typ2]._r + k
trail._g = _particleTypes[typ2]._g + k
trail._b = _particleTypes[typ2]._b + k
trail._stt = _now
emitter._particleList.AddLast( trail )
particle._tea = particle._tea - 1.0
Wend
End If
End If
' CIRCULAR MOTION
If( _particleTypes[particle._typ]._cms <> 0.0 )
EntityParent( _dummyPivot, particle._piv, False )
PositionEntity( _dummyMesh, particle._x, particle._y, particle._z, True )
EntityParent( _dummyMesh, _dummyPivot, True )
TurnEntity( _dummyPivot, 0, _particleTypes[particle._typ]._cms * _diff, 0.0 )
particle._x = EntityX( _dummyMesh, True )
particle._y = EntityY( _dummyMesh, True )
particle._z = EntityZ( _dummyMesh, True )
End If
' Delete PARTICLE?
If( _now - _particleTypes[typ]._lft > particle._stt )
If( GetParent( _dummyPivot ) = particle._piv ) EntityParent( _dummyPivot, Null, False )
emitter._particleList.Remove( particle )
Else If( particle._sze < 0 )
If( GetParent( _dummyPivot ) = particle._piv ) EntityParent( _dummyPivot, Null, False )
emitter._particleList.Remove( particle )
Else If( particle._alp < 0 )
If( GetParent( _dummyPivot ) = particle._piv ) EntityParent( _dummyPivot, Null, False )
emitter._particleList.Remove( particle )
Else If( particle._bnc > _particleTypes[typ]._bnm )
If( GetParent( _dummyPivot ) = particle._piv ) EntityParent( _dummyPivot, Null, False )
emitter._particleList.Remove( particle )
'Else If Particle.r + Particle.g + Particle.b < 1 ' <-- Delete If PARTICLE xColor BECOMES BLACK
'Delete Particle
Else
' DRAW PARTICLE?
If( inView( particle._x, particle._y, particle._z, particle._sze ) )
draw( particle )
_particlesRendered = _particlesRendered + 1
End If
End If
Next' PARTICLES LOOP
Next
End Method
Method inView( x:Float, y:Float, z:Float, size:Float )
TFormPoint( x, y, z, _ptmsh, Null )
CameraProject( _camera, TFormedX(), TFormedY(), TFormedZ() )
If( ProjectedZ() > 0 )
If( ProjectedX() > -size And ProjectedX() < _screenW + size )
If( ProjectedY() > -size And ProjectedY() < _screenH + size )
Return True
End If
End If
End If
Return False
End Method
Method draw( particle:Particle )
Local sz:Float, x:Float, y:Float, z:Float, u1:Float, u2:Float, v1:Float, v2:Float, r:Int, g:Int, b:Int, v:Int, rom:Int
x = particle._x
y = particle._y
z = particle._z
r = Int( particle._r )
g = Int( particle._g )
b = Int( particle._b )
u1 = _particleTypes[particle._typ]._u
v1 = _particleTypes[particle._typ]._v
u2 = u1 + _uvUnit
v2 = v1 + _uvUnit
sz = ( particle._sze + Rnd( -_particleTypes[particle._typ]._pls, _particleTypes[particle._typ]._pls) ) * particle._scl
' ADJUST DUMMY QUAD
ScaleEntity ( _dummyMesh, sz, sz, 0, True )
PositionEntity( _dummyMesh, x, y, z, True )
If( _particleTypes[particle._typ]._rom = 2 )
' FACE CAMERA
PointEntity( _dummyMesh, _camera )
' ALIGN ROTATION To MOVEMENT
AlignToVector( _dummyMesh, x-particle._lx, y-particle._ly, z-particle._lz, 1 )
'AlignToVector( _dummyMesh, x-particle._lx, y-particle._ly, z-particle._lz, 1 )
Else If( _particleTypes[particle._typ]._hor > 0 )
' ALIGN HORIZONTALLY
RotateEntity( _dummyMesh, -90, 0, particle._rot, True )
Else
' FACE CAMERA & ROTATE
PointEntity( _dummyMesh, _camera, particle._rot )
End If
' GET DUMMY VERTEX-COORDS
TFormPoint( VertexX( _dummySurface, 0 ), VertexY( _dummySurface, 0 ), VertexZ( _dummySurface, 0 ), _dummyMesh, Null )
x = TFormedX()
y = TFormedY()
z = TFormedZ()
v = AddVertex( _ptsrf, x, y, z, u1, v1 )
TFormPoint( VertexX( _dummySurface, 1 ), VertexY( _dummySurface, 1 ), VertexZ( _dummySurface, 1 ), _dummyMesh, Null )
x = TFormedX()
y = TFormedY()
z = TFormedZ()
AddVertex( _ptsrf, x, y, z, u2, v1 )
TFormPoint( VertexX( _dummySurface, 2 ), VertexY( _dummySurface, 2 ), VertexZ(_dummySurface, 2 ), _dummyMesh, Null )
x = TFormedX()
y = TFormedY()
z = TFormedZ()
AddVertex( _ptsrf, x, y, z, u1, v2 )
If( Not _useTriangles )
TFormPoint( VertexX( _dummySurface, 3 ), VertexY( _dummySurface, 3 ), VertexZ( _dummySurface, 3 ), _dummyMesh, Null )
x = TFormedX()
y = TFormedY()
z = TFormedZ()
AddVertex( _ptsrf, x, y, z, u2, v2 )
AddTriangle( _ptsrf, v+1, v+3, v+2 )
End If
AddTriangle( _ptsrf, v, v+1, v+2 )
' FADE NEAR CAMERA
Local d:Float = 1.0
If( _particleTypes[particle._typ]._cfa > 0.0 )
Local d:Float = EntityDistance( _camera, _dummyMesh ) / _particleTypes[particle._typ]._cfa
If( d > 1.0 )
d = 1.0
Else If( d < 0.0 )
d = 0.0
End If
End If
VertexColor( _ptsrf, v , r, g, b, d * particle._alp )
VertexColor( _ptsrf, v+1, r, g, b, d * particle._alp )
VertexColor( _ptsrf, v+2, r, g, b, d * particle._alp )
VertexColor( _ptsrf, v+3, r, g, b, d * particle._alp )
End Method
End Type