Beispiel #1
0
void Particle::avoidWalls(float d) {
    
    ofPoint desired;
    desired.set(0, 0);
    
    if (pos.x < d) {
        desired.set(maxSpeed, vel.y);
    }
    else if (pos.x > ofGetWidth()-d) {
        desired.set(-maxSpeed, vel.y);
    }
    
    if (pos.y < d) {
        desired.set(vel.x, maxSpeed);
    }
    else if (pos.y > ofGetHeight()-d) {
        desired.set(vel.x, -maxSpeed);
    }
    
    
    
    if (desired.length() != 0.0) {
        desired.normalize();
        desired *= maxSpeed;
        ofPoint steer = desired - vel;
        steer.limit(maxForce);
        //applyForce(steer);
        addForce(steer);
    }
    
}
Beispiel #2
0
void Agent::seek(ofVec3f oTarget)
{

    //From Roxlu's Boids code ( www.roxlu.com )
    // This is how it works.
    // 1. We calculate the change in position which would bring
    // use directly to the target. This is "desired_vel". Though we don't
    // want to jump directly to this target, but slowly move to it.
    ofVec3f desiredVelocity = oTarget - position;

    // 2. Therefore we want to move to this position at the maximum
    // allowed speed. We do this by normalizing the vector and then
    // multiplying it with the maximum allowed speed. This is exactly
    // what ofxVec3f.scale() does.
    desiredVelocity.scale(maxVelocity);

    // 3. Now we have the maximum desired velocity at the maximum speed.
    // Though we need to adjust this speed as we want to go into that direction
    // at the best we are allowed, which is the remaining velocity.
    desiredVelocity -= velocity;

    addForce(desiredVelocity);

    //cout << "Desired vel: " << desired_vel.x << ", " << desired_vel.y << endl;
}
//------------------------------------------------------------
void Particle::addCounterClockwiseForce(Particle *p, float radius, float scale){
	
	// ----------- (1) make a vector of where this Particle p is:
	ofPoint posOfForce;
	posOfForce.set(*p);
	
	// ----------- (2) calculate the difference & length
	
	ofPoint diff	= (*this) - posOfForce;
	float length	= diff.length();
	
	// ----------- (3) check close enough
	
	bool bAmCloseEnough = true;
    if (radius > 0){
        if (length > radius){
            bAmCloseEnough = false;
        }
    }
	
	// ----------- (4) if so, update force
    
	if (bAmCloseEnough == true){
		float pct = 1 - (length / radius);  // stronger on the inside
		diff.normalize();
        addForce(ofPoint(diff.y * scale * pct,
                         diff.x * scale * pct * -1));
        p->addForce(ofPoint(diff.y * scale * pct * -1,
                           diff.x * scale * pct));
    }
}
	void ActorDynamic::update(float f_timeStepInterval){		
		if (bUpdated){
			bActive = true;
			Actor::update(f_timeStepInterval);
		}
		if (bActive){
			vShapes[0]->setColour(glm::vec4(0,1,0,0.5f));
			vShapes[1]->setColour(glm::vec4(0,1,0,0.5f));
			float g = 0.0f;
			if (parentScene != nullptr){
				g = parentScene->getGravity();
				if (g != 0.0f){
					addForce(glm::vec3(0,g * fMass * f_timeStepInterval,0));
					bActive = true;
				}
			}
			if (abs(v3Velocity.x) < 0.1f && abs(v3Velocity.y) == 0.0f && abs(v3Velocity.z) < 0.1f ){
				v3Velocity = glm::vec3(0.0f);
				bActive = false;
			} else {
				glm::vec3 OldPos = v3Translate;
				v3Velocity *= glm::vec3(1.0f);
				addTranslate(v3Velocity * f_timeStepInterval);
				((Line*)vShapes[1])->setDirection(OldPos - v3Translate);
				((Line*)vShapes[1])->setDistance(glm::distance(OldPos,v3Translate));
			}
		}else{
			vShapes[0]->setColour(glm::vec4(1,0,0,0.5f));
			vShapes[1]->setColour(glm::vec4(1,0,0,0.5f));
		}
	}
