Package jinngine.physics.constraint.contact

Source Code of jinngine.physics.constraint.contact.DefaultContactConstraintManager

/**
* 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.constraint.contact;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import jinngine.physics.*;
import jinngine.collision.BroadphaseCollisionDetection;
import jinngine.geometry.Geometry;
import jinngine.geometry.SupportMap3;
import jinngine.geometry.contact.ContactGenerator;
import jinngine.geometry.contact.ContactGeneratorClassifier;
import jinngine.geometry.contact.SphereContactGenerator;
import jinngine.geometry.contact.SupportMapContactGenerator;
import jinngine.geometry.contact.SupportMapSphereContactGenerator;
import jinngine.physics.constraint.Constraint;
import jinngine.physics.constraint.contact.ContactConstraint;
import jinngine.physics.constraint.contact.ContactConstraintCreator;
import jinngine.physics.constraint.contact.FrictionalContactConstraint;
import jinngine.util.ComponentGraph;
import jinngine.util.Pair;

/**
* Maintains constraints in a graph structure
*/
public class DefaultContactConstraintManager implements ContactConstraintManager {
  private final List<Handler> handlers = new ArrayList<Handler>();
 
  // the external broadphase collision detection
  private final BroadphaseCollisionDetection broadphase;
 
  // the broad phase collision handler installed by this contact constraint manager
  private final BroadphaseCollisionDetection.Handler handler;
 
  // list of geometry classifiers
  private final List<ContactGeneratorClassifier> geometryClassifiers = new ArrayList<ContactGeneratorClassifier>();

  // list of contact constraint creators
  private final List<ContactConstraintCreator> contactConstraintCreators = new ArrayList<ContactConstraintCreator>();

  // set of maintained contact constraints and generators
  private final Map<Pair<Body>,ContactConstraint> contactConstraints = new LinkedHashMap<Pair<Body>,ContactConstraint>();
  private final Map<Pair<Geometry>,ContactGenerator> contactGenerators = new LinkedHashMap<Pair<Geometry>,ContactGenerator>();
   
  // the constraint graph to be updated by this contact constraint manager
  private final ComponentGraph<Body,Constraint, DefaultScene.ConstraintGroup> constraintGraph;

