principia/src/fluidbuffer.cc

128 lines
2.8 KiB
C++

#include "fluidbuffer.hh"
#include "world.hh"
tms::gbuffer *fluidbuffer::verts;
tms::gbuffer *fluidbuffer::indices;
tms::varray *fluidbuffer::va;
tms::mesh *fluidbuffer::mesh;
tms::entity *fluidbuffer::e;
tms::entity *fluidbuffer::e2;
uint32_t fluidbuffer::n = 0;
struct fluidbuf_vert {
tvec3 pos;
tvec3 uv;
};
fluidbuf_vert fluidbuffer::base[4];
void fluidbuffer::reset()
{
n = 0;
}
tms::entity *
fluidbuffer::get_entity()
{
if (e) return e;
mesh = new tms::mesh(va, indices);
mesh->i32 = 1;
e = new tms::entity();
e->prio = 0;
e->set_mesh(mesh);
e->set_material(&m_fluidbuf);
mesh->i_start = 0;
mesh->i_count = n*9*3;
return e;
}
void fluidbuffer::_init()
{
tms_infof("Initializing fluidbuffer...");
verts = new tms::gbuffer(4*(FLUIDBUFFER_MAX)*sizeof(struct fluidbuf_vert));
verts->usage = TMS_GBUFFER_STREAM_DRAW;
indices = new tms::gbuffer(6*FLUIDBUFFER_MAX*sizeof(uint32_t));
indices->usage = TMS_GBUFFER_STATIC_DRAW;
indices->target = GL_ELEMENT_ARRAY_BUFFER;
va = new tms::varray(2);
va->map_attribute("position", 3, GL_FLOAT, verts);
va->map_attribute("uv", 3, GL_FLOAT, verts);
uint32_t *i = (uint32_t*)indices->get_buffer();
for (uint32_t x=0; x<FLUIDBUFFER_MAX; x++) {
uint32_t o = x*6;
uint32_t vo = x*4;
i[o+0] = vo;
i[o+1] = vo+1;
i[o+2] = vo+2;
i[o+3] = vo;
i[o+4] = vo+2;
i[o+5] = vo+3;
}
indices->upload();
base[0] = (fluidbuf_vert){
(tvec3){.5f,.5f,0.f},
(tvec3){.5f, 1.f, 0.f}
};
base[1] = (fluidbuf_vert){
(tvec3){-.5f,.5f,0.f},
(tvec3){0.f, 1.f, 0.f},
};
base[2] = (fluidbuf_vert){
(tvec3){-.5f,-.5f,0.f},
(tvec3){0.f, .75f, 0.f},
};
base[3] = (fluidbuf_vert){
(tvec3){.5f,-.5f,0.f},
(tvec3){.5f, .75f, 0.f},
};
reset();
}
void fluidbuffer::add(
float x, float y, float z,
//float r, float g, float b, float a,
float pressure,
float w, float h
) {
uint32_t particle_limit = ((W->level.version <= LEVEL_VERSION_1_5_1) ? FLUIDBUFFER_MAX_1_5_1 : FLUIDBUFFER_MAX);
if (n >= particle_limit) return;
fluidbuf_vert *vert_buf = (fluidbuf_vert *) verts->get_buffer();
for (int ix=0; ix<4; ix++) {
vert_buf[n*4+ix] = base[ix];
vert_buf[n*4+ix].pos.x *= w;
vert_buf[n*4+ix].pos.y *= h;
vert_buf[n*4+ix].pos.x += x;
vert_buf[n*4+ix].pos.y += y;
vert_buf[n*4+ix].pos.z += z;
vert_buf[n*4+ix].uv.x += .5f*(3%2);
vert_buf[n*4+ix].uv.y -= .25f*(3/2);
vert_buf[n*4+ix].uv.z = pressure;
}
n++;
}
void fluidbuffer::upload()
{
if (mesh) {
mesh->i_start = 0;
mesh->i_count = n*6;
}
if (n) verts->upload_partial(n*4*sizeof(struct fluidbuf_vert));
}