231 lines
6.7 KiB
C++
231 lines
6.7 KiB
C++
/*
|
|
QGLView
|
|
Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "water_system.h"
|
|
|
|
|
|
WaterSystem::WaterSystem(): GLObjectBase() {
|
|
texture = 0;
|
|
near_offsets
|
|
<< Vector3i(-1, 0, 0)
|
|
<< Vector3i( 1, 0, 0)
|
|
<< Vector3i(-1, -1, 0)
|
|
<< Vector3i( 1, -1, 0)
|
|
<< Vector3i( 0, -1, 0)
|
|
<< Vector3i(-1, 1, 0)
|
|
<< Vector3i( 1, 1, 0)
|
|
<< Vector3i( 0, 1, 0)
|
|
<< Vector3i(-1, 0, -1)
|
|
<< Vector3i( 1, 0, -1)
|
|
<< Vector3i( 0, 0, -1)
|
|
<< Vector3i(-1, -1, -1)
|
|
<< Vector3i( 1, -1, -1)
|
|
<< Vector3i( 0, -1, -1)
|
|
<< Vector3i(-1, 1, -1)
|
|
<< Vector3i( 1, 1, -1)
|
|
<< Vector3i( 0, 1, -1)
|
|
<< Vector3i(-1, 0, 1)
|
|
<< Vector3i( 1, 0, 1)
|
|
<< Vector3i( 0, 0, 1)
|
|
<< Vector3i(-1, -1, 1)
|
|
<< Vector3i( 1, -1, 1)
|
|
<< Vector3i( 0, -1, 1)
|
|
<< Vector3i(-1, 1, 1)
|
|
<< Vector3i( 1, 1, 1)
|
|
<< Vector3i( 0, 1, 1);
|
|
}
|
|
|
|
|
|
WaterSystem::~WaterSystem() {
|
|
QList<BigChunk * > cv = big_chunks.values();
|
|
foreach (BigChunk * i, cv) {
|
|
qDebug() << "delete" << i;
|
|
delete i;
|
|
}
|
|
cv.clear();
|
|
}
|
|
|
|
|
|
void WaterSystem::update() {
|
|
QList<BigChunk * > cv = big_chunks.values();
|
|
//qDebug() << "save states" << cv.size();
|
|
foreach (BigChunk * i, cv)
|
|
i->saveState();
|
|
Particle tp;
|
|
if (part_count < 5000)
|
|
for (int i = 0; i < 10; ++i) {
|
|
tp.pos = QVector3D(urand()*20+30, urand()*20+30, 30);
|
|
tp.speed = QVector3D(urand(1.), urand(1.), 0.);
|
|
newBigChunk(tp.bigChunkIndex())->newChunk(tp.chunkIndex())->particles << tp;
|
|
}
|
|
QList<BigChunk * > near_big;
|
|
QList<Chunk * > near_;
|
|
QList<QVector<Particle> * > near_parts;
|
|
Vector3i cind, nind;
|
|
#if QT_VERSION >= 0x040700
|
|
near_big.reserve(27);
|
|
near_.reserve(27);
|
|
near_parts.reserve(27);
|
|
#endif
|
|
foreach (BigChunk * bc, cv) {
|
|
Vector3i bci = bc->index;
|
|
near_big.clear();
|
|
near_big << bc;
|
|
foreach (const Vector3i & o, near_offsets)
|
|
near_big << big_chunks.value(bci + o);
|
|
near_big.removeAll(0);
|
|
for (int i = 0; i < BIG_CHUNK_SIZE; ++i)
|
|
for (int j = 0; j < BIG_CHUNK_SIZE; ++j)
|
|
for (int k = 0; k < BIG_CHUNK_SIZE; ++k) {
|
|
Chunk * cc = bc->chunks[i][j][k];
|
|
if (cc == 0) continue;
|
|
near_.clear();
|
|
//foreach (const Vector3i & o, near_offsets)
|
|
// near_ << big_chunks.value(bci + o);
|
|
near_ << cc;
|
|
near_.removeAll(0);
|
|
near_parts.clear();
|
|
foreach (Chunk * ci, near_)
|
|
if (!ci->prev_particles.isEmpty())
|
|
near_parts << &(ci->prev_particles);
|
|
QVector<Particle> & parts(cc->particles);
|
|
//qDebug() << "chunk" << cc->index.toQVector3D() << "proc" << parts.size() << "particles";
|
|
for (int p = 0; p < parts.size(); ++p) {
|
|
Particle & cp(parts[p]);
|
|
//Vector3i obi = cp.bigChunkIndex(), oi = cp.chunkIndex();
|
|
if (cp.processed) continue;
|
|
cp.processed = true;
|
|
cind = cp.chunkIndex();
|
|
cp.process(near_parts);
|
|
nind = cp.chunkIndex();
|
|
if (nind == cind) continue;
|
|
newBigChunk(cp.bigChunkIndex())->newChunk(nind)->particles << cp;
|
|
parts.remove(p);
|
|
--p;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void WaterSystem::Particle::process(const QList<QVector<Particle> * > & near_parts) {
|
|
accel += Vector3d(0., 0., -0.98 / 60.) / mass;
|
|
speed += accel;
|
|
pos += speed;
|
|
speed *= 0.95;
|
|
GLfloat sm = speed.length();//piMax<GLfloat>(fabs(speed.x), fabs(speed.y), fabs(speed.z));
|
|
if (sm > 0.2)
|
|
speed.normalize() *= 0.2;
|
|
if (pos.z - radius < 0.) {
|
|
pos.z = radius;
|
|
speed.z = -speed.z * 0.2;
|
|
speed *= 0.9;
|
|
accel.clear();
|
|
}
|
|
GLfloat sdist, srad, ssrad;
|
|
Vector3d dpos;
|
|
//return;
|
|
/*int cnt = 0;
|
|
foreach (QVector<Particle> * pl, near_parts)
|
|
cnt += pl->size();
|
|
qDebug() << cnt;*/
|
|
foreach (QVector<Particle> * pl, near_parts) {
|
|
QVector<Particle> & rpl(*pl);
|
|
for (int i = 0; i < rpl.size(); ++i) {
|
|
Particle & cp(rpl[i]);
|
|
srad = radius + cp.radius;
|
|
dpos = pos - cp.pos;
|
|
if (fabs(dpos.x) >= srad || fabs(dpos.y) >= srad || fabs(dpos.z) >= srad) continue;
|
|
ssrad = srad * srad;
|
|
sdist = dpos.lengthSquared();
|
|
if (sdist >= ssrad) continue;
|
|
//continue;
|
|
sdist = sqrt(sdist);
|
|
ssrad = (srad - sdist) / 2;
|
|
dpos *= ssrad / sdist;
|
|
//pos += dpos;
|
|
//cp.pos -= dpos;
|
|
//qDebug() << "intersect" << sdist << (pos - cp.pos).length();
|
|
speed -= speed.projectTo(dpos) * 2.;
|
|
cp.speed -= cp.speed.projectTo(dpos) * 2.;
|
|
speed *= 0.8;
|
|
cp.speed *= 0.8;
|
|
accel *= 0.8;
|
|
cp.accel *= 0.8;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void WaterSystem::draw(QGLShaderProgram * prog, bool simplest) {
|
|
//return;
|
|
pass_ = GLObjectBase::Transparent;
|
|
//qDebug() << "save states" << cv.size();
|
|
glPointSize(20);
|
|
GLfloat pp[] = {1.f, 1.f, 0.f};
|
|
//glEnable(GL_BLEND);
|
|
glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, pp);
|
|
//glDepthMask(GL_FALSE);
|
|
glNormal3f(0.f, 0.f, 1.f);
|
|
//glEnable(GL_POINT_SPRITE);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_VERTEX_ARRAY);
|
|
//glDisable(GL_BLEND);
|
|
//glDisable(GL_ALPHA_TEST);
|
|
glDisable(GL_NORMAL_ARRAY);
|
|
glDisable(GL_COLOR_ARRAY);
|
|
glDisable(GL_TEXTURE_COORD_ARRAY);
|
|
double ha = 1. / (big_chunks.size() + 1.), ch = 0.;
|
|
QVector<GLfloat> v;
|
|
QList<BigChunk * > cv = big_chunks.values();
|
|
part_count = 0;
|
|
foreach (BigChunk * bc, cv) {
|
|
for (int i = 0; i < BIG_CHUNK_SIZE; ++i)
|
|
for (int j = 0; j < BIG_CHUNK_SIZE; ++j)
|
|
for (int k = 0; k < BIG_CHUNK_SIZE; ++k) {
|
|
Chunk * cc = bc->chunks[i][j][k];
|
|
if (cc == 0) continue;
|
|
const QVector<Particle> & cp(cc->particles);
|
|
part_count += cp.size();
|
|
v.clear();
|
|
foreach (const Particle & p, cp)
|
|
v << p.pos.x << p.pos.y << p.pos.z;
|
|
qglColor(QColor::fromHsvF(ch, 1., 1.));
|
|
glVertexPointer(3, GL_FLOAT, 0, v.constData());
|
|
glDrawArrays(GL_POINTS, 0, v.size() / 3);
|
|
ch += ha;
|
|
while (ch > 1.) ch -= 1.;
|
|
}
|
|
}
|
|
qDebug() << "draw" << part_count << "water particles";
|
|
//glDepthMask(GL_TRUE);
|
|
/*if (!d_vertices.isEmpty()) {
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glVertexPointer(3, GL_FLOAT, 0, d_vertices.constData());
|
|
glTexCoordPointer(2, GL_FLOAT, 0, d_uvs.constData());
|
|
//glColorPointer(4, GL_FLOAT, 0, d_colors.constData());
|
|
glNormalPointer(GL_FLOAT, 0, d_normals.constData());
|
|
glDrawArrays(geom_prim, 0, d_vertices.size() / 3);*/
|
|
/*if (pass_ == Reflection) {
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
|
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
|
|
}*/
|
|
//}
|
|
}
|