  // the default contact constraint creator
  private final ContactConstraintCreator defaultcreator = new ContactConstraintCreator() {
    public final ContactConstraint createContactConstraint(Body b1, Body b2, ContactGenerator g) {
      return new FrictionalContactConstraint(b1,b2,g);
//      return new SimplifiedContactConstraint(b1,b2,g);
//      return new StabilisationContactConstraint(b1,b2,g);
//      return new BaumgardeContactConstraint(b1,b2,g);
//     
    }
    public void removeContactConstraint(ContactConstraint constraint) {}
  };

 
  public DefaultContactConstraintManager( BroadphaseCollisionDetection broadphase,
      ComponentGraph<Body, Constraint, DefaultScene.ConstraintGroup> constraintgraph ) {

    // store the broadphase and the constraint graph references
    this.broadphase = broadphase;
    this.constraintGraph = constraintgraph;
       
    // Setup a broad-phase handler. The handler ensures that ContactConstraints are properly inserted and
    // removed from the contact graph, whenever the broad-phase collision detection detects overlaps and separations
    handler = new BroadphaseCollisionDetection.Handler() {
        public final void overlap(Pair<Geometry> inputpair) {
//          System.out.println("overlap");
          //retrieve the bodies associated with overlapping geometries
          Body b1 = inputpair.getFirst().getBody();
          Body b2 = inputpair.getSecond().getBody();
         
          //ignore overlaps stemming from the same body       
          if ( b1 == b2) return;
          //ignore overlaps for non-body geometries
          if ( b1 == null || b2 == null) return;
          //ignore overlaps of fixed bodies
          if ( b1.isFixed() && b2.isFixed() ) return;
         
          //always order bodies and geometries the same way, so that normals
          //will be pointing the right direction
          Pair<Body> bodypair;
          Pair<Geometry> geometrypair;
         
          bodypair = new Pair<Body>(b1,b2);
         
//          if ( b1.hashCode() > b2.hashCode() ) {
//            bodypair = new Pair<Body>(b1,b2);
//            geometrypair = new Pair<Geometry>(inputpair.getFirst(), inputpair.getSecond());
//          } else {
//            bodypair = new Pair<Body>(b2,b1);
//            geometrypair = new Pair<Geometry>(inputpair.getSecond(), inputpair.getFirst());
//          }
         
         
          ContactConstraint contactConstraint = null;

          //a contact constraint already exists
          if (contactConstraints.containsKey(bodypair)) {
            contactConstraint = contactConstraints.get(bodypair);
           
            // order the geometry pair to match the order of the contact constraint.
            // this is necessary to keep normals pointing in the right direction when
            // contact constraints have more than one contact generator
            Pair<Body> orderedpair = contactConstraint.getBodies();
            if (orderedpair.getFirst() == bodypair.getFirst()) {
              // same order
              geometrypair = inputpair;
            } else {
              // swap
              geometrypair = new Pair<Geometry>(inputpair.getSecond(),inputpair.getFirst());           
            }
           
                               
            //add a new contact generator to this contact constraint
            ContactGenerator generator = getContactGenerator(geometrypair);
            contactGenerators.put(geometrypair, generator);
            contactConstraint.addGenerator(generator);

          //no contact constraint is present
          } else {         
            //do not act if some other constraint(joint) is already present
            //in the contact graph
            if (constraintGraph.getEdge(bodypair) == null)  {
              //create a new contact generator
              ContactGenerator generator = getContactGenerator(inputpair);
             
              // try custom contact constraint generators
              for ( ContactConstraintCreator c : contactConstraintCreators) {
                contactConstraint = c.createContactConstraint(bodypair.getFirst(), bodypair.getSecond(), generator);
                if (contactConstraint != null)
                  break;
              }
             
              // if no contact constraint was obtained, use the default creator
              if ( contactConstraint == null) {
                contactConstraint = defaultcreator.createContactConstraint(bodypair.getFirst(), bodypair.getSecond(), generator);
              }
                 
              //insert into data structures
              contactConstraints.put(bodypair, contactConstraint);
              contactGenerators.put(inputpair, generator);
              constraintGraph.addEdge( bodypair, contactConstraint);
             
              // signal handlers
              for (Handler h: handlers) {
                h.contactConstraintCreated(bodypair, contactConstraint);
              }
             
            }
          }
        }
       
        @Override
        public final void separation(Pair<Geometry> geometrypair) {
          //retrieve the bodies associated with overlapping geometries
          Body a = geometrypair.getFirst().getBody();
          Body b = geometrypair.getSecond().getBody();
          Pair<Body> bodypair = new Pair<Body>(a,b);

          //ignore overlaps stemming from the same body       
          if ( a == b) return;
          //ignore overlaps for non-body geometries
          if ( a == null || b == null) return;
          //ignore overlaps of fixed bodies
          if ( a.isFixed() && b.isFixed() ) return;
         
          //if this geometry pair has an acting contact constraint,
          //we must remove the contact generator
          if (contactConstraints.containsKey(bodypair)) {
            //check that we have the generator (if not, something is very wrong)
            if (contactGenerators.containsKey(geometrypair)) {
         
              //remove the generator from the contact constraint
              ContactConstraint constraint = contactConstraints.get(bodypair);
              ContactGenerator cg = contactGenerators.get(geometrypair);
             
              //notify contact generator (for possible clean-up)
              cg.remove();
             
              // remove from contact constraint
              constraint.removeGenerator(cg);
             
              //remove the generator from our list
              contactGenerators.remove(geometrypair);

              //if the contact constraint has no more generators, also
              //remove the contact constraint
              if (constraint.getNumberOfGenerators() < 1 ) {
                contactConstraints.remove(bodypair);
                constraintGraph.removeEdge(bodypair)
               
                // signal event handlers
                for (Handler h: handlers) {
                  h.contactConstraintRemoved(bodypair, constraint);
                }
              }
                 
            } else {
              // attempt to remove a contact generator that was not there
              throw new IllegalStateException("DefaultContactConstraintManager: contact generator missing from ContactConstraint?");
            }
          } else {
            // no contact constraint present
            // this could be due to bodies that are connected with other constraints
            // than contact constraints.
            //System.out.println("no constraint pressent");
            //System.exit(0);
          }
        } // separation()
    }; // new broadphase handler   
   
   
    // add the handler to the broad phase
    broadphase.addHandler(handler);
   
    // create some initial ContactGeneratorClassifiers
    // The Sphere - Sphere classifier
    geometryClassifiers.add(new ContactGeneratorClassifier() {
      @Override
      public final ContactGenerator getGenerator(Geometry a,
          Geometry b) {
        if ( a instanceof jinngine.geometry.Sphere && b instanceof jinngine.geometry.Sphere) {
          return new SphereContactGenerator((jinngine.geometry.Sphere)a, (jinngine.geometry.Sphere)b);
        }
        //not recognised
        return null
      }
    });
   
    // The Sphere - SupportMap classifier
    geometryClassifiers.add(new ContactGeneratorClassifier() {
      @Override
      public final ContactGenerator getGenerator(Geometry a,
          Geometry b) {
        if ( a instanceof jinngine.geometry.SupportMap3 && b instanceof jinngine.geometry.Sphere) {
          return new SupportMapSphereContactGenerator(a.getBody(), a, (jinngine.geometry.SupportMap3)a, b.getBody(), (jinngine.geometry.Sphere)b);
        }
        if ( a instanceof jinngine.geometry.Sphere && b instanceof jinngine.geometry.SupportMap3) {
          return new SupportMapSphereContactGenerator(a.getBody(), (jinngine.geometry.Sphere)a, b.getBody(), b, (jinngine.geometry.SupportMap3)b);
        }
        //not recognised
        return null
      }
    });
   
   
    // General convex support maps
    geometryClassifiers.add(new ContactGeneratorClassifier() {
      @Override
      public final ContactGenerator getGenerator(Geometry a,
          Geometry b) {
        if ( a instanceof SupportMap3 && b instanceof SupportMap3) {
          return new SupportMapContactGenerator((SupportMap3)a, a,  (SupportMap3)b, b);
//          return new BulletNativeContactGenerator(a,b);
        }
        //not recognised
        return null
      }
    });

  }
 