void Particle::seek( ofPoint dest ) {
    
    float maxSpeed = 10.0;
    float maxForce = 0.4;
    
    float slowDownRadius = 200.0;
    
    ofPoint desired = dest - pos;
    
    if( desired.length() < slowDownRadius ){
        
        float newMag = ofMap( desired.length(), 0, slowDownRadius, 0, maxSpeed);
        
        desired.normalize();
        desired *= newMag;
    }else{
        desired.normalize();
        desired *= maxSpeed;
    }
    
    ofPoint steer = desired - vel;
    steer.limit( maxForce );
    
    addForce( steer );
    
}
Beispiel #6
0
void Particle::addAttraction(ofPoint _pos, float _rad, float _scale){
    ofPoint diff = _pos - pos;
    if( diff.length() < _rad ){
        diff *= 1.0-diff.length()/_rad;
        addForce(diff*_scale);
    }
}
void Particle::addRepulsionForce( const ofVec2f &fromPos ){
    ofVec2f diff = pos - fromPos;
    
    float strength = 1- (diff.length() / 200.0);
    
    addForce( diff.normalized() * (strength) );
}
Beispiel #8
0
/**
 * Arrive makes the boid slow down when it moves towards its targets. The closer
 * it gets the slower it will move. The boid only slows down when it is withing a
 * certain distance of the target.
 */
