Exemple #1
0
void cloth::setFixedPoints(int x, int y)
{
	getParticle(x ,y)->makeUnmovable(); 
	getParticle(x ,y)->setFixed();
	fixedParticles.push_back(getParticle(x ,y));
	
}
Exemple #2
0
void cloth::initParticlePairConstraint(int x1, int y1, int x2, int y2) {
	Particle *p1 = getParticle(x1,y1);
	Particle *p2 = getParticle(x2,y2);

	constraints.push_back( Constraint(p1,p2));//p1,p2,及弹簧之间的自然长度存为一个结构体

	vec3 vec = p1->getPos()-p2->getPos();
	float rest_distance = length(vec);

	ParticleConstraint pc1 = {x2,y2,rest_distance};//p1点受到p2点的constraint
	constrainsPerParticle[getParticleIndex(x1,y1)].push_back(pc1);//将p1收到的p2的constraint压入p1的constraint集合

	ParticleConstraint pc2 = {x1,y1,rest_distance};//p2点受到p1点的constraint
	constrainsPerParticle[getParticleIndex(x2,y2)].push_back(pc2);//将p2收到的p1的constraint压入p1的constraint集合
}
Exemple #3
0
void RobotStabilizeEffect::draw()
{
    for(int i = 0; i < STABILIZE_PARTICLE_COUNT; i++) {
        GLParticleDummy * p = getParticle(i);
        p->draw();
    }
}
Exemple #4
0
ofxMSAPhysics* ofxMSAPhysics::addToCollision(ofxMSAParticle* p) {
	for(int i=0; i< numberOfParticles(); i++) {
		ofxMSAParticle *target = getParticle(i);
		if(target->hasCollision()) makeCollision(target, p);
	}
	return this;
}
Exemple #5
0
void RobotStabilizeEffect::moveTo(GLfloat x, GLfloat y)
{
    GLvector2f dir = GLvector2f(x, y) - mPos;
    mPos = GLvector2f(x, y);
    for(int i = 0; i < STABILIZE_PARTICLE_COUNT; i++) {
        GLParticleDummy * p = getParticle(i);
        GLvector2f dest = p->pos() + dir;
        p->moveTo(dest.x, dest.y);
    }
}
Exemple #6
0
void Ignite::runAction()
{
    auto particle = getParticle();
    auto invoke   = ScaleTo::create(0.2f, 0.3f);
    FiniteTimeAction* actionCompleted = CallFuncN::create(CC_CALLBACK_1(Ignite::onActionCompletedThenRemove, this));

    particle->setPosition(getPositionX(), getPositionY());
    getParent()->addChild(particle);
    particle->runAction(Sequence::create(invoke, actionCompleted, nullptr));
}
Exemple #7
0
void RobotRocketEffect::draw()
{
  if(mHeight <= 0.0f) return;
  for(int i = 0; i < mCount; i++) {
    GLParticleDummy * p = getParticle(i);
    spawn(p, i);
    p->move();
    p->setAlpha(mAlpha);
    p->draw();
  }
}
Exemple #8
0
void cloth::createParticles(float width, float height, int num_particles_x, int num_particles_y)
{
	
	num_particles_width = num_particles_x; 
	num_particles_height = num_particles_y;
	particles.resize(num_particles_width*num_particles_height); 

	// creating particles in a grid of particles from (0,0,0) to (width,-height,0)
	for(int x=0; x<num_particles_width; x++)
	{
		for(int y=0; y<num_particles_height; y++)
		{
			float unitLength_x = width/(float)num_particles_width;
			float unitLength_y = height/(float)num_particles_height;
			vec3 particlePos = vec3(x * unitLength_x, -y * unitLength_y, 0);
			//Particle temp = Particle(particlePos);
			particles[y*num_particles_width+x] = Particle(particlePos); //(x,y)处的粒子在第y行x列
			particles[y*num_particles_width+x].particleIndex = y*num_particles_width+x;
			//printf("  %f particle position X\n", particles[y*num_particles_width+x].position.x);
			//printf("  %f particle position Y\n", particles[y*num_particles_width+x].position.y);
			constrainsPerParticle.push_back(std::vector<ParticleConstraint>()); //作用在particle上的限制力
		}
	}
	for(int x = 0; x<num_particles_width-1; x++)
	{
		for(int y=0; y<num_particles_height-1; y++)
		{
			generateFace(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1));
			generateFace(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1));
		}
	}
	printf("faces number is %d \n",faces.size());
}
Exemple #9
0
void RobotStabilizeEffect::integrate(GLfloat dt)
{
    for(int i = 0; i < STABILIZE_PARTICLE_COUNT; i++) {
        GLParticleDummy * p = getParticle(i);
        GLvector2f velocity = p->velocity();

        GLvector2f direction = mPos - p->pos();
        velocity += direction.normal() * 9.0f * dt;
        p->setVelocity(velocity);

        p->move();
    }
}
Exemple #10
0
void RobotStabilizeEffect::reset()
{
    for(int i = 0; i < STABILIZE_PARTICLE_COUNT; i++) {
        GLParticleDummy * p = getParticle(i);
        GLfloat angle = 2.0f * M_PI * frand();
        GLfloat radius = 30.0f + frand() * 5.0f;
        p->moveTo(mPos.x + radius * cos(angle), mPos.y + radius * sin(angle));
        p->setVelocity2f(2.0f * frand(), 2.0f * frand());
    }
    GLvector2f backup = mPos;
    for(int i = 0; i < STABILIZE_PARTICLE_COUNT; i++) {
        //mPos += GLvector2f(0.05f, 0.05f);
        integrate(0.1f);
    }
    mPos = backup;
}
Exemple #11
0
void cloth::windForce(const vec3 direction)
{
	for(int x = 0; x<num_particles_width-1; x++)
	{
		for(int y=0; y<num_particles_height-1; y++)
		{
			addWindForcesForTriangle(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1),direction);
			addWindForcesForTriangle(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1),direction);
		}
	}
}
Exemple #12
0
void RobotRocketEffect::moveTo(GLfloat x, GLfloat y)
{
  GLvector2f diff = mPos - GLvector2f(x, y);
  mPos.x = x; 
  mPos.y = y;

  recalculateVectors();
  for(int i = 0; i < mCount; i++) {
    GLParticleDummy * p = getParticle(i);
    GLvector2f pos = p->pos();
    GLvector2f dest = mdestA + (mdestAB * frand());

    p->moveTo(pos.x - diff.x, pos.y - diff.y);
    GLvector2f velocity = (dest - pos).normal() * frand() * 6.0f;
    p->setVelocity(velocity);  
  }
}
Exemple #13
0
void cloth::render(Shader* shader)
{
	 glPolygonMode(GL_FRONT_AND_BACK, (draw_wire ? GL_LINE : GL_FILL));
	// reset normals (which where written to last frame)
	std::vector<Particle>::iterator particle;
	for(particle = particles.begin(); particle != particles.end(); particle++)
	{
		(*particle).resetNormal();
	}

	updateFaceNormal();

	static GLuint vertexArrayObject = 0;
	static GLuint vertexBuffer = 0;
	static GLuint texture;
	static int elementSize;
	if (vertexArrayObject == 0){
		glGenVertexArrays(1, &vertexArrayObject);
		glBindVertexArray(vertexArrayObject);

		glGenBuffers(1, &vertexBuffer);
		glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

		GLuint positionAttributeLocation = glGetAttribLocation(shader->ProgramID, "position");
		GLuint uvAttributeLocation = glGetAttribLocation(shader->ProgramID, "uv");
		GLuint normalAttributeLocation = glGetAttribLocation(shader->ProgramID, "normal");
		glEnableVertexAttribArray(positionAttributeLocation);
		glEnableVertexAttribArray(uvAttributeLocation);
		glEnableVertexAttribArray(normalAttributeLocation);
		glVertexAttribPointer(positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)0);
		glVertexAttribPointer(uvAttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)sizeof(vec3));
		glVertexAttribPointer(normalAttributeLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)(sizeof(vec3)+sizeof(vec2)));

		std::vector<int> indices;


		for (int j = 0; j < num_particles_height-1; j++) {
			int index;
			if (j > 0) {
				indices.push_back(j * num_particles_width); // make degenerate
			}
			for (int i = 0; i <= num_particles_width-1; i++) {
				index = j * num_particles_width + i;
				indices.push_back(index);
				indices.push_back(index + num_particles_width);
			}
			if (j + 1 < num_particles_height-1) {
				indices.push_back(index + num_particles_width); // make degenerate
			}
		}
		elementSize = indices.size();

		GLuint elementArrayBuffer;
		glGenBuffers(1, &elementArrayBuffer);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementSize * sizeof(int), &(indices[0]), GL_STATIC_DRAW);
		texture = loadClothTexture("clothTexture.jpg");
	}
	std::vector<Vertex> vertexData;

	for(int y=0; y<num_particles_height; y++)
	{
		for(int x = 0; x<num_particles_width; x++)
		{
			vec2 uv(x/(num_particles_width - 1.0f),y/(num_particles_height-1.0f));

			SaveParticleVertexInfo(getParticle(x, y), uv, vertexData);
		}
	}
	glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
	glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vertex), value_ptr(vertexData[0].position), GL_STREAM_DRAW);
	computeMatricesFromInputs();
	glm::mat4 ModelMatrix = glm::mat4(1.0f);
	glm::mat4 ProjectionMatrix = getProjectionMatrix();
	glm::mat4 ViewMatrix = getViewMatrix();
	mat4 mvp = ProjectionMatrix * ViewMatrix * ModelMatrix;
	mat4 modelView = ViewMatrix * ModelMatrix;
	glUniformMatrix4fv(glGetUniformLocation(shader->ProgramID, "mvp"),1,false, value_ptr(mvp));
	mat3 normalMatrix = inverse(transpose(mat3(modelView)));
	glUniformMatrix3fv(glGetUniformLocation(shader->ProgramID, "normalMatrix"),1,false, value_ptr(normalMatrix));

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, texture);
	glUniform1i(glGetUniformLocation(shader->ProgramID, "mainTexture"), 0);

	glBindVertexArray(vertexArrayObject);
	glDrawElements(GL_TRIANGLE_STRIP, elementSize, GL_UNSIGNED_INT, 0);
}
Exemple #14
0
void cloth::updateFaceNormal()
{
	for(int x = 0; x<num_particles_width-1; x++)
	{
		for(int y=0; y<num_particles_height-1; y++)
		{
			vec3 normal = calcTriangleNormal(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1));
			getParticle(x+1,y)->addToNormal(normal);
			getParticle(x,y)->addToNormal(normal);
			getParticle(x,y+1)->addToNormal(normal);

			normal = calcTriangleNormal(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1));
			getParticle(x+1,y+1)->addToNormal(normal);
			getParticle(x+1,y)->addToNormal(normal);
			getParticle(x,y+1)->addToNormal(normal);
		}
	}
}
Exemple #15
0
	bool Group::updateParticles(float deltaTime)
	{
		// Prepares the additionnal data
		prepareAdditionnalData();

		size_t nbAutoBorn = 0;
		size_t nbManualBorn = nbBufferedParticles;

		// Checks the number of born particles
		bool hasAliveEmitters = false;
		activeEmitters.clear();

		for (std::vector<Ref<Emitter> >::const_iterator it = emitters.begin(); it != emitters.end(); ++it)
			if ((*it)->isActive())
			{
				int nb = (*it)->updateTankFromTime(deltaTime);
				if (nb > 0)
				{
					activeEmitters.push_back(WeakEmitterPair(*it,nb));
					nbAutoBorn += nb;
				}

				hasAliveEmitters |= ((*it)->getCurrentTank() != 0); // An emitter with some particles in its tank is still potentially alive
			}

		size_t emitterIndex = 0;
		size_t nbBorn = nbAutoBorn + nbManualBorn;

		// Updates the age of the particles function of the delta time
		for (size_t i = 0; i < particleData.nbParticles; ++i)
			particleData.ages[i] += deltaTime;

		// Computes the energy of the particles (if they are not immortal)
		if (!immortal)
			for (size_t i = 0; i < particleData.nbParticles; ++i)
				particleData.energies[i] = 1.0f - particleData.ages[i] / particleData.lifeTimes[i];

		// Updates the position of particles function of their velocity
		if (!still)
			for (size_t i = 0; i < particleData.nbParticles; ++i)
			{
				particleData.oldPositions[i] = particleData.positions[i];
				particleData.positions[i] += particleData.velocities[i] * deltaTime;
			}

		// Interpolates the parameters
		if (colorInterpolator.obj)
			colorInterpolator.obj->interpolate(particleData.colors,*this,colorInterpolator.dataSet);
		for (size_t i = 0; i < nbEnabledParameters; ++i)
		{
			FloatInterpolatorDef& interpolator = paramInterpolators[enabledParamIndices[i]];
			interpolator.obj->interpolate(particleData.parameters[enabledParamIndices[i]],*this,interpolator.dataSet);
		}

		// Updates the octree if one
		if (octree != NULL)
			octree->update();

		// Modifies the particles with specific active modifiers behavior
		for (std::vector<WeakModifierDef>::const_iterator it = activeModifiers.begin(); it != activeModifiers.end(); ++it)
			it->obj->modify(*this,it->dataSet,deltaTime);

		// Updates the renderer data
		if (renderer.obj)
			renderer.obj->update(*this,renderer.dataSet);

		// Checks dead particles and reinits or swaps
		for (size_t i = 0; i < particleData.nbParticles; ++i)
			if (particleData.energies[i] <= 0.0f)
			{
				// Death action
				if (deathAction && deathAction->isActive())
				{
				    Particle particle = getParticle(i); // fix for gcc
					deathAction->apply(particle);
				}

				bool replaceDeadParticle = false;
				while (!replaceDeadParticle && nbBorn > 0)
				{
					if (initParticle(i,emitterIndex,nbManualBorn))
						replaceDeadParticle = true;
					--nbBorn;
				}

				if (!replaceDeadParticle)
				{
					swapParticles(i,particleData.nbParticles - 1);
					--particleData.nbParticles;
					--i; // As we need to test the swapped particle
				}
			}

		// Emits new particles if some left
		while (nbBorn > 0 && particleData.maxParticles - particleData.nbParticles > 0)
		{
			if (!initParticle(particleData.nbParticles++,emitterIndex,nbManualBorn))
				--particleData.nbParticles;
			--nbBorn;
		}

		// Computes the distance of particles from the camera
		if (distanceComputationEnabled)
		{
			for (size_t i = 0; i < particleData.nbParticles; ++i)
				particleData.sqrDists[i] = getSqrDist(particleData.positions[i],system->getCameraPosition());
		}

		emptyBufferedParticles();

		return hasAliveEmitters || particleData.nbParticles > 0;
	}
	/* This is a important constructor for the entire system of particles and constraints*/
	Cloth(float width, float height, int num_particles_width, int num_particles_height) : num_particles_width(num_particles_width), num_particles_height(num_particles_height)
	{
		particles.resize(num_particles_width*num_particles_height); //I am essentially using this vector as an array with room for num_particles_width*num_particles_height particles

		// creating particles in a grid of particles from (0,0,0) to (width,-height,0)
		for(int x=0; x<num_particles_width; x++)
		{
			for(int y=0; y<num_particles_height; y++)
			{
				Vec3 pos = Vec3(width * (x/(float)num_particles_width),
								-height * (y/(float)num_particles_height),
								0);
				particles[y*num_particles_width+x]= Particle(pos); // insert particle in column x at y'th row
			}
		}

		// Connecting immediate neighbor particles with constraints (distance 1 and sqrt(2) in the grid)
		for(int x=0; x<num_particles_width; x++)
		{
			for(int y=0; y<num_particles_height; y++)
			{
				if (x<num_particles_width-1) makeConstraint(getParticle(x,y),getParticle(x+1,y));
				if (y<num_particles_height-1) makeConstraint(getParticle(x,y),getParticle(x,y+1));
				if (x<num_particles_width-1 && y<num_particles_height-1) makeConstraint(getParticle(x,y),getParticle(x+1,y+1));
				if (x<num_particles_width-1 && y<num_particles_height-1) makeConstraint(getParticle(x+1,y),getParticle(x,y+1));
			}
		}


		// Connecting secondary neighbors with constraints (distance 2 and sqrt(4) in the grid)
		for(int x=0; x<num_particles_width; x++)
		{
			for(int y=0; y<num_particles_height; y++)
			{
				if (x<num_particles_width-2) makeConstraint(getParticle(x,y),getParticle(x+2,y));
				if (y<num_particles_height-2) makeConstraint(getParticle(x,y),getParticle(x,y+2));
				if (x<num_particles_width-2 && y<num_particles_height-2) makeConstraint(getParticle(x,y),getParticle(x+2,y+2));
				if (x<num_particles_width-2 && y<num_particles_height-2) makeConstraint(getParticle(x+2,y),getParticle(x,y+2));			}
		}


		// making the upper left most three and right most three particles unmovable
		for(int i=0;i<3; i++)
		{
			getParticle(0+i ,0)->offsetPos(Vec3(0.5,0.0,0.0)); // moving the particle a bit towards the center, to make it hang more natural - because I like it ;)
			getParticle(0+i ,0)->makeUnmovable(); 

			getParticle(0+i ,0)->offsetPos(Vec3(-0.5,0.0,0.0)); // moving the particle a bit towards the center, to make it hang more natural - because I like it ;)
			getParticle(num_particles_width-1-i ,0)->makeUnmovable();
		}
	}
