Initial commit of CustomParticles

And changed size in struct Particle to be a float instead of cc_uint8
This commit is contained in:
Goodlyay 2020-02-21 16:53:23 -08:00
parent 9c5406cc43
commit c925f31445
2 changed files with 197 additions and 7 deletions

View File

@ -148,7 +148,7 @@ static void RainParticle_Render(struct Particle* p, float t, VertexP3fT2fC4b* ve
int x, y, z; int x, y, z;
Vec3_Lerp(&pos, &p->lastPos, &p->nextPos, t); Vec3_Lerp(&pos, &p->lastPos, &p->nextPos, t);
size.X = (float)p->size * 0.015625f; size.Y = size.X; size.X = p->size * 0.015625f; size.Y = size.X;
x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z); x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z);
col = World_Contains(x, y, z) ? Lighting_Col(x, y, z) : Env.SunCol; col = World_Contains(x, y, z) ? Lighting_Col(x, y, z) : Env.SunCol;
@ -218,7 +218,7 @@ static void TerrainParticle_Render(struct TerrainParticle* p, float t, VertexP3f
int x, y, z; int x, y, z;
Vec3_Lerp(&pos, &p->base.lastPos, &p->base.nextPos, t); Vec3_Lerp(&pos, &p->base.lastPos, &p->base.nextPos, t);
size.X = (float)p->base.size * 0.015625f; size.Y = size.X; size.X = p->base.size * 0.015625f; size.Y = size.X;
if (!Blocks.FullBright[p->block]) { if (!Blocks.FullBright[p->block]) {
x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z); x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z);
@ -293,12 +293,90 @@ static void Terrain_Tick(double delta) {
} }
} }
/*########################################################################################################################*
*-------------------------------------------------------Custom particle---------------------------------------------------*
*#########################################################################################################################*/
struct CustomParticle {
struct Particle base;
struct CustomParticleProperty* prop;
float totalLifespan;
};
static struct CustomParticle customParticle_particles[PARTICLES_MAX];
static int customParticle_count;
static TextureRec defaultCustomParticle_rec = { 0.0f / 128.0f, 24.0f / 128.0f, 16.0f / 128.0f, 40.0f / 128.0f };
static cc_bool CustomParticle_Tick(struct CustomParticle* p, double delta) {
particle_hitTerrain = false;
return Particle_PhysicsTick(&p->base, p->prop->gravity, false, delta) || particle_hitTerrain;
}
static void CustomParticle_Render(struct CustomParticle* p, float t, VertexP3fT2fC4b* vertices) {
Vec3 pos;
Vec2 size;
PackedCol col;
TextureRec rec = p->prop->rec;
float frame_time = p->totalLifespan / p->prop->frameCount;
float inverted_lifetime = Math_AbsF(p->base.lifetime - p->totalLifespan);
int curFrame = Math_Floor(inverted_lifetime / frame_time);
float shiftU = curFrame * (rec.U2 - rec.U1);
rec.U1 += shiftU;// * 0.0078125f;
rec.U2 += shiftU;// * 0.0078125f;
int x, y, z;
Vec3_Lerp(&pos, &p->base.lastPos, &p->base.nextPos, t);
size.X = p->base.size; size.Y = size.X;
x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z);
col = p->prop->fullBright ? PACKEDCOL_WHITE : (World_Contains(x, y, z) ? Lighting_Col(x, y, z) : Env.SunCol);
Particle_DoRender(&size, &pos, &rec, col, vertices);
}
static void Custom_Render(float t) {
VertexP3fT2fC4b* data;
int i;
if (!customParticle_count) return;
data = (VertexP3fT2fC4b*)Gfx_LockDynamicVb(Particles_VB, VERTEX_FORMAT_P3FT2FC4B, customParticle_count * 4);
for (i = 0; i < customParticle_count; i++) {
CustomParticle_Render(&customParticle_particles[i], t, data);
data += 4;
}
Gfx_BindTexture(Particles_TexId);
Gfx_UnlockDynamicVb(Particles_VB);
Gfx_DrawVb_IndexedTris(customParticle_count * 4);
}
static void Custom_RemoveAt(int index) {
struct CustomParticle removed = customParticle_particles[index];
int i;
for (i = index; i < customParticle_count - 1; i++) {
customParticle_particles[i] = customParticle_particles[i + 1];
}
customParticle_particles[customParticle_count - 1] = removed;
customParticle_count--;
}
static void Custom_Tick(double delta) {
int i;
for (i = 0; i < customParticle_count; i++) {
if (CustomParticle_Tick(&customParticle_particles[i], delta)) {
Custom_RemoveAt(i); i--;
}
}
}
/*########################################################################################################################* /*########################################################################################################################*
*--------------------------------------------------------Particles--------------------------------------------------------* *--------------------------------------------------------Particles--------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
void Particles_Render(float t) { void Particles_Render(float t) {
if (!terrain_count && !rain_count) return; if (!terrain_count && !rain_count && !customParticle_count) return;
if (Gfx.LostContext) return; if (Gfx.LostContext) return;
Gfx_SetTexturing(true); Gfx_SetTexturing(true);
@ -307,6 +385,7 @@ void Particles_Render(float t) {
Gfx_SetVertexFormat(VERTEX_FORMAT_P3FT2FC4B); Gfx_SetVertexFormat(VERTEX_FORMAT_P3FT2FC4B);
Terrain_Render(t); Terrain_Render(t);
Rain_Render(t); Rain_Render(t);
Custom_Render(t);
Gfx_SetAlphaTest(false); Gfx_SetAlphaTest(false);
Gfx_SetTexturing(false); Gfx_SetTexturing(false);
@ -315,6 +394,7 @@ void Particles_Render(float t) {
void Particles_Tick(struct ScheduledTask* task) { void Particles_Tick(struct ScheduledTask* task) {
Terrain_Tick(task->Interval); Terrain_Tick(task->Interval);
Rain_Tick(task->Interval); Rain_Tick(task->Interval);
Custom_Tick(task->Interval);
} }
void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) { void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) {
@ -392,7 +472,7 @@ void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) {
p->texLoc = loc; p->texLoc = loc;
p->block = old; p->block = old;
type = Random_Next(&rnd, 30); type = Random_Next(&rnd, 30);
p->base.size = (cc_uint8)(type >= 28 ? 12 : (type >= 25 ? 10 : 8)); p->base.size = type >= 28 ? 12 : (type >= 25 ? 10 : 8);
} }
} }
} }
@ -418,7 +498,63 @@ void Particles_RainSnowEffect(float x, float y, float z) {
p->lifetime = 40.0f; p->lifetime = 40.0f;
type = Random_Next(&rnd, 30); type = Random_Next(&rnd, 30);
p->size = (cc_uint8)(type >= 28 ? 2 : (type >= 25 ? 4 : 3)); p->size = type >= 28 ? 2 : (type >= 25 ? 4 : 3);
}
}
//Vec3 GetRandomSpherePoint() {
// float u = Random_Float(&rnd);
// float v = Random_Float(&rnd);
// float theta = u * 2.0 * MATH_PI;
// float phi = Math.acos(2.0 * v - 1.0);
// float r = Math.cbrt(Random_Float(&rnd));
// float sinTheta = Math.sin(theta);
// float cosTheta = Math.cos(theta);
// float sinPhi = Math.sin(phi);
// float cosPhi = Math.cos(phi);
// float x = r * sinPhi * cosTheta;
// float y = r * sinPhi * sinTheta;
// float z = r * cosPhi;
// return { x: x, y : y, z : z };
//}
void Particles_CustomEffect(float x, float y, float z, int propertyID) {
struct CustomParticle* p;
struct CustomParticleProperty* prop = &customParticle_properties[propertyID];
int i;
int count = prop->particleCount;
for (i = 0; i < count; i++) {
if (customParticle_count == PARTICLES_MAX) Custom_RemoveAt(0);
p = &customParticle_particles[customParticle_count++];
p->prop = prop;
//TODO: Add prop speed and origin working here
p->base.velocity.X = 0;
p->base.velocity.Z = 0;
p->base.velocity.Y = 0;
Vec3 offset = { Random_Float(&rnd) - 0.5f, Random_Float(&rnd) - 0.5f, Random_Float(&rnd) - 0.5f };
Vec3_Normalize(&offset, &offset);
float d = Random_Float(&rnd);
d = Math_Exp(Math_Log(d) / 3.0);
Vec3_Mul1By(&offset, d);
Vec3_Mul1By(&offset, p->prop->spread*0.03125f);
p->base.lastPos.X = x + (offset.X);
p->base.lastPos.Y = y + (offset.Y);
p->base.lastPos.Z = z + (offset.Z);
p->base.nextPos = p->base.lastPos;
p->base.lifetime = p->prop->baseLifetime + ( (p->prop->baseLifetime * p->prop->lifetimeVariation) * ((Random_Float(&rnd) - 0.5f) * 2));
p->totalLifespan = p->base.lifetime;
p->base.size = p->prop->size + ( (p->prop->size * p->prop->sizeVariation) * ((Random_Float(&rnd) - 0.5f) * 2) ) ;
} }
} }
@ -434,6 +570,7 @@ static void OnContextRecreated(void* obj) {
} }
static void OnBreakBlockEffect_Handler(void* obj, IVec3 coords, BlockID old, BlockID now) { static void OnBreakBlockEffect_Handler(void* obj, IVec3 coords, BlockID old, BlockID now) {
Particles_BreakBlockEffect(coords, old, now); Particles_BreakBlockEffect(coords, old, now);
Particles_CustomEffect(coords.X+0.5f, coords.Y+2.5f, coords.Z+0.5f, 0);
} }
static void OnFileChanged(void* obj, struct Stream* stream, const String* name) { static void OnFileChanged(void* obj, struct Stream* stream, const String* name) {
@ -443,6 +580,41 @@ static void OnFileChanged(void* obj, struct Stream* stream, const String* name)
} }
static void Particles_Init(void) { static void Particles_Init(void) {
//struct CustomParticleProperty {
// TextureRec rec;
// int frameCount;
// int amount; //how many of this particle are spawned per spawn-packet
// float size; //size of the particle in fixed-point world units (e.g. 32 is a full block's size)
// float sizeVariation;
// float spread; //how far from the spawnpoint their location can vary (in fixed-point world units)
// float speed; //how fast they move away/towards the origin
// float gravity;
// float baseLifetime;
// float lifetimeVariation;
// cc_bool fullBright;
// cc_bool converge; ////true means the particles move toward the origin. False means they move away from the origin
//};
//TEMP CODE IN LIEU OF ANY DEFINING PACKETS
struct CustomParticleProperty* prop;
prop = &customParticle_properties[0];
prop->rec = defaultCustomParticle_rec;
prop->frameCount = 8;
prop->particleCount = 50;
prop->size = 32 * 0.03125f;
prop->sizeVariation = 0.5f;
prop->spread = 96;
prop->speed = 2;
prop->gravity = 0.0f;
prop->baseLifetime = 0.7f;
prop->lifetimeVariation = 0.25f;
prop->fullBright = true;
prop->converge = false;
//END TEMP CODE
ScheduledTask_Add(GAME_DEF_TICKS, Particles_Tick); ScheduledTask_Add(GAME_DEF_TICKS, Particles_Tick);
Random_SeedFromCurrentTime(&rnd); Random_SeedFromCurrentTime(&rnd);
OnContextRecreated(NULL); OnContextRecreated(NULL);
@ -463,7 +635,7 @@ static void Particles_Free(void) {
Event_UnregisterVoid(&GfxEvents.ContextRecreated, NULL, OnContextRecreated); Event_UnregisterVoid(&GfxEvents.ContextRecreated, NULL, OnContextRecreated);
} }
static void Particles_Reset(void) { rain_count = 0; terrain_count = 0; } static void Particles_Reset(void) { rain_count = 0; terrain_count = 0; customParticle_count = 0; }
struct IGameComponent Particles_Component = { struct IGameComponent Particles_Component = {
Particles_Init, /* Init */ Particles_Init, /* Init */