  /**
   * Remove the broad-phase collision detection handler, that was previously installed by this
   * contact constraint manager
   */
  public void removeBroadphaseHandler() {
    broadphase.removeHandler(handler);
  }
 
  /**
   * Add a new ContactConstraintCreator
   */
  public final void addContactConstraintCreator( ContactConstraintCreator c) {
    contactConstraintCreators.add(c);
  }

  /**
   * Remove an existing contact constraint creator
   * @param c
   */
  public final void removeContactConstraintCreator( ContactConstraintCreator c) {
    contactConstraintCreators.remove(c);
  }
 
  private ContactGenerator getContactGenerator(Pair<Geometry> pair) {
    for ( ContactGeneratorClassifier gc: geometryClassifiers) {
      ContactGenerator g = gc.getGenerator(pair.getFirst(), pair.getSecond());
     
      if (g!=null) {
        return g;
      }
    }
    return null;
  }

  @Override
  public void cleanup(Scene scene) {
    // TODO Auto-generated method stub
   
  }

  @Override
  public void setup(Scene scene) {
    // TODO Auto-generated method stub
   
  }

  @Override
  public void addHandler(Handler handler) {
    handlers.add(handler);
  }

  @Override
  public void removeHandler(Handler handler) {
    handlers.remove(handler);
  }

}
TOP

Related Classes of jinngine.physics.constraint.contact.DefaultContactConstraintManager

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.