Bug fixes and split to k3_internal.h
This commit is contained in:
parent
a06aacd405
commit
deb6387908
229
src/k3.c
229
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);
|
||||
}
|
||||
|
||||
|
6
src/k3.h
6
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);
|
||||
|
67
src/k3_internal.h
Normal file
67
src/k3_internal.h
Normal file
@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include"k3.h"
|
||||
|
||||
#include"gl.h"
|
||||
|
||||
#include<cglm/vec2.h>
|
||||
#include<cglm/frustum.h>
|
||||
#include<cglm/cam.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))
|
||||
|
||||
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;
|
||||
};
|
181
src/k3particles.c
Normal file
181
src/k3particles.c
Normal file
@ -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);
|
||||
}
|
32
src/k3particles.h
Normal file
32
src/k3particles.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include<cglm/vec3.h>
|
||||
#include<stdbool.h>
|
||||
#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);
|
Loading…
Reference in New Issue
Block a user