From deb638790804186b9fbec9d0f37bd8d7a8bfb27a Mon Sep 17 00:00:00 2001 From: mid <> Date: Sun, 23 Mar 2025 15:09:26 +0200 Subject: [PATCH] Bug fixes and split to k3_internal.h --- src/k3.c | 229 ++++++++++++++++++++-------------------------- src/k3.h | 6 +- src/k3_internal.h | 67 ++++++++++++++ src/k3particles.c | 181 ++++++++++++++++++++++++++++++++++++ src/k3particles.h | 32 +++++++ 5 files changed, 385 insertions(+), 130 deletions(-) create mode 100644 src/k3_internal.h create mode 100644 src/k3particles.c create mode 100644 src/k3particles.h diff --git a/src/k3.c b/src/k3.c index f6930cd..f75f9a9 100644 --- a/src/k3.c +++ b/src/k3.c @@ -1,4 +1,4 @@ -#include"k3.h" +#include"k3_internal.h" #include"gl.h" @@ -15,42 +15,17 @@ #include"ssort.h" -#define GL_FROM_K3TEX(k3t) ((k3t) ? (k3t)->tex : 0) -#define GL_FROM_K3MARCHER(k3m) ((GLuint) (uintptr_t) (k3m)) -#define GL_FROM_K3ARBVP(k3m) ((GLuint) (uintptr_t) (k3m)) -#define GL_FROM_K3ARBFP(k3m) ((GLuint) (uintptr_t) (k3m)) -#define GL_FROM_K3GLSL(k3m) ((GLuint) (uintptr_t) (k3m)) - #define RAST_DIFF 0 #define RAST_NORM 1 #define RAST_DISP 2 #define RAST_LEVELS 3 -static int k3CPUSkinning = 0; - -int k3IsCore = 0; +bool k3IsSoftSkinning = 0; +bool k3IsCore = 0; static struct k3GLSLP *basicBlitProgram; static struct k3GLSLP *basicCubemapProgram; -struct k3Tex { - GLuint tex; - int cubemap; - uint32_t szX; - uint32_t szY; - uint32_t szZ; -}; - -struct k3Storage { - int16_t ref; - void(*free)(struct k3Storage*); -}; - -struct k3StorageBasic { - struct k3Storage; - GLuint gl; -}; - void k3StorageRef(struct k3Storage *s) { s->ref++; } @@ -73,40 +48,6 @@ struct k3StorageBasic *k3StorageBasic() { return ret; } -struct k3Offscreen { - GLuint fbo; - struct k3Tex *diffuse; - struct k3Tex *depth; -}; - -struct k3Mdl { - struct { - vec3 *pos; - uint8_t *boneids; - uint16_t *boneweights; - } cpuSkinning; - - size_t verts; - struct k3StorageBasic *vstore; - struct k3StorageBasic *estore; - - uint16_t meshCount; - struct k3Mesh *meshes; - - size_t boneCount; - mat4 *invBind; - uint8_t *boneParents; - - uint16_t animCount; - struct k3Animation **anims; - - vec3 aabb[2]; - - int offV, offN, offC, offU, offB, offT; - - const char *debugname; -}; - static uint16_t MainWidth, MainHeight; void k3Resize(uint16_t width, uint16_t height) { MainWidth = width; @@ -119,6 +60,12 @@ void k3SetTime(float t) { } static void update_aabb(struct k3Mdl *mdl, vec3 *pos) { + if(pos == k3_ATTRIB_NONE || pos == k3_ATTRIB_EMPTY || mdl->verts == 0) { + glm_vec3_zero(mdl->aabb[0]); + glm_vec3_zero(mdl->aabb[1]); + return; + } + glm_vec3_copy(pos[0], mdl->aabb[0]); glm_vec3_copy(pos[0], mdl->aabb[1]); for(size_t i = 0; i < mdl->verts; i++) { @@ -212,7 +159,7 @@ struct k3Mdl *k3MdlCreate(size_t verts, size_t indices, size_t boneCount, vec3 * ret->animCount = 0; ret->anims = NULL; - if(k3CPUSkinning && pos && boneids && boneweights) { + if(k3IsSoftSkinning && pos && boneids && boneweights) { ret->cpuSkinning.pos = malloc(sizeof(*ret->cpuSkinning.pos) * verts); memcpy(ret->cpuSkinning.pos, pos, sizeof(*ret->cpuSkinning.pos) * verts); @@ -241,35 +188,44 @@ struct k3Mdl *k3MdlCreate(size_t verts, size_t indices, size_t boneCount, vec3 * int o = 0; ret->offV = o; - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 12 * verts, pos); + if(pos != k3_ATTRIB_EMPTY) { + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 12 * verts, pos); + } o += 12 * verts; if(nrm) { ret->offN = o; - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 3 * verts, nrm); + if(nrm != k3_ATTRIB_EMPTY) { + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 3 * verts, nrm); + } o += 3 * verts; } else ret->offN = -1; if(uvs) { ret->offU = o; - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 8 * verts, uvs); + if(uvs != k3_ATTRIB_EMPTY) { + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 8 * verts, uvs); + } o += 8 * verts; } else ret->offU = -1; if(nrm && uvs) { ret->offT = o; - - int8_t *tans = generate_tangents(verts, indices, inds, pos, nrm, uvs); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 3 * verts, tans); - free(tans); + + if(nrm != k3_ATTRIB_EMPTY && uvs != k3_ATTRIB_EMPTY) { + int8_t *tans = generate_tangents(verts, indices, inds, pos, nrm, uvs); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 3 * verts, tans); + free(tans); + } o += 3 * verts; } else ret->offT = -1; if(cols) { ret->offC = o; - - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 4 * verts, cols); + if(cols != k3_ATTRIB_EMPTY) { + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, o, 4 * verts, cols); + } o += 4 * verts; } else ret->offC = -1; @@ -284,7 +240,9 @@ struct k3Mdl *k3MdlCreate(size_t verts, size_t indices, size_t boneCount, vec3 * } else ret->offB = -1; glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ret->estore->gl); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indices * sizeof(uint16_t), inds, GL_STATIC_DRAW_ARB); + if(inds && inds != k3_ATTRIB_EMPTY) { + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indices * sizeof(uint16_t), inds, GL_STATIC_DRAW_ARB); + } update_aabb(ret, pos); @@ -972,23 +930,23 @@ static int bind_shadow_texture(int textureUnit) { } static void enable_glsl_bones(GLuint bound, struct k3Mdl *mdl, struct k3AnimationBone *bones) { - if(mdl->boneCount) { - GLint a0; - GLint a1; - - if(!k3IsCore) { - a0 = glGetAttribLocationARB(bound, "a_boneids"); - a1 = glGetAttribLocationARB(bound, "a_boneweights"); - } else { - a0 = glGetAttribLocation(bound, "a_boneids"); - a1 = glGetAttribLocation(bound, "a_boneweights"); - } - - if((a0 == -1) != (a1 == -1)) { - k3Log(k3_ERR, "a_boneids and a_boneweights must be both null or non-null"); - } - - if(a0 != -1) { + GLint a0; + GLint a1; + + if(!k3IsCore) { + a0 = glGetAttribLocationARB(bound, "a_boneids"); + a1 = glGetAttribLocationARB(bound, "a_boneweights"); + } else { + a0 = glGetAttribLocation(bound, "a_boneids"); + a1 = glGetAttribLocation(bound, "a_boneweights"); + } + + if((a0 == -1) != (a1 == -1)) { + k3Log(k3_ERR, "a_boneids and a_boneweights must be both null or non-null"); + } + + if(a0 != -1) { + if(bones) { if(!k3IsCore) { glEnableVertexAttribArrayARB(a0); glEnableVertexAttribArrayARB(a1); @@ -1000,45 +958,51 @@ static void enable_glsl_bones(GLuint bound, struct k3Mdl *mdl, struct k3Animatio glVertexAttribPointer(a0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, (void*) (mdl->offB + 0 * mdl->verts)); glVertexAttribPointer(a1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0, (void*) (mdl->offB + 4 * mdl->verts)); } + } else { + if(!k3IsCore) { + glVertexAttrib4fARB(a0, 0, 0, 0, 0); + glVertexAttrib4fARB(a1, 1, 0, 0, 0); + } else { + glVertexAttrib4f(a0, 0, 0, 0, 0); + glVertexAttrib4f(a1, 1, 0, 0, 0); + } + } + } + + if(bones) { + if(!k3IsCore) { + glUniform4fvARB(glGetUniformLocationARB(bound, "u_bonedata"), 2 * mdl->boneCount, (float*) bones); + } else { + glUniform4fv(glGetUniformLocationARB(bound, "u_bonedata"), 2 * mdl->boneCount, (float*) bones); + } + } else { + vec4 data[48] = {}; + for(int i = 0; i < 48; i++) { + data[i][3] = 1; } - if(bones) { - if(!k3IsCore) { - glUniform4fvARB(glGetUniformLocationARB(bound, "u_bonedata"), 2 * mdl->boneCount, (float*) bones); - } else { - glUniform4fv(glGetUniformLocationARB(bound, "u_bonedata"), 2 * mdl->boneCount, (float*) bones); - } + if(!k3IsCore) { + glUniform4fvARB(glGetUniformLocationARB(bound, "u_bonedata"), 48, (float*) data); } else { - vec4 data[48] = {}; - for(int i = 0; i < 48; i++) { - data[i][3] = 1; - } - - if(!k3IsCore) { - glUniform4fvARB(glGetUniformLocationARB(bound, "u_bonedata"), 48, (float*) data); - } else { - glUniform4fv(glGetUniformLocationARB(bound, "u_bonedata"), 48, (float*) data); - } + glUniform4fv(glGetUniformLocationARB(bound, "u_bonedata"), 48, (float*) data); } } } static void disable_glsl_bones(struct k3Mdl *mdl, GLuint bound) { - if(mdl->boneCount) { - GLint a0; - GLint a1; - - a0 = glGetAttribLocationARB(bound, "a_boneids"); - a1 = glGetAttribLocationARB(bound, "a_boneweights"); - - if(a0 != -1) { - if(!k3IsCore) { - glDisableVertexAttribArrayARB(a0); - glDisableVertexAttribArrayARB(a1); - } else { - glDisableVertexAttribArray(a0); - glDisableVertexAttribArray(a1); - } + GLint a0; + GLint a1; + + a0 = glGetAttribLocationARB(bound, "a_boneids"); + a1 = glGetAttribLocationARB(bound, "a_boneweights"); + + if(a0 != -1) { + if(!k3IsCore) { + glDisableVertexAttribArrayARB(a0); + glDisableVertexAttribArrayARB(a1); + } else { + glDisableVertexAttribArray(a0); + glDisableVertexAttribArray(a1); } } } @@ -1300,6 +1264,7 @@ static void forward_subpass(mat4 view, int transparent, int lightsStart, int lig GLuint lastVP = 0, lastFP = 0; struct k3Mat *lastMaterial = NULL; int lastAdditive = -1; + int lastDepthwrite = -1; for(size_t rble = rbleStart; rble < rbleEnd; rble++) { struct k3Mdl *mdl = renderQueue[rble].mdl; @@ -1346,6 +1311,15 @@ static void forward_subpass(mat4 view, int transparent, int lightsStart, int lig lastAdditive = mat->passes[0].additive; } + if(lastDepthwrite != mat->passes[0].depthwrite) { + lastDepthwrite = mat->passes[0].depthwrite; + if(lastDepthwrite) { + glDepthMask(GL_TRUE); + } else { + glDepthMask(GL_FALSE); + } + } + if(glsl) { if(lastGLSL != glsl) { if(k3IsCore) @@ -1455,7 +1429,7 @@ static void forward_subpass(mat4 view, int transparent, int lightsStart, int lig enable_glsl_tangents(glsl, mdl); } - if(k3CPUSkinning) { + if(k3IsSoftSkinning) { apply_cpu_skinning(mdl, bones); } @@ -1490,7 +1464,6 @@ void k3PassForward(mat4 projection, mat4 cam) { glEnable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); if(GLAD_GL_EXT_framebuffer_sRGB) { @@ -1504,6 +1477,8 @@ void k3PassForward(mat4 projection, mat4 cam) { if(!k3IsCore) { glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); } int l = 0, k = LightCount; @@ -1639,9 +1614,7 @@ void k3PassDepthOnly(mat4 projection, mat4 cam, int clear, int cull) { enable_glsl_bones(glsl, mdl, bones); } - enable_vertex_buffers(mdl, glsl); - - if(k3CPUSkinning) { + if(k3IsSoftSkinning) { apply_cpu_skinning(mdl, bones); } @@ -1854,9 +1827,7 @@ static void pass_irregular(int passnum, mat4 mainproj, mat4 maincam, mat4 lightp enable_glsl_bones(glsl, mdl, bones); } - enable_vertex_buffers(mdl, glsl); - - if(k3CPUSkinning) { + if(k3IsSoftSkinning) { apply_cpu_skinning(mdl, bones); } diff --git a/src/k3.h b/src/k3.h index 7dc9f01..d448948 100644 --- a/src/k3.h +++ b/src/k3.h @@ -43,7 +43,8 @@ struct k3ARBFP; struct k3ARBFP *k3ProgramARBFP(const char *src); extern uint8_t k3GraphicalReduction; -extern int k3IsCore; +extern bool k3IsCore; +extern bool k3IsSoftSkinning; struct k3Mat { struct { @@ -91,6 +92,7 @@ struct k3Mat { char transparent; char nocull; char alphatest; + char depthwrite; } passes[1]; }; @@ -155,6 +157,8 @@ struct k3Storage; void k3StorageRef(struct k3Storage*); void k3StorageUnref(struct k3Storage*); +#define k3_ATTRIB_NONE (NULL) +#define k3_ATTRIB_EMPTY ((void*) 1) struct k3Mdl; struct k3Mdl *k3MdlCreate(size_t verts, size_t indices, size_t boneCount, vec3 *pos, uint8_t *nrm, float *uvs, uint8_t *cols, uint8_t *boneids, uint16_t *boneweights, uint16_t *inds, mat4 *invBind, uint8_t *boneParents); void k3MdlUpdatePos(struct k3Mdl *mdl, vec3 *pos); diff --git a/src/k3_internal.h b/src/k3_internal.h new file mode 100644 index 0000000..2ec7740 --- /dev/null +++ b/src/k3_internal.h @@ -0,0 +1,67 @@ +#pragma once + +#include"k3.h" + +#include"gl.h" + +#include +#include +#include + +#define GL_FROM_K3TEX(k3t) ((k3t) ? (k3t)->tex : 0) +#define GL_FROM_K3MARCHER(k3m) ((GLuint) (uintptr_t) (k3m)) +#define GL_FROM_K3ARBVP(k3m) ((GLuint) (uintptr_t) (k3m)) +#define GL_FROM_K3ARBFP(k3m) ((GLuint) (uintptr_t) (k3m)) +#define GL_FROM_K3GLSL(k3m) ((GLuint) (uintptr_t) (k3m)) + +struct k3Tex { + GLuint tex; + int cubemap; + uint32_t szX; + uint32_t szY; + uint32_t szZ; +}; + +struct k3Storage { + int16_t ref; + void(*free)(struct k3Storage*); +}; + +struct k3StorageBasic { + struct k3Storage; + GLuint gl; +}; + +struct k3Offscreen { + GLuint fbo; + struct k3Tex *diffuse; + struct k3Tex *depth; +}; + +struct k3Mdl { + struct { + vec3 *pos; + uint8_t *boneids; + uint16_t *boneweights; + } cpuSkinning; + + size_t verts; + struct k3StorageBasic *vstore; + struct k3StorageBasic *estore; + + uint16_t meshCount; + struct k3Mesh *meshes; + + size_t boneCount; + mat4 *invBind; + uint8_t *boneParents; + + uint16_t animCount; + struct k3Animation **anims; + + vec3 aabb[2]; + + int offV, offN, offC, offU, offB, offT; + + const char *debugname; +}; diff --git a/src/k3particles.c b/src/k3particles.c new file mode 100644 index 0000000..f653fae --- /dev/null +++ b/src/k3particles.c @@ -0,0 +1,181 @@ +#include"k3particles.h" + +#include"k3_internal.h" + +struct xorshift128_state { + uint32_t x[4]; +}; + +uint32_t xorshift128(struct xorshift128_state *state) { + uint32_t t = state->x[3]; + uint32_t s = state->x[0]; + state->x[3] = state->x[2]; + state->x[2] = state->x[1]; + state->x[1] = s; + t ^= t << 11; + t ^= t >> 8; + return state->x[0] = t ^ s ^ (s >> 19); +} + +struct xorshift128_state xs = {{1, 2, 3, 4}}; + +static uint32_t randint(uint32_t min, uint32_t max) { + uint32_t x; + do { + x = xorshift128(&xs); + } while(0x100000000UL - 0x100000000UL % ((uint64_t) max + 1) <= x); + return x / (0x100000000UL / ((uint64_t) max + 1)); +} + +static float randfloat() { + union { uint32_t u32; float f; } u = { .u32 = xorshift128(&xs) >> 9 | 0x3f800000 }; + return u.f - 1.0; +} + +void k3CPUQuadParticlesInit(struct k3CPUQuadParticles *this, struct k3Mat *mat) { + uint16_t *inds = calloc(sizeof(*inds), this->capacity * 6); + for(size_t i = 0; i < this->capacity; i++) { + inds[i * 6 + 0] = i * 4 + 0; + inds[i * 6 + 1] = i * 4 + 1; + inds[i * 6 + 2] = i * 4 + 2; + inds[i * 6 + 3] = i * 4 + 0; + inds[i * 6 + 4] = i * 4 + 2; + inds[i * 6 + 5] = i * 4 + 3; + } + + this->mdl = k3MdlCreate(this->capacity * 4, this->capacity * 6, 0, k3_ATTRIB_EMPTY, k3_ATTRIB_EMPTY, k3_ATTRIB_EMPTY, k3_ATTRIB_EMPTY, NULL, NULL, inds, NULL, NULL); + k3MdlAddMesh(this->mdl, mat, 0, this->capacity * 6); + k3MdlSetDebugName(this->mdl, "k3CPUQuadParticles"); + + free(inds); + + this->positions = calloc(sizeof(*this->positions), this->capacity); + this->velocities = calloc(sizeof(*this->velocities), this->capacity); + this->sizes = calloc(sizeof(*this->sizes), this->capacity); + this->lifetimes = calloc(sizeof(*this->lifetimes), this->capacity); +} + +static void random_cone_vector(float coneAngle, vec3 output) { + float minZ = cosf(coneAngle); + float z = randfloat() * (1 - minZ) + minZ; + + float phi = randfloat() * 6.2831853; + + output[0] = sqrtf(1 - z * z) * cosf(phi); + output[1] = z; + output[2] = sqrtf(1 - z * z) * sinf(phi); +} + +static void regenerate_model(struct k3CPUQuadParticles *this, vec3 cameraRight, vec3 cameraUp, vec3 cameraFront) { + vec3 *vpos = calloc(sizeof(*vpos), 4 * this->capacity); + uint8_t *vcols = calloc(4, 4 * this->capacity); + vec2 *vuvs = calloc(sizeof(*vuvs), 4 * this->capacity); + uint8_t *vnrms = calloc(3, 4 * this->capacity); + + vec3 halfRight, halfUp; + glm_vec3_scale(cameraRight, 0.5, halfRight); + glm_vec3_scale(cameraUp, 0.5, halfUp); + + for(size_t i = 0; i < this->count; i++) { + glm_vec3_copy(this->positions[i], vpos[i * 4 + 0]); + glm_vec3_copy(this->positions[i], vpos[i * 4 + 1]); + glm_vec3_copy(this->positions[i], vpos[i * 4 + 2]); + glm_vec3_copy(this->positions[i], vpos[i * 4 + 3]); + + glm_vec3_muladds(halfRight, -this->sizes[i], vpos[i * 4 + 0]); + glm_vec3_muladds(halfUp, -this->sizes[i], vpos[i * 4 + 0]); + + glm_vec3_muladds(halfRight, this->sizes[i], vpos[i * 4 + 1]); + glm_vec3_muladds(halfUp, -this->sizes[i], vpos[i * 4 + 1]); + + glm_vec3_muladds(halfRight, this->sizes[i], vpos[i * 4 + 2]); + glm_vec3_muladds(halfUp, this->sizes[i], vpos[i * 4 + 2]); + + glm_vec3_muladds(halfRight, -this->sizes[i], vpos[i * 4 + 3]); + glm_vec3_muladds(halfUp, this->sizes[i], vpos[i * 4 + 3]); + + vec4 color; + glm_vec4_lerp(this->colorEnd, this->colorStart, this->lifetimes[i] / this->particleLifetime, color); + + for(size_t c = 0; c < 16; c += 4) { + vcols[i * 16 + c + 0] = color[0] * 255; + vcols[i * 16 + c + 1] = color[1] * 255; + vcols[i * 16 + c + 2] = color[2] * 255; + vcols[i * 16 + c + 3] = color[3] * 255; + } + + glm_vec2_copy((vec2) {0, 0}, vuvs[i * 4 + 0]); + glm_vec2_copy((vec2) {1, 0}, vuvs[i * 4 + 1]); + glm_vec2_copy((vec2) {1, 1}, vuvs[i * 4 + 2]); + glm_vec2_copy((vec2) {0, 1}, vuvs[i * 4 + 3]); + + for(size_t c = 0; c < 12; c += 3) { + vnrms[i * 12 + c + 0] = (uint8_t) (cameraFront[0] * 127); + vnrms[i * 12 + c + 1] = (uint8_t) (cameraFront[1] * 127); + vnrms[i * 12 + c + 2] = (uint8_t) (cameraFront[2] * 127); + } + } + + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->mdl->vstore->gl); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, this->mdl->offV, sizeof(*vpos) * this->capacity * 4, vpos); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, this->mdl->offC, sizeof(*vcols) * this->capacity * 4 * 4, vcols); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, this->mdl->offU, sizeof(*vuvs) * this->capacity * 4, vuvs); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, this->mdl->offN, sizeof(*vnrms) * this->capacity * 4 * 3, vnrms); + + this->mdl->meshes[0].idxNumber = this->count * 6; + + free(vpos); + free(vcols); + free(vuvs); + free(vnrms); +} + +static void copy_particle(struct k3CPUQuadParticles *this, size_t from, size_t to) { + glm_vec3_copy(this->positions[from], this->positions[to]); + glm_vec3_copy(this->velocities[from], this->velocities[to]); + this->sizes[to] = this->sizes[from]; + this->lifetimes[to] = this->lifetimes[from]; +} + +void k3CPUQuadParticlesUpdate(struct k3CPUQuadParticles *this, float dt, vec3 cameraRight, vec3 cameraUp, vec3 cameraFront) { + size_t numGenerated = dt * this->emissionRate; + + if((this->emissionLifetime -= dt) <= 0) { + this->emissionEnabled = false; + } + + if(!this->emissionEnabled) numGenerated = 0; + + if(this->count + numGenerated > this->capacity) { + numGenerated = this->capacity - this->count; + } + + for(size_t i = this->count, j = 0; j < numGenerated; i++, j++, this->count++) { + glm_vec3_copy(this->origin, this->positions[i]); + random_cone_vector(this->emissionConeAngle, this->velocities[i]); + glm_vec3_scale(this->velocities[i], 2, this->velocities[i]); + this->sizes[i] = 1; + this->lifetimes[i] = this->particleLifetime; + } + + vec3 accdt; + glm_vec3_scale(this->gravity, dt, accdt); + + for(size_t i = 0; i < this->count;) { + glm_vec3_add(this->velocities[i], accdt, this->velocities[i]); + + vec3 veldt; + glm_vec3_scale(this->velocities[i], dt, veldt); + + glm_vec3_add(this->positions[i], veldt, this->positions[i]); + + this->lifetimes[i] -= dt; + if(this->lifetimes[i] <= 0) { + copy_particle(this, --this->count, i); + } else { + i++; + } + } + + regenerate_model(this, cameraRight, cameraUp, cameraFront); +} diff --git a/src/k3particles.h b/src/k3particles.h new file mode 100644 index 0000000..e5e7198 --- /dev/null +++ b/src/k3particles.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include"k3.h" + +struct k3CPUQuadParticles { + size_t capacity; + size_t count; + vec3 *positions; + vec3 *velocities; + float *sizes; + float *lifetimes; + + struct k3Mdl *mdl; + + vec4 colorStart; + vec4 colorEnd; + + vec3 origin; + vec3 gravity; + float emissionRate; + vec3 emissionConeDirection; + float emissionConeAngle; + float particleLifetime; + + bool emissionEnabled; + float emissionLifetime; +}; + +void k3CPUQuadParticlesInit(struct k3CPUQuadParticles*, struct k3Mat*); +void k3CPUQuadParticlesUpdate(struct k3CPUQuadParticles*, float dt, vec3 cameraRight, vec3 cameraUp, vec3 cameraFront);