Package jinngine.physics

Source Code of jinngine.physics.ContactTrigger$Callback

/**
* Copyright (c) 2008-2010  Morten Silcowitz.
*
* This file is part of the Jinngine physics library
*
* Jinngine is published under the GPL license, available
* at http://www.gnu.org/copyleft/gpl.html.
*/
package jinngine.physics;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import jinngine.physics.constraint.Constraint;
import jinngine.physics.constraint.contact.ContactConstraint;
import jinngine.physics.constraint.contact.ContactConstraintManager;
import jinngine.physics.solver.Solver.NCPConstraint;
import jinngine.util.Pair;


/**
* The contact trigger monitors a specific body for contact interactions. When the total contact
* force of some contact interaction exceeds the user defined value, an event is triggered. Likewise, when the total
* force drops below the threshold, or the contact vanishes all together, another event is triggered.
*/
public class ContactTrigger implements Trigger {

  private final Body body;
  private final double impulsethreshold;
  private final Callback callback;

  // helper variables
  private double totalforce = 0;   
  private int numberOfNcpConstraints = 0;

  // handler to install in the contact constraint manager
  private ContactConstraintManager.Handler contactConstraintHandler;

  // constraints that have not triggered an event
  private final List<ContactConstraint> monitoredconstraints = new ArrayList<ContactConstraint>();
 
  // constraints that have triggered an event
  private final List<ContactConstraint> triggeredconstraints = new ArrayList<ContactConstraint>();
 
  // interface for callback from this trigger type
  public interface Callback {
    public void contactAboveThreshold( Body interactingBody, ContactConstraint constraint );
    public void contactBelowThreshold( Body interactingBody, ContactConstraint constraint );   
  }
 
  /**
   * Create new contact trigger
   * @param body Body to monitor
   * @param impulsethreshold the total normal impulse exerted by the contact in last time-step
   */
  public ContactTrigger( Body body, double impulsethreshold, ContactTrigger.Callback callback ) {
    this.body = body;
    this.impulsethreshold = impulsethreshold;
    this.callback = callback;
  }
 
  @Override
  public void update(Scene s) {
//    timestep = s.getTimestep();

    // see if the monitored constraints can trigger an event
    ListIterator<ContactConstraint> monitored = monitoredconstraints.listIterator();
    while ( monitored.hasNext() ) {
      ContactConstraint constraint = monitored.next();
      totalforce = 0;
      numberOfNcpConstraints = 0;

      // sum up the applied contact force
      Iterator<NCPConstraint> ncps = constraint.getNcpConstraints();
      while(ncps.hasNext()) {
        NCPConstraint ncp = ncps.next();
        totalforce += ncp.lambda;     
        numberOfNcpConstraints += 1;
      }

      // check condition
      if (totalforce > impulsethreshold) { 
       
        // move constraint to triggered list
        monitored.remove();
        triggeredconstraints.add(constraint);
       
        // perform trigger event callback
        Pair<Body> bodies =  constraint.getBodies();
        Body interacting = bodies.getFirst()==body? bodies.getSecond(): bodies.getFirst();
        callback.contactAboveThreshold(interacting, constraint);

      } // if force > forcethreshold
    } // for monitored constraints 
   
    // see if triggered constraints should be moved back to monitored
    ListIterator<ContactConstraint> triggered = triggeredconstraints.listIterator();
    while ( triggered.hasNext()) {

      ContactConstraint constraint = triggered.next();
      totalforce = 0;
      numberOfNcpConstraints = 0;

      // sum up the applied contact force
      Iterator<NCPConstraint> ncps = constraint.getNcpConstraints();
      while(ncps.hasNext()) {
        NCPConstraint ncp = ncps.next();
        totalforce += ncp.lambda;       
        numberOfNcpConstraints += 1;
      }

      // check condition
      if (totalforce < impulsethreshold) { 
       
        // move constraint to monitored list
        triggered.remove();
        monitoredconstraints.add(constraint);
       
        // perform trigger event callback
        Pair<Body> bodies =  constraint.getBodies();
        Body interacting = bodies.getFirst()==body? bodies.getSecond(): bodies.getFirst();
        callback.contactBelowThreshold(interacting, constraint);

      } // if force > forcethreshold
    } // for monitored constraints 
  }
 
  @Override
  public void cleanup(Scene scene) {
    // remove the handler that we previously installed in the contact constraint manager
    ContactConstraintManager manager = scene.getContactConstraintManager();   
    manager.removeHandler(contactConstraintHandler);
  }

  @Override
  public void setup(Scene scene) {
    // first of, find contact constraints that involves the body we want to monitor
    Iterator<Constraint> iter = scene.getConstraints(body);
    while (iter.hasNext()) {
      Constraint constraint = iter.next();
      // if the constraint is a contact constraint, add it to the monitoring list
      if (constraint instanceof ContactConstraint ) {
        monitoredconstraints.add((ContactConstraint)constraint);
      }
    }// while constraints
   
    // setup a handler that tells us when contact constraints are created and deleted
    contactConstraintHandler = new ContactConstraintManager.Handler() {
      @Override
      public void contactConstraintCreated(Pair<Body> bodies, ContactConstraint contact) {
//        System.out.println("created");
        // if the constraint involves the body that we are monitoring, add it to our
        // internal list of contact constraints
        if (bodies.contains(body)) {
          monitoredconstraints.add(contact);
        }
      }
      @Override
      public void contactConstraintRemoved(Pair<Body> bodies, ContactConstraint contact ) {
//        System.out.println("deleted");

        if (bodies.contains(body)) {
          // if we had this constraint on our list of triggerd constraints, signal an event
          if (triggeredconstraints.contains(contact)) {

            // perform the call back
            Body interacting = bodies.getFirst()==body? bodies.getSecond(): bodies.getFirst();
            callback.contactBelowThreshold(interacting, contact);

            // remove from internal list
            triggeredconstraints.remove(contact);
          }


          // if the constraint is just on the monitor list, simply remove it
          if (monitoredconstraints.contains(contact)) {
            // remove from monitor list
            monitoredconstraints.remove(contact);
          }
         
        } // if contains body
      }
    };
   
    // install the handler
    ContactConstraintManager manager = scene.getContactConstraintManager();   
    manager.addHandler(contactConstraintHandler);
           
  }

}
TOP

Related Classes of jinngine.physics.ContactTrigger$Callback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.