Exemple #17
0
void Cloth::findUnmovablePoint(	const std::vector<XY>& connected,
								const std::vector<double>& heightvals,
								std::vector<int>& edgePoints)
{
	for (size_t i = 0; i < connected.size(); i++)
	{
		int x = connected[i].x;
		int y = connected[i].y;
		int index = y*num_particles_width + x;
		Particle& ptc = getParticle(x, y);
		if (x > 0)
		{
			const Particle& ptc_x = getParticle(x - 1, y);
			if (!ptc_x.isMovable())
			{
				int index_ref = y*num_particles_width + x - 1;
				if (fabs(heightvals[index] - heightvals[index_ref]) < smoothThreshold && ptc.pos.y - heightvals[index] < heightThreshold)
				{
					Vec3 offsetVec(0, heightvals[index] - ptc.pos.y, 0);
					particles[index].offsetPos(offsetVec);
					ptc.makeUnmovable();
					edgePoints.push_back(static_cast<int>(i));
					continue;
				}
			}
		}

		if (x < num_particles_width - 1)
		{
			const Particle& ptc_x = getParticle(x + 1, y);
			if (!ptc_x.isMovable())
			{
				int index_ref = y*num_particles_width + x + 1;
				if (fabs(heightvals[index] - heightvals[index_ref]) < smoothThreshold && ptc.pos.y - heightvals[index] < heightThreshold)
				{
					Vec3 offsetVec(0, heightvals[index] - ptc.pos.y, 0);
					particles[index].offsetPos(offsetVec);
					ptc.makeUnmovable();
					edgePoints.push_back(static_cast<int>(i));
					continue;
				}
			}
		}

		if (y > 0)
		{
			const Particle& ptc_y = getParticle(x, y - 1);
			if (!ptc_y.isMovable())
			{
				int index_ref = (y - 1)*num_particles_width + x;
				if (fabs(heightvals[index] - heightvals[index_ref]) < smoothThreshold && ptc.pos.y - heightvals[index] < heightThreshold)
				{
					Vec3 offsetVec(0, heightvals[index] - ptc.pos.y, 0);
					particles[index].offsetPos(offsetVec);
					ptc.makeUnmovable();
					edgePoints.push_back(static_cast<int>(i));
					continue;
				}
			}

		}

		if (y < num_particles_height - 1)
		{
			const Particle& ptc_y = getParticle(x, y + 1);
			if (!ptc_y.isMovable())
			{
				int index_ref = (y + 1)*num_particles_width + x;
				if (fabs(heightvals[index] - heightvals[index_ref]) < smoothThreshold && ptc.pos.y - heightvals[index] < heightThreshold)
				{
					Vec3 offsetVec(0, heightvals[index] - ptc.pos.y, 0);
					particles[index].offsetPos(offsetVec);
					ptc.makeUnmovable();
					edgePoints.push_back(static_cast<int>(i));
					continue;
				}
			}
		}
	}
}
Exemple #18
0
void Cloth::movableFilter()
{
	for (int x = 0; x < num_particles_width; x++)
	{
		for (int y = 0; y < num_particles_height; y++)
		{
			Particle& ptc = getParticle(x, y);
			if (ptc.isMovable() && !ptc.isVisited)
			{
				std::queue<int> que;
				std::vector<XY> connected; //store the connected component
				std::vector< std::vector<int> > neibors;
				int sum = 1;
				int index = y*num_particles_width + x;
				// visit the init node
				connected.push_back(XY(x,y));
				particles[index].isVisited = true;
				//enqueue the init node
				que.push(index);
				while (!que.empty())
				{
					Particle& ptc_f = particles[que.front()];
					que.pop();
					int cur_x = ptc_f.pos_x;
					int cur_y = ptc_f.pos_y;
					std::vector<int> neighbor;

					if (cur_x > 0)
					{
						Particle& ptc_left = getParticle(cur_x - 1, cur_y);
						if (ptc_left.isMovable())
						{
							if (!ptc_left.isVisited)
							{
								sum++;
								ptc_left.isVisited = true;
								connected.push_back(XY(cur_x - 1, cur_y));
								que.push(num_particles_width*cur_y + cur_x - 1);
								neighbor.push_back(sum - 1);
								ptc_left.c_pos = sum - 1;
							}
							else
							{
								neighbor.push_back(ptc_left.c_pos);
							}
						}
					}

					if (cur_x < num_particles_width - 1)
					{
						Particle& ptc_right = getParticle(cur_x + 1, cur_y);
						if (ptc_right.isMovable())
						{
							if (!ptc_right.isVisited)
							{
								sum++;
								ptc_right.isVisited = true;
								connected.push_back(XY(cur_x + 1, cur_y));
								que.push(num_particles_width*cur_y + cur_x + 1);
								neighbor.push_back(sum - 1);
								ptc_right.c_pos = sum - 1;
							}
							else
							{
								neighbor.push_back(ptc_right.c_pos);
							}
						}
					}

					if (cur_y > 0)
					{
						Particle& ptc_bottom = getParticle(cur_x, cur_y - 1);
						if (ptc_bottom.isMovable())
						{
							if (!ptc_bottom.isVisited)
							{
								sum++;
								ptc_bottom.isVisited = true;
								connected.push_back(XY(cur_x, cur_y - 1));
								que.push(num_particles_width*(cur_y - 1) + cur_x);
								neighbor.push_back(sum - 1);
								ptc_bottom.c_pos = sum - 1;
							}
							else
							{
								neighbor.push_back(ptc_bottom.c_pos);
							}
						}
					}

					if (cur_y < num_particles_height - 1)
					{
						Particle& ptc_top = getParticle(cur_x, cur_y + 1);
						if (ptc_top.isMovable())
						{
							if (!ptc_top.isVisited)
							{
								sum++;
								ptc_top.isVisited = true;
								connected.push_back(XY(cur_x, cur_y + 1));
								que.push(num_particles_width*(cur_y + 1) + cur_x);
								neighbor.push_back(sum - 1);
								ptc_top.c_pos = sum - 1;
							}
							else
							{
								neighbor.push_back(ptc_top.c_pos);
							}
						}
					}
					neibors.push_back(neighbor);
				}

				//Slope postprocessing
				if (sum > 100)
				{
					std::vector<int> edgePoints;
					findUnmovablePoint(connected, heightvals, edgePoints);
					handle_slop_connected(edgePoints, connected, neibors, heightvals);
				}
			}
		}
	}
}
Exemple #19
0
Cloth::Cloth(	const Vec3& _origin_pos,
				int _num_particles_width,
				int _num_particles_height,
				double _step_x,
				double _step_y,
				double _smoothThreshold,
				double _heightThreshold,
				int rigidness,
				double time_step)
	: constraint_iterations(rigidness)
	, time_step(time_step)
	, smoothThreshold(_smoothThreshold)
	, heightThreshold(_heightThreshold)
	, num_particles_width(_num_particles_width)
	, num_particles_height(_num_particles_height)
	, origin_pos(_origin_pos)
	, step_x(_step_x)
	, step_y(_step_y)
{
	particles.resize(num_particles_width*num_particles_height); //I am essentially using this vector as an array with room for num_particles_width*num_particles_height particles

	double time_step2 = time_step*time_step;

	// creating particles in a grid
	for (int i = 0; i < num_particles_width; i++)
	{
		for (int j = 0; j < num_particles_height; j++)
		{
			Vec3 pos(	origin_pos.x + i * step_x,
						origin_pos.y,
						origin_pos.z + j * step_y);

			particles[j*num_particles_width + i] = Particle(pos, time_step2); // insert particle in column i at j'th row
			particles[j*num_particles_width + i].pos_x = i;
			particles[j*num_particles_width + i].pos_y = j;
		}
	}

	// Connecting immediate neighbor particles with constraints (distance 1 and sqrt(2) in the grid)
	for (int x = 0; x<num_particles_width; x++)
	{
		for (int y = 0; y<num_particles_height; y++)
		{
			if (x < num_particles_width - 1)
			{
				addConstraint(&getParticle(x, y), &getParticle(x + 1, y));
			}

			if (y < num_particles_height - 1)
			{
				addConstraint(&getParticle(x, y), &getParticle(x, y + 1));
			}

			if (x < num_particles_width - 1 && y < num_particles_height - 1)
			{
				addConstraint(&getParticle(x, y), &getParticle(x + 1, y + 1));
				addConstraint(&getParticle(x + 1, y), &getParticle(x, y + 1));
			}
		}
	}

	// Connecting secondary neighbors with constraints (distance 2 and sqrt(4) in the grid)
	for (int x = 0; x < num_particles_width; x++)
	{
		for (int y = 0; y < num_particles_height; y++)
		{
			if (x < num_particles_width - 2)
			{
				addConstraint(&getParticle(x, y), &getParticle(x + 2, y));
			}


			if (y < num_particles_height - 2)
			{
				addConstraint(&getParticle(x, y), &getParticle(x, y + 2));
			}


			if (x < num_particles_width - 2 && y < num_particles_height - 2)
			{
				addConstraint(&getParticle(x, y), &getParticle(x + 2, y + 2));
				addConstraint(&getParticle(x + 2, y), &getParticle(x, y + 2));
			}
		}
	}
}
IRWItem<QPollarF> * BrownianMotion::getParticleItem(int partp){
    IRWItem<QPollarF> * ret = new PollarRwDp();
    QVector<QPollarF> temp= getParticle(partp);
    ret->receiveData(temp.data(),temp.size());
    return ret;
}
	/* drawing the cloth as a smooth shaded (and colored according to column) OpenGL triangular mesh
	Called from the display() method
	The cloth is seen as consisting of triangles for four particles in the grid as follows:

	(x,y)   *--* (x+1,y)
	        | /|
	        |/ |
	(x,y+1) *--* (x+1,y+1)

	*/
	void drawShaded()
	{
		// reset normals (which where written to last frame)
		std::vector<Particle>::iterator particle;
		for(particle = particles.begin(); particle != particles.end(); particle++)
		{
			(*particle).resetNormal();
		}

		//create smooth per particle normals by adding up all the (hard) triangle normals that each particle is part of
		for(int x = 0; x<num_particles_width-1; x++)
		{
			for(int y=0; y<num_particles_height-1; y++)
			{
				Vec3 normal = calcTriangleNormal(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1));
				getParticle(x+1,y)->addToNormal(normal);
				getParticle(x,y)->addToNormal(normal);
				getParticle(x,y+1)->addToNormal(normal);

				normal = calcTriangleNormal(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1));
				getParticle(x+1,y+1)->addToNormal(normal);
				getParticle(x+1,y)->addToNormal(normal);
				getParticle(x,y+1)->addToNormal(normal);
			}
		}

		glBegin(GL_TRIANGLES);
		for(int x = 0; x<num_particles_width-1; x++)
		{
			for(int y=0; y<num_particles_height-1; y++)
			{
				Vec3 color(0,0,0);
				if (x%2) // red and white color is interleaved according to which column number
					color = Vec3(0.6f,0.2f,0.2f);
				else
					color = Vec3(1.0f,1.0f,1.0f);

				drawTriangle(getParticle(x+1,y),getParticle(x,y),getParticle(x,y+1),color);
				drawTriangle(getParticle(x+1,y+1),getParticle(x+1,y),getParticle(x,y+1),color);
			}
		}
		glEnd();
	}