View File

@ -14,13 +14,31 @@ struct Particle {
Vec3 velocity; Vec3 velocity;
float lifetime; float lifetime;
Vec3 lastPos, nextPos; Vec3 lastPos, nextPos;
cc_uint8 size; float size;
}; };
struct CustomParticleProperty {
TextureRec rec;
int frameCount;
int particleCount; //how many of this particle are spawned per spawn-packet
float size; //size of the particle in fixed-point world units (e.g. 32 is a full block's size)
float sizeVariation;
float spread; //how far from the spawnpoint their location can vary (in fixed-point world units)
float speed; //how fast they move away/towards the origin
float gravity;
float baseLifetime;
float lifetimeVariation;
cc_bool fullBright;
cc_bool converge; ////true means the particles move toward the origin. False means they move away from the origin
};
static struct CustomParticleProperty customParticle_properties[256];
/* http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ */ /* http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ */
void Particle_DoRender(const Vec2* size, const Vec3* pos, const TextureRec* rec, PackedCol col, VertexP3fT2fC4b* vertices); void Particle_DoRender(const Vec2* size, const Vec3* pos, const TextureRec* rec, PackedCol col, VertexP3fT2fC4b* vertices);
void Particles_Render(float t); void Particles_Render(float t);
void Particles_Tick(struct ScheduledTask* task); void Particles_Tick(struct ScheduledTask* task);
void Particles_BreakBlockEffect(IVec3 coords, BlockID oldBlock, BlockID block); void Particles_BreakBlockEffect(IVec3 coords, BlockID oldBlock, BlockID block);
void Particles_RainSnowEffect(float x, float y, float z); void Particles_RainSnowEffect(float x, float y, float z);
void Particles_CustomEffect(float x, float y, float z, int propertyID);
#endif #endif