TParticle


Croquet-Teapot

Comment:

TParticle

This is a very simple particle system.


size - the length or the particle array, determines max number of particles.
pPosition - B3DVector3Array of particle positions
pVelocity - B3DVector3Array of particle velocities
pAcceleration - B3DVector3Array of particle accelerations
pLifetime - number of seconds (floating point) of life that each particle has left
positionRange - the TBox within which new particles get created (see TBox >> #atRandom:)
velocityRange - the 3D velocity range within which the new particles start life.
accelerationRange - the 3D acceleration range applied to each particle on creation.
lifetimeRange - the lifespan range of each particle.
lastTime - for #the stepAt: method, used to determine time between this and the last cycle.
material - what color are the particles.

To use the particle system you do the following:

	ps _ TParticle initialize: ogl size: 1000
	ps setPositionRangeMin:(-0.1@-0.1@-0.1) max: (0.1@0.1@0.1).
	ps setVelocityRangeMin:(-1.2@6.4@-1.2) max:(1.2@9.6@1.2).
	ps setAccelerationRangeMin:(0@-10@0) max:(0@-8@0).
	ps setLifetimeRange: (1500 to: 2000).

These values are called inside of the initialize method, but this is how you would set your one.

Hierarchy:

ProtoObject
Object
TObject
TFrame
TParticle

Summary:

instance variables:

accelerationRange attrArray attractors billBoard boundBox boundSphere boundsChanged deltaTime endColor globalVelocity lastGlobalPosition lastStepTime lastTime lengthArray lifetimeRange material maxTime pAcceleration pColor pDeltaColor pLastPosition pLifetime pPosition pVelocity positionRange size startColor tar tpr tvr velocityRange

methods:

instance class
accessing initialize render stepping testing instance creation

Detail:

instance variables:

accelerationRange
attrArray
attractors
billBoard
boundBox
boundSphere
boundsChanged
deltaTime
endColor
globalVelocity
lastGlobalPosition
lastStepTime
lastTime
lengthArray
lifetimeRange
material
maxTime
pAcceleration
pColor
pDeltaColor
pLastPosition
pLifetime
pPosition
pVelocity
positionRange
size
startColor
tar
tpr
tvr
velocityRange

instance methods:

accessing
addAttractor: attr


	attractors add: attr.	
	attrArray ifNil:[
		attrArray _ B3DVector3Array new: size.
		lengthArray _ FloatArray new: size.
		].
billBoard: bool


	billBoard _ bool.
endColor


	^ endColor.
endColor: col


"This requires either a B3DVector4 or a B3DColor4 "
	endColor _ col.
	self updateVars.
hasAttractor: attr


	attractors do:[:a | a = attr ifTrue:[^ true]].	
	^ false.
material


	^ material.
material: mat


	material _ mat.
removeAttractor: attr


	attractors remove: attr.	
setAccelerationRangeMin: min max: max


	accelerationRange _ TBox min: min max: max.
setLifetimeFrom: from to: to


	lifetimeRange _ from to: to.
	1 to: size do:[:index | pLifetime at: index put: (lifetimeRange max atRandom).].
	self updateVars.
setLifetimeRange: range


	lifetimeRange _ range.
	1 to: size do:[:index | pLifetime at: index put: (lifetimeRange max atRandom).].
	self updateVars.
setPositionRangeMin: min max: max


	positionRange _ TBox min: min max: max.
setVelocityRangeMin: min max: max


	velocityRange _ TBox min: min max: max.
startColor


	^ startColor.
startColor: col


"This requires either a B3DVector4 or a B3DColor4 "
	startColor _ col.
	self updateVars.
updateVars


	| |
	maxTime _ lifetimeRange max.
	endColor ifNotNil:[
		pColor ifNil:[ pColor _ B3DColor4Array new: size.
					pDeltaColor _ B3DColor4Array new: size.
				].
		].
	material ambientColor: startColor.
	material diffuseColor: startColor.

initialize
boundSphere

	| vbox bb |
	boundsChanged ifTrue:[
		boundBox _ positionRange copy.
		vbox _ velocityRange copy.
		lifetimeRange max timesRepeat:[
			bb _ boundBox addBox: (vbox * 0.001).
			boundBox _ boundBox unionBox: bb.
			vbox _ vbox addBox: (accelerationRange * 0.001).
			].
		boundSphere _ TBoundSphere localPosition: boundBox center radius: (boundBox diagonal/2.0).
		boundSphere frame: self.
		boundsChanged _ false.
		].
	^ boundSphere.
boundsChanged


	boundsChanged _ true.
initializeWithSize: sz


	super initialize.
	size _ sz.
	pPosition _ B3DVector3Array new: sz.
	pLastPosition _ B3DVector3Array new: sz.
	pVelocity _ B3DVector3Array new: sz.
	pAcceleration _ B3DVector3Array new: sz.
	pLifetime _ FloatArray new: sz.
	pColor _ nil.
	pDeltaColor _ nil.
	startColor _ B3DColor4 r:1.0  g:1.0 b:1.0 a:0.9.
	endColor _ nil. "default is to not change the color of particles over their lifetimes."
	material _ TMaterial new.
	material ambientColor: startColor.
	material diffuseColor: startColor.
	material fullBright: true.

	self setPositionRangeMin:(-0.1@-0.1@-0.1) max: (0.1@0.1@0.1).
	self setVelocityRangeMin:(-1.2@6.4@-1.2) max:(1.2@9.6@1.2).
	self setAccelerationRangeMin:(0@-10@0) max:(0@-8@0).
	self setLifetimeRange: (1500 to: 2000).
	maxTime _ lifetimeRange max.

	deltaTime _ 0.
	billBoard _ true.
	self updateVars.
	self boundsChanged.
	globalVelocity _ 0@0@0.
	lastStepTime _ 0.0.
	lastGlobalPosition _ nil.
	attractors _ OrderedCollection new.
	^self

render
determinePosition

	| msecs tt |
	msecs _ ((tt _ Croquet teaTime asFloat) - lastStepTime)asFloat.
	msecs = 0 ifTrue: [^self].
	deltaTime _ msecs.
	lastStepTime _ tt.
	lastGlobalPosition ifNotNil:[
		globalVelocity _ (self globalPosition - lastGlobalPosition)/msecs * 1000.0.
		].
	lastGlobalPosition _ self globalPosition.
doRender: ogl

	
	| secs transfer go |
	material enable: ogl.

	ogl glPointSize: 2.0. 
"	ogl	glBegin: GLPoints."
	ogl glPushMatrix.
	globalPosition _ self globalPosition.
	ogl glMultMatrixf: self globalTransform orthoNormInverse transposed.
	pLifetime -= deltaTime.
	secs _ deltaTime/1000.0.
	secs _ secs min: 0.1.
	attractors size > 0 ifTrue:[self doAttractors: secs].
	pPosition replaceFrom: 1 to: pPosition size with: pLastPosition startingAt: 1.
	pPosition += (pVelocity * secs).
	pVelocity += (pAcceleration * secs).
	go _ self globalOrientation.
	tpr _ go localBoxToGlobal: positionRange.
	tvr _ go localBoxToGlobal: velocityRange.
	tar _ go localBoxToGlobal: accelerationRange.
	ogl glLineWidth: 2.0.
	material enable: ogl.
	ogl glColor3fv: material ambientColor.
	1 to: size do:[:index |
		ogl	glBegin: GLLineStrip;
			glVertex3fv: (pPosition at: index);
			glVertex3fv:(pLastPosition at: index);
			glEnd.
		(pLifetime at: index) < 0.0 ifTrue:[self regenerate: index.].
		].
	material disable: ogl.
	transfer _ pPosition.
	pPosition _ pLastPosition.
	pLastPosition _ transfer.
	ogl glPopMatrix.
doRenderColor: ogl

	
	| secs transfer go |
	material enable: ogl.

	ogl glPointSize: 2.0. 
	ogl glPushMatrix.
	globalPosition _ self globalPosition.
	ogl glMultMatrixf: self globalTransform orthoNormInverse transposed.
	pLifetime -= deltaTime.
	secs _ deltaTime/1000.0.
	secs _ secs min: 0.1.
	attractors size > 0 ifTrue:[self doAttractors: secs].
	pPosition replaceFrom: 1 to: pPosition size with: pLastPosition startingAt: 1.
	pPosition += (pVelocity * secs).
	pVelocity += (pAcceleration * secs).
	go _ self globalOrientation.
	tpr _ go localBoxToGlobal: positionRange.
	tvr _ go localBoxToGlobal: velocityRange.
	tar _ go localBoxToGlobal: accelerationRange.
	pColor -= pDeltaColor*deltaTime.
	ogl glLineWidth: 2.0.
	1 to: size do:[:index |
		ogl	glColor3fv: (pColor at: index);
			glBegin: GLLineStrip;
			glVertex3fv: (pPosition at: index);
			glVertex3fv:(pLastPosition at: index);
			glEnd.
		(pLifetime at: index) < 0.0 ifTrue:[self regenerate: index.].
		].
"Transcript show: (self globalOrientation orthoNormInverse localPointToGlobal:globalVelocity); cr.
"	ogl glLineWidth: 2.0.
	material disable: ogl.
	transfer _ pPosition.
	pPosition _ pLastPosition.
	pLastPosition _ transfer.
	ogl glPopMatrix.
hasAlpha


	^ true.
regenerate: index


	| lt |
	lt _ lifetimeRange atRandom asFloat.
	pLifetime at: index put: lt.
	pPosition at: index put: (tpr atRandom: 1000)+globalPosition.
	pVelocity at: index put: (tvr atRandom: 1000)+globalVelocity.
	pAcceleration at: index put: (tar atRandom: 1000).
	pColor ifNotNil:[
		pColor at: index put: startColor.
		pDeltaColor at: index put: (startColor - endColor)/lt.
		].

"
	a _ Float pi*(500-(1000 atRandom))/500.0.

	x _ a cos.
	z _ a sin.

	a _ Float pi*(500-(1000 atRandom))/1000.0.
	x2 _ a cos.
	gp _ (attractors at: 1) globalPosition.
	r_1.0+(attractors at:1)radius.
	x_ x*x2*r.
	y _ a sin*r.
	z_ z*x2*r.
	pPosition at: index put:gp+(x@y@z).
"
	
render: space


	self hasAlpha ifFalse:[
		self determinePosition.
		pColor
			ifNil:[self doRender: space]
			ifNotNil:[self doRenderColor: space]
		].
	
renderAlpha: ogl


	self determinePosition.	
	self doRender: ogl
	

stepping
doAttractors: secs


	| loc v n |

	attractors do:[:attr |  
		attr hard ifTrue:[
			loc_attr globalPosition.
			1 to: size do:[:index | attrArray at: index put: loc.].
			attrArray -= pLastPosition.
			attrArray squaredLengthInto: lengthArray.
			attrArray divideByArray: (lengthArray sqrted).
			1 to: size do:[:index | 
				(lengthArray at: index)<attr radiusSquared ifTrue:[ 
					v _ pVelocity at: index.			
					n _ attrArray at: index.
					pVelocity at:index put: v-(2*n*(v dot: n)).
					attrArray at: index put: (0.0@0.0@0.0). "This sets force inside sphere to 0"
				].
			].
			attrArray divideByArray: lengthArray.
			attrArray *= (attr mass*secs).
			pVelocity += attrArray.
		]ifFalse:[
			loc_attr globalPosition.
			1 to: size do:[:index | attrArray at: index put: loc.].
			attrArray -= pLastPosition.
			attrArray squaredLengthInto: lengthArray.
			attrArray divideByArray: (lengthArray sqrted).
			1 to: size do:[:index | 
				(lengthArray at: index)<attr radiusSquared ifTrue:[ 
				((lengthArray at: index))<(attr radiusSquared) ifTrue:[pLifetime at: index put:-1.]
				ifFalse:[
					v _ pVelocity at: index.			
					n _ attrArray at: index.
					pLastPosition at:index put: loc-(n*attr radius).
					attrArray at: index put: (0.0@0.0@0.0). 
				].
				].
			].
			attrArray divideByArray: lengthArray.
			attrArray *= (attr mass*secs).
			pVelocity += attrArray.
		].
	].

testing
isComponent


	^ true.

class methods:

^top


- made by Dandelion -