All pastes #2071379 Raw Edit

Anonymous

public cpp v1 · immutable
#2071379 ·published 2011-05-28 22:46 UTC
rendered paste body
////  influence_map.h//  Metaballs_2d////  Created by Simon Harvey on 11-05-10.//  Copyright 2011 __MyCompanyName__. All rights reserved.//#include <list>#include <set>#include <map>#include <vector>#include "cinder/Vector.h"#include "cinder/gl/gl.h"using namespace std;using namespace cinder;namespace influence {	typedef Vec2<int> index_t;	typedef unsigned int square_state_t;	typedef enum {		UP, RIGHT, DOWN, LEFT	} move;	const move move_lookup[12] = {		DOWN,		LEFT, 		RIGHT,		RIGHT,				DOWN,		LEFT,		LEFT,		UP,		UP,		UP,		LEFT,		LEFT,	};	const index_t moves[4] = {		index_t(0, -1),		index_t(1, 0),		index_t(0, 1),		index_t(-1, 0)	};	class Emitter {	public:		Vec2f position;		float radius;		void *owner;				Emitter(Vec2f pos, float radius, void *owner) {			this->position = pos;			this->radius = radius;			this->owner = owner;		}		inline bool might_affect(Vec2f pos) {			return abs(pos.x - position.x) <= radius			&& abs(pos.y - position.y) <= radius;		}		inline float effect_at(Vec2f pos) {			float d2 = position.distanceSquared(pos);			if (d2 <= radius*radius)				return (radius-sqrt(d2))/radius/* * modifier*/;			return 0;		}	};		typedef map<void *, float> index_influences;		bool value_comparer(index_influences::value_type &i1, index_influences::value_type &i2) {		return i1.second<i2.second;	}		class InfluenceMap {	public:		unsigned int width, height, size_f;		std::list<void *> influences;		std::set<Emitter *> emitters;				InfluenceMap() : width(256), height(256), size_f(4) { }		InfluenceMap(unsigned int w, unsigned int h) : width(w), height(h), size_f(4) { }				void add_emitter(Emitter *e) {			emitters.insert(e);		}		typedef std::map<index_t, void *> cache_t;		cache_t owner_cache;		void * compute_owner_at(index_t pos) {			set<Emitter *>::iterator it = emitters.begin();			index_influences values;			for ( ; it != emitters.end(); it++) {				Emitter *e = *it;				Vec2f f_pos = pos * (2 << size_f); // position on the field, not on the grid				if (e->might_affect(f_pos)) {					values[e->owner] += e->effect_at(f_pos);				}			}			//index_influences::value_type best = *values.begin();			/*values.count();			index_influences::iterator itor = std::max_element(values.begin(), values.end(), value_comparer);			index_influences::value_type best = *itor;*/			/*if (best.second >= .001) { // treshold				return best.first;			} else {*/				return 0;			//}		}				void * owner_at(index_t pos) {						// calculate if not in cache			void * owner;			cache_t::iterator it = owner_cache.begin();			if (it == owner_cache.end()) {				// compute it!				owner = compute_owner_at(pos);			} else {				owner = it->second;				//owner_cache.insert(pos, owner);			}			return 0;		}				bool active_at(void *owner, int px, int py) {			if (px < 0 || py < 0 || px >= width || py >= height)				return false;			index_t i = index_t(px, py);			return owner_at(i) == owner;		}				square_state_t state_at(void *owner, index_t i) {			return active_at(owner, i.x, i.y) << 3 | active_at(owner, i.x+1, i.y) << 2 | active_at(owner, i.x, i.y+1) << 1 | active_at(owner, i.x+1, i.y+1);		}						void update () {			map<void *, list<index_t> >blobs;			set<Emitter *> open(emitters);			unsigned int grid_size = 2 << size_f;			printf("update\n");			glColor3f(1, 1, 1);			while(open.size()) {				Emitter e = **open.begin();				open.erase(open.begin());				index_t pos = index_t(e.position.x/grid_size, e.position.y/grid_size);				vector<Vec2f> verts;				int i = 0;				do {					square_state_t state = state_at(e.owner, pos);					pos += moves[move_lookup[state]];					verts.push_back(Vec2f(pos.x*10.0f, pos.y*10.0f));					i++;				} while(true && i < 50);				if (verts.size()) {					glEnableClientState(GL_VERTEX_ARRAY);					glVertexPointer(2, GL_FLOAT, 0, verts[0]);					glDrawArrays(GL_LINE_LOOP, 0, verts.size());				}			}		}	};}