diff options
-rw-r--r-- | particle.cpp | 51 | ||||
-rw-r--r-- | particle.h | 66 | ||||
-rw-r--r-- | scene.cpp | 83 | ||||
-rw-r--r-- | scene.h | 5 | ||||
-rw-r--r-- | shaders/selection_fragment.glsl | 10 | ||||
-rw-r--r-- | shaders/selection_vertex.glsl | 15 | ||||
-rw-r--r-- | textures/circle.png | bin | 0 -> 2106 bytes | |||
-rw-r--r-- | vector.h | 2 |
8 files changed, 229 insertions, 3 deletions
diff --git a/particle.cpp b/particle.cpp new file mode 100644 index 0000000..9e0b130 --- /dev/null +++ b/particle.cpp @@ -0,0 +1,51 @@ +#include "particle.h" + +#include <cmath> + +float SelectionParticle::t = 0; + +SelectionParticle::SelectionParticle() { + init(t += .1); +} + +SelectionParticle::SelectionParticle(const SelectionParticle& p) { + pos = p.pos; + vel = p.vel; + alpha = p.alpha; + decay = p.decay; +} + +void SelectionParticle::init(float seed) { + pt = seed; + speed = .0005 + fmodf(seed, .001); + speed = .001 + fmodf(seed, .002); + alpha = 1.0; + decay = 0.001 * ((rand() % 5 + 5) / 20.0); + pos = Vector3(cosf(rand()), 0, sinf(rand())); + //pos = Vector3(cosf(seed), 0, sinf(seed)); + //p.pos = src; + //p.pos.x *= ((rand() % 20 + 10) / + vel = Vector3(cosf(rand()), 10, sinf(rand())); + vel /= vel.length();// * ((rand() % 10 + 5) / 10); +} + +void SelectionParticle::update(unsigned int steps, vec4f *v) { + pt += speed * steps; + alpha -= decay * steps; + if(alpha <= 0) { + init(t += 0.1); + return; + } else { + pos += vel * (steps / 1000.0); + pos.y += vel.y * (steps / 1000.0); + //it->vel += Vector3(0, -.1, 0) * (steps / 1000.0); + } + //update(steps); + //vec4f *v = &vertices[i]; + //v->x = pos.x * cosf(t * (i+1) / 800); + v->x = pos.x * cosf(pt); + v->y = pos.y; + //v->z = pos.z * sinf(t * (i+1) / 800); + v->z = pos.z * sinf(pt); + v->w = alpha; +} diff --git a/particle.h b/particle.h new file mode 100644 index 0000000..433b557 --- /dev/null +++ b/particle.h @@ -0,0 +1,66 @@ +#ifndef PARTICLE_H +#define PARTICLE_H + +#include "vector.h" + +#include <list> + +struct vec4f { + float x, y, z, w; +}; + +class SelectionParticle { + public: + Vector3 pos; + float alpha; + float decay; + static float t; + float pt; + float speed; + Vector3 vel; + + SelectionParticle(); + SelectionParticle(const SelectionParticle& p); + + void init(float seed); + void update(unsigned int steps, vec4f *v); +}; + +template<class T> +class ParticleGroup { + public: + T *particles; + vec4f *vertices; + unsigned int num; + unsigned int count; + Vector3 src; + Vector3 dir; + + ParticleGroup(Vector3 src, Vector3 dir, unsigned int count) { + srand(time(NULL)); + this->src = src; + this->dir = dir; + this->num = count; + this->count = 0; + T::t = 0; + particles = new T[count]; + vertices = new vec4f[count]; + }; + ~ParticleGroup() { + delete[] particles; + delete[] vertices; + } + + void update(unsigned int steps) { + if(count < num) { + particles[count].init(T::t += 0.1); + count++; + } + for(unsigned int i = 0; i < count; i++) { + T *p = &particles[i]; + p->update(steps, &vertices[i]); + } + } +}; + +#endif @@ -39,11 +39,20 @@ Scene::Scene() { glUniform1i(markloc, 3); glUseProgram(0); + GLFragmentShader selection_fragment("shaders/selection_fragment.glsl"); + GLVertexShader selection_vertex("shaders/selection_vertex.glsl"); + selection_program.attach(selection_fragment); + selection_program.attach(selection_vertex); + selection_program.link(); + + selection_particles = NULL; + /* load textures */ grass_texture = load_texture("textures/zooboing-366-grass.jpg"); rock_texture = load_texture("textures/zooboing-825-stone-modified.jpg"); soil_texture = load_texture("textures/zooboing-469-sand-modified.jpg"); marker_texture = load_texture("textures/cross.png"); + circle_texture = load_texture("textures/circle.png"); /* load heightmap */ SDL_Surface *hm = IMG_Load("heightmap.png"); @@ -200,8 +209,11 @@ void Scene::events() { case SDL_BUTTON_RIGHT: if(dialog) CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton); - else + else { show_selection = false; + delete selection_particles; + selection_particles = NULL; + } break; case SDL_BUTTON_WHEELUP: if(dialog) @@ -397,6 +409,71 @@ void Scene::render() { do_select = false; selected = Vector3(px, py, pz); show_selection = true; + if(selection_particles) + delete selection_particles; + selection_particles = new ParticleGroup<SelectionParticle>(selected, Vector3(0, 1, 0), 1000); + } + + float pdist; + if(selection_particles && (pdist = (selected.xz() - pos.xz()).length()) < 100) { + Quadtree::QuadNode *node = qt->find(selected.x, selected.z); + selected.y = node->get_height(selected.x, selected.z); + selection_particles->src = selected; + glPushMatrix(); + glTranslatef(selection_particles->src.x, selection_particles->src.y, selection_particles->src.z); + GLdouble m[16]; + glGetDoublev(GL_MODELVIEW_MATRIX, m); + Vector3 up(m[0], m[4], m[8]); + Vector3 right(m[1], m[5], m[9]); + GLdouble temp[3] = {m[3], m[7], m[11]}; + m[3] = m[12]; + m[7] = m[13]; + m[11] = m[14]; + m[12] = temp[0]; + m[13] = temp[1]; + m[14] = temp[2]; + m[0] = 1; m[4] = 0; m[8] = 0; + m[1] = 0; m[5] = 1; m[9] = 0; + m[2] = 0; m[6] = 0; m[10] = 1; + //glLoadMatrixd(m); + //glRotatef(yaw*180/M_PI, 0, 1, 0); + //glTranslatef(selection_particles->src.x, selection_particles->src.y, selection_particles->src.z); + //glRotatef(-yaw*180/M_PI, 0, 1, 0); + //glRotatef(-yaw*180/M_PI+90, 0, 1, 0); + + glDepthMask(GL_FALSE); + selection_particles->update(steps); + selection_program.use(); + GLint dist = glGetUniformLocation(selection_program.get_program(), "dist"); + glUniform1f(dist, pdist); + glPointSize(100); + const GLfloat att[3] = {1, .01, 0}; + glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, att); + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + glEnable(GL_POINT_SPRITE); + glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, circle_texture); + glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); + glVertexPointer(4, GL_FLOAT, 0, selection_particles->vertices); + glEnableClientState(GL_VERTEX_ARRAY); + glDrawArrays(GL_POINTS, 0, selection_particles->count); + glDisableClientState(GL_VERTEX_ARRAY); + //glBegin(GL_QUADS); + /*glBegin(GL_POINTS); + for(std::list<Particle>::iterator it = selection_particles->particles.begin(); it != selection_particles->particles.end(); it++) { + glColor4f(1, 1, 1, it->alpha); + glVertex3f(it->pos.x, it->pos.y, it->pos.z); + } + glEnd();*/ + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glUseProgram(0); + glDepthMask(GL_TRUE); + glPopMatrix(); } video::ortho(); @@ -413,6 +490,10 @@ void Scene::render() { font->Render(move_str.c_str()); glTranslatef(0, -height, 0); font->Render(selected.str().c_str()); + if(selection_particles) { + glTranslatef(0, -height, 0); + font->Render((boost::format("particles: %d") % selection_particles->count).str().c_str()); + } /*if(selected) { glTranslatef(0, height, 0); //font->Render((boost::format("(%s %s %s %s)") % selected->a->str() % selected->b->str() % selected->c->str() % selected->d->str()).str().c_str()); @@ -6,6 +6,7 @@ #include "gl.h" #include "shader.h" #include "gui.h" +#include "particle.h" #include <FTGL/ftgl.h> @@ -33,8 +34,12 @@ class Scene { int sx, sy; GLShaderProgram terrain_program; + GLShaderProgram selection_program; + + ParticleGroup<SelectionParticle> *selection_particles; GLuint grass_texture, rock_texture, soil_texture, marker_texture; + GLuint circle_texture; Scene(); ~Scene(); diff --git a/shaders/selection_fragment.glsl b/shaders/selection_fragment.glsl new file mode 100644 index 0000000..33b6cf1 --- /dev/null +++ b/shaders/selection_fragment.glsl @@ -0,0 +1,10 @@ +#version 120 + +uniform sampler2D tex; +uniform float dist; + +void main() { + vec4 tc = texture2D(tex, gl_TexCoord[0].st); + gl_FragColor = tc * gl_Color * .3; +} +/* vim: set syn=glsl: */ diff --git a/shaders/selection_vertex.glsl b/shaders/selection_vertex.glsl new file mode 100644 index 0000000..b5f0aa7 --- /dev/null +++ b/shaders/selection_vertex.glsl @@ -0,0 +1,15 @@ +#version 120 + +uniform float dist; + +void main() { + gl_PointSize = min(200/dist * log(gl_Vertex.w+2), 200); + gl_FrontColor = vec4(1, gl_Vertex.w/2, 0, 1); + + gl_PointSize = 100/dist * min(gl_Vertex.w+.5, 1); + gl_FrontColor = vec4(1, 1-log(gl_Vertex.w+1.0), 0, 1); + + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1); +} +/* vim: set syn=glsl: */ diff --git a/textures/circle.png b/textures/circle.png Binary files differnew file mode 100644 index 0000000..0baf0b2 --- /dev/null +++ b/textures/circle.png @@ -1,8 +1,6 @@ #ifndef VECTOR_H #define VECTOR_H -#include <boost/shared_ptr.hpp> - #include <string> class Vector2 { |