void Boid::arrive(ofxVec3f oTarget) {
	ofxVec3f desired_vel = oTarget - pos;
	float dist = desired_vel.length();
	desired_vel.normalize();

	//ofSetColor(0xFF0000);
	//ofCircle(oTarget.x, oTarget.y, 4);

	// When we are within the arrive distance, we switch to slow-down mode.
	if (dist <= arrive_dist) {
		desired_vel *= ((max_vel * dist / arrive_dist));
		ofSetColor(0x00);
	}
	// else we continue our journey they same we did when we were seeking
	else {
		desired_vel *= max_vel;
	}
	// We add a little margin here;
	// w/o the boid will oversh0ot its target.
	if (dist > 10) {
		desired_vel -= vel;
		addForce(desired_vel);
	}
	// When were are within the margin, stop moving.
	else{
		force = 0;
		vel = 0;
	}
}
Beispiel #9
0
void LinearSpring::addFDK(const OdeState& state, Vector* F, Matrix* D, Matrix* K)
{
	Matrix33d De, Ke;

	// Assembly stage in F. Note that the force calculation does not rely on any matrices.
	addForce(state, F);

	// The spring has 2 nodes with positions {x1, x2}, velocities {v1, v2} and force {F1, F2=-F1}
	// Also note from addForce that the positions and velocities play a symmetric role in the force calculation
	// i.e. dFi/dx1 = -dFi/dx2 and dFi/dv1 = -dFi/dv2
	// The stiffness matrix is K = -dF/dx = (-dF1/dx1 -dF1/dx2) = (-dF1/dx1  dF1/dx1)
	//                                      (-dF2/dx1 -dF2/dx2)   ( dF1/dx1 -dF1/dx1)
	// The damping matrix is D = -dF/dv = (-dF1/dv1 -dF1/dv2) = (-dF1/dv1  dF1/dv1)
	//                                    (-dF2/dv1 -dF2/dv2)   ( dF1/dv1 -dF1/dv1)

	// Let's compute De = -dF1/dv1 and Ke = -dF1/dx1
	if (!computeDampingAndStiffness(state, &De, &Ke))
	{
		return;
	}

	// Assembly stage in K
	K->block<3, 3>(3 * m_nodeIds[0], 3 * m_nodeIds[0]) += Ke; // -dF1/dx1 = Ke
	K->block<3, 3>(3 * m_nodeIds[0], 3 * m_nodeIds[1]) -= Ke; // -dF1/dx2 =-Ke
	K->block<3, 3>(3 * m_nodeIds[1], 3 * m_nodeIds[0]) -= Ke; // -dF2/dx1 =-Ke
	K->block<3, 3>(3 * m_nodeIds[1], 3 * m_nodeIds[1]) += Ke; // -dF2/dx2 = Ke

	// Assembly stage in D
	D->block<3, 3>(3 * m_nodeIds[0], 3 * m_nodeIds[0]) += De; // -dF1/dv1 = De
	D->block<3, 3>(3 * m_nodeIds[0], 3 * m_nodeIds[1]) -= De; // -dF1/dv2 =-De
	D->block<3, 3>(3 * m_nodeIds[1], 3 * m_nodeIds[0]) -= De; // -dF2/dv1 =-De
	D->block<3, 3>(3 * m_nodeIds[1], 3 * m_nodeIds[1]) += De; // -dF2/dv2 = De
}
void Particle::addRepulsionForce(ofPoint _pos, float _rad, float _scale){
    
    ofPoint diff = _pos - pos;
    if( diff.length() < _rad ){
        diff *= 1.0-diff.length()/_rad;// PRO way
        addForce(-diff*_scale);
    }
}
Beispiel #11
0
ofxBox& ofxBox::setOrientation(string _orientation){
	if (_orientation != orientation) {
		orientation = _orientation;
		if (body != NULL){
			vel = getVelocity();
			addForce(ofVec2f(vel.x*-1,0), 15);
		}
	}
	return * this;
};
Beispiel #12
0
static void updateForces(int firstStar, int secondStar, struct star* star_array)
{
  if (firstStar > 0){
    if (secondStar > 1){
    addForce(&star_array[firstStar],&star_array[secondStar]);
    updateForces(firstStar, secondStar - 1, star_array);
    }else{
      updateForces(firstStar - 1, firstStar - 2, star_array);
    }
  }
}
Beispiel #13
0
void Particle::applyFlockingForce(ofPoint * _offset, float _neighbordhood, float _independece, float _scale){
    addForce( ofVec3f(ofSignedNoise(pos.x / _neighbordhood + _offset->x + localOffset.x * _independece,
                                    pos.y / _neighbordhood,
                                    pos.z / _neighbordhood),
                      ofSignedNoise(pos.x / _neighbordhood,
                                    pos.y / _neighbordhood + _offset->y  + localOffset.y * _independece,
                                    pos.z / _neighbordhood),
                      ofSignedNoise(
                                    pos.x / _neighbordhood,
                                    pos.y / _neighbordhood,
                                    pos.z / _neighbordhood + _offset->z + localOffset.z * _independece)) * _scale );
}
Beispiel #14
0
void getForce(int currentPtc) {
	getInternalForce(currentPtc);
	//getCollisionForce(currentPtc);
	M3DVector3f gravity = {0.0f, -ClothLnk[currentPtc].Mass, 0.0f};
	m3dScaleVector3(gravity, 0.2f);
	addForce(currentPtc, gravity);

	m3dScaleVector3(ClothLnk[currentPtc].force, DampCoefficient);

	//if (currentPtc==55)
	//	printf("[%d].force		{%.1f, %.1f, %.1f} \n", currentPtc, ClothLnk[currentPtc].force[0], ClothLnk[currentPtc].force[1], ClothLnk[currentPtc].force[2]);
}
void ComponentSteering::onMessage(const Message& message)
{
	switch (message.type)
	{
	case Message::NEW_TARGET:
		changeTarget(message.target);
		break;
	case Message::NEW_FORCE:
		addForce(message.target);
		break;
	}
}
Beispiel #16
0
//////////////////////////////////////////////////////////////////////
// step simulation once
//////////////////////////////////////////////////////////////////////
void FLUID_3D::step()
{
	// addSmokeTestCase(_density, _res);
	// addSmokeTestCase(_heat, _res);

	wipeBoundaries();

	// run the solvers
	addVorticity();
	addBuoyancy(_heat, _density);
	addForce();
	project();
	diffuseHeat();

	// advect everything
	advectMacCormack();

	// if(_wTurbulence) {
	// 	_wTurbulence->stepTurbulenceFull(_dt/_dx,
	//			_xVelocity, _yVelocity, _zVelocity, _obstacles);
		// _wTurbulence->stepTurbulenceReadable(_dt/_dx,
		//  _xVelocity, _yVelocity, _zVelocity, _obstacles);
	// }
/*
 // no file output
  float *src = _density;
	string prefix = string("./original.preview/density_fullxy_");
	writeImageSliceXY(src,_res, _res[2]/2, prefix, _totalSteps);
*/
	// artificial damping -- this is necessary because we use a
  // collated grid, and at very coarse grid resolutions, banding
  // artifacts can occur
	artificialDamping(_xVelocity);
	artificialDamping(_yVelocity);
	artificialDamping(_zVelocity);
/*
// no file output
  string pbrtPrefix = string("./pbrt/density_small_");
  IMAGE::dumpPBRT(_totalSteps, pbrtPrefix, _density, _res[0],_res[1],_res[2]);
  */
	_totalTime += _dt;
	_totalSteps++;	

	// todo xxx dg: only clear obstacles, not boundaries
	// memset(_obstacles, 0, sizeof(unsigned char)*_xRes*_yRes*_zRes);

	// wipe forces
	// for external forces we can't do it at the beginning of this function but at the end
	for (int i = 0; i < _totalCells; i++)
	{
		_xForce[i] = _yForce[i] = _zForce[i] = 0.0f;
	}
}
Beispiel #17
0
void Body::addGlobalForce( Ogre::Vector3& force, Ogre::Vector3& pos )
{
	Ogre::Vector3 bodypos;
	Ogre::Quaternion bodyorient;
	getPositionOrientation( bodyorient, bodypos );

	Ogre::Vector3 topoint = pos - bodypos;
	Ogre::Vector3 torque = topoint.crossProduct( force );

	addForce( force );
	addTorque( torque );
}
Beispiel #18
0
//----------------------------------------------------------------------------
void RigidBody::setEnabled(const bool enabled)
{
	SimComponent().setEnabled(enabled);
	if(mPhysShape)
		mPhysShape->setEnable(enabled);

	// When enabling add a tiniest force, to
	// prevent body from flying motionless in the air.
	if(enabled)
	{
		addForce(VectorF(0.0001f, 0.0001f, 0.0001f));
	}
}
Beispiel #19
0
void init() {
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
    } else {
        if (GLEW_VERSION_3_3) {
            std::cout << "Driver supports OpenGL 3.3\nDetails:" << std::endl;
            std::cout << "Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
            std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
            std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
            std::cout << "Version: " << glGetString(GL_VERSION) << std::endl;
            std::cout << "GLSL: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
        }
    }

    // FIXME: GLEW Init causes "Invalid enumerant" OpenGL error!
    //        Supressing it now as the pipeline seems working.
    GLenum error = glGetError();
    if (GL_NO_ERROR != error) {
        // std::cout << "Error: " << gluErrorString(error) << std::endl;
    }

    fullscreenQuad = new Quad();
    simpleShader = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/simple.frag");
    gaussShader = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/gauss.frag");
    gaussShaderH = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/gaussH.frag");
    gaussShaderV = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/gaussV.frag");
    WE_addForce = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/addForce.frag");
    WE_iteration_1 = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/iteration.frag");
    WE_iteration_2 = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/iteration2.frag");
    WE_iteration_3 = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/iteration3.frag");
    WE_visualize = new Shader("../src/lab3/shaders/passthrough.vert", "../src/lab3/shaders/visualize.frag");

    texture = new Texture2D();
    texture->loadFromFile(std::string("../img/lena.jpg"));

    if (1 == example) {
        glutReshapeWindow(texture->getWidth(), texture->getHeight());
    }

    computeBuffer[0] = new Framebuffer(texture->getWidth(), texture->getHeight(), 1);
    computeBuffer[1] = new Framebuffer(texture->getWidth(), texture->getHeight(), 1);

    WE_computeBuffer[0] = new Framebuffer(600, 600, 1);
    WE_computeBuffer[1] = new Framebuffer(600, 600, 1);

    resetWave();
    addForce(300, 300);
}
Beispiel #20
0
//Collide with an outside object (generally the player's location)
void Spring :: collide(const vec2 & heroLoc, float collideDist ){
 
    if(dist(heroLoc, global) < collideDist){
        vec2 d = heroLoc - global;
        float angle = atan2(d.y, d.x);
        vec2 target = vec2(heroLoc.x - cos(angle) * collideDist, heroLoc.y - sin(angle) * collideDist);
        vec2 force = (target - global) * stiffness * 3.0f;
        addForce( force );
        
        global = target;
        
        springContact = true;      //allows parent to see if spring has been contacted
    } else {
        springContact = false;
    }
}
Beispiel #21
0
void GravityForceGenerator::update(floatType timeDelta_ms) {
    //iterate over the list of collision components
    for (auto collisionComponent : this->getRegisteredComponents()) {
	auto physicsComponent = collisionComponent->getPhysicsRelation();
	if (physicsComponent == nullptr) {
	    continue;
	}

	//don't calculate if it doesn't have a finite mass
	const floatType inverseMass = physicsComponent->getInverseMass();
	if (inverseMass <= 0) {
	    continue;
	}

	physicsComponent->addForce(this->gravity * inverseMass);
    }
}
void Particle::seek( const ofVec2f &dest ) {
    ofVec2f desired = dest - pos;
    
    if( desired.length() < slowDownRadius ){
        float newMag = ofMap( desired.length(), 0, slowDownRadius, 0, maxSpeed);
        
        desired.normalize();
        desired *= newMag;
    }else{
        desired.normalize();
        desired *= maxSpeed;
    }

    ofVec2f steer = desired - vel;
    steer.limit( maxForce );
    
    addForce( steer );
}
Beispiel #23
0
void Particle::addRepulsion(ofPoint _pos, float _rad, float _scale){
    
//    //  if is inside the radius
//    if( pos.distance(_pos) < _rad ){
//        // - calculate de difference
//        ofPoint diff = pos - _pos;
//    
//        // - add like a opposite force
//        addForce(-diff);
//    }
    
    ofPoint diff = _pos - pos;
    if( diff.length() < _rad ){
//        diff *= ofMap(diff.length(),0,_rad,1.0,0.0);  // Easy way
        diff *= 1.0-diff.length()/_rad;// PRO way
        addForce(-diff*_scale);
    }
}
Beispiel #24
0
void PlinkParticles::init() {

	sprite.loadImage("feather_sprite.png");
	sprite.resize(30,30);
	emitSize = 1;

	addForce(ofVec3f(1.02,1.005,1));

	emitterPosition = ofVec3f(0,0,0);
	for(int i = 0; i < emitSize; i ++) {

		PlinkSimple particle; 
		particle.init(sprite,forces, emitterPosition, target);
		particles.push_back(particle);

	}
	emit();
}
Beispiel #25
0
void boid::arrive(ofxVec3f oTarget) {
	ofxVec3f desired_vel = oTarget - pos;
	float dist = desired_vel.length();
	desired_vel.normalize();
	
	if (dist <= arrive_dist) {
		desired_vel *= ((max_vel * dist / arrive_dist));
		ofSetColor(0x00);
	}
	else {
		desired_vel *= max_vel;
	}
	
	if (dist > 10) {
		desired_vel -= vel;
		addForce(desired_vel);
	}
	else {
		force = 0;
		vel = 0;
	}
}
Beispiel #26
0
	/*! Convenience function to apply force and torque from one force at contact point. Not sure if this is the right place for it. */
	void applyForceAtContactPoint(const Vector3r& force, const Vector3r& contactPoint, const Body::id_t id1, const Vector3r& pos1, const Body::id_t id2, const Vector3r& pos2){
		addForce(id1, force,scene); addTorque(id1, (contactPoint-pos1).cross(force),scene);
		addForce(id2,-force,scene); addTorque(id2,-(contactPoint-pos2).cross(force),scene);
	}
