1228 lines
35 KiB
C++
1228 lines
35 KiB
C++
#include "CKAll.h"
|
|
#include <time.h>
|
|
|
|
#include "ParticleEmitter.h"
|
|
#include "ParticleManager.h"
|
|
#include "ParticleSystemRenderCallbacks.h"
|
|
|
|
// 128 Bytes to have 16 bytes aligned data for Pentium3 optimisations 32 DWORDS
|
|
BYTE _PS_AlignedMemory[128];
|
|
|
|
DWORD* g_PS_AlignZone =(DWORD *)((DWORD)(_PS_AlignedMemory + 15) & 0xFFFFFFF0);
|
|
float* g_Min =(float *)g_PS_AlignZone; // 16 Bytes (4 floats) +4
|
|
float* g_Max =(float *)(g_PS_AlignZone+4); // 16 Bytes (4 floats) +8
|
|
float* g_One =(float *)(g_PS_AlignZone+8); // 16 Bytes (4 floats) +12 (1.0f,1.0f,1.0f,1.0f);
|
|
float* g_Delta =(float *)(g_PS_AlignZone+12); // 16 Bytes (4 floats) +16 (delta,delta,delta,delta);
|
|
|
|
WORD* ParticleEmitter::m_GlobalIndices = 0;
|
|
int ParticleEmitter::m_GlobalIndicesCount = 0;
|
|
|
|
// Constructeur
|
|
ParticleEmitter::ParticleEmitter(CKContext* ctx,CK_ID entity,char* name)
|
|
{
|
|
m_Context = ctx;
|
|
|
|
g_One[0]=g_One[1]=g_One[2]=g_One[3]=1.0f;
|
|
m_MaximumParticles = 100;
|
|
m_BackPool = NULL;
|
|
m_InteractorsFlags = 0;
|
|
|
|
m_YawVariation = 0;
|
|
m_PitchVariation = 0;
|
|
m_Speed = 0;
|
|
m_SpeedVariation = 0;
|
|
m_AngularSpeed = 0;
|
|
m_AngularSpeedVariation = 0;
|
|
|
|
totalParticles = 0;
|
|
particleCount = 0;
|
|
emitsPerFrame = 0;
|
|
emitsVar = 0;
|
|
m_Life = 0;
|
|
m_LifeVariation = 0;
|
|
m_StartSize = 0;
|
|
m_StartSizeVar = 0;
|
|
m_EndSize = 0;
|
|
m_EndSizeVar = 0;
|
|
m_Weight = 0;
|
|
m_WeightVariation = 0;
|
|
m_Surface = 0;
|
|
m_SurfaceVariation = 0;
|
|
m_Bounce = 0;
|
|
m_BounceVariation = 0;
|
|
m_StartColor.r = 0.6f;
|
|
m_StartColor.g = 0.6f;
|
|
m_StartColor.b = 0.8f;
|
|
m_StartColor.b = 1.0f;
|
|
m_StartColorVar.r = 0.0f;
|
|
m_StartColorVar.g = 0.0f;
|
|
m_StartColorVar.b = 0.0f;
|
|
m_StartColorVar.a = 0.0f;
|
|
m_EndColor.r = 0.0f;
|
|
m_EndColor.g = 0.0f;
|
|
m_EndColor.b = 0.0f;
|
|
m_EndColor.a = 0.0f;
|
|
m_EndColorVar.r = 0.0f;
|
|
m_EndColorVar.g = 0.0f;
|
|
m_EndColorVar.b = 0.0f;
|
|
m_EndColorVar.a = 0.0f;
|
|
m_InitialTextureFrame = 0;
|
|
m_InitialTextureFrameVariance = 0;
|
|
m_SpeedTextureFrame = 0;
|
|
m_SpeedTextureFrameVariance = 0;
|
|
m_TextureFrameCount = 0;
|
|
m_TextureFrameloop = FALSE;
|
|
m_EvolutionsFlags = 0;
|
|
m_VariancesFlags = 0;
|
|
m_InteractorsFlags = 0;
|
|
m_DeflectorsFlags = 0;
|
|
m_RenderMode = 3;
|
|
m_TrailCount = 0;
|
|
m_RadialParticleOffset = 0.f;
|
|
|
|
m_Mesh = 0;
|
|
m_Entity = entity;
|
|
CK3dEntity* ent = (CK3dEntity*)m_Context->GetObject(m_Entity);
|
|
if (ent)
|
|
m_EntityBbox = ent->GetBoundingBox(TRUE);
|
|
|
|
m_Texture = 0;
|
|
m_Group = 0;
|
|
m_MessageType = -1;
|
|
|
|
m_CurrentImpact = 0;
|
|
m_Behavior = NULL;
|
|
#ifdef WIN32
|
|
// ACC, July 10, 2002 Create Event to be waited in Render CB
|
|
hasBeenComputedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
hasBeenRendered =false;
|
|
hasBeenEnqueud =false;
|
|
#endif
|
|
|
|
InitParticleSystem();
|
|
};
|
|
|
|
#ifdef USE_THR
|
|
#include "blockingqueue.h"
|
|
#include "GeneralParticleSystem.h"
|
|
|
|
extern BlockingQueue<ThreadParam> PSqueue;
|
|
|
|
#endif
|
|
|
|
// Destructeur
|
|
ParticleEmitter::~ParticleEmitter()
|
|
{
|
|
#ifdef USE_THR
|
|
|
|
if (hasBeenEnqueud) {
|
|
WaitForSingleObject(hasBeenComputedEvent, INFINITE);
|
|
|
|
while (hasBeenEnqueud) {
|
|
int a = 0;
|
|
}
|
|
}
|
|
|
|
EnterCriticalSection(&PSqueue.mGuardAccess);
|
|
for (list<ThreadParam>::iterator it = PSqueue.mQueue.begin(); it != PSqueue.mQueue.end(); ) {
|
|
if (it->pe == this) {
|
|
it = PSqueue.mQueue.erase(it);
|
|
int a = 0;
|
|
} else ++it;
|
|
}
|
|
LeaveCriticalSection(&PSqueue.mGuardAccess);
|
|
|
|
#endif
|
|
|
|
delete [] m_BackPool;
|
|
m_BackPool = NULL;
|
|
CK3dEntity* ent = (CK3dEntity*)m_Context->GetObject(m_Entity);
|
|
if (ent)
|
|
ent->SetBoundingBox(&m_EntityBbox, TRUE);
|
|
m_Entity = 0;
|
|
#ifdef WIN32
|
|
CloseHandle(hasBeenComputedEvent);
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
ParticleEmitter::InitParticleSystem()
|
|
{
|
|
if(m_BackPool) {
|
|
delete [] m_BackPool;
|
|
m_BackPool = NULL;
|
|
}
|
|
m_BackPool = new BYTE[m_MaximumParticles*sizeof(Particle)+16];
|
|
memset(m_BackPool,0,m_MaximumParticles*sizeof(Particle)+16);
|
|
|
|
m_Pool = (Particle *)((DWORD)(m_BackPool + 15) & 0xFFFFFFF0);
|
|
for (int loop = 0; loop < m_MaximumParticles - 1; loop++)
|
|
{
|
|
m_Pool[loop].next = &m_Pool[loop + 1];
|
|
}
|
|
m_Pool[m_MaximumParticles - 1].next = NULL;
|
|
particles = NULL;
|
|
particleCount = 0;
|
|
|
|
// Clear Historic pool.
|
|
old_pos.Clear();
|
|
old_pos.Reserve(m_MaximumParticles);
|
|
for (int i = 0; i < m_MaximumParticles; i++)
|
|
old_pos.PushBack(ParticleHistoric(m_TrailCount));
|
|
}
|
|
|
|
void
|
|
ParticleEmitter::UpdateParticles(float rdeltat)
|
|
{
|
|
ParticleManager* pm = m_Manager;
|
|
|
|
//--- Kill over-max-number particles
|
|
if( totalParticles < particleCount ){
|
|
int pCount = particleCount;
|
|
Particle* p = particles;
|
|
while( p && totalParticles<pCount ) {
|
|
|
|
p->m_Life = -1;
|
|
p = p->next;
|
|
|
|
--pCount;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// We clear the impact array
|
|
m_Impacts.Clear();
|
|
m_CurrentImpact = 0;
|
|
|
|
float deltat;
|
|
Particle* particle=particles;
|
|
// If there is no particles yet, we buzz off
|
|
if(!particles) return;
|
|
|
|
VxVector minv(100000,100000,100000),maxv(-100000,-100000,-100000);
|
|
g_Min[0]=g_Min[1]=g_Min[2]=g_Min[3]=1e6f;
|
|
g_Max[0]=g_Max[1]=g_Max[2]=g_Max[3]=-1e6f;
|
|
|
|
///
|
|
// Interactors management
|
|
|
|
// Gravity
|
|
float gravityForce = 0.0f;
|
|
if (m_InteractorsFlags & PI_GRAVITY) {
|
|
const XObjectPointerArray& Array = m_Context->GetAttributeManager()->GetAttributeListPtr(pm->m_GravityAttribute);
|
|
|
|
for (CKObject** it = Array.Begin(); it != Array.End(); ++it) {
|
|
// we get attribute owner
|
|
CKBeObject* ent = (CKBeObject*)*it;
|
|
|
|
// we get the attribute value
|
|
CKParameterOut* pout = ent->GetAttributeParameter(pm->m_GravityAttribute);
|
|
|
|
float f = 0.0f;
|
|
pout->GetValue(&f);
|
|
|
|
gravityForce += f;
|
|
}
|
|
|
|
gravityForce *= rdeltat;
|
|
}
|
|
|
|
|
|
if(m_InteractorsFlags & PI_ATMOSPHERE) pm->ManageAtmosphere(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_GLOBALWIND) pm->ManageGlobalWind(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_LOCALWIND) pm->ManageLocalWind(this,rdeltat);
|
|
// The magnet act on the position so it came after positionning
|
|
if(m_InteractorsFlags & PI_MAGNET) pm->ManageMagnet(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_VORTEX) pm->ManageVortex(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_DISRUPTIONBOX) pm->ManageDisruptionBox(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_MUTATIONBOX) pm->ManageMutationBox(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_TUNNEL) pm->ManageTunnel(this,rdeltat);
|
|
if(m_InteractorsFlags & PI_PROJECTOR) pm->ManageProjector(this,rdeltat);
|
|
|
|
|
|
// Disable SSE code generation for this file
|
|
// cause of interferences with hand made asm optimizations
|
|
#if (_M_IX86_FP != 0)
|
|
#error "Cannot Compile this file with the /arch SSE or SS2"
|
|
#endif
|
|
|
|
DWORD ProcessorFeatures = GetProcessorFeatures();
|
|
#ifdef SIMD_SUPPORTED
|
|
if (ProcessorFeatures & PROC_SIMD) {
|
|
__asm {
|
|
// preload katmai registers
|
|
mov esi,g_Min
|
|
mov edi,g_Max
|
|
mov edx,g_One
|
|
|
|
movaps xmm7,[edi] // Load Max
|
|
movaps xmm6,[esi] // Load Min
|
|
movaps xmm5,[edx] // Load One
|
|
xorps xmm3,xmm3 // Zero xmm3
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
while(particle) {
|
|
// IF THIS IS AN VALID PARTICLE
|
|
if (particle->m_Life > 0) {
|
|
if(particle->m_Life < rdeltat) {
|
|
deltat = particle->m_Life;
|
|
} else {
|
|
deltat = rdeltat;
|
|
}
|
|
|
|
particle->prevpos = particle->pos;
|
|
|
|
// Gravity management
|
|
particle->dir.y += gravityForce*particle->m_Weight;
|
|
|
|
#ifdef SIMD_SUPPORTED
|
|
if (ProcessorFeatures & PROC_SIMD) {
|
|
__asm {
|
|
lea ecx,[deltat]
|
|
mov ebx,particle
|
|
|
|
movss xmm0,[ecx] // Load delta factor
|
|
movaps xmm2,[ebx+16] // Load Delta Color
|
|
shufps xmm0,xmm0,0 // propagate delta to 4 floats
|
|
|
|
mulps xmm2,xmm0 // Delta Color * delta Factor
|
|
movaps xmm4,[ebx+48] // Load Delta position + Delta Angle
|
|
|
|
addps xmm2,[ebx] // Add to original color
|
|
mulps xmm4,xmm0 // Delta Position * delta Factor
|
|
|
|
minps xmm6,[ebx+32] // compute minpos before adding delta
|
|
maxps xmm7,[ebx+32] // compute maxpos before adding delta
|
|
|
|
minps xmm2,xmm5 // Ceil Color to One
|
|
addps xmm4,[ebx+32] // Add to original position
|
|
|
|
maxps xmm2,xmm3 // Floor to Zero
|
|
movaps [ebx+32],xmm4 // Store position
|
|
|
|
movaps [ebx],xmm2 // Store Color
|
|
|
|
minps xmm6,xmm4 // compute minpos
|
|
maxps xmm7,xmm4 // compute maxpos
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
// Calculating new angle
|
|
particle->m_Angle += particle->m_DeltaAngle*deltat;
|
|
|
|
if(particle->pos.x < minv.x) {
|
|
minv.x = particle->pos.x;
|
|
}
|
|
if(particle->pos.y < minv.y) {
|
|
minv.y = particle->pos.y;
|
|
}
|
|
if(particle->pos.z < minv.z) {
|
|
minv.z = particle->pos.z;
|
|
}
|
|
if( maxv.x < particle->pos.x) {
|
|
maxv.x = particle->pos.x;
|
|
}
|
|
if( maxv.y < particle->pos.y) {
|
|
maxv.y = particle->pos.y;
|
|
}
|
|
if( maxv.z < particle->pos.z) {
|
|
maxv.z = particle->pos.z;
|
|
}
|
|
|
|
// CALCULATE THE NEW
|
|
particle->pos += (particle->dir*deltat);
|
|
|
|
//////////////////////////////
|
|
// BOUNDING BOX UPDATING
|
|
//////////////////////////////
|
|
|
|
if(particle->pos.x < minv.x) {
|
|
minv.x = particle->pos.x;
|
|
}
|
|
if(particle->pos.y < minv.y) {
|
|
minv.y = particle->pos.y;
|
|
}
|
|
if(particle->pos.z < minv.z) {
|
|
minv.z = particle->pos.z;
|
|
}
|
|
if( maxv.x < particle->pos.x) {
|
|
maxv.x = particle->pos.x;
|
|
}
|
|
if( maxv.y < particle->pos.y) {
|
|
maxv.y = particle->pos.y;
|
|
}
|
|
if( maxv.z < particle->pos.z) {
|
|
maxv.z = particle->pos.z;
|
|
}
|
|
|
|
/////////////////////////////
|
|
// EVOLUTIONS MANAGEMENT
|
|
/////////////////////////////
|
|
|
|
// color management
|
|
if(m_EvolutionsFlags & PE_COLOR) {
|
|
particle->m_Color.r += particle->deltaColor.r*deltat;
|
|
if(particle->m_Color.r < 0.0f) particle->m_Color.r = 0.0f;
|
|
else if(particle->m_Color.r > 1.0f) particle->m_Color.r = 1.0f;
|
|
particle->m_Color.g += particle->deltaColor.g*deltat;
|
|
if(particle->m_Color.g < 0.0f) particle->m_Color.g = 0.0f;
|
|
else if(particle->m_Color.g > 1.0f) particle->m_Color.g = 1.0f;
|
|
particle->m_Color.b += particle->deltaColor.b*deltat;
|
|
if(particle->m_Color.b < 0.0f) particle->m_Color.b = 0.0f;
|
|
else if(particle->m_Color.b > 1.0f) particle->m_Color.b = 1.0f;
|
|
particle->m_Color.a += particle->deltaColor.a*deltat;
|
|
if(particle->m_Color.a < 0.0f) particle->m_Color.a = 0.0f;
|
|
else if(particle->m_Color.a > 1.0f) particle->m_Color.a = 1.0f;
|
|
}
|
|
|
|
|
|
}
|
|
// Size management
|
|
if (m_EvolutionsFlags & PE_SIZE) particle->m_Size += particle->m_DeltaSize*deltat;
|
|
|
|
// texture management
|
|
if (particle->m_DeltaFrametime)
|
|
if (m_EvolutionsFlags & PE_TEXTURE && m_RenderMode!=PR_OBJECT) {
|
|
particle->m_CurrentFrametime += deltat;
|
|
float dft = particle->m_DeltaFrametime;
|
|
int tfi = 1;
|
|
if(particle->m_DeltaFrametime < 0) {
|
|
dft = -particle->m_DeltaFrametime;
|
|
tfi = -1;
|
|
}
|
|
while(particle->m_CurrentFrametime > dft) {
|
|
particle->m_CurrentFrame+=tfi;
|
|
if(particle->m_CurrentFrame >= m_TextureFrameCount) {
|
|
switch(m_TextureFrameloop) {
|
|
case PL_NOLOOP:particle->m_CurrentFrame = m_TextureFrameCount-1;
|
|
break;
|
|
case PL_LOOP:particle->m_CurrentFrame = 0;
|
|
break;
|
|
case PL_PINGPONG:
|
|
particle->m_CurrentFrame = m_TextureFrameCount-2;
|
|
particle->m_DeltaFrametime = -particle->m_DeltaFrametime;
|
|
break;
|
|
}
|
|
} else {
|
|
if(particle->m_CurrentFrame < 0) {
|
|
switch(m_TextureFrameloop) {
|
|
case PL_NOLOOP:particle->m_CurrentFrame = 0;
|
|
break;
|
|
case PL_LOOP:particle->m_CurrentFrame = m_TextureFrameCount-1;
|
|
break;
|
|
case PL_PINGPONG:
|
|
particle->m_CurrentFrame = 1;
|
|
particle->m_DeltaFrametime = -particle->m_DeltaFrametime;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
particle->m_CurrentFrametime -= dft;
|
|
}
|
|
}
|
|
|
|
// New lifespan
|
|
particle->m_Life -= deltat;
|
|
// new delta time
|
|
particle->m_DeltaTime = deltat;
|
|
|
|
// Updates trail position.
|
|
if (m_TrailCount)
|
|
{
|
|
int idx = ((BYTE*)particle - m_BackPool) / sizeof (Particle);
|
|
XASSERT(idx < m_MaximumParticles);
|
|
ParticleHistoric &ph = old_pos[idx];
|
|
if (ph.count == m_TrailCount)
|
|
{
|
|
ph.particles[ph.start++] = *particle;
|
|
if (ph.start >= m_TrailCount)
|
|
ph.start = 0;
|
|
}
|
|
else
|
|
ph.particles[ph.count++] = *particle;
|
|
}
|
|
particle = particle->next;
|
|
} else {
|
|
// Delete particle
|
|
if (m_TrailCount)
|
|
{
|
|
int idx = ((BYTE*)particle - m_BackPool) / sizeof (Particle);
|
|
XASSERT(idx < m_MaximumParticles);
|
|
ParticleHistoric &ph = old_pos[idx];
|
|
ph.start = 0;
|
|
ph.count = 0;
|
|
}
|
|
Particle*tmp = particle->next;
|
|
if (particle->prev) particle->prev->next = particle->next;
|
|
else particles = particle->next;
|
|
if (particle->next) particle->next->prev = particle->prev;
|
|
particle->next = m_Pool;
|
|
m_Pool = particle; // NEW POOL POINTER
|
|
particleCount--; // ADD ONE TO POOL
|
|
particle = tmp;
|
|
}
|
|
}
|
|
|
|
VxBbox bbox;
|
|
#ifdef SIMD_SUPPORTED
|
|
if (ProcessorFeatures & PROC_SIMD) {
|
|
__asm {
|
|
// preload katmai registers
|
|
mov esi,g_Min
|
|
mov edi,g_Max
|
|
movaps [esi],xmm6 // Save Min
|
|
movaps [edi],xmm7 // Save Max
|
|
}
|
|
bbox.Min = *(VxVector *)g_Min;
|
|
bbox.Max = *(VxVector *)g_Max;
|
|
|
|
} else
|
|
#endif
|
|
{
|
|
bbox.Min = minv;
|
|
bbox.Max = maxv;
|
|
}
|
|
CK3dEntity* entity = (CK3dEntity*)m_Context->GetObject(m_Entity);
|
|
if (particleCount>0) {
|
|
float particleExtent = XMax(m_StartSize + m_StartSizeVar, m_EndSize + m_EndSizeVar);
|
|
bbox.Max.x += particleExtent;
|
|
bbox.Max.y += particleExtent;
|
|
bbox.Max.z += particleExtent;
|
|
bbox.Min.x -= particleExtent;
|
|
bbox.Min.y -= particleExtent;
|
|
bbox.Min.z -= particleExtent;
|
|
//The real bbox is the union between the object box and the particules box
|
|
VxBbox real_bbox;
|
|
real_bbox.TransformFrom(m_EntityBbox, entity->GetWorldMatrix());
|
|
real_bbox.Merge(bbox.Max);
|
|
real_bbox.Merge(bbox.Min);
|
|
entity->SetBoundingBox(&real_bbox);
|
|
|
|
// enlarge with particle sizes
|
|
}
|
|
else {
|
|
entity->SetBoundingBox(&m_EntityBbox, TRUE);
|
|
}
|
|
|
|
// Deflectors management
|
|
if(m_DeflectorsFlags & PD_PLANE) pm->ManagePlaneDeflectors(this,rdeltat);
|
|
if(m_DeflectorsFlags & PD_INFINITEPLANE) pm->ManageInfinitePlaneDeflectors(this,rdeltat);
|
|
if(m_DeflectorsFlags & PD_CYLINDER) pm->ManageCylinderDeflectors(this,rdeltat);
|
|
if(m_DeflectorsFlags & PD_SPHERE) pm->ManageSphereDeflectors(this,rdeltat);
|
|
if(m_DeflectorsFlags & PD_BOX) pm->ManageBoxDeflectors(this,rdeltat);
|
|
if(m_DeflectorsFlags & PD_OBJECT) pm->ManageObjectDeflectors(this,rdeltat);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
ParticleEmitter::AddParticles()
|
|
{
|
|
// emits particles for this frame
|
|
int emits;
|
|
if(m_VariancesFlags & PV_EMISSION) {
|
|
emits = emitsPerFrame + (int)((float)emitsVar * RANDNUM);
|
|
} else {
|
|
emits = emitsPerFrame;
|
|
}
|
|
if(emits<=0) return;
|
|
|
|
do {
|
|
if (m_Pool != NULL && particleCount < totalParticles)
|
|
{
|
|
Particle *p;
|
|
p = m_Pool;
|
|
m_Pool = m_Pool->next;
|
|
|
|
if (particles != NULL) particles->prev = p;
|
|
p->next = particles;
|
|
p->prev = NULL;
|
|
particleCount++;
|
|
particles = p;
|
|
|
|
// Calculate the initial Position
|
|
InitiateParticle(p);
|
|
|
|
// CALCULATE THE STARTING DIRECTION VECTOR
|
|
InitiateDirection(p);
|
|
|
|
// Initiate density
|
|
p->m_Density = rand()*INV_RAND;
|
|
|
|
// Calculate the speed
|
|
if(m_VariancesFlags & PV_SPEED) {
|
|
p->dir *= m_Speed + (m_SpeedVariation * RANDNUM);
|
|
} else {
|
|
p->dir *= m_Speed;
|
|
}
|
|
|
|
switch(m_RenderMode) {
|
|
case PR_LINE:
|
|
case PR_OSPRITE:
|
|
case PR_CSPRITE:
|
|
// we manage here latency
|
|
p->m_Angle = m_AngularSpeed;
|
|
p->m_DeltaAngle = m_AngularSpeedVariation;
|
|
break;
|
|
case PR_SPRITE:
|
|
case PR_FSPRITE:
|
|
p->m_Angle = 0;
|
|
if(m_VariancesFlags & PV_ANGULARSPEED) {
|
|
p->m_DeltaAngle = m_AngularSpeed + m_AngularSpeedVariation*RANDNUM;
|
|
} else {
|
|
p->m_DeltaAngle = 0;
|
|
}
|
|
break;
|
|
case PR_OBJECT:
|
|
{
|
|
CKGroup* group = (CKGroup*)m_Context->GetObject(m_Group);
|
|
int oc;
|
|
if(group) oc = group->GetObjectCount();
|
|
else oc=0;
|
|
p->m_GroupIndex = (int)(oc*((float)rand()*INV_RAND));
|
|
p->m_Angle = 0;
|
|
if(m_VariancesFlags & PV_ANGULARSPEED) {
|
|
p->m_DeltaAngle = m_AngularSpeed + m_AngularSpeedVariation*RANDNUM;
|
|
} else {
|
|
p->m_DeltaAngle = 0;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
p->m_Angle = 0;
|
|
p->m_DeltaAngle = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
////////////////////////
|
|
// LifeSpan Management
|
|
////////////////////////
|
|
if(m_VariancesFlags & PV_LIFESPAN) {
|
|
p->m_Life = m_Life + m_LifeVariation * RANDNUM;
|
|
} else {
|
|
p->m_Life = m_Life;
|
|
}
|
|
float invlife = 1.0f/p->m_Life;
|
|
|
|
////////////////////////
|
|
// Color Management
|
|
////////////////////////
|
|
|
|
// Initial Color
|
|
if(m_VariancesFlags & PV_INITIALCOLOR) {
|
|
p->m_Color.r = m_StartColor.r + (m_StartColorVar.r * RANDNUM);
|
|
p->m_Color.g = m_StartColor.g + (m_StartColorVar.g * RANDNUM);
|
|
p->m_Color.b = m_StartColor.b + (m_StartColorVar.b * RANDNUM);
|
|
p->m_Color.a = m_StartColor.a + (m_StartColorVar.a * RANDNUM);
|
|
} else {
|
|
p->m_Color = m_StartColor;
|
|
}
|
|
// Color Delta
|
|
if(m_EvolutionsFlags & PE_COLOR) {
|
|
if(m_VariancesFlags & PV_ENDINGCOLOR) {
|
|
p->deltaColor.r = ((m_EndColor.r + (m_EndColorVar.r * RANDNUM)) - p->m_Color.r) * invlife;
|
|
p->deltaColor.g = ((m_EndColor.g + (m_EndColorVar.g * RANDNUM)) - p->m_Color.g) * invlife;
|
|
p->deltaColor.b = ((m_EndColor.b + (m_EndColorVar.b * RANDNUM)) - p->m_Color.b) * invlife;
|
|
p->deltaColor.a = ((m_EndColor.a + (m_EndColorVar.a * RANDNUM)) - p->m_Color.a) * invlife;
|
|
} else {
|
|
p->deltaColor.r = (m_EndColor.r - p->m_Color.r) * invlife;
|
|
p->deltaColor.g = (m_EndColor.g - p->m_Color.g) * invlife;
|
|
p->deltaColor.b = (m_EndColor.b - p->m_Color.b) * invlife;
|
|
p->deltaColor.a = (m_EndColor.a - p->m_Color.a) * invlife;
|
|
}
|
|
} else {
|
|
p->deltaColor.r = 0;
|
|
p->deltaColor.g = 0;
|
|
p->deltaColor.b = 0;
|
|
p->deltaColor.a = 0;
|
|
}
|
|
|
|
/////////////////////////
|
|
// Size Management
|
|
/////////////////////////
|
|
|
|
// Initial Size
|
|
if(m_VariancesFlags & PV_INITIALSIZE) {
|
|
p->m_Size = m_StartSize + (m_StartSizeVar * RANDNUM);
|
|
} else {
|
|
p->m_Size = m_StartSize;
|
|
}
|
|
// Size Delta
|
|
if(m_EvolutionsFlags & PE_SIZE) {
|
|
if(m_VariancesFlags & PV_ENDINGSIZE) {
|
|
p->m_DeltaSize = (m_EndSize + (m_EndSizeVar * RANDNUM) - p->m_Size) * invlife;
|
|
} else {
|
|
p->m_DeltaSize = (m_EndSize - p->m_Size) * invlife;
|
|
}
|
|
} else {
|
|
p->m_DeltaSize = 0;
|
|
}
|
|
|
|
/////////////////////////
|
|
// Texture management
|
|
/////////////////////////
|
|
|
|
switch(m_RenderMode) {
|
|
case PR_SPRITE:
|
|
case PR_FSPRITE:
|
|
case PR_OSPRITE:
|
|
case PR_CSPRITE:
|
|
case PR_RSPRITE:
|
|
// Initial Texture
|
|
if(m_VariancesFlags & PV_INITIALTEXTURE) {
|
|
p->m_CurrentFrame = m_InitialTextureFrame + (int)(m_InitialTextureFrameVariance * RANDNUMP);
|
|
} else {
|
|
p->m_CurrentFrame = m_InitialTextureFrame;
|
|
}
|
|
|
|
// Initialisation of the current frame time
|
|
p->m_CurrentFrametime = 0;
|
|
|
|
// Texture Delta time
|
|
if ((m_EvolutionsFlags & PE_TEXTURE) && (m_TextureFrameCount>1)){
|
|
if(m_VariancesFlags & PV_SPEEDTEXTURE) {
|
|
p->m_DeltaFrametime = m_SpeedTextureFrame + m_SpeedTextureFrameVariance*RANDNUM;
|
|
} else {
|
|
p->m_DeltaFrametime = (float)m_SpeedTextureFrame;
|
|
}
|
|
} else {
|
|
p->m_DeltaFrametime = 0;
|
|
}
|
|
break;
|
|
default:
|
|
p->m_DeltaFrametime = 0;
|
|
break;
|
|
}
|
|
|
|
//////////////////////////
|
|
// Deflectors Management
|
|
//////////////////////////
|
|
|
|
// Particle Bouncing factor
|
|
if(m_DeflectorsFlags) {
|
|
if(m_VariancesFlags & PV_BOUNCE) {
|
|
p->m_Bounce = m_Bounce+(m_BounceVariation*RANDNUM);
|
|
} else {
|
|
p->m_Bounce = m_Bounce;
|
|
}
|
|
}
|
|
|
|
//////////////////////////
|
|
// Interactors Management
|
|
//////////////////////////
|
|
|
|
// Particle Weight
|
|
if(m_InteractorsFlags&PI_GRAVITY) {
|
|
if(m_VariancesFlags & PV_WEIGHT) {
|
|
p->m_Weight = m_Weight+(m_WeightVariation * RANDNUM);
|
|
} else {
|
|
p->m_Weight = m_Weight;
|
|
}
|
|
}
|
|
|
|
// Time Management
|
|
p->m_DeltaTime = 0.01f;
|
|
|
|
// Particle Surface
|
|
if(m_InteractorsFlags&(PI_LOCALWIND|PI_GLOBALWIND|PI_ATMOSPHERE)) {
|
|
if(m_VariancesFlags & PV_SURFACE) {
|
|
p->m_Surface = m_Surface+(m_SurfaceVariation * RANDNUM);
|
|
} else {
|
|
p->m_Surface = m_Surface;
|
|
}
|
|
}
|
|
} else break;
|
|
} while(--emits);
|
|
}
|
|
|
|
void
|
|
ParticleEmitter::InitiateDirection(Particle* p)
|
|
{
|
|
VxVector dir;
|
|
CK3dEntity* entity = (CK3dEntity*)m_Context->GetObject(m_Entity);
|
|
dir.z = cosf(m_PitchVariation * RANDNUM);
|
|
dir.x = dir.z * sinf(m_YawVariation * RANDNUM);
|
|
dir.z *= cosf(m_YawVariation * RANDNUM);
|
|
dir.y = sinf(m_PitchVariation * RANDNUM);
|
|
entity->TransformVector(&(p->dir),&dir);
|
|
}
|
|
|
|
void
|
|
ParticleEmitter::ReadInputs(CKBehavior* beh)
|
|
{
|
|
beh->GetInputParameterValue(YAWVARIATION,&m_YawVariation);
|
|
beh->GetInputParameterValue(PITCHVARIATION,&m_PitchVariation);
|
|
beh->GetInputParameterValue(SPEED,&m_Speed);
|
|
if(m_VariancesFlags & PV_SPEED) beh->GetInputParameterValue(SPEEDVARIATION,&m_SpeedVariation);
|
|
beh->GetInputParameterValue(ANGSPEED,&m_AngularSpeed);
|
|
if(m_VariancesFlags & PV_ANGULARSPEED) beh->GetInputParameterValue(ANGSPEEDVARIATION,&m_AngularSpeedVariation);
|
|
|
|
////////
|
|
// Size
|
|
////////
|
|
// Initial Size
|
|
beh->GetInputParameterValue(STARTSIZE,&m_StartSize);
|
|
if(m_VariancesFlags & PV_INITIALSIZE) {
|
|
beh->GetInputParameterValue(STARTSIZEVARIANCE,&m_StartSizeVar);
|
|
}
|
|
// End Size
|
|
if(m_EvolutionsFlags & PE_SIZE) {
|
|
beh->GetInputParameterValue(ENDSIZE,&m_EndSize);
|
|
if(m_VariancesFlags & PV_ENDINGSIZE) {
|
|
beh->GetInputParameterValue(ENDSIZEVARIANCE,&m_EndSizeVar);
|
|
}
|
|
}
|
|
|
|
beh->GetInputParameterValue(LIFE,&m_Life);
|
|
if(m_VariancesFlags & PV_LIFESPAN) beh->GetInputParameterValue(LIFEVARIATION,&m_LifeVariation);
|
|
|
|
beh->GetInputParameterValue(NUMBER,&totalParticles);
|
|
|
|
beh->GetInputParameterValue(EMITION,&emitsPerFrame);
|
|
if(m_VariancesFlags & PV_EMISSION) beh->GetInputParameterValue(EMITIONVARIATION,&emitsVar);
|
|
|
|
///////////
|
|
// Colors
|
|
///////////
|
|
// Initial Color
|
|
beh->GetInputParameterValue(STARTCOLOR,&m_StartColor);
|
|
if(m_VariancesFlags & PV_INITIALCOLOR) {
|
|
beh->GetInputParameterValue(STARTCOLORVARIANCE,&m_StartColorVar);
|
|
}
|
|
// Ending Color
|
|
if(m_EvolutionsFlags & PE_COLOR) {
|
|
beh->GetInputParameterValue(ENDCOLOR,&m_EndColor);
|
|
if(m_VariancesFlags & PV_ENDINGCOLOR) {
|
|
beh->GetInputParameterValue(ENDCOLORVARIANCE,&m_EndColorVar);
|
|
}
|
|
}
|
|
|
|
///////////
|
|
// Textures
|
|
///////////
|
|
|
|
// We get the texture
|
|
beh->GetInputParameterValue(TEXTURE,&m_Texture);
|
|
|
|
// Initial Texture
|
|
beh->GetInputParameterValue(STARTTEXTURE,&m_InitialTextureFrame);
|
|
if(m_VariancesFlags & PV_INITIALTEXTURE) {
|
|
beh->GetInputParameterValue(STARTTEXTUREVARIANCE,&m_InitialTextureFrameVariance);
|
|
}
|
|
|
|
// Speed Texture
|
|
if(m_EvolutionsFlags & PE_TEXTURE) {
|
|
beh->GetInputParameterValue(SPEEDTEXTURE,&m_SpeedTextureFrame);
|
|
if(m_VariancesFlags & PV_SPEEDTEXTURE) {
|
|
beh->GetInputParameterValue(SPEEDTEXTUREVARIANCE,&m_SpeedTextureFrameVariance);
|
|
}
|
|
}
|
|
|
|
// Texture Count
|
|
beh->GetInputParameterValue(TEXTURECOUNT,&m_TextureFrameCount);
|
|
|
|
// Texture Loop
|
|
beh->GetInputParameterValue(TEXTURELOOP,&m_TextureFrameloop);
|
|
|
|
// Deflectors parameter
|
|
if(m_DeflectorsFlags) {
|
|
beh->GetInputParameterValue(BOUNCE,&m_Bounce);
|
|
if(m_VariancesFlags & PV_BOUNCE) beh->GetInputParameterValue(BOUNCEVARIATION,&m_BounceVariation);
|
|
}
|
|
|
|
// Gravity parameters
|
|
if(m_InteractorsFlags & PI_GRAVITY) {
|
|
beh->GetInputParameterValue(WEIGHT,&m_Weight);
|
|
if(m_VariancesFlags & PV_WEIGHT) beh->GetInputParameterValue(WEIGHTVARIATION,&m_WeightVariation);
|
|
}
|
|
|
|
// Wind parameters
|
|
if(m_InteractorsFlags& (PI_LOCALWIND|PI_GLOBALWIND|PI_ATMOSPHERE)) {
|
|
beh->GetInputParameterValue(SURFACE,&m_Surface);
|
|
if(m_VariancesFlags & PV_SURFACE) beh->GetInputParameterValue(SURFACEVARIATION,&m_SurfaceVariation);
|
|
}
|
|
}
|
|
|
|
void
|
|
ParticleEmitter::ReadSettings(CKBehavior* beh)
|
|
{
|
|
// Patch to see if its not an old behavior
|
|
CKParameterLocal* pl = beh->GetLocalParameter(MESSAGE);
|
|
if(pl && pl->GetGUID() != CKPGUID_MESSAGE) {
|
|
char buffer[256];
|
|
sprintf(buffer,"Wrong Particle System Version. Please Delete and Reattach : %s on object %s",beh->GetName(),beh->GetOwner()->GetName());
|
|
m_Context->OutputToConsole(buffer);
|
|
return;
|
|
}
|
|
|
|
// Trail
|
|
int tc = 0;
|
|
beh->GetLocalParameterValue(TRAILCOUNT, &tc);
|
|
|
|
///////////////////////////
|
|
// Memory Management
|
|
///////////////////////////
|
|
int pn;
|
|
beh->GetLocalParameterValue(PARTICLENUMBER,&pn);
|
|
if ((pn != m_MaximumParticles && pn > 0)
|
|
|| (tc != m_TrailCount && tc > 0))
|
|
{
|
|
m_TrailCount = tc;
|
|
m_MaximumParticles = pn;
|
|
InitParticleSystem();
|
|
}
|
|
else
|
|
{
|
|
m_TrailCount = tc;
|
|
m_MaximumParticles = pn;
|
|
}
|
|
|
|
///////////////////////////
|
|
// Interactors Diplay
|
|
///////////////////////////
|
|
ParticleManager* pm = m_Manager;
|
|
BOOL display;
|
|
beh->GetLocalParameterValue(DISPLAYINTERACTORS,&display);
|
|
pm->ShowInteractors(display);
|
|
|
|
///////////////////////////
|
|
// Render Mode Management
|
|
///////////////////////////
|
|
beh->GetLocalParameterValue(RENDERMODES,&m_RenderMode);
|
|
if(m_RenderMode == PR_POINT) m_RenderParticlesCallback = RenderParticles_P;
|
|
else
|
|
if(m_RenderMode == PR_LINE)
|
|
{
|
|
if (m_TrailCount > 1)
|
|
m_RenderParticlesCallback = RenderParticles_LL;
|
|
else
|
|
m_RenderParticlesCallback = RenderParticles_L;
|
|
}
|
|
else
|
|
if(m_RenderMode == PR_SPRITE)
|
|
{
|
|
if (m_TrailCount > 1)
|
|
m_RenderParticlesCallback = RenderParticles_LS;
|
|
else
|
|
m_RenderParticlesCallback = RenderParticles_S;
|
|
}
|
|
else
|
|
if(m_RenderMode == PR_OBJECT) m_RenderParticlesCallback = RenderParticles_O;
|
|
else
|
|
if(m_RenderMode == PR_FSPRITE) m_RenderParticlesCallback = RenderParticles_FS;
|
|
else
|
|
if(m_RenderMode == PR_POINTSPRITE) m_RenderParticlesCallback = RenderParticles_PS;
|
|
else
|
|
if(m_RenderMode == PR_FIXEDPOINTSPRITE) m_RenderParticlesCallback = RenderParticles_FPS;
|
|
else
|
|
if(m_RenderMode == PR_OSPRITE)
|
|
{
|
|
if (m_TrailCount > 1)
|
|
m_RenderParticlesCallback = RenderParticles_LOS;
|
|
else
|
|
m_RenderParticlesCallback = RenderParticles_OS;
|
|
}
|
|
else
|
|
if(m_RenderMode == PR_CSPRITE) m_RenderParticlesCallback = RenderParticles_CS;
|
|
else
|
|
if(m_RenderMode == PR_RSPRITE) m_RenderParticlesCallback = RenderParticles_RS;
|
|
else m_RenderParticlesCallback = 0;
|
|
|
|
/*
|
|
CK3dEntity* entity = (CK3dEntity*)CKGetObject(m_Entity);
|
|
entity->SetRenderCallBack( m_RenderParticlesCallback, this );
|
|
*/
|
|
|
|
//////////////////////////////
|
|
// Blend Factors management
|
|
//////////////////////////////
|
|
beh->GetLocalParameterValue(SRCBLEND,&m_SrcBlend);
|
|
beh->GetLocalParameterValue(DESTBLEND,&m_DestBlend);
|
|
|
|
///////////////////////////
|
|
// Flags Management
|
|
///////////////////////////
|
|
|
|
// we clear the flags
|
|
m_EvolutionsFlags = 0;
|
|
m_VariancesFlags = 0;
|
|
m_DeflectorsFlags = 0;
|
|
m_InteractorsFlags = 0;
|
|
|
|
//////////////////////////////
|
|
// Evolution Management
|
|
//////////////////////////////
|
|
|
|
beh->GetLocalParameterValue(EVOLUTIONS,&m_EvolutionsFlags);
|
|
|
|
// management of the input parameters
|
|
beh->EnableInputParameter(ENDSIZE,m_EvolutionsFlags&PE_SIZE);
|
|
beh->EnableInputParameter(ENDCOLOR,m_EvolutionsFlags&PE_COLOR);
|
|
beh->EnableInputParameter(SPEEDTEXTURE,m_EvolutionsFlags&PE_TEXTURE);
|
|
beh->EnableInputParameter(TEXTURELOOP,m_EvolutionsFlags&PE_TEXTURE);
|
|
|
|
//////////////////////////////
|
|
// Variances Management
|
|
//////////////////////////////
|
|
|
|
beh->GetLocalParameterValue(VARIANCES,&m_VariancesFlags);
|
|
|
|
// management of the input parameters
|
|
beh->EnableInputParameter(SPEEDVARIATION,m_VariancesFlags&PV_SPEED);
|
|
beh->EnableInputParameter(ANGSPEEDVARIATION,m_VariancesFlags&PV_ANGULARSPEED);
|
|
beh->EnableInputParameter(LIFEVARIATION,m_VariancesFlags&PV_LIFESPAN);
|
|
beh->EnableInputParameter(EMITIONVARIATION,m_VariancesFlags&PV_EMISSION);
|
|
beh->EnableInputParameter(STARTSIZEVARIANCE,m_VariancesFlags&PV_INITIALSIZE);
|
|
beh->EnableInputParameter(BOUNCEVARIATION,m_VariancesFlags&PV_BOUNCE);
|
|
beh->EnableInputParameter(WEIGHTVARIATION,m_VariancesFlags&PV_WEIGHT);
|
|
beh->EnableInputParameter(SURFACEVARIATION,m_VariancesFlags&PV_SURFACE);
|
|
beh->EnableInputParameter(STARTCOLORVARIANCE,m_VariancesFlags&PV_INITIALCOLOR);
|
|
beh->EnableInputParameter(STARTTEXTUREVARIANCE,m_VariancesFlags&PV_INITIALTEXTURE);
|
|
|
|
////////////////////////////////
|
|
// Combined Parameters
|
|
////////////////////////////////
|
|
|
|
beh->EnableInputParameter(ENDCOLORVARIANCE,m_EvolutionsFlags&PE_COLOR && m_VariancesFlags&PV_ENDINGCOLOR);
|
|
beh->EnableInputParameter(ENDSIZEVARIANCE,m_EvolutionsFlags&PE_SIZE && m_VariancesFlags&PV_ENDINGSIZE);
|
|
beh->EnableInputParameter(SPEEDTEXTUREVARIANCE,m_EvolutionsFlags&PE_TEXTURE && m_VariancesFlags&PV_SPEEDTEXTURE);
|
|
|
|
// DEFLECTORS
|
|
//-----------
|
|
beh->GetLocalParameterValue(MANAGEDEFLECTORS,&m_DeflectorsFlags);
|
|
// Bounce Parameter Only if Deflector
|
|
beh->EnableInputParameter(BOUNCE,m_DeflectorsFlags&PD_ALL);
|
|
beh->EnableInputParameter(BOUNCEVARIATION,m_DeflectorsFlags&PD_ALL && m_VariancesFlags&PV_BOUNCE);
|
|
|
|
// Collision Outputs
|
|
|
|
if (m_DeflectorsFlags&PD_IMPACTS) { // we have to create outputs param and ios
|
|
if (beh->GetInputCount() == 3) {
|
|
|
|
// first we destroy all the outputs
|
|
while (beh->GetOutputParameterCount()) {
|
|
CKDestroyObject(beh->RemoveOutputParameter(0));
|
|
}
|
|
|
|
beh->CreateInput("Impacts Loop In");
|
|
beh->CreateOutput("Impacts Loop Out");
|
|
beh->CreateOutputParameter("Impact Position",CKPGUID_VECTOR);
|
|
beh->CreateOutputParameter("Impact Direction",CKPGUID_VECTOR);
|
|
beh->CreateOutputParameter("Impact Object",CKPGUID_3DENTITY);
|
|
beh->CreateOutputParameter("Impact Texture Coordinates",CKPGUID_2DVECTOR);
|
|
}
|
|
} else { // we have to delete outputs param and ios
|
|
beh->DeleteInput(3);
|
|
beh->DeleteOutput(3);
|
|
|
|
if (beh->GetOutputParameterCount() >= 4) {
|
|
CKDestroyObject(beh->RemoveOutputParameter(3));
|
|
CKDestroyObject(beh->RemoveOutputParameter(2));
|
|
CKDestroyObject(beh->RemoveOutputParameter(1));
|
|
CKDestroyObject(beh->RemoveOutputParameter(0));
|
|
}
|
|
}
|
|
|
|
///
|
|
// Output are either C C C C, or C C C C P or P and nothing else
|
|
|
|
CKBOOL outputParticleCount = FALSE;
|
|
beh->GetLocalParameterValue(PARTICLESCOUNT,&outputParticleCount);
|
|
|
|
if (outputParticleCount) {
|
|
if (beh->GetOutputParameterCount() == 0 || beh->GetOutputParameterCount() == 4) {
|
|
beh->CreateOutputParameter("Particle Count",CKPGUID_INT);
|
|
}
|
|
} else {
|
|
|
|
if (beh->GetOutputParameterCount() == 1) {
|
|
CKDestroyObject(beh->RemoveOutputParameter(0));
|
|
} else { // there is the collision outputs, then the p count
|
|
CKDestroyObject(beh->RemoveOutputParameter(4));
|
|
}
|
|
|
|
}
|
|
|
|
// INTERACTORS
|
|
//------------
|
|
|
|
beh->GetLocalParameterValue(MANAGEINTERACTORS,&m_InteractorsFlags);
|
|
// Weight Parameter Only if Gravity
|
|
beh->EnableInputParameter(WEIGHT,m_InteractorsFlags&PI_GRAVITY);
|
|
beh->EnableInputParameter(WEIGHTVARIATION,m_InteractorsFlags&PI_GRAVITY && m_VariancesFlags&PV_WEIGHT);
|
|
// Surface Parameter Only if Wind
|
|
beh->EnableInputParameter(SURFACE,m_InteractorsFlags & (PI_LOCALWIND|PI_GLOBALWIND|PI_ATMOSPHERE));
|
|
beh->EnableInputParameter(SURFACEVARIATION,m_InteractorsFlags & (PI_LOCALWIND|PI_GLOBALWIND|PI_ATMOSPHERE) && m_VariancesFlags&PV_SURFACE);
|
|
|
|
// Group of object to throw
|
|
beh->GetLocalParameterValue(OBJECTS,&m_Group);
|
|
|
|
// Message to deflectors...
|
|
beh->GetLocalParameterValue(MESSAGE,&m_MessageType);
|
|
|
|
// fix for radial particles
|
|
beh->GetLocalParameterValue(RADIALPARTICLEOFFSET, &m_RadialParticleOffset);
|
|
}
|
|
|
|
int ParticleEmitter::BeginPasses(CKRenderContext* dev,CKBOOL gouraud)
|
|
{
|
|
if (!m_Manager->m_ParticleMaterial) return 1;
|
|
CKRenderContext* RdCtx = (CKRenderContext*) dev;
|
|
CKMaterial* mat = m_Manager->m_ParticleMaterial;
|
|
CKTexture* tex = (CKTexture*)RdCtx->GetCKContext()->GetObject(m_Texture);
|
|
mat->SetTexture(tex);
|
|
mat->SetSourceBlend(m_SrcBlend);
|
|
mat->SetDestBlend(m_DestBlend);
|
|
mat->SetShadeMode(gouraud ? VXSHADE_GOURAUD : VXSHADE_FLAT);
|
|
|
|
if(m_DestBlend == VXBLEND_ZERO && ((m_SrcBlend == VXBLEND_SRCALPHA) || (m_SrcBlend == VXBLEND_SRCCOLOR) || (m_SrcBlend == VXBLEND_ONE))) {
|
|
mat->EnableAlphaBlend(FALSE);
|
|
mat->EnableZWrite(TRUE);
|
|
} else {
|
|
mat->EnableAlphaBlend(TRUE);
|
|
mat->EnableZWrite(FALSE);
|
|
}
|
|
//
|
|
RdCtx->OverrideMaterial(mat, m_OverridenMaterial);
|
|
|
|
CKMaterialShader* matShader = m_OverridenMaterial.m_MaterialShader;
|
|
CKShaderManager* sMan = RdCtx->m_ShaderManager;
|
|
if (sMan && m_OverridenMaterial.m_MaterialShader && m_OverridenMaterial.m_ShaderTechniqueIndex >= 0)
|
|
{
|
|
sMan->BeginShaders(RdCtx);
|
|
CKShader* fx = matShader->m_Shader;
|
|
XASSERT(fx != NULL);
|
|
fx->SetTechnique( m_OverridenMaterial.m_ShaderTechniqueIndex );
|
|
fx->SetParameters( matShader->m_Params );
|
|
int num_passes = fx->Begin(RdCtx);
|
|
sMan->m_CurrentPassCount = num_passes;
|
|
RdCtx->SetValuesOfUsedAutomatics( *fx, m_OverridenMaterial.m_ShaderMeaningMaterial, m_OverridenMaterial.m_MaterialShader, NULL);
|
|
m_InShaderMode = TRUE;
|
|
return num_passes;
|
|
}
|
|
else
|
|
{
|
|
dev->SetCurrentMaterial(mat, FALSE /* Lit */);
|
|
// no shader mode
|
|
m_InShaderMode = FALSE;
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
void ParticleEmitter::SetState(CKRenderContext* dev,CKBOOL gouraud)
|
|
{
|
|
// The Texture
|
|
CKTexture* tex = (CKTexture*)dev->GetCKContext()->GetObject(m_Texture);
|
|
dev->SetTexture(tex);
|
|
|
|
dev->SetState(VXRENDERSTATE_SPECULARENABLE, FALSE);
|
|
dev->SetState(VXRENDERSTATE_FILLMODE, VXFILL_SOLID);
|
|
// Gouraud / Flat
|
|
if (gouraud)
|
|
dev->SetState(VXRENDERSTATE_SHADEMODE, VXSHADE_GOURAUD);
|
|
else
|
|
dev->SetState(VXRENDERSTATE_SHADEMODE, VXSHADE_FLAT);
|
|
|
|
dev->SetTextureStageState(CKRST_TSS_TEXTUREMAPBLEND,VXTEXTUREBLEND_MODULATEALPHA);
|
|
dev->SetTextureStageState(CKRST_TSS_MAGFILTER , VXTEXTUREFILTER_LINEAR);
|
|
dev->SetTextureStageState(CKRST_TSS_MINFILTER , VXTEXTUREFILTER_LINEARMIPLINEAR);
|
|
|
|
// States
|
|
dev->SetState(VXRENDERSTATE_WRAP0 , 0);
|
|
dev->SetState(VXRENDERSTATE_CULLMODE, VXCULL_NONE);
|
|
dev->SetState(VXRENDERSTATE_SRCBLEND, m_SrcBlend);
|
|
dev->SetState(VXRENDERSTATE_DESTBLEND, m_DestBlend);
|
|
if(m_DestBlend == VXBLEND_ZERO && ((m_SrcBlend == VXBLEND_SRCALPHA) || (m_SrcBlend == VXBLEND_SRCCOLOR) || (m_SrcBlend == VXBLEND_ONE))) {
|
|
dev->SetState(VXRENDERSTATE_ALPHABLENDENABLE, FALSE);
|
|
dev->SetState(VXRENDERSTATE_ZWRITEENABLE , TRUE);
|
|
} else {
|
|
dev->SetState(VXRENDERSTATE_ALPHABLENDENABLE, TRUE);
|
|
dev->SetState(VXRENDERSTATE_ZWRITEENABLE , FALSE);
|
|
}
|
|
dev->SetTextureStageState(CKRST_TSS_STAGEBLEND,0,1);
|
|
dev->SetTextureStageState(CKRST_TSS_TEXTURETRANSFORMFLAGS, 0);
|
|
dev->SetTextureStageState(CKRST_TSS_TEXCOORDINDEX, 0);
|
|
}
|
|
*/
|
|
|
|
void ParticleEmitter::BeginPass(CKRenderContext* dev, int passIndex)
|
|
{
|
|
if (!m_InShaderMode) return;
|
|
CKRenderContext* RdCtx = (CKRenderContext*) dev;
|
|
CKShaderManager* sMan = RdCtx->m_ShaderManager;
|
|
sMan->m_CurrentPassIndex = passIndex;
|
|
CKMaterialShader* matShader = m_OverridenMaterial.m_MaterialShader;
|
|
CKShader* fx = matShader->m_Shader;
|
|
XASSERT(fx != NULL);
|
|
fx->ExecutePerPassMeanings( (CK3dEntity*)this, m_OverridenMaterial.m_ShaderMeaningMaterial, m_OverridenMaterial.m_MaterialShader, RdCtx );
|
|
|
|
fx->BeginPass(passIndex, dev);
|
|
|
|
}
|
|
|
|
void ParticleEmitter::EndPass(CKRenderContext* dev)
|
|
{
|
|
if (!m_InShaderMode) return;
|
|
CKMaterialShader* matShader = m_OverridenMaterial.m_MaterialShader;
|
|
CKShader* fx = matShader->m_Shader;
|
|
XASSERT(fx != NULL);
|
|
fx->EndPass(dev);
|
|
}
|
|
|
|
void ParticleEmitter::EndPasses(CKRenderContext* dev)
|
|
{
|
|
if (!m_InShaderMode) return;
|
|
CKRenderContext* RdCtx = (CKRenderContext *)dev;
|
|
CKShaderManager* sMan = RdCtx->m_ShaderManager;
|
|
CKMaterialShader* matShader = m_OverridenMaterial.m_MaterialShader;
|
|
CKShader* fx = matShader->m_Shader;
|
|
XASSERT(fx != NULL);
|
|
fx->End(dev);
|
|
if (sMan) sMan->EndShaders(dev);
|
|
}
|
|
|
|
|
|
void ParticleEmitter::DrawPrimitive(CKRenderContext* dev, CKBOOL gouraud, VXPRIMITIVETYPE pType,DWORD* indices,int indexcount,VxDrawPrimitiveData* data)
|
|
{
|
|
// slow but working
|
|
int passCount = BeginPasses(dev, gouraud);
|
|
for (int i = 0; i < passCount; ++i)
|
|
{
|
|
BeginPass(dev, i);
|
|
dev->DrawPrimitive(pType, indices, indexcount, data);
|
|
EndPass(dev);
|
|
}
|
|
EndPasses(dev);
|
|
}
|
|
|
|
void ParticleEmitter::DrawPrimitive(CKRenderContext* dev, CKBOOL gouraud, VXPRIMITIVETYPE pType, WORD* indices,int indexcount,VxDrawPrimitiveData* data)
|
|
{
|
|
// slow but working
|
|
int passCount = BeginPasses(dev, gouraud);
|
|
for (int i = 0; i < passCount; ++i)
|
|
{
|
|
BeginPass(dev, i);
|
|
dev->DrawPrimitive(pType, indices, indexcount, data);
|
|
EndPass(dev);
|
|
}
|
|
EndPasses(dev);
|
|
}
|
|
|
|
ParticleEmitter::ParticleHistoric &
|
|
ParticleEmitter::GetParticleHistoric(Particle *part)
|
|
{
|
|
typedef XClassArray<ParticleEmitter::ParticleHistoric> t_array_ph;
|
|
int idx = ((BYTE *)part - m_BackPool) / sizeof (Particle);
|
|
XASSERT(idx < m_MaximumParticles);
|
|
return old_pos[idx];
|
|
}
|