From 6fdaf5de46b8ab29cfb67d49661a63fff5a6995a Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 5 Oct 2012 18:59:49 +0200 Subject: CParticle rewrite --- src/graphics/engine/particle.cpp | 3946 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 3777 insertions(+), 169 deletions(-) (limited to 'src/graphics/engine/particle.cpp') diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 9d3d084..acc40df 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -20,289 +20,3897 @@ #include "common/logger.h" +#include "graphics/core/device.h" +#include "graphics/engine/engine.h" +#include "graphics/engine/terrain.h" +#include "graphics/engine/water.h" + +#include "math/geometry.h" + +#include "object/object.h" +#include "object/robotmain.h" + +#include + // Graphics module namespace namespace Gfx { -CParticle::CParticle(CInstanceManager* iMan, CEngine* engine) +const float FOG_HSUP = 10.0f; +const float FOG_HINF = 100.0f; + + + + +//! Check if an object can be destroyed, but is not an enemy +bool IsSoft(ObjectType type) +{ + return ( type == OBJECT_HUMAN || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr || // robot? + type == OBJECT_METAL || + type == OBJECT_POWER || + type == OBJECT_ATOMIC || // cargo? + type == OBJECT_DERRICK || + type == OBJECT_STATION || + type == OBJECT_FACTORY || + type == OBJECT_REPAIR || + type == OBJECT_DESTROYER|| + type == OBJECT_CONVERT || + type == OBJECT_TOWER || + type == OBJECT_RESEARCH || + type == OBJECT_RADAR || + type == OBJECT_INFO || + type == OBJECT_ENERGY || + type == OBJECT_LABO || + type == OBJECT_NUCLEAR || + type == OBJECT_PARA ); // building? +} + +//! Check if an object is a destroyable enemy +bool IsAlien(ObjectType type) +{ + return ( type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM || + type == OBJECT_MOTHER || + type == OBJECT_NEST || + type == OBJECT_BULLET || + type == OBJECT_EGG || + type == OBJECT_MOBILEtg || + type == OBJECT_TEEN28 || + type == OBJECT_TEEN31 ); +} + +//! Returns the damping factor for friendly fire +float GetDecay(ObjectType type) +{ + if (IsSoft(type)) return 0.2f; + return 1.0f; +} + + + +CParticle::CParticle(CInstanceManager *iMan, CEngine* engine) { - GetLogger()->Trace("CParticle::CParticle() stub!\n"); - // TODO! + m_iMan = iMan; + m_iMan->AddInstance(CLASS_PARTICULE, this); + + m_device = nullptr; + m_engine = engine; + m_main = nullptr; + m_terrain = nullptr; + m_water = nullptr; + m_sound = nullptr; + m_uniqueStamp = 0; + m_exploGunCounter = 0; + m_lastTimeGunDel = 0.0f; + m_absTime = 0.0f; + + FlushParticle(); } CParticle::~CParticle() { - GetLogger()->Trace("CParticle::~CParticle() stub!\n"); - // TODO! + m_iMan->DeleteInstance(CLASS_PARTICULE, this); } void CParticle::SetDevice(CDevice* device) { - GetLogger()->Trace("CParticle::SetDevice() stub!\n"); - // TODO! + m_device = device; } void CParticle::FlushParticle() { - GetLogger()->Trace("CParticle::FlushParticle() stub!\n"); - // TODO! + for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++) + m_particle[i].used = false; + + for (int i = 0; i < MAXPARTITYPE; i++) + { + for (int j = 0; j < SH_MAX; j++) + { + m_totalInterface[i][j] = 0; + } + } + + for (int i = 0; i < MAXTRACK; i++) + m_track[i].used = false; + + m_wheelTraceTotal = 0; + m_wheelTraceIndex = 0; + + for (int i = 0; i < SH_MAX; i++) + m_frameUpdate[i] = true; + + m_fogTotal = 0; + m_exploGunCounter = 0; } void CParticle::FlushParticle(int sheet) { - GetLogger()->Trace("CParticle::FlushParticle() stub!\n"); - // TODO! + for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++) + { + if (!m_particle[i].used) continue; + if (m_particle[i].sheet != sheet) continue; + + m_particle[i].used = false; + } + + for (int i = 0; i < MAXPARTITYPE; i++) + m_totalInterface[i][sheet] = 0; + + for (int i = 0; i < MAXTRACK; i++) + m_track[i].used = false; + + if (sheet == SH_WORLD) + { + m_wheelTraceTotal = 0; + m_wheelTraceIndex = 0; + } +} + + +//! Returns file name of the effect effectNN.png, with NN = number +void NameParticle(std::string &name, int num) +{ + if (num == 1) name = "effect00.png"; + else if (num == 2) name = "effect01.png"; + else if (num == 3) name = "effect02.png"; + else if (num == 4) name = "text.png"; + else name = ""; } +/** Returns the channel of the particle created or -1 on error. */ int CParticle::CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, - ParticleType type, float duration, float mass, - float windSensitivity, int sheet) + ParticleType type, + float duration, float mass, + float windSensitivity, int sheet) { - GetLogger()->Trace("CParticle::CreateParticle() stub!\n"); - // TODO! - return 0; + if (m_main == nullptr) + m_main = static_cast(m_iMan->SearchInstance(CLASS_MAIN)); + + int t = -1; + if ( type == PARTIEXPLOT || + type == PARTIEXPLOO || + type == PARTIMOTOR || + type == PARTIBLITZ || + type == PARTICRASH || + type == PARTIVAPOR || + type == PARTIGAS || + type == PARTIBASE || + type == PARTIFIRE || + type == PARTIFIREZ || + type == PARTIBLUE || + type == PARTIROOT || + type == PARTIRECOVER || + type == PARTIEJECT || + type == PARTISCRAPS || + type == PARTIGUN2 || + type == PARTIGUN3 || + type == PARTIGUN4 || + type == PARTIQUEUE || + type == PARTIORGANIC1 || + type == PARTIORGANIC2 || + type == PARTIFLAME || + type == PARTIBUBBLE || + type == PARTIERROR || + type == PARTIWARNING || + type == PARTIINFO || + type == PARTISPHERE1 || + type == PARTISPHERE2 || + type == PARTISPHERE4 || + type == PARTISPHERE5 || + type == PARTISPHERE6 || + type == PARTIPLOUF0 || + type == PARTITRACK1 || + type == PARTITRACK2 || + type == PARTITRACK3 || + type == PARTITRACK4 || + type == PARTITRACK5 || + type == PARTITRACK6 || + type == PARTITRACK7 || + type == PARTITRACK8 || + type == PARTITRACK9 || + type == PARTITRACK10 || + type == PARTITRACK11 || + type == PARTITRACK12 || + type == PARTILENS1 || + type == PARTILENS2 || + type == PARTILENS3 || + type == PARTILENS4 || + type == PARTIGFLAT || + type == PARTIDROP || + type == PARTIWATER || + type == PARTILIMIT1 || + type == PARTILIMIT2 || + type == PARTILIMIT3 || + type == PARTILIMIT4 || + type == PARTIEXPLOG1 || + type == PARTIEXPLOG2 ) + { + t = 1; // effect00 + } + if ( type == PARTIGLINT || + type == PARTIGLINTb || + type == PARTIGLINTr || + type == PARTITOTO || + type == PARTISELY || + type == PARTISELR || + type == PARTIQUARTZ || + type == PARTIGUNDEL || + type == PARTICONTROL || + type == PARTISHOW || + type == PARTICHOC || + type == PARTIFOG4 || + type == PARTIFOG5 || + type == PARTIFOG6 || + type == PARTIFOG7 ) + { + t = 2; // effect01 + } + if ( type == PARTIGUN1 || + type == PARTIFLIC || + type == PARTISPHERE0 || + type == PARTISPHERE3 || + type == PARTIFOG0 || + type == PARTIFOG1 || + type == PARTIFOG2 || + type == PARTIFOG3 ) + { + t = 3; // effect02 + } + if ( type == PARTISMOKE1 || + type == PARTISMOKE2 || + type == PARTISMOKE3 || + type == PARTIBLOOD || + type == PARTIBLOODM || + type == PARTIVIRUS1 || + type == PARTIVIRUS2 || + type == PARTIVIRUS3 || + type == PARTIVIRUS4 || + type == PARTIVIRUS5 || + type == PARTIVIRUS6 || + type == PARTIVIRUS7 || + type == PARTIVIRUS8 || + type == PARTIVIRUS9 || + type == PARTIVIRUS10 ) + { + t = 4; // text (D3DSTATETTw) + } + if (t >= MAXPARTITYPE) return -1; + if (t == -1) return -1; + + for (int j = 0; j < MAXPARTICULE; j++) + { + int i = MAXPARTICULE*t+j; + + if (! m_particle[i].used) + { + memset(&m_particle[i], 0, sizeof(Particle)); + m_particle[i].used = true; + m_particle[i].ray = false; + m_particle[i].uniqueStamp = m_uniqueStamp++; + m_particle[i].sheet = sheet; + m_particle[i].mass = mass; + m_particle[i].duration = duration; + m_particle[i].pos = pos; + m_particle[i].goal = pos; + m_particle[i].speed = speed; + m_particle[i].windSensitivity = windSensitivity; + m_particle[i].dim = dim; + m_particle[i].zoom = 1.0f; + m_particle[i].angle = 0.0f; + m_particle[i].intensity = 1.0f; + m_particle[i].type = type; + m_particle[i].phase = PARPHSTART; + m_particle[i].texSup.x = 0.0f; + m_particle[i].texSup.y = 0.0f; + m_particle[i].texInf.x = 0.0f; + m_particle[i].texInf.y = 0.0f; + m_particle[i].time = 0.0f; + m_particle[i].phaseTime = 0.0f; + m_particle[i].testTime = 0.0f; + m_particle[i].objLink = 0; + m_particle[i].objFather = 0; + m_particle[i].trackRank = -1; + + m_totalInterface[t][sheet] ++; + + if ( type == PARTIEXPLOT || + type == PARTIEXPLOO ) + { + m_particle[i].angle = Math::Rand()*Math::PI*2.0f; + } + + if ( type == PARTIGUN1 || + type == PARTIGUN4 ) + { + m_particle[i].testTime = 1.0f; // impact immediately + } + + if ( type >= PARTIFOG0 && + type <= PARTIFOG9 ) + { + if (m_fogTotal < MAXPARTIFOG) + m_fog[m_fogTotal++] = i; + } + + return i | ((m_particle[i].uniqueStamp&0xffff)<<16); + } + } + + return -1; } -int CParticle::CreateFrag(Math::Vector pos, Math::Vector speed, EngineTriangle *triangle, - ParticleType type, float duration, float mass, - float windSensitivity, int sheet) +/** Returns the channel of the particle created or -1 on error */ +int CParticle::CreateFrag(Math::Vector pos, Math::Vector speed, + EngineTriangle *triangle, + ParticleType type, + float duration, float mass, + float windSensitivity, int sheet) +{ + int t = 0; + for (int j = 0; j < MAXPARTICULE; j++) + { + int i = MAXPARTICULE*t+j; + + if (!m_particle[i].used) + { + memset(&m_particle[i], 0, sizeof(Particle)); + m_particle[i].used = true; + m_particle[i].ray = false; + m_particle[i].uniqueStamp = m_uniqueStamp++; + m_particle[i].sheet = sheet; + m_particle[i].mass = mass; + m_particle[i].duration = duration; + m_particle[i].pos = pos; + m_particle[i].goal = pos; + m_particle[i].speed = speed; + m_particle[i].windSensitivity = windSensitivity; + m_particle[i].zoom = 1.0f; + m_particle[i].angle = 0.0f; + m_particle[i].intensity = 1.0f; + m_particle[i].type = type; + m_particle[i].phase = PARPHSTART; + m_particle[i].texSup.x = 0.0f; + m_particle[i].texSup.y = 0.0f; + m_particle[i].texInf.x = 0.0f; + m_particle[i].texInf.y = 0.0f; + m_particle[i].time = 0.0f; + m_particle[i].phaseTime = 0.0f; + m_particle[i].testTime = 0.0f; + m_particle[i].objLink = 0; + m_particle[i].objFather = 0; + m_particle[i].trackRank = -1; + m_triangle[i] = *triangle; + + m_totalInterface[t][sheet] ++; + + Math::Vector p1; + p1.x = m_triangle[i].triangle[0].coord.x; + p1.y = m_triangle[i].triangle[0].coord.y; + p1.z = m_triangle[i].triangle[0].coord.z; + + Math::Vector p2; + p2.x = m_triangle[i].triangle[1].coord.x; + p2.y = m_triangle[i].triangle[1].coord.y; + p2.z = m_triangle[i].triangle[1].coord.z; + + Math::Vector p3; + p3.x = m_triangle[i].triangle[2].coord.x; + p3.y = m_triangle[i].triangle[2].coord.y; + p3.z = m_triangle[i].triangle[2].coord.z; + + float l1 = Math::Distance(p1, p2); + float l2 = Math::Distance(p2, p3); + float l3 = Math::Distance(p3, p1); + float dx = fabs(Math::Min(l1, l2, l3))*0.5f; + float dy = fabs(Math::Max(l1, l2, l3))*0.5f; + p1 = Math::Vector(-dx, dy, 0.0f); + p2 = Math::Vector( dx, dy, 0.0f); + p3 = Math::Vector(-dx, -dy, 0.0f); + + m_triangle[i].triangle[0].coord.x = p1.x; + m_triangle[i].triangle[0].coord.y = p1.y; + m_triangle[i].triangle[0].coord.z = p1.z; + + m_triangle[i].triangle[1].coord.x = p2.x; + m_triangle[i].triangle[1].coord.y = p2.y; + m_triangle[i].triangle[1].coord.z = p2.z; + + m_triangle[i].triangle[2].coord.x = p3.x; + m_triangle[i].triangle[2].coord.y = p3.y; + m_triangle[i].triangle[2].coord.z = p3.z; + + Math::Vector n(0.0f, 0.0f, -1.0f); + + m_triangle[i].triangle[0].normal.x = n.x; + m_triangle[i].triangle[0].normal.y = n.y; + m_triangle[i].triangle[0].normal.z = n.z; + + m_triangle[i].triangle[1].normal.x = n.x; + m_triangle[i].triangle[1].normal.y = n.y; + m_triangle[i].triangle[1].normal.z = n.z; + + m_triangle[i].triangle[2].normal.x = n.x; + m_triangle[i].triangle[2].normal.y = n.y; + m_triangle[i].triangle[2].normal.z = n.z; + + if (type == PARTIFRAG) + m_particle[i].angle = Math::Rand()*Math::PI*2.0f; + + return i | ((m_particle[i].uniqueStamp&0xffff)<<16); + } + } + + return -1; +} + + +/** Returns the channel of the particle created or -1 on error */ +int CParticle::CreatePart(Math::Vector pos, Math::Vector speed, + ParticleType type, + float duration, float mass, float weight, + float windSensitivity, int sheet) { - GetLogger()->Trace("CParticle::CreateFrag() stub!\n"); - // TODO! - return 0; + int t = 0; + for (int j = 0; j < MAXPARTICULE; j++) + { + int i = MAXPARTICULE*t+j; + + if (!m_particle[i].used) + { + memset(&m_particle[i], 0, sizeof(Particle)); + m_particle[i].used = true; + m_particle[i].ray = false; + m_particle[i].uniqueStamp = m_uniqueStamp++; + m_particle[i].sheet = sheet; + m_particle[i].mass = mass; + m_particle[i].weight = weight; + m_particle[i].duration = duration; + m_particle[i].pos = pos; + m_particle[i].goal = pos; + m_particle[i].speed = speed; + m_particle[i].windSensitivity = windSensitivity; + m_particle[i].zoom = 1.0f; + m_particle[i].angle = 0.0f; + m_particle[i].intensity = 1.0f; + m_particle[i].type = type; + m_particle[i].phase = PARPHSTART; + m_particle[i].texSup.x = 0.0f; + m_particle[i].texSup.y = 0.0f; + m_particle[i].texInf.x = 0.0f; + m_particle[i].texInf.y = 0.0f; + m_particle[i].time = 0.0f; + m_particle[i].phaseTime = 0.0f; + m_particle[i].testTime = 0.0f; + m_particle[i].trackRank = -1; + + m_totalInterface[t][sheet] ++; + + return i | ((m_particle[i].uniqueStamp&0xffff)<<16); + } + } + + return -1; +} + +/** Returns the channel of the particle created or -1 on error */ +int CParticle::CreateRay(Math::Vector pos, Math::Vector goal, + ParticleType type, Math::Point dim, + float duration, int sheet) +{ + int t = -1; + if ( type == PARTIRAY1 || + type == PARTIRAY2 || + type == PARTIRAY3 || + type == PARTIRAY4 ) + { + t = 3; // effect02 + } + if (t >= MAXPARTITYPE) return -1; + if (t == -1) return -1; + + for (int j = 0; j < MAXPARTICULE; j++) + { + int i = MAXPARTICULE*t+j; + + if (!m_particle[i].used) + { + memset(&m_particle[i], 0, sizeof(Particle)); + m_particle[i].used = true; + m_particle[i].ray = true; + m_particle[i].uniqueStamp = m_uniqueStamp++; + m_particle[i].sheet = sheet; + m_particle[i].mass = 0.0f; + m_particle[i].duration = duration; + m_particle[i].pos = pos; + m_particle[i].goal = goal; + m_particle[i].speed = Math::Vector(0.0f, 0.0f, 0.0f); + m_particle[i].windSensitivity = 0.0f; + m_particle[i].dim = dim; + m_particle[i].zoom = 1.0f; + m_particle[i].angle = 0.0f; + m_particle[i].intensity = 1.0f; + m_particle[i].type = type; + m_particle[i].phase = PARPHSTART; + m_particle[i].texSup.x = 0.0f; + m_particle[i].texSup.y = 0.0f; + m_particle[i].texInf.x = 0.0f; + m_particle[i].texInf.y = 0.0f; + m_particle[i].time = 0.0f; + m_particle[i].phaseTime = 0.0f; + m_particle[i].testTime = 0.0f; + m_particle[i].objLink = 0; + m_particle[i].objFather = 0; + m_particle[i].trackRank = -1; + + m_totalInterface[t][sheet] ++; + + return i | ((m_particle[i].uniqueStamp&0xffff)<<16); + } + } + + return -1; } -int CParticle::CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type, - float duration, float mass, float weight, - float windSensitivity, int sheet) +/** "length" is the length of the tail of drag (in seconds)! */ +int CParticle::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, + ParticleType type, float duration, float mass, + float length, float width) { - GetLogger()->Trace("CParticle::CreatePart() stub!\n"); - // TODO! - return 0; + // Creates the normal particle. + int channel = CreateParticle(pos, speed, dim, type, duration, mass, 0.0f, 0); + if (channel == -1) return -1; + + // Seeks a streak free. + for (int i = 0; i < MAXTRACK; i++) + { + if (!m_track[i].used) // free? + { + int rank = channel; + if (!CheckChannel(rank)) return -1; + m_particle[rank].trackRank = i; + + m_track[i].used = true; + m_track[i].step = (length/duration) / MAXTRACKLEN; + m_track[i].last = 0.0f; + m_track[i].intensity = 1.0f; + m_track[i].width = width; + m_track[i].posUsed = 1; + m_track[i].head = 0; + m_track[i].pos[0] = pos; + break; + } + } + + return channel; } -int CParticle::CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim, - float duration, int sheet) +void CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, + const Math::Vector &p3, const Math::Vector &p4, + ParticleType type) { - GetLogger()->Trace("CParticle::CreateRay() stub!\n"); - // TODO! - return 0; + int max = MAXWHEELTRACE; + int i = m_wheelTraceIndex++; + if (m_wheelTraceIndex > max) m_wheelTraceIndex = 0; + + m_wheelTrace[i].type = type; + m_wheelTrace[i].pos[0] = p1; // ul + m_wheelTrace[i].pos[1] = p2; // dl + m_wheelTrace[i].pos[2] = p3; // ur + m_wheelTrace[i].pos[3] = p4; // dr + m_wheelTrace[i].startTime = m_absTime; + + if (m_terrain == nullptr) + m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); + + m_terrain->AdjustToFloor(m_wheelTrace[i].pos[0]); + m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground + + m_terrain->AdjustToFloor(m_wheelTrace[i].pos[1]); + m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground + + m_terrain->AdjustToFloor(m_wheelTrace[i].pos[2]); + m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground + + m_terrain->AdjustToFloor(m_wheelTrace[i].pos[3]); + m_wheelTrace[i].pos[3].y += 0.2f; // just above the ground + + if (m_wheelTraceTotal < max) + m_wheelTraceTotal++; + else + m_wheelTraceTotal = max; } -int CParticle::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, - float duration, float mass, float length, float width) + + +/** Adapts the channel so it can be used as an offset in m_particle */ +bool CParticle::CheckChannel(int &channel) { - GetLogger()->Trace("CParticle::CreateTrack() stub!\n"); - // TODO! - return 0; + int uniqueStamp = (channel>>16)&0xffff; + channel &= 0xffff; + + if (channel < 0) return false; + if (channel >= MAXPARTICULE*MAXPARTITYPE) return false; + + if (!m_particle[channel].used) + { + GetLogger()->Error("CheckChannel used=false !\n"); + return false; + } + + if (m_particle[channel].uniqueStamp != uniqueStamp) + { + GetLogger()->Error("CheckChannel uniqueStamp !\n"); + return false; + } + + return true; } -void CParticle::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, - const Math::Vector &p4, ParticleType type) +void CParticle::DeleteRank(int rank) { - GetLogger()->Trace("CParticle::CreateWheelTrace() stub!\n"); - // TODO! + if (m_totalInterface[rank/MAXPARTICULE][m_particle[rank].sheet] > 0) + m_totalInterface[rank/MAXPARTICULE][m_particle[rank].sheet]--; + + int i = m_particle[rank].trackRank; + if (i != -1) // drag associated? + m_track[i].used = false; // frees the drag + + m_particle[rank].used = false; } void CParticle::DeleteParticle(ParticleType type) { - GetLogger()->Trace("CParticle::DeleteParticle() stub!\n"); - // TODO! + for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++) + { + if (!m_particle[i].used) continue; + if (m_particle[i].type != type) continue; + + DeleteRank(i); + } } void CParticle::DeleteParticle(int channel) { - GetLogger()->Trace("CParticle::DeleteParticle() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + + if (m_totalInterface[channel/MAXPARTICULE][m_particle[channel].sheet] > 0 ) + m_totalInterface[channel/MAXPARTICULE][m_particle[channel].sheet]--; + + int i = m_particle[channel].trackRank; + if (i != -1) // drag associated? + m_track[i].used = false; // frees the drag + + m_particle[channel].used = false; } void CParticle::SetObjectLink(int channel, CObject *object) { - GetLogger()->Trace("CParticle::SetObjectLink() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].objLink = object; } void CParticle::SetObjectFather(int channel, CObject *object) { - GetLogger()->Trace("CParticle::SetObjectFather() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].objFather = object; } void CParticle::SetPosition(int channel, Math::Vector pos) { - GetLogger()->Trace("CParticle::SetPosition() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].pos = pos; } void CParticle::SetDimension(int channel, Math::Point dim) { - GetLogger()->Trace("CParticle::SetDimension() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].dim = dim; } void CParticle::SetZoom(int channel, float zoom) { - GetLogger()->Trace("CParticle::SetZoom() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].zoom = zoom; } void CParticle::SetAngle(int channel, float angle) { - GetLogger()->Trace("CParticle::SetAngle() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].angle = angle; } void CParticle::SetIntensity(int channel, float intensity) { - GetLogger()->Trace("CParticle::SetIntensity() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].intensity = intensity; } -void CParticle::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity) +void CParticle::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, + float angle, float intensity) { - GetLogger()->Trace("CParticle::SetParam() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].pos = pos; + m_particle[channel].dim = dim; + m_particle[channel].zoom = zoom; + m_particle[channel].angle = angle; + m_particle[channel].intensity = intensity; } void CParticle::SetPhase(int channel, ParticlePhase phase, float duration) { - GetLogger()->Trace("CParticle::SetPhase() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return; + m_particle[channel].phase = phase; + m_particle[channel].duration = duration; + m_particle[channel].phaseTime = m_particle[channel].time; } bool CParticle::GetPosition(int channel, Math::Vector &pos) { - GetLogger()->Trace("CParticle::GetPosition() stub!\n"); - // TODO! + if (!CheckChannel(channel)) return false; + pos = m_particle[channel].pos; return true; } -Color CParticle::GetFogColor(Math::Vector pos) -{ - GetLogger()->Trace("CParticle::GetFogColor() stub!\n"); - // TODO! - return Color(); -} - void CParticle::SetFrameUpdate(int sheet, bool update) { - GetLogger()->Trace("CParticle::SetFrameUpdate() stub!\n"); - // TODO! + m_frameUpdate[sheet] = update; } void CParticle::FrameParticle(float rTime) { - GetLogger()->Trace("CParticle::FrameParticle() stub!\n"); - // TODO! -} + if (m_main == nullptr) + m_main = static_cast(m_iMan->SearchInstance(CLASS_MAIN)); -void CParticle::DrawParticle(int sheet) -{ - GetLogger()->Trace("CParticle::DrawParticle() stub!\n"); - // TODO! -} + bool pause = (m_engine->GetPause() && !m_main->GetInfoLock()); -bool CParticle::WriteWheelTrace(const char *filename, int width, int height, Math::Vector dl, Math::Vector ur) -{ - GetLogger()->Trace("CParticle::WriteWheelTrace() stub!\n"); - // TODO! - return true; -} + if (m_terrain == nullptr) + m_terrain = static_cast(m_iMan->SearchInstance(CLASS_TERRAIN)); -void CParticle::DeleteRank(int rank) -{ - GetLogger()->Trace("CParticle::DeleteRank() stub!\n"); - // TODO! -} + if (m_water == nullptr) + m_water = static_cast(m_iMan->SearchInstance(CLASS_WATER)); -bool CParticle::CheckChannel(int &channel) -{ - GetLogger()->Trace("CParticle::CheckChannel() stub!\n"); - // TODO! - return true; -} + if (!pause) + { + m_lastTimeGunDel += rTime; + m_absTime += rTime; + } -void CParticle::DrawParticleTriangle(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleTriangle() stub!\n"); - // TODO! -} + Math::Vector wind = m_terrain->GetWind(); + Math::Vector eye = m_engine->GetEyePt(); -void CParticle::DrawParticleNorm(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleNorm() stub!\n"); - // TODO! -} + Math::Point ts, ti; + Math::Vector pos; -void CParticle::DrawParticleFlat(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleFlat() stub!\n"); - // TODO! -} + for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++) + { + if (!m_particle[i].used) continue; + if (!m_frameUpdate[m_particle[i].sheet]) continue; -void CParticle::DrawParticleFog(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleFog() stub!\n"); - // TODO! -} + if (m_particle[i].type != PARTISHOW) + { + if (pause && m_particle[i].sheet != SH_INTERFACE) continue; + } -void CParticle::DrawParticleRay(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleRay() stub!\n"); - // TODO! -} + if (m_particle[i].type != PARTIQUARTZ) + m_particle[i].pos += m_particle[i].speed*rTime; -void CParticle::DrawParticleSphere(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleSphere() stub!\n"); - // TODO! -} + if (m_particle[i].sheet == SH_WORLD) + { + float h = rTime*m_particle[i].windSensitivity*Math::Rand()*2.0f; + m_particle[i].pos += wind*h; + } -void CParticle::DrawParticleCylinder(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleCylinder() stub!\n"); - // TODO! -} + float progress = (m_particle[i].time-m_particle[i].phaseTime)/m_particle[i].duration; -void CParticle::DrawParticleWheel(int i) -{ - GetLogger()->Trace("CParticle::DrawParticleWheel() stub!\n"); - // TODO! -} + // Manages the particles with mass that bounce. + if ( m_particle[i].mass != 0.0f && + m_particle[i].type != PARTIQUARTZ ) + { + m_particle[i].speed.y -= m_particle[i].mass*rTime; -CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father) -{ - GetLogger()->Trace("CParticle::SearchObjectGun() stub!\n"); - // TODO! - return nullptr; -} + float h; + if (m_particle[i].sheet == SH_INTERFACE) + h = 0.0f; + else + h = m_terrain->GetFloorLevel(m_particle[i].pos, true); -CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father) -{ - GetLogger()->Trace("CParticle::SearchObjectRay() stub!\n"); - // TODO! - return nullptr; -} + h += m_particle[i].dim.y*0.75f; + if (m_particle[i].pos.y < h) // impact with the ground? + { + if ( m_particle[i].type == PARTIPART && + m_particle[i].weight > 3.0f && // heavy enough? + m_particle[i].bounce < 3 ) + { + float amplitude = m_particle[i].weight*0.1f; + amplitude *= 1.0f-0.3f*m_particle[i].bounce; + if (amplitude > 1.0f) amplitude = 1.0f; + if (amplitude > 0.0f) + { + Play(SOUND_BOUM, m_particle[i].pos, amplitude); + } + } -void CParticle::Play(Sound sound, Math::Vector pos, float amplitude) -{ - GetLogger()->Trace("CParticle::Play() stub!\n"); - // TODO! -} + if (m_particle[i].bounce < 3) + { + m_particle[i].pos.y = h; + m_particle[i].speed.y *= -0.4f; + m_particle[i].speed.x *= 0.4f; + m_particle[i].speed.z *= 0.4f; + m_particle[i].bounce ++; // more impact + } + else // disappears after 3 bounces? + { + if ( m_particle[i].pos.y < h-10.0f || + m_particle[i].time >= 20.0f ) + { + DeleteRank(i); + continue; + } + } + } + } -bool CParticle::TrackMove(int i, Math::Vector pos, float progress) -{ - GetLogger()->Trace("CParticle::TrackMove() stub!\n"); - // TODO! - return true; -} + // Manages drag associated. + int r = m_particle[i].trackRank; + if (r != -1) // drag exists? + { + if (TrackMove(r, m_particle[i].pos, progress)) + { + DeleteRank(i); + continue; + } -void CParticle::TrackDraw(int i, ParticleType type) -{ - GetLogger()->Trace("CParticle::TrackDraw() stub!\n"); - // TODO! -} + m_track[r].drawParticle = (progress < 1.0f); + } + + if (m_particle[i].type == PARTITRACK1) // explosion technique? + { + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.375f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTITRACK2) // spray blue? + { + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.500f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTITRACK3) // spider? + { + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.500f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTITRACK4) // insect explosion? + { + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.625f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTITRACK5) // derrick? + { + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.750f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTITRACK6) // reset in/out? + { + ts.x = 0.0f; + ts.y = 0.0f; + ti.x = 0.0f; + ti.y = 0.0f; + } + + if ( m_particle[i].type == PARTITRACK7 || // win-1 ? + m_particle[i].type == PARTITRACK8 || // win-2 ? + m_particle[i].type == PARTITRACK9 || // win-3 ? + m_particle[i].type == PARTITRACK10 ) // win-4 ? + { + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.25f*(m_particle[i].type-PARTITRACK7); + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTITRACK11) // phazer shot? + { + CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); + m_particle[i].goal = m_particle[i].pos; + if (object != nullptr) + { + if (object->GetType() == OBJECT_MOTHER) + object->ExploObject(EXPLO_BOUM, 0.1f); + else + object->ExploObject(EXPLO_BOUM, 0.0f, GetDecay(object->GetType())); + } + + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.375f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTITRACK12) // drag reactor? + { + m_particle[i].zoom = 1.0f; + + ts.x = 0.375f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIMOTOR) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.000f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIBLITZ) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + m_particle[i].angle = Math::Rand()*Math::PI*2.0f; + + ts.x = 0.125f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTICRASH) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.25f) + m_particle[i].zoom = progress/0.25f; + else + m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f; + + ts.x = 0.000f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIVAPOR) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].intensity = 1.0f-progress; + m_particle[i].zoom = 1.0f+progress*3.0f; + + ts.x = 0.000f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIGAS) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + + ts.x = 0.375f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIBASE) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f+progress*7.0f; + m_particle[i].intensity = powf(1.0f-progress, 3.0f); + + ts.x = 0.375f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if ( m_particle[i].type == PARTIFIRE || + m_particle[i].type == PARTIFIREZ ) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].type == PARTIFIRE) + m_particle[i].zoom = 1.0f-progress; + else + m_particle[i].zoom = progress; + + ts.x = 0.500f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIGUN1) // fireball shot? + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].testTime >= 0.1f) + { + m_particle[i].testTime = 0.0f; + + if (m_terrain->GetHeightToFloor(m_particle[i].pos, true) < -2.0f) + { + m_exploGunCounter++; + + if (m_exploGunCounter % 2 == 0) + { + pos = m_particle[i].goal; + m_terrain->AdjustToFloor(pos, true); + Math::Vector speed; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 0.0f; + Math::Point dim; + dim.x = Math::Rand()*6.0f+6.0f; + dim.y = dim.x; + float duration = Math::Rand()*1.0f+1.0f; + float mass = 0.0f; + CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f); + + pos.y += 1.0f; + int total = static_cast(2.0f*m_engine->GetParticleDensity()); + for (int j = 0; j < total; j++) + { + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + speed.y = Math::Rand()*20.0f; + dim.x = 1.0f; + dim.y = dim.x; + duration = Math::Rand()*1.0f+1.0f; + mass = Math::Rand()*10.0f+15.0f; + CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f); + } + } + + if (m_exploGunCounter % 4 == 0) + Play(SOUND_EXPLOg1, pos, 0.5f); + + DeleteRank(i); + continue; + } + + CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); + m_particle[i].goal = m_particle[i].pos; + if (object != nullptr) + { + object->ExploObject(EXPLO_BURN, 0.0f, GetDecay(object->GetType())); + + m_exploGunCounter++; + + if (m_exploGunCounter % 2 == 0) + { + pos = m_particle[i].pos; + Math::Vector speed; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 0.0f; + Math::Point dim; + dim.x = Math::Rand()*6.0f+6.0f; + dim.y = dim.x; + float duration = Math::Rand()*1.0f+1.0f; + float mass = 0.0f; + CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f); + + pos.y += 1.0f; + int total = static_cast(2.0f*m_engine->GetParticleDensity()); + for (int j = 0; j < total; j++) + { + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + speed.y = Math::Rand()*20.0f; + dim.x = 1.0f; + dim.y = dim.x; + duration = Math::Rand()*1.0f+1.0f; + mass = Math::Rand()*10.0f+15.0f; + CreateParticle(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f); + } + } + + if (m_exploGunCounter % 4 == 0) + Play(SOUND_EXPLOg1, pos, 0.5f); + + DeleteRank(i); + continue; + } + } + + m_particle[i].angle -= rTime*Math::PI*8.0f; + m_particle[i].zoom = 1.0f-progress; + + ts.x = 0.00f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIGUN2) // ant shot? + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].testTime >= 0.2f) + { + m_particle[i].testTime = 0.0f; + CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); + m_particle[i].goal = m_particle[i].pos; + if (object != nullptr) + { + if (object->GetShieldRadius() > 0.0f) // protected by shield? + { + CreateParticle(m_particle[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f); + if (m_lastTimeGunDel > 0.2f) + { + m_lastTimeGunDel = 0.0f; + Play(SOUND_GUNDEL, m_particle[i].pos, 1.0f); + } + DeleteRank(i); + continue; + } + else + { + if (object->GetType() != OBJECT_HUMAN) + Play(SOUND_TOUCH, m_particle[i].pos, 1.0f); + + object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion + } + } + } + + m_particle[i].angle = Math::Rand()*Math::PI*2.0f; + m_particle[i].zoom = 1.0f-progress; + + ts.x = 0.125f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIGUN3) // spider suicides? + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].testTime >= 0.2f) + { + m_particle[i].testTime = 0.0f; + CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); + m_particle[i].goal = m_particle[i].pos; + if (object != nullptr) + { + if (object->GetShieldRadius() > 0.0f) + { + CreateParticle(m_particle[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f); + if (m_lastTimeGunDel > 0.2f) + { + m_lastTimeGunDel = 0.0f; + Play(SOUND_GUNDEL, m_particle[i].pos, 1.0f); + } + DeleteRank(i); + continue; + } + else + { + object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion + } + } + } + + ts.x = 0.500f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIGUN4) // orgaball shot? + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].testTime >= 0.1f) + { + m_particle[i].testTime = 0.0f; + + if (m_terrain->GetHeightToFloor(m_particle[i].pos, true) < -2.0f) + { + m_exploGunCounter ++; + + if (m_exploGunCounter % 2 == 0) + { + pos = m_particle[i].goal; + m_terrain->AdjustToFloor(pos, true); + Math::Vector speed; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 0.0f; + Math::Point dim; + dim.x = Math::Rand()*4.0f+2.0f; + dim.y = dim.x; + float duration = Math::Rand()*0.7f+0.7f; + float mass = 0.0f; + CreateParticle(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f); + } + + if (m_exploGunCounter % 4 == 0) + { + Play(SOUND_EXPLOg2, pos, 0.5f); + } + + DeleteRank(i); + continue; + } + + CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather); + m_particle[i].goal = m_particle[i].pos; + if (object != nullptr) + { + object->ExploObject(EXPLO_BOUM, 0.0f, GetDecay(object->GetType())); + + m_exploGunCounter ++; + + if (m_exploGunCounter % 2 == 0) + { + pos = m_particle[i].pos; + Math::Vector speed; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 0.0f; + Math::Point dim; + dim.x = Math::Rand()*4.0f+2.0f; + dim.y = dim.x; + float duration = Math::Rand()*0.7f+0.7f; + float mass = 0.0f; + CreateParticle(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f); + } + + if (m_exploGunCounter % 4 == 0) + Play(SOUND_EXPLOg2, pos, 0.5f); + + DeleteRank(i); + continue; + } + } + + m_particle[i].angle = Math::Rand()*Math::PI*2.0f; + m_particle[i].zoom = 1.0f-progress; + + ts.x = 0.125f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIFLIC) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 0.1f+progress; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.00f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTISHOW) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.5f) m_particle[i].intensity = progress/0.5f; + else m_particle[i].intensity = 2.0f-progress/0.5f; + m_particle[i].zoom = 1.0f-progress*0.8f; + m_particle[i].angle -= rTime*Math::PI*0.5f; + + ts.x = 0.50f; + ts.y = 0.00f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTICHOC) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 0.1f+progress; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.50f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIGFLAT) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 0.1f+progress; + m_particle[i].intensity = 1.0f-progress; + m_particle[i].angle -= rTime*Math::PI*2.0f; + + ts.x = 0.00f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTILIMIT1) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f; + m_particle[i].intensity = 1.0f; + + ts.x = 0.000f; + ts.y = 0.125f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + if (m_particle[i].type == PARTILIMIT2) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f; + m_particle[i].intensity = 1.0f; + + ts.x = 0.375f; + ts.y = 0.125f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + if (m_particle[i].type == PARTILIMIT3) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f; + m_particle[i].intensity = 1.0f; + + ts.x = 0.500f; + ts.y = 0.125f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIFOG0) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.3f+sinf(progress)*0.15f; + m_particle[i].angle += rTime*0.05f; + + ts.x = 0.25f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + if (m_particle[i].type == PARTIFOG1) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.3f+sinf(progress)*0.15f; + m_particle[i].angle -= rTime*0.07f; + ts.x = 0.25f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIFOG2) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.6f+sinf(progress)*0.15f; + m_particle[i].angle += rTime*0.05f; + + ts.x = 0.75f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + if (m_particle[i].type == PARTIFOG3) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.6f+sinf(progress)*0.15f; + m_particle[i].angle -= rTime*0.07f; + + ts.x = 0.75f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIFOG4) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.5f+sinf(progress)*0.2f; + m_particle[i].angle += rTime*0.05f; + + ts.x = 0.00f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + if (m_particle[i].type == PARTIFOG5) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.5f+sinf(progress)*0.2f; + m_particle[i].angle -= rTime*0.07f; + + ts.x = 0.00f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIFOG6) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.5f+sinf(progress)*0.2f; + m_particle[i].angle += rTime*0.05f; + + ts.x = 0.50f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + if (m_particle[i].type == PARTIFOG7) + { + m_particle[i].zoom = progress; + m_particle[i].intensity = 0.5f+sinf(progress)*0.2f; + m_particle[i].angle -= rTime*0.07f; + + ts.x = 0.50f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + // Decreases the intensity if the camera + // is almost at the same height (fog was eye level). + if ( m_particle[i].type >= PARTIFOG0 && + m_particle[i].type <= PARTIFOG9 ) + { + float h = 10.0f; + + if ( m_particle[i].pos.y >= eye.y && + m_particle[i].pos.y < eye.y+h ) + { + m_particle[i].intensity *= (m_particle[i].pos.y-eye.y)/h; + } + if ( m_particle[i].pos.y > eye.y-h && + m_particle[i].pos.y < eye.y ) + { + m_particle[i].intensity *= (eye.y-m_particle[i].pos.y)/h; + } + } + + if ( m_particle[i].type == PARTIEXPLOT || + m_particle[i].type == PARTIEXPLOO ) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress/2.0f; + m_particle[i].intensity = 1.0f-progress; + + if (m_particle[i].type == PARTIEXPLOT) ts.x = 0.750f; + else ts.x = 0.875f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIEXPLOG1) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.375f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + if (m_particle[i].type == PARTIEXPLOG2) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.625f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIFLAME) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress/2.0f; + if (progress < 0.5f) + { + m_particle[i].intensity = progress/0.5f; + } + else + { + m_particle[i].intensity = 2.0f-progress/0.5f; + } + + ts.x = 0.750f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIBUBBLE) + { + if ( progress >= 1.0f || + m_particle[i].pos.y >= m_water->GetLevel() ) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress/2.0f; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.250f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if ( m_particle[i].type == PARTISMOKE1 || + m_particle[i].type == PARTISMOKE2 || + m_particle[i].type == PARTISMOKE3 ) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.25f) + { + m_particle[i].zoom = progress/0.25f; + } + else + { + m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f; + } + + ts.x = 0.500f+0.125f*(m_particle[i].type-PARTISMOKE1); + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIBLOOD) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.750f+(rand()%2)*0.125f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIBLOODM) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.875f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if ( m_particle[i].type == PARTIVIRUS1 || + m_particle[i].type == PARTIVIRUS2 || + m_particle[i].type == PARTIVIRUS3 || + m_particle[i].type == PARTIVIRUS4 || + m_particle[i].type == PARTIVIRUS5 || + m_particle[i].type == PARTIVIRUS6 || + m_particle[i].type == PARTIVIRUS7 || + m_particle[i].type == PARTIVIRUS8 || + m_particle[i].type == PARTIVIRUS9 || + m_particle[i].type == PARTIVIRUS10 ) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.25f) + m_particle[i].zoom = progress/0.25f; + else + m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f; + + m_particle[i].angle += rTime*Math::PI*1.0f; + + if (m_particle[i].type == PARTIVIRUS1) // A ? + { + ts.x = 0.0f/256.0f; ts.y = 19.0f/256.0f; + ti.x = 10.0f/256.0f; ti.y = 30.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS2) // C ? + { + ts.x = 19.0f/256.0f; ts.y = 19.0f/256.0f; + ti.x = 28.0f/256.0f; ti.y = 30.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS3) // E ? + { + ts.x = 36.0f/256.0f; ts.y = 19.0f/256.0f; + ti.x = 45.0f/256.0f; ti.y = 30.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS4) // N ? + { + ts.x = 110.0f/256.0f; ts.y = 19.0f/256.0f; + ti.x = 120.0f/256.0f; ti.y = 30.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS5) // R ? + { + ts.x = 148.0f/256.0f; ts.y = 19.0f/256.0f; + ti.x = 158.0f/256.0f; ti.y = 30.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS6) // T ? + { + ts.x = 166.0f/256.0f; ts.y = 19.0f/256.0f; + ti.x = 175.0f/256.0f; ti.y = 30.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS7) // 0 ? + { + ts.x = 90.0f/256.0f; ts.y = 2.0f/256.0f; + ti.x = 98.0f/256.0f; ti.y = 13.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS8) // 2 ? + { + ts.x = 103.0f/256.0f; ts.y = 2.0f/256.0f; + ti.x = 111.0f/256.0f; ti.y = 13.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS9) // 5 ? + { + ts.x = 125.0f/256.0f; ts.y = 2.0f/256.0f; + ti.x = 132.0f/256.0f; ti.y = 13.0f/256.0f; + } + if (m_particle[i].type == PARTIVIRUS10) // 9 ? + { + ts.x = 153.0f/256.0f; ts.y = 2.0f/256.0f; + ti.x = 161.0f/256.0f; ti.y = 13.0f/256.0f; + } + } + + if (m_particle[i].type == PARTIBLUE) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + + ts.x = 0.625f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIROOT) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.25f) + { + m_particle[i].zoom = progress/0.25f; + } + else + { + m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f; + } + + ts.x = 0.000f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIRECOVER) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.25f) + { + m_particle[i].zoom = progress/0.25f; + } + else + { + m_particle[i].intensity = 1.0f-(progress-0.25f)/0.75f; + } + + ts.x = 0.875f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIEJECT) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.625f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTISCRAPS) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + + ts.x = 0.625f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIFRAG) + { + m_particle[i].angle += rTime*Math::PI*0.5f; + + ts.x = 0.0f; + ts.y = 0.0f; + ti.x = 0.0f; + ti.y = 0.0f; + } + + if (m_particle[i].type == PARTIPART) + { + ts.x = 0.0f; + ts.y = 0.0f; + ti.x = 0.0f; + ti.y = 0.0f; + } + + if (m_particle[i].type == PARTIQUEUE) + { + if (m_particle[i].testTime >= 0.05f) + { + m_particle[i].testTime = 0.0f; + + pos = m_particle[i].pos; + Math::Vector speed = Math::Vector(0.0f, 0.0f, 0.0f); + Math::Point dim; + dim.x = 1.0f*(Math::Rand()*0.8f+0.6f); + dim.y = dim.x; + CreateParticle(pos, speed, dim, PARTIGAS, 0.5f); + } + + ts.x = 0.375f; + ts.y = 0.750f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIORGANIC1) + { + if (progress >= 1.0f) + { + DeleteRank(i); + + pos = m_particle[i].pos; + Math::Point dim; + dim.x = m_particle[i].dim.x/4.0f; + dim.y = dim.x; + float duration = m_particle[i].duration; + float mass = m_particle[i].mass; + int total = static_cast((10.0f*m_engine->GetParticleDensity())); + for (int j = 0; j < total; j++) + { + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.y = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + CreateParticle(pos, speed, dim, PARTIORGANIC2, duration, mass); + } + total = static_cast((5.0f*m_engine->GetParticleDensity())); + for (int j = 0; j < total; j++) + { + Math::Vector speed; + speed.x = (Math::Rand()-0.5f)*20.0f; + speed.y = (Math::Rand()-0.5f)*20.0f; + speed.z = (Math::Rand()-0.5f)*20.0f; + duration *= Math::Rand()+0.8f; + CreateTrack(pos, speed, dim, PARTITRACK4, duration, mass, duration*0.2f, dim.x*2.0f); + } + continue; + } + + m_particle[i].zoom = (m_particle[i].time-m_particle[i].duration); + + ts.x = 0.125f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIORGANIC2) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); + + ts.x = 0.125f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIGLINT) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress > 0.5f) + m_particle[i].zoom = 1.0f-(progress-0.5f)*2.0f; + + m_particle[i].angle = m_particle[i].time*Math::PI; + + ts.x = 0.75f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIGLINTb) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress > 0.5f) + m_particle[i].zoom = 1.0f-(progress-0.5f)*2.0f; + + m_particle[i].angle = m_particle[i].time*Math::PI; + + ts.x = 0.75f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIGLINTr) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress > 0.5f) + m_particle[i].zoom = 1.0f-(progress-0.5f)*2.0f; + + m_particle[i].angle = m_particle[i].time*Math::PI; + + ts.x = 0.75f; + ts.y = 0.00f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if ( m_particle[i].type >= PARTILENS1 && + m_particle[i].type <= PARTILENS4 ) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.5f) + m_particle[i].zoom = progress*2.0f; + else + m_particle[i].intensity = 1.0f-(progress-0.5f)*2.0f; + + ts.x = 0.25f*(m_particle[i].type-PARTILENS1); + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTICONTROL) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.3f) + { + m_particle[i].zoom = progress/0.3f; + } + else + { + m_particle[i].zoom = 1.0f; + m_particle[i].intensity = 1.0f-(progress-0.3f)/0.7f; + } + + ts.x = 0.00f; + ts.y = 0.00f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIGUNDEL) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress > 0.5f) + m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration/2.0f); + + m_particle[i].angle = m_particle[i].time*Math::PI; + + ts.x = 0.75f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIQUARTZ) + { + if (progress >= 1.0f) + { + m_particle[i].time = 0.0f; + m_particle[i].duration = 0.5f+Math::Rand()*2.0f; + m_particle[i].pos.x = m_particle[i].speed.x + (Math::Rand()-0.5f)*m_particle[i].mass; + m_particle[i].pos.y = m_particle[i].speed.y + (Math::Rand()-0.5f)*m_particle[i].mass; + m_particle[i].pos.z = m_particle[i].speed.z + (Math::Rand()-0.5f)*m_particle[i].mass; + m_particle[i].dim.x = 0.5f+Math::Rand()*1.5f; + m_particle[i].dim.y = m_particle[i].dim.x; + progress = 0.0f; + } + + if (progress < 0.2f) + { + m_particle[i].zoom = progress/0.2f; + m_particle[i].intensity = 1.0f; + } + else + { + m_particle[i].zoom = 1.0f; + m_particle[i].intensity = 1.0f-(progress-0.2f)/0.8f; + } + + ts.x = 0.25f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTITOTO) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + if (progress < 0.15f) + m_particle[i].intensity = progress/0.15f; + else + m_particle[i].intensity = 1.0f-(progress-0.15f)/0.85f; + + m_particle[i].intensity *= 0.5f; + + ts.x = 0.25f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIERROR) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = progress*1.0f; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.500f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIWARNING) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = progress*1.0f; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.875f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIINFO) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = progress*1.0f; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.750f; + ts.y = 0.875f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTISELY) + { + ts.x = 0.75f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + if (m_particle[i].type == PARTISELR) + { + ts.x = 0.75f; + ts.y = 0.00f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTISPHERE0) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = progress*m_particle[i].dim.x; + + if (progress < 0.65f) + m_particle[i].intensity = progress/0.65f; + else + m_particle[i].intensity = 1.0f-(progress-0.65f)/0.35f; + + m_particle[i].intensity *= 0.5f; + + ts.x = 0.50f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTISPHERE1) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.30f) + m_particle[i].intensity = progress/0.30f; + else + m_particle[i].intensity = 1.0f-(progress-0.30f)/0.70f; + + m_particle[i].zoom = progress*m_particle[i].dim.x; + m_particle[i].angle = m_particle[i].time*Math::PI*2.0f; + + ts.x = 0.000f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTISPHERE2) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (progress < 0.20f) + m_particle[i].intensity = 1.0f; + else + m_particle[i].intensity = 1.0f-(progress-0.20f)/0.80f; + + m_particle[i].zoom = progress*m_particle[i].dim.x; + m_particle[i].angle = m_particle[i].time*Math::PI*2.0f; + + ts.x = 0.125f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTISPHERE3) + { + if (m_particle[i].phase == PARPHEND && + progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].phase == PARPHSTART) + { + m_particle[i].intensity = progress; + if (m_particle[i].intensity > 1.0f) + m_particle[i].intensity = 1.0f; + } + + if (m_particle[i].phase == PARPHEND) + m_particle[i].intensity = 1.0f-progress; + + m_particle[i].zoom = m_particle[i].dim.x; + m_particle[i].angle = m_particle[i].time*Math::PI*0.2f; + + ts.x = 0.25f; + ts.y = 0.75f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTISPHERE4) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = progress*m_particle[i].dim.x; + + if (progress < 0.65 ) + m_particle[i].intensity = progress/0.65f; + else + m_particle[i].intensity = 1.0f-(progress-0.65f)/0.35f; + + m_particle[i].intensity *= 0.5f; + + ts.x = 0.125f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTISPHERE5) + { + m_particle[i].intensity = 0.7f+sinf(progress)*0.3f; + m_particle[i].zoom = m_particle[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f); + m_particle[i].angle = m_particle[i].time*Math::PI*0.2f; + + ts.x = 0.25f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTISPHERE6) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = (1.0f-progress)*m_particle[i].dim.x; + m_particle[i].intensity = progress*0.5f; + + ts.x = 0.125f; + ts.y = 0.000f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIPLOUF0) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = progress; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.50f; + ts.y = 0.50f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIDROP) + { + if (progress >= 1.0f || + m_particle[i].pos.y < m_water->GetLevel()) + { + DeleteRank(i); + continue; + } + + m_particle[i].zoom = 1.0f-progress; + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.750f; + ts.y = 0.500f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIWATER) + { + if (progress >= 1.0f || + m_particle[i].pos.y < m_water->GetLevel()) + { + DeleteRank(i); + continue; + } + + m_particle[i].intensity = 1.0f-progress; + + ts.x = 0.125f; + ts.y = 0.125f; + ti.x = ts.x+0.125f; + ti.y = ts.y+0.125f; + } + + if (m_particle[i].type == PARTIRAY1) // rayon tour ? + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + if (m_particle[i].testTime >= 0.2f) + { + m_particle[i].testTime = 0.0f; + CObject* object = SearchObjectRay(m_particle[i].pos, m_particle[i].goal, + m_particle[i].type, m_particle[i].objFather); + if (object != nullptr) + object->ExploObject(EXPLO_BOUM, 0.0f); + } + + ts.x = 0.00f; + ts.y = 0.00f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + if (m_particle[i].type == PARTIRAY2 || + m_particle[i].type == PARTIRAY3) + { + if (progress >= 1.0f) + { + DeleteRank(i); + continue; + } + + ts.x = 0.00f; + ts.y = 0.25f; + ti.x = ts.x+0.25f; + ti.y = ts.y+0.25f; + } + + float dp = (1.0f/256.0f)/2.0f; + m_particle[i].texSup.x = ts.x+dp; + m_particle[i].texSup.y = ts.y+dp; + m_particle[i].texInf.x = ti.x-dp; + m_particle[i].texInf.y = ti.y-dp; + m_particle[i].time += rTime; + m_particle[i].testTime += rTime; + } +} + +bool CParticle::TrackMove(int i, Math::Vector pos, float progress) +{ + if (i < 0 || i >= MAXTRACK) return true; + if (! m_track[i].used) return true; + + if (progress < 1.0f) // particle exists? + { + int h = m_track[i].head; + + Math::Vector last; + + if ( m_track[i].posUsed == 1 || + m_track[i].last+m_track[i].step <= progress ) + { + m_track[i].last = progress; + last = m_track[i].pos[h]; + h ++; + if (h == MAXTRACKLEN) h = 0; + if (m_track[i].posUsed < MAXTRACKLEN) m_track[i].posUsed++; + } + else + { + int hh = h-1; + if (hh < 0) hh = MAXTRACKLEN-1; + last = m_track[i].pos[hh]; + } + m_track[i].pos[h] = pos; + m_track[i].len[h] = Math::Distance(pos, last); + + m_track[i].head = h; + + m_track[i].intensity = 1.0f-progress; + } + else // slow death of the track ? + { + m_track[i].intensity = 0.0f; + } + + return (m_track[i].intensity <= 0.0f); +} + +void CParticle::TrackDraw(int i, ParticleType type) +{ + // Calculates the total length memorized. + float lTotal = 0.0f; + int h = m_track[i].head; + for (int counter = 0; counter < m_track[i].posUsed-1; counter++) + { + lTotal += m_track[i].len[h]; + h--; + if (h < 0) h = MAXTRACKLEN-1; + } + + Math::Matrix mat; + mat.LoadIdentity(); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Point texInf, texSup; + + if (type == PARTITRACK1) // explosion technique? + { + texInf.x = 64.5f/256.0f; + texInf.y = 21.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 22.0f/256.0f; // orange + } + if (type == PARTITRACK2) // blue spray? + { + texInf.x = 64.5f/256.0f; + texInf.y = 13.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 14.0f/256.0f; // blue + } + if (type == PARTITRACK3) // spider? + { + texInf.x = 64.5f/256.0f; + texInf.y = 5.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 6.0f/256.0f; // brown + } + if (type == PARTITRACK4) // insect explosion? + { + texInf.x = 64.5f/256.0f; + texInf.y = 9.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 10.0f/256.0f; // dark green + } + if (type == PARTITRACK5) // derrick? + { + texInf.x = 64.5f/256.0f; + texInf.y = 29.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 30.0f/256.0f; // dark brown + } + if (type == PARTITRACK6) // reset in/out? + { + texInf.x = 64.5f/256.0f; + texInf.y = 17.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 18.0f/256.0f; // cyan + } + if (type == PARTITRACK7) // win-1? + { + texInf.x = 64.5f/256.0f; + texInf.y = 41.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 42.0f/256.0f; // orange + } + if (type == PARTITRACK8) // win-2? + { + texInf.x = 64.5f/256.0f; + texInf.y = 45.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 46.0f/256.0f; // yellow + } + if (type == PARTITRACK9) // win-3? + { + texInf.x = 64.5f/256.0f; + texInf.y = 49.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 50.0f/256.0f; // red + } + if (type == PARTITRACK10) // win-4? + { + texInf.x = 64.5f/256.0f; + texInf.y = 53.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 54.0f/256.0f; // violet + } + if (type == PARTITRACK11) // phazer shot? + { + texInf.x = 64.5f/256.0f; + texInf.y = 21.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 22.0f/256.0f; // orange + } + if (type == PARTITRACK12) // drag reactor? + { + texInf.x = 64.5f/256.0f; + texInf.y = 21.0f/256.0f; + texSup.x = 95.5f/256.0f; + texSup.y = 22.0f/256.0f; // orange + } + + h = m_track[i].head; + Math::Vector p1 = m_track[i].pos[h]; + float f1 = m_track[i].intensity; + + Math::Vector eye = m_engine->GetEyePt(); + float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z); + + Vertex vertex[4]; + Math::Vector corner[4]; + + for (int counter = 0; counter < m_track[i].posUsed-1; counter++) + { + float f2 = f1-(m_track[i].len[h]/lTotal); + if (f2 < 0.0f) f2 = 0.0f; + + h --; + if (h < 0) h = MAXTRACKLEN-1; + + Math::Vector p2 = m_track[i].pos[h]; + + Math::Vector n = Normalize(p1-eye); + + Math::Vector p; + Math::Point rot; + + p = p1; + p.x += f1*m_track[i].width; + rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z)); + corner[0].x = rot.x; + corner[0].y = p1.y; + corner[0].z = rot.y; + rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z)); + corner[1].x = rot.x; + corner[1].y = p1.y; + corner[1].z = rot.y; + + p = p2; + p.x += f2*m_track[i].width; + rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z)); + corner[2].x = rot.x; + corner[2].y = p2.y; + corner[2].z = rot.y; + rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z)); + corner[3].x = rot.x; + corner[3].y = p2.y; + corner[3].z = rot.y; + + if (p2.y < p1.y) + { + vertex[0] = Vertex(corner[1], n, Math::Point(texSup.x, texSup.y)); + vertex[1] = Vertex(corner[0], n, Math::Point(texInf.x, texSup.y)); + vertex[2] = Vertex(corner[3], n, Math::Point(texSup.x, texInf.y)); + vertex[3] = Vertex(corner[2], n, Math::Point(texInf.x, texInf.y)); + } + else + { + vertex[0] = Vertex(corner[0], n, Math::Point(texSup.x, texSup.y)); + vertex[1] = Vertex(corner[1], n, Math::Point(texInf.x, texSup.y)); + vertex[2] = Vertex(corner[2], n, Math::Point(texSup.x, texInf.y)); + vertex[3] = Vertex(corner[3], n, Math::Point(texInf.x, texInf.y)); + } + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); + + if (f2 < 0.0f) break; + f1 = f2; + p1 = p2; + } +} + +void CParticle::DrawParticleTriangle(int i) +{ + if (m_particle[i].zoom == 0.0f) return; + + Math::Vector eye = m_engine->GetEyePt(); + Math::Vector pos = m_particle[i].pos; + + CObject* object = m_particle[i].objLink; + if (object != nullptr) + pos += object->GetPosition(0); + + Math::Vector angle; + angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y); + angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x); + angle.z = m_particle[i].angle; + + Math::Matrix mat; + Math::LoadRotationXZYMatrix(mat, angle); + mat.Set(1, 4, pos.x); + mat.Set(2, 4, pos.y); + mat.Set(3, 4, pos.z); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLES, m_triangle[i].triangle, 3); + m_engine->AddStatisticTriangle(1); +} + +void CParticle::DrawParticleNorm(int i) +{ + float zoom = m_particle[i].zoom; + + if (zoom == 0.0f) return; + if (m_particle[i].intensity == 0.0f) return; + + + Math::Vector corner[4]; + Vertex vertex[4]; + + if (m_particle[i].sheet == SH_INTERFACE) + { + Math::Vector pos = m_particle[i].pos; + + Math::Vector n(0.0f, 0.0f, -1.0f); + + Math::Point dim; + dim.x = m_particle[i].dim.x * zoom; + dim.y = m_particle[i].dim.y * zoom; + + corner[0].x = pos.x+dim.x; + corner[0].y = pos.y+dim.y; + corner[0].z = 0.0f; + + corner[1].x = pos.x-dim.x; + corner[1].y = pos.y+dim.y; + corner[1].z = 0.0f; + + corner[2].x = pos.x+dim.x; + corner[2].y = pos.y-dim.y; + corner[2].z = 0.0f; + + corner[3].x = pos.x-dim.x; + corner[3].y = pos.y-dim.y; + corner[3].z = 0.0f; + + vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y)); + vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y)); + vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y)); + vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y)); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); + } + else + { + Math::Vector eye = m_engine->GetEyePt(); + Math::Vector pos = m_particle[i].pos; + + CObject* object = m_particle[i].objLink; + if (object != nullptr) + pos += object->GetPosition(0); + + Math::Vector angle; + angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y); + angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x); + angle.z = m_particle[i].angle; + + Math::Matrix mat; + Math::LoadRotationXZYMatrix(mat, angle); + mat.Set(1, 4, pos.x); + mat.Set(2, 4, pos.y); + mat.Set(3, 4, pos.z); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Vector n(0.0f, 0.0f, -1.0f); + + Math::Point dim; + dim.x = m_particle[i].dim.x * zoom; + dim.y = m_particle[i].dim.y * zoom; + + corner[0].x = dim.x; + corner[0].y = dim.y; + corner[0].z = 0.0f; + + corner[1].x = -dim.x; + corner[1].y = dim.y; + corner[1].z = 0.0f; + + corner[2].x = dim.x; + corner[2].y = -dim.y; + corner[2].z = 0.0f; + + corner[3].x = -dim.x; + corner[3].y = -dim.y; + corner[3].z = 0.0f; + + vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y)); + vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y)); + vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y)); + vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y)); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); + } +} + +void CParticle::DrawParticleFlat(int i) +{ + if (m_particle[i].zoom == 0.0f) return; + if (m_particle[i].intensity == 0.0f) return; + + Math::Vector pos = m_particle[i].pos; + + CObject* object = m_particle[i].objLink; + if (object != nullptr) + pos += object->GetPosition(0); + + Math::Vector angle; + angle.x = Math::PI/2.0f; + angle.y = 0.0f; + angle.z = m_particle[i].angle; + + if (m_engine->GetRankView() == 1) // underwater? + pos.y -= 1.0f; + + Math::Vector eye = m_engine->GetEyePt(); + if (pos.y > eye.y) // seen from below? + angle.x = -Math::PI/2.0f; + + Math::Matrix mat; + Math::LoadRotationXZYMatrix(mat, angle); + mat.Set(1, 4, pos.x); + mat.Set(2, 4, pos.y); + mat.Set(3, 4, pos.z); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Vector n(0.0f, 0.0f, -1.0f); + + Math::Point dim; + dim.x = m_particle[i].dim.x * m_particle[i].zoom; + dim.y = m_particle[i].dim.y * m_particle[i].zoom; + + Math::Vector corner[4]; + corner[0].x = dim.x; + corner[0].y = dim.y; + corner[0].z = 0.0f; + + corner[1].x = -dim.x; + corner[1].y = dim.y; + corner[1].z = 0.0f; + + corner[2].x = dim.x; + corner[2].y = -dim.y; + corner[2].z = 0.0f; + + corner[3].x = -dim.x; + corner[3].y = -dim.y; + corner[3].z = 0.0f; + + Vertex vertex[4]; + vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y)); + vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y)); + vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y)); + vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y)); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); +} + +void CParticle::DrawParticleFog(int i) +{ + if (!m_engine->GetFog()) return; + if (m_particle[i].intensity == 0.0f) return; + + Math::Vector pos = m_particle[i].pos; + + Math::Point dim; + dim.x = m_particle[i].dim.x; + dim.y = m_particle[i].dim.y; + + Math::Point zoom; + + if ( m_particle[i].type == PARTIFOG0 || + m_particle[i].type == PARTIFOG2 || + m_particle[i].type == PARTIFOG4 || + m_particle[i].type == PARTIFOG6 ) + { + zoom.x = 1.0f+sinf(m_particle[i].zoom*2.0f)/6.0f; + zoom.y = 1.0f+cosf(m_particle[i].zoom*2.7f)/6.0f; + } + if ( m_particle[i].type == PARTIFOG1 || + m_particle[i].type == PARTIFOG3 || + m_particle[i].type == PARTIFOG5 || + m_particle[i].type == PARTIFOG7 ) + { + zoom.x = 1.0f+sinf(m_particle[i].zoom*3.0f)/6.0f; + zoom.y = 1.0f+cosf(m_particle[i].zoom*3.7f)/6.0f; + } + + dim.x *= zoom.x; + dim.y *= zoom.y; + + CObject* object = m_particle[i].objLink; + if (object != nullptr) + pos += object->GetPosition(0); + + Math::Vector angle; + angle.x = Math::PI/2.0f; + angle.y = 0.0f; + angle.z = m_particle[i].angle; + + if (m_engine->GetRankView() == 1) // underwater? + pos.y -= 1.0f; + + Math::Vector eye = m_engine->GetEyePt(); + if (pos.y > eye.y) // seen from below? + angle.x = -Math::PI/2.0f; + + Math::Matrix mat; + Math::LoadRotationXZYMatrix(mat, angle); + mat.Set(1, 4, pos.x); + mat.Set(2, 4, pos.y); + mat.Set(3, 4, pos.z); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Vector n(0.0f, 0.0f, -1.0f); + + Math::Vector corner[4]; + + corner[0].x = dim.x; + corner[0].y = dim.y; + corner[0].z = 0.0f; + + corner[1].x = -dim.x; + corner[1].y = dim.y; + corner[1].z = 0.0f; + + corner[2].x = dim.x; + corner[2].y = -dim.y; + corner[2].z = 0.0f; + + corner[3].x = -dim.x; + corner[3].y = -dim.y; + corner[3].z = 0.0f; + + Vertex vertex[4]; + + vertex[0] = Vertex(corner[1], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texSup.y)); + vertex[1] = Vertex(corner[0], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texSup.y)); + vertex[2] = Vertex(corner[3], n, Math::Point(m_particle[i].texSup.x, m_particle[i].texInf.y)); + vertex[3] = Vertex(corner[2], n, Math::Point(m_particle[i].texInf.x, m_particle[i].texInf.y)); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); +} + +void CParticle::DrawParticleRay(int i) +{ + if (m_particle[i].zoom == 0.0f) return; + if (m_particle[i].intensity == 0.0f) return; + + Math::Vector eye = m_engine->GetEyePt(); + Math::Vector pos = m_particle[i].pos; + Math::Vector goal = m_particle[i].goal; + + CObject* object = m_particle[i].objLink; + if (object != nullptr) + pos += object->GetPosition(0); + + float a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z)); + bool left = (a < Math::PI); + + Math::Vector proj = Math::Projection(pos, goal, eye); + Math::Vector angle; + angle.x = -Math::RotateAngle(Math::DistanceProjected(proj, eye), proj.y-eye.y); + angle.y = Math::RotateAngle(pos.z-goal.z, pos.x-goal.x)+Math::PI/2.0f; + angle.z = -Math::RotateAngle(Math::DistanceProjected(pos, goal), pos.y-goal.y); + if (left) angle.x = -angle.x; + + Math::Matrix mat; + Math::LoadRotationZXYMatrix(mat, angle); + mat.Set(1, 4, pos.x); + mat.Set(2, 4, pos.y); + mat.Set(3, 4, pos.z); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Vector n(0.0f, 0.0f, left ? 1.0f : -1.0f); + + Math::Point dim; + dim.x = m_particle[i].dim.x * m_particle[i].zoom; + dim.y = m_particle[i].dim.y * m_particle[i].zoom; + + if (left) dim.y = -dim.y; + + float len = Math::Distance(pos, goal); + float adv = 0.0f; + + int step = static_cast((len/(dim.x*2.0f))+1); + + float vario1, vario2; + + if (step == 1) + { + vario1 = 1.0f; + vario2 = 1.0f; + } + else + { + vario1 = 0.0f; + vario2 = 2.0f; + } + + int first, last; + + if (m_particle[i].type == PARTIRAY2) + { + first = 0; + last = step; + vario1 = 0.0f; + vario2 = 0.0f; + } + else if (m_particle[i].type == PARTIRAY3) + { + if (m_particle[i].time < m_particle[i].duration*0.40f) + { + float prop = m_particle[i].time / (m_particle[i].duration*0.40f); + first = 0; + last = static_cast(prop*step); + } + else if (m_particle[i].time < m_particle[i].duration*0.60f) + { + first = 0; + last = step; + } + else + { + float prop = (m_particle[i].time-m_particle[i].duration*0.60f) / (m_particle[i].duration*0.40f); + first = static_cast(prop*step); + last = step; + } + } + else + { + if (m_particle[i].time < m_particle[i].duration*0.50f) + { + float prop = m_particle[i].time / (m_particle[i].duration*0.50f); + first = 0; + last = static_cast(prop*step); + } + else if (m_particle[i].time < m_particle[i].duration*0.75f) + { + first = 0; + last = step; + } + else + { + float prop = (m_particle[i].time-m_particle[i].duration*0.75f) / (m_particle[i].duration*0.25f); + first = static_cast(prop*step); + last = step; + } + } + + Math::Vector corner[4]; + + corner[0].x = adv; + corner[2].x = adv; + corner[0].y = dim.y; + corner[2].y = -dim.y; + corner[0].z = (Math::Rand()-0.5f)*vario1; + corner[1].z = (Math::Rand()-0.5f)*vario1; + corner[2].z = (Math::Rand()-0.5f)*vario1; + corner[3].z = (Math::Rand()-0.5f)*vario1; + + Vertex vertex[4]; + + for (int rank = 0; rank < step; rank++) + { + corner[1].x = corner[0].x; + corner[3].x = corner[2].x; + corner[0].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2; + corner[2].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2; + + corner[1].y = corner[0].y; + corner[3].y = corner[2].y; + corner[0].y = dim.y+(Math::Rand()-0.5f)*vario2; + corner[2].y = -dim.y+(Math::Rand()-0.5f)*vario2; + + if (rank >= first && rank <= last) + { + Math::Point texInf = m_particle[i].texInf; + Math::Point texSup = m_particle[i].texSup; + + int r = rand() % 16; + texInf.x += 0.25f*(r/4); + texSup.x += 0.25f*(r/4); + if (r % 2 < 1 && adv > 0.0f && m_particle[i].type != PARTIRAY1) + Math::Swap(texInf.x, texSup.x); + + if (r % 4 < 2) + Math::Swap(texInf.y, texSup.y); + + vertex[0] = Vertex(corner[1], n, Math::Point(texSup.x, texSup.y)); + vertex[1] = Vertex(corner[0], n, Math::Point(texInf.x, texSup.y)); + vertex[2] = Vertex(corner[3], n, Math::Point(texSup.x, texInf.y)); + vertex[3] = Vertex(corner[2], n, Math::Point(texInf.x, texInf.y)); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); + } + adv += dim.x*2.0f; + } +} + +void CParticle::DrawParticleSphere(int i) +{ + float zoom = m_particle[i].zoom; + + if (zoom == 0.0f) return; + + m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE | ENG_RSTATE_WRAP, + IntensityToColor(m_particle[i].intensity)); + + Math::Matrix mat; + mat.LoadIdentity(); + mat.Set(1, 1, zoom); + mat.Set(2, 2, zoom); + mat.Set(3, 3, zoom); + mat.Set(1, 4, m_particle[i].pos.x); + mat.Set(2, 4, m_particle[i].pos.y); + mat.Set(3, 4, m_particle[i].pos.z); + + if (m_particle[i].angle != 0.0f) + { + Math::Vector angle; + angle.x = m_particle[i].angle*0.4f; + angle.y = m_particle[i].angle*1.0f; + angle.z = m_particle[i].angle*0.7f; + Math::Matrix rot; + Math::LoadRotationZXYMatrix(rot, angle); + mat = Math::MultiplyMatrices(rot, mat); + } + + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Point ts, ti; + ts.x = m_particle[i].texSup.x; + ts.y = m_particle[i].texSup.y; + ti.x = m_particle[i].texInf.x; + ti.y = m_particle[i].texInf.y; + + int numRings, numSegments; + + // Choose a tesselation level. + if ( m_particle[i].type == PARTISPHERE3 || + m_particle[i].type == PARTISPHERE5 ) + { + numRings = 16; + numSegments = 16; + } + else + { + numRings = 8; + numSegments = 10; + } + + // Establish constants used in sphere generation. + float deltaRingAngle = Math::PI/numRings; + float deltaSegAngle = 2.0f*Math::PI/numSegments; + + Vertex vertex[2*16*(16+1)]; + + // Generate the group of rings for the sphere. + int j = 0; + for (int ring = 0; ring < numRings; ring++) + { + float r0 = sinf((ring+0)*deltaRingAngle); + float r1 = sinf((ring+1)*deltaRingAngle); + + Math::Vector v0, v1; + + v0.y = cosf((ring+0)*deltaRingAngle); + v1.y = cosf((ring+1)*deltaRingAngle); + + float tv0 = (ring+0)/static_cast(numRings); + float tv1 = (ring+1)/static_cast(numRings); + tv0 = ts.y+(ti.y-ts.y)*tv0; + tv1 = ts.y+(ti.y-ts.y)*tv1; + + // Generate the group of segments for the current ring. + for (int seg = 0; seg < numSegments+1; seg++) + { + v0.x = r0*sinf(seg*deltaSegAngle); + v0.z = r0*cosf(seg*deltaSegAngle); + v1.x = r1*sinf(seg*deltaSegAngle); + v1.z = r1*cosf(seg*deltaSegAngle); + + // Add two vertices to the strip which makes up the sphere. + float tu0 = (static_cast(seg))/numSegments; + tu0 = ts.x+(ti.x-ts.x)*tu0; + float tu1 = tu0; + + vertex[j++] = Vertex(v0, v0, Math::Point(tu0, tv0)); + vertex[j++] = Vertex(v1, v1, Math::Point(tu1, tv1)); + } + } + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, j); + m_engine->AddStatisticTriangle(j); + + m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK, IntensityToColor(m_particle[i].intensity)); +} + +//! Returns the height depending on the progress +float ProgressCylinder(float progress) +{ + if (progress < 0.5f) + return 1.0f - (powf(1.0f-progress*2.0f, 2.0f)); + else + return 1.0f - (powf(progress*2.0f-1.0f, 2.0f)); +} + +void CParticle::DrawParticleCylinder(int i) +{ + float progress = m_particle[i].zoom; + float zoom = m_particle[i].dim.x; + float diam = m_particle[i].dim.y; + if (progress >= 1.0f || zoom == 0.0f) return; + + m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE | ENG_RSTATE_WRAP, + IntensityToColor(m_particle[i].intensity)); + + Math::Matrix mat; + mat.LoadIdentity(); + mat.Set(1, 1, zoom); + mat.Set(2, 2, zoom); + mat.Set(3, 3, zoom); + mat.Set(1, 4, m_particle[i].pos.x); + mat.Set(2, 4, m_particle[i].pos.y); + mat.Set(3, 4, m_particle[i].pos.z); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + Math::Point ts, ti; + ts.x = m_particle[i].texSup.x; + ts.y = m_particle[i].texSup.y; + ti.x = m_particle[i].texInf.x; + ti.y = m_particle[i].texInf.y; + + int numRings = 5; + int numSegments = 10; + float deltaSegAngle = 2.0f*Math::PI/numSegments; + + float h[6] = { 0.0f }; + float d[6] = { 0.0f }; + + if (m_particle[i].type == PARTIPLOUF0) + { + float p1 = progress; // front + float p2 = powf(progress, 5.0f); // back + + for (int ring = 0; ring <= numRings; ring++) + { + float pp = p2+(p1-p2)*(static_cast(ring)/numRings); + d[ring] = diam/zoom+pp*2.0f; + h[ring] = ProgressCylinder(pp); + } + } + + Vertex vertex[2*5*(10+1)]; + + int j = 0; + for (int ring = 0; ring < numRings; ring++) + { + Math::Vector v0, v1; + + float r0 = 1.0f*d[ring+0]; // radius at the base + float r1 = 1.0f*d[ring+1]; // radius at the top + + v0.y = 1.0f*h[ring+0]; // bottom + v1.y = 1.0f*h[ring+1]; // top + + float tv0 = 1.0f-(ring+0)*(1.0f/numRings); + float tv1 = 1.0f-(ring+1)*(1.0f/numRings); + tv0 = ts.y+(ti.y-ts.y)*tv0; + tv1 = ts.y+(ti.y-ts.y)*tv1; + + for (int seg = 0; seg < numSegments+1; seg++) + { + v0.x = r0*sinf(seg*deltaSegAngle); + v0.z = r0*cosf(seg*deltaSegAngle); + v1.x = r1*sinf(seg*deltaSegAngle); + v1.z = r1*cosf(seg*deltaSegAngle); + + float tu0 = (seg % 2) ? 0.0f : 1.0f; + tu0 = ts.x+(ti.x-ts.x)*tu0; + float tu1 = tu0; + + vertex[j++] = Vertex(v0, v0, Math::Point(tu0, tv0)); + vertex[j++] = Vertex(v1, v1, Math::Point(tu1, tv1)); + } + } + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, j); + m_engine->AddStatisticTriangle(j); + + m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK, IntensityToColor(m_particle[i].intensity)); +} + +void CParticle::DrawParticleWheel(int i) +{ + float dist = Math::DistanceProjected(m_engine->GetEyePt(), m_wheelTrace[i].pos[0]); + if (dist > 300.0f) return; + + Math::Vector pos[4]; + pos[0] = m_wheelTrace[i].pos[0]; + pos[1] = m_wheelTrace[i].pos[1]; + pos[2] = m_wheelTrace[i].pos[2]; + pos[3] = m_wheelTrace[i].pos[3]; + + Math::Point ts; + + if (m_wheelTrace[i].type == PARTITRACE0) // white ground track? + { + ts.x = 8.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE1) // black ground track? + { + ts.x = 0.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE2) // gray ground track? + { + ts.x = 0.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE3) // light gray ground track? + { + ts.x = 8.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE4) // red ground track? + { + ts.x = 32.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE5) // pink ground track? + { + ts.x = 40.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE6) // violet ground track? + { + ts.x = 32.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE7) // orange ground track? + { + ts.x = 40.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE8) // yellow ground track? + { + ts.x = 16.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE9) // beige ground track? + { + ts.x = 24.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE10) // brown ground track? + { + ts.x = 16.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE11) // skin ground track? + { + ts.x = 24.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE12) // green ground track? + { + ts.x = 48.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE13) // light green ground track? + { + ts.x = 56.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE14) // blue ground track? + { + ts.x = 48.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE15) // light blue ground track? + { + ts.x = 56.0f/256.0f; + ts.y = 232.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE16) // black arrow ground track? + { + ts.x = 160.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else if (m_wheelTrace[i].type == PARTITRACE17) // red arrow ground track? + { + ts.x = 176.0f/256.0f; + ts.y = 224.0f/256.0f; + } + else + { + return; + } + + Math::Point ti; + + if ( m_wheelTrace[i].type == PARTITRACE16 || + m_wheelTrace[i].type == PARTITRACE17 ) + { + ti.x = ts.x+16.0f/256.0f; + ti.y = ts.y+16.0f/256.0f; + } + else + { + ti.x = ts.x+8.0f/256.0f; + ti.y = ts.y+8.0f/256.0f; + } + + float dp = (1.0f/256.0f)/2.0f; + ts.x = ts.x+dp; + ts.y = ts.y+dp; + ti.x = ti.x-dp; + ti.y = ti.y-dp; + + Math::Vector n(0.0f, 1.0f, 0.0f); + + Vertex vertex[4]; + vertex[0] = Vertex(pos[0], n, Math::Point(ts.x, ts.y)); + vertex[1] = Vertex(pos[1], n, Math::Point(ti.x, ts.y)); + vertex[2] = Vertex(pos[2], n, Math::Point(ts.x, ti.y)); + vertex[3] = Vertex(pos[3], n, Math::Point(ti.x, ti.y)); + + m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); + m_engine->AddStatisticTriangle(2); +} + +void CParticle::DrawParticle(int sheet) +{ + // Draw the basic particles of triangles. + if (m_totalInterface[0][sheet] > 0) + { + for (int i = 0; i < MAXPARTICULE; i++) + { + if (!m_particle[i].used) continue; + if (m_particle[i].sheet != sheet) continue; + if (m_particle[i].type == PARTIPART) continue; + + m_engine->SetTexture(m_triangle[i].tex1Name); + m_engine->SetMaterial(m_triangle[i].material); + m_engine->SetState(m_triangle[i].state); + DrawParticleTriangle(i); + } + } + + Material mat; + mat.diffuse.r = 1.0f; + mat.diffuse.g = 1.0f; + mat.diffuse.b = 1.0f; // white + mat.ambient.r = 0.5f; + mat.ambient.g = 0.5f; + mat.ambient.b = 0.5f; + m_engine->SetMaterial(mat); + + // Draw tire marks. + if (m_wheelTraceTotal > 0 && sheet == SH_WORLD) + { + m_engine->SetTexture("text.png"); + m_engine->SetState(ENG_RSTATE_TTEXTURE_WHITE); + Math::Matrix mat; + mat.LoadIdentity(); + m_device->SetTransform(TRANSFORM_WORLD, mat); + + for (int i = 0; i < m_wheelTraceTotal; i++) + DrawParticleWheel(i); + } + + for (int t = MAXPARTITYPE-1; t >= 1; t--) // black behind! + { + if (m_totalInterface[t][sheet] == 0) continue; + + bool loadTexture = false; + + int state; + if (t == 4) state = ENG_RSTATE_TTEXTURE_WHITE; // text.png + else state = ENG_RSTATE_TTEXTURE_BLACK; // effect[00..02].png + m_engine->SetState(state); + + for (int j = 0; j < MAXPARTICULE; j++) + { + int i = MAXPARTICULE*t+j; + if (!m_particle[i].used) continue; + if (m_particle[i].sheet != sheet) continue; + + if (!loadTexture) + { + std::string name; + NameParticle(name, t); + m_engine->SetTexture(name); + loadTexture = true; + } + + int r = m_particle[i].trackRank; + if (r != -1) + { + m_engine->SetState(state); + TrackDraw(r, m_particle[i].type); // draws the drag + if (!m_track[r].drawParticle) continue; + } + + m_engine->SetState(state, IntensityToColor(m_particle[i].intensity)); + + if (m_particle[i].ray) // ray? + { + DrawParticleRay(i); + } + else if ( m_particle[i].type == PARTIFLIC || // circle in the water? + m_particle[i].type == PARTISHOW || + m_particle[i].type == PARTICHOC || + m_particle[i].type == PARTIGFLAT ) + { + DrawParticleFlat(i); + } + else if ( m_particle[i].type >= PARTIFOG0 && + m_particle[i].type <= PARTIFOG9 ) + { + DrawParticleFog(i); + } + else if ( m_particle[i].type >= PARTISPHERE0 && + m_particle[i].type <= PARTISPHERE9 ) // sphere? + { + DrawParticleSphere(i); + } + else if ( m_particle[i].type >= PARTIPLOUF0 && + m_particle[i].type <= PARTIPLOUF4 ) // cylinder? + { + DrawParticleCylinder(i); + } + else // normal? + { + DrawParticleNorm(i); + } + } + } +} + +CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, + ParticleType type, CObject *father) +{ + if (m_main->GetMovieLock()) return nullptr; // current movie? + + bool himself = m_main->GetHimselfDamage(); + + float min = 5.0f; + if (type == PARTIGUN2) min = 2.0f; // shooting insect? + if (type == PARTIGUN3) min = 3.0f; // suiciding spider? + + Math::Vector box1 = old; + Math::Vector box2 = pos; + if (box1.x > box2.x) Math::Swap(box1.x, box2.x); // box1 < box2 + if (box1.y > box2.y) Math::Swap(box1.y, box2.y); + if (box1.z > box2.z) Math::Swap(box1.z, box2.z); + box1.x -= min; + box1.y -= min; + box1.z -= min; + box2.x += min; + box2.y += min; + box2.z += min; + + CObject* best = 0; + bool shield = false; + for (int i = 0; i < 1000000; i++) + { + CObject* obj = static_cast(m_iMan->SearchInstance(CLASS_OBJECT, i)); + if (obj == 0) break; + + if (!obj->GetActif()) continue; // inactive? + if (obj == father) continue; + + ObjectType oType = obj->GetType(); + + if (oType == OBJECT_TOTO) continue; + + if (type == PARTIGUN1) // fireball shooting? + { + if (oType == OBJECT_MOTHER) continue; + if (himself) // damage is oneself? + { + if ( !IsAlien(oType) && + !IsSoft(oType) ) continue; + } + else // damage only to enemies? + { + if (!IsAlien(oType)) continue; + } + } + else if (type == PARTIGUN2) // shooting insect? + { + if (!IsSoft(oType)) continue; + } + else if (type == PARTIGUN3) // suiciding spider? + { + if (!IsSoft(oType)) continue; + } + else if (type == PARTIGUN4) // orgaball shooting? + { + if (oType == OBJECT_MOTHER) continue; + if (himself) // damage is oneself? + { + if ( !IsAlien(oType) && + !IsSoft(oType) ) continue; + } + else // damage only to enemies? + { + if (!IsAlien(oType)) continue; + } + } + else if (type == PARTITRACK11) // phazer shooting? + { + if (himself) // damage is oneself? + { + if ( !IsAlien(oType) && + !IsSoft(oType) ) continue; + } + else // damage only to enemies? + { + if (!IsAlien(oType)) continue; + } + } + else + { + continue; + } + + Math::Vector oPos = obj->GetPosition(0); + + if ( type == PARTIGUN2 || // shooting insect? + type == PARTIGUN3 ) // suiciding spider? + { + // Test if the ball is entered into the sphere of a shield. + float shieldRadius = obj->GetShieldRadius(); + if (shieldRadius > 0.0f) + { + float dist = Math::Distance(oPos, pos); + if (dist <= shieldRadius) + { + best = obj; + shield = true; + } + } + } + if (shield) continue; + + // Test the center of the object, which is necessary for objects + // that have no sphere in the center (station). + float dist = Math::Distance(oPos, pos)-4.0f; + if (dist < min) + best = obj; + + // Test with all spheres of the object. + int j = 0; + float oRadius; + while (obj->GetCrashSphere(j++, oPos, oRadius)) + { + if ( oPos.x+oRadius < box1.x || oPos.x-oRadius > box2.x || // outside the box? + oPos.y+oRadius < box1.y || oPos.y-oRadius > box2.y || + oPos.z+oRadius < box1.z || oPos.z-oRadius > box2.z ) continue; + + Math::Vector p = Math::Projection(old, pos, oPos); + float ddist = Math::Distance(p, oPos)-oRadius; + if (ddist < min) + best = obj; + } + } + + return best; +} + +CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal, + ParticleType type, CObject *father) +{ + if (m_main->GetMovieLock()) return nullptr; // current movie? + + float min = 10.0f; + + Math::Vector box1 = pos; + Math::Vector box2 = goal; + if (box1.x > box2.x) Math::Swap(box1.x, box2.x); // box1 < box2 + if (box1.y > box2.y) Math::Swap(box1.y, box2.y); + if (box1.z > box2.z) Math::Swap(box1.z, box2.z); + box1.x -= min; + box1.y -= min; + box1.z -= min; + box2.x += min; + box2.y += min; + box2.z += min; + + for (int i = 0; i < 1000000; i++) + { + CObject* obj = static_cast( m_iMan->SearchInstance(CLASS_OBJECT, i) ); + if (obj == nullptr) break; + + if (!obj->GetActif()) continue; // inactive? + if (obj == father) continue; + + ObjectType oType = obj->GetType(); + + if (oType == OBJECT_TOTO) continue; + + if ( type == PARTIRAY1 && + oType != OBJECT_MOBILEtg && + oType != OBJECT_TEEN28 && + oType != OBJECT_TEEN31 && + oType != OBJECT_ANT && + oType != OBJECT_SPIDER && + oType != OBJECT_BEE && + oType != OBJECT_WORM && + oType != OBJECT_MOTHER && + oType != OBJECT_NEST ) continue; + + Math::Vector oPos = obj->GetPosition(0); + + if ( oPos.x < box1.x || oPos.x > box2.x || // outside the box? + oPos.y < box1.y || oPos.y > box2.y || + oPos.z < box1.z || oPos.z > box2.z ) continue; + + Math::Vector p = Math::Projection(pos, goal, oPos); + float dist = Math::Distance(p, oPos); + if (dist < min) return obj; + } + + return nullptr; +} + +void CParticle::Play(Sound sound, Math::Vector pos, float amplitude) +{ + if (m_sound == nullptr) + m_sound = static_cast(m_iMan->SearchInstance(CLASS_SOUND)); + + m_sound->Play(sound, pos, amplitude); +} + +Color CParticle::GetFogColor(Math::Vector pos) +{ + Color result; + result.r = 0.0f; + result.g = 0.0f; + result.b = 0.0f; + result.a = 0.0f; + + for (int fog = 0; fog < m_fogTotal; fog++) + { + int i = m_fog[fog]; // i = rank of the particle + + if (pos.y >= m_particle[i].pos.y+FOG_HSUP) continue; + if (pos.y <= m_particle[i].pos.y-FOG_HINF) continue; + + float dist = Math::DistanceProjected(pos, m_particle[i].pos); + if (dist >= m_particle[i].dim.x*1.5f) continue; + + // Calculates the horizontal distance. + float factor = 1.0f-powf(dist/(m_particle[i].dim.x*1.5f), 4.0f); + + // Calculates the vertical distance. + if (pos.y > m_particle[i].pos.y) + factor *= 1.0f-(pos.y-m_particle[i].pos.y)/FOG_HSUP; + else + factor *= 1.0f-(m_particle[i].pos.y-pos.y)/FOG_HINF; + + factor *= 0.3f; + + Color color; + + if ( m_particle[i].type == PARTIFOG0 || + m_particle[i].type == PARTIFOG1 ) // blue? + { + color.r = 0.0f; + color.g = 0.5f; + color.b = 1.0f; + } + else if ( m_particle[i].type == PARTIFOG2 || + m_particle[i].type == PARTIFOG3 ) // red? + { + color.r = 2.0f; + color.g = 1.0f; + color.b = 0.0f; + } + else if ( m_particle[i].type == PARTIFOG4 || + m_particle[i].type == PARTIFOG5 ) // white? + { + color.r = 1.0f; + color.g = 1.0f; + color.b = 1.0f; + } + else if ( m_particle[i].type == PARTIFOG6 || + m_particle[i].type == PARTIFOG7 ) // yellow? + { + color.r = 0.8f; + color.g = 1.0f; + color.b = 0.4f; + } + else + { + color.r = 0.0f; + color.g = 0.0f; + color.b = 0.0f; + } + + result.r += color.r*factor; + result.g += color.g*factor; + result.b += color.b*factor; + } + + if (result.r > 0.6f) result.r = 0.6f; + if (result.g > 0.6f) result.g = 0.6f; + if (result.b > 0.6f) result.b = 0.6f; + + return result; +} + +bool CParticle::WriteWheelTrace(const char *filename, int width, int height, + Math::Vector dl, Math::Vector ur) +{ + // TODO: stub! + GetLogger()->Trace("CParticle::WriteWheelTrace(): stub!\n"); + return true; +} } // namespace Gfx -- cgit v1.2.3-1-g7c22