summaryrefslogtreecommitdiffstats
path: root/src/graphics/engine/particle.cpp
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-10-05 18:59:49 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-10-05 18:59:49 +0200
commit6fdaf5de46b8ab29cfb67d49661a63fff5a6995a (patch)
tree01f387c01bf89c6230725ce38dfefde726faa260 /src/graphics/engine/particle.cpp
parentff99b74b25c34b721f507da18b0b6d26a41b670a (diff)
downloadcolobot-6fdaf5de46b8ab29cfb67d49661a63fff5a6995a.tar.gz
colobot-6fdaf5de46b8ab29cfb67d49661a63fff5a6995a.tar.bz2
colobot-6fdaf5de46b8ab29cfb67d49661a63fff5a6995a.zip
CParticle rewrite
Diffstat (limited to 'src/graphics/engine/particle.cpp')
-rw-r--r--src/graphics/engine/particle.cpp3866
1 files changed, 3737 insertions, 129 deletions
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 <cstring>
+
// 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)
{
- GetLogger()->Trace("CParticle::CParticle() stub!\n");
- // TODO!
+ 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)
+{
+ 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)
+{
+ if (m_main == nullptr)
+ m_main = static_cast<CRobotMain*>(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;
+}
+
+/** 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)
{
- GetLogger()->Trace("CParticle::CreateParticle() 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].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;
}
-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::CreatePart(Math::Vector pos, Math::Vector speed,
+ ParticleType type,
+ float duration, float mass, float weight,
+ 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].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)
{
- GetLogger()->Trace("CParticle::CreateFrag() stub!\n");
- // TODO!
- return 0;
+ 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<CTerrain*>(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<CRobotMain*>(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<CTerrain*>(m_iMan->SearchInstance(CLASS_TERRAIN));
+
+ if (m_water == nullptr)
+ m_water = static_cast<CWater*>(m_iMan->SearchInstance(CLASS_WATER));
+
+ if (!pause)
+ {
+ m_lastTimeGunDel += rTime;
+ m_absTime += rTime;
+ }
+
+ Math::Vector wind = m_terrain->GetWind();
+ Math::Vector eye = m_engine->GetEyePt();
+
+ Math::Point ts, ti;
+ Math::Vector pos;
+
+ for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++)
+ {
+ if (!m_particle[i].used) continue;
+ if (!m_frameUpdate[m_particle[i].sheet]) continue;
+
+ if (m_particle[i].type != PARTISHOW)
+ {
+ if (pause && m_particle[i].sheet != SH_INTERFACE) continue;
+ }
+
+ if (m_particle[i].type != PARTIQUARTZ)
+ m_particle[i].pos += m_particle[i].speed*rTime;
+
+ if (m_particle[i].sheet == SH_WORLD)
+ {
+ float h = rTime*m_particle[i].windSensitivity*Math::Rand()*2.0f;
+ m_particle[i].pos += wind*h;
+ }
+
+ float progress = (m_particle[i].time-m_particle[i].phaseTime)/m_particle[i].duration;
+
+ // 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;
+
+ float h;
+ if (m_particle[i].sheet == SH_INTERFACE)
+ h = 0.0f;
+ else
+ h = m_terrain->GetFloorLevel(m_particle[i].pos, true);
+
+ 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);
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+
+ // 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;
+ }
+
+ 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<int>(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<int>(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<int>((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<int>((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;
+ }
}
-void CParticle::DeleteRank(int rank)
+bool CParticle::TrackMove(int i, Math::Vector pos, float progress)
{
- GetLogger()->Trace("CParticle::DeleteRank() stub!\n");
- // TODO!
+ 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);
}
-bool CParticle::CheckChannel(int &channel)
+void CParticle::TrackDraw(int i, ParticleType type)
{
- GetLogger()->Trace("CParticle::CheckChannel() stub!\n");
- // TODO!
- return true;
+ // 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)
{
- GetLogger()->Trace("CParticle::DrawParticleTriangle() stub!\n");
- // TODO!
+ 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)
{
- GetLogger()->Trace("CParticle::DrawParticleNorm() stub!\n");
- // TODO!
+ 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)
{
- GetLogger()->Trace("CParticle::DrawParticleFlat() stub!\n");
- // TODO!
+ 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)
{
- GetLogger()->Trace("CParticle::DrawParticleFog() stub!\n");
- // TODO!
+ 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)
{
- GetLogger()->Trace("CParticle::DrawParticleRay() stub!\n");
- // TODO!
+ 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<int>((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<int>(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<int>(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<int>(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<int>(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)
{
- GetLogger()->Trace("CParticle::DrawParticleSphere() stub!\n");
- // TODO!
+ 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<float>(numRings);
+ float tv1 = (ring+1)/static_cast<float>(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<float>(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)
{
- GetLogger()->Trace("CParticle::DrawParticleCylinder() stub!\n");
- // TODO!
+ 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<float>(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)
{
- GetLogger()->Trace("CParticle::DrawParticleWheel() stub!\n");
- // TODO!
+ 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);
}
-CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father)
+void CParticle::DrawParticle(int sheet)
{
- GetLogger()->Trace("CParticle::SearchObjectGun() stub!\n");
- // TODO!
- return nullptr;
+ // 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<CObject*>(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)
+CObject* CParticle::SearchObjectRay(Math::Vector pos, Math::Vector goal,
+ ParticleType type, CObject *father)
{
- GetLogger()->Trace("CParticle::SearchObjectRay() stub!\n");
- // TODO!
+ 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<CObject*>( 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)
{
- GetLogger()->Trace("CParticle::Play() stub!\n");
- // TODO!
+ if (m_sound == nullptr)
+ m_sound = static_cast<CSoundInterface*>(m_iMan->SearchInstance(CLASS_SOUND));
+
+ m_sound->Play(sound, pos, amplitude);
}
-bool CParticle::TrackMove(int i, Math::Vector pos, float progress)
+Color CParticle::GetFogColor(Math::Vector pos)
{
- GetLogger()->Trace("CParticle::TrackMove() stub!\n");
- // TODO!
- return true;
+ 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;
}
-void CParticle::TrackDraw(int i, ParticleType type)
+bool CParticle::WriteWheelTrace(const char *filename, int width, int height,
+ Math::Vector dl, Math::Vector ur)
{
- GetLogger()->Trace("CParticle::TrackDraw() stub!\n");
- // TODO!
+ // TODO: stub!
+ GetLogger()->Trace("CParticle::WriteWheelTrace(): stub!\n");
+ return true;
}
-
} // namespace Gfx