/* QGLView Copyright (C) 2016 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 . */ #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 cv = big_chunks.values(); foreach (BigChunk * i, cv) { qDebug() << "delete" << i; delete i; } cv.clear(); } void WaterSystem::update() { QList 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 near_big; QList near_; QList * > 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 & 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 * > & near_parts) { accel += Vector3d(0., 0., -0.98 / 60.) / mass; speed += accel; pos += speed; speed *= 0.95; GLfloat sm = speed.length();//piMax(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 * pl, near_parts) cnt += pl->size(); qDebug() << cnt;*/ foreach (QVector * pl, near_parts) { QVector & 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 v; QList 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 & 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); }*/ //} }