void ofxParticle::addForce(ofVec2f f)
{
    addForce(f.x,f.y);
}
Beispiel #28
0
void Boid::applyForce( ofVec2f force ){
    acc += force;
    addForce(force, 1.0);
}
Beispiel #29
0
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
bool PartEmitter::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
	//////////////////////////////////////////////////////////////////////////
	// SetBorder
	//////////////////////////////////////////////////////////////////////////
	if (strcmp(name, "SetBorder") == 0) {
		stack->correctParams(4);
		int borderX      = stack->pop()->getInt();
		int borderY      = stack->pop()->getInt();
		int borderWidth  = stack->pop()->getInt();
		int borderHeight = stack->pop()->getInt();

		stack->pushBool(DID_SUCCEED(setBorder(borderX, borderY, borderWidth, borderHeight)));

		return STATUS_OK;
	}
	//////////////////////////////////////////////////////////////////////////
	// SetBorderThickness
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "SetBorderThickness") == 0) {
		stack->correctParams(4);
		int left   = stack->pop()->getInt();
		int right  = stack->pop()->getInt();
		int top    = stack->pop()->getInt();
		int bottom = stack->pop()->getInt();

		stack->pushBool(DID_SUCCEED(setBorderThickness(left, right, top, bottom)));

		return STATUS_OK;
	}
	//////////////////////////////////////////////////////////////////////////
	// AddSprite
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "AddSprite") == 0) {
		stack->correctParams(1);
		const char *spriteFile = stack->pop()->getString();
		stack->pushBool(DID_SUCCEED(addSprite(spriteFile)));

		return STATUS_OK;
	}
	//////////////////////////////////////////////////////////////////////////
	// RemoveSprite
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "RemoveSprite") == 0) {
		stack->correctParams(1);
		const char *spriteFile = stack->pop()->getString();
		stack->pushBool(DID_SUCCEED(removeSprite(spriteFile)));

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Start
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "Start") == 0) {
		stack->correctParams(1);
		_overheadTime = stack->pop()->getInt();
		stack->pushBool(DID_SUCCEED(start()));

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Stop
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "Stop") == 0) {
		stack->correctParams(0);

		for (uint32 i = 0; i < _particles.size(); i++) {
			delete _particles[i];
		}
		_particles.clear();

		_running = false;
		stack->pushBool(true);

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Pause
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "Pause") == 0) {
		stack->correctParams(0);
		_running = false;
		stack->pushBool(true);

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Resume
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "Resume") == 0) {
		stack->correctParams(0);
		_running = true;
		stack->pushBool(true);

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// AddGlobalForce
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "AddGlobalForce") == 0) {
		stack->correctParams(3);
		const char *forceName = stack->pop()->getString();
		float angle = stack->pop()->getFloat();
		float strength = stack->pop()->getFloat();

		stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, 0, 0, angle, strength)));

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// AddPointForce
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "AddPointForce") == 0) {
		stack->correctParams(5);
		const char *forceName = stack->pop()->getString();
		int posX = stack->pop()->getInt();
		int posY = stack->pop()->getInt();
		float angle = stack->pop()->getFloat();
		float strength = stack->pop()->getFloat();

		stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, posX, posY, angle, strength)));

		return STATUS_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// RemoveForce
	//////////////////////////////////////////////////////////////////////////
	else if (strcmp(name, "RemoveForce") == 0) {
		stack->correctParams(1);
		const char *forceName = stack->pop()->getString();

		stack->pushBool(DID_SUCCEED(removeForce(forceName)));

		return STATUS_OK;
	} else {
		return BaseObject::scCallMethod(script, stack, thisStack, name);
	}
}
/* Law2_ScGeom_ViscElPhys_Basic */
void Law2_ScGeom_ViscElPhys_Basic::go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I){

	const ScGeom& geom=*static_cast<ScGeom*>(_geom.get());
	ViscElPhys& phys=*static_cast<ViscElPhys*>(_phys.get());

	const int id1 = I->getId1();
	const int id2 = I->getId2();
	
	if (geom.penetrationDepth<0) {
		if (phys.liqBridgeCreated and -geom.penetrationDepth<phys.sCrit and phys.Capillar) {
			phys.normalForce = -calculateCapillarForce(geom, phys)*geom.normal;
		  if (I->isActive) {
				addForce (id1,-phys.normalForce,scene);
				addForce (id2, phys.normalForce,scene);
			};
			return;
		} else {
			scene->interactions->requestErase(I);
			return;
		};
	};

	const BodyContainer& bodies = *scene->bodies;

	const State& de1 = *static_cast<State*>(bodies[id1]->state.get());
	const State& de2 = *static_cast<State*>(bodies[id2]->state.get());

  /*
   * This part for implementation of the capillar model.
   * All main equations are in calculateCapillarForce function. 
   * There is only the determination of critical distance between spheres, 
   * after that the liquid bridge will be broken.
   */ 
   
	if (not(phys.liqBridgeCreated) and phys.Capillar) {
		phys.liqBridgeCreated = true;
		Sphere* s1=dynamic_cast<Sphere*>(bodies[id1]->shape.get());
		Sphere* s2=dynamic_cast<Sphere*>(bodies[id2]->shape.get());
		if (s1 and s2) {
			phys.R = 2 * s1->radius * s2->radius / (s1->radius + s2->radius);
		} else if (s1 and not(s2)) {
			phys.R = s1->radius;
		} else {
			phys.R = s2->radius;
		}
		
		const Real Vstar = phys.Vb/(phys.R*phys.R*phys.R);
		const Real Sstar = (1+0.5*phys.theta)*(pow(Vstar,1/3.0) + 0.1*pow(Vstar,2.0/3.0));   // [Willett2000], equation (15), use the full-length e.g 2*Sc
		
		phys.sCrit = Sstar*phys.R;
	}

	Vector3r& shearForce = phys.shearForce;
	if (I->isFresh(scene)) shearForce=Vector3r(0,0,0);
	const Real& dt = scene->dt;
	shearForce = geom.rotate(shearForce);
	

	// Handle periodicity.
	const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(I->cellDist): Vector3r::Zero(); 
	const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(I->cellDist): Vector3r::Zero(); 

	const Vector3r c1x = (geom.contactPoint - de1.pos);
	const Vector3r c2x = (geom.contactPoint - de2.pos - shift2);
	
	const Vector3r relativeVelocity = (de1.vel+de1.angVel.cross(c1x)) - (de2.vel+de2.angVel.cross(c2x)) + shiftVel;
	const Real normalVelocity	= geom.normal.dot(relativeVelocity);
	const Vector3r shearVelocity	= relativeVelocity-normalVelocity*geom.normal;
	
	// As Chiara Modenese suggest, we store the elastic part 
	// and then add the viscous part if we pass the Mohr-Coulomb criterion.
	// See http://www.mail-archive.com/[email protected]/msg01391.html
	shearForce += phys.ks*dt*shearVelocity; // the elastic shear force have a history, but
	Vector3r shearForceVisc = Vector3r::Zero(); // the viscous shear damping haven't a history because it is a function of the instant velocity 


	// Prevent appearing of attraction forces due to a viscous component
	// [Radjai2011], page 3, equation [1.7]
	// [Schwager2007]
	const Real normForceReal = phys.kn * geom.penetrationDepth + phys.cn * normalVelocity;
	if (normForceReal < 0) {
		phys.normalForce = Vector3r::Zero();
	} else {
		phys.normalForce = normForceReal * geom.normal;
	}
	
	Vector3r momentResistance = Vector3r::Zero();
	if (phys.mR>0.0) {
		const Vector3r relAngVel  = de1.angVel - de2.angVel;
		relAngVel.normalized();
		
		if (phys.mRtype == 1) { 
			momentResistance = -phys.mR*phys.normalForce.norm()*relAngVel;																														// [Zhou1999536], equation (3)
		} else if (phys.mRtype == 2) { 
			momentResistance = -phys.mR*(c1x.cross(de1.angVel) - c2x.cross(de2.angVel)).norm()*phys.normalForce.norm()*relAngVel;			// [Zhou1999536], equation (4)
		}
	}
	
	const Real maxFs = phys.normalForce.squaredNorm() * std::pow(phys.tangensOfFrictionAngle,2);
	if( shearForce.squaredNorm() > maxFs )
	{
		// Then Mohr-Coulomb is violated (so, we slip), 
		// we have the max value of the shear force, so 
		// we consider only friction damping.
		const Real ratio = sqrt(maxFs) / shearForce.norm();
		shearForce *= ratio;
	} 
	else 
	{
		// Then no slip occurs we consider friction damping + viscous damping.
		shearForceVisc = phys.cs*shearVelocity; 
	}
	
	if (I->isActive) {
		const Vector3r f = phys.normalForce + shearForce + shearForceVisc;
		addForce (id1,-f,scene);
		addForce (id2, f,scene);
		addTorque(id1,-c1x.cross(f)+momentResistance,scene);
		addTorque(id2, c2x.cross(f)-momentResistance,scene);
  }
}