org.jtrfp.trcl.beh.phy.BouncesOffSurfaces.java Source code

Java tutorial

Introduction

Here is the source code for org.jtrfp.trcl.beh.phy.BouncesOffSurfaces.java

Source

/*******************************************************************************
 * This file is part of TERMINAL RECALL
 * Copyright (c) 2012-2014 Chuck Ritola
 * Part of the jTRFP.org project
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     chuck - initial API and implementation
 ******************************************************************************/
package org.jtrfp.trcl.beh.phy;

import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.jtrfp.trcl.beh.Behavior;
import org.jtrfp.trcl.beh.SurfaceImpactListener;
import org.jtrfp.trcl.obj.Velocible;
import org.jtrfp.trcl.obj.WorldObject;

public class BouncesOffSurfaces extends Behavior implements SurfaceImpactListener {
    private boolean reflectHeading = true;
    private double velocityRetainmentCoefficient = .5;

    @Override
    public void collidedWithSurface(WorldObject wo, double[] surfaceNormal) {
        final WorldObject parent = getParent();
        final Vector3D oldHeading = parent.getHeading();
        final Vector3D oldTop = parent.getTop();
        final Vector3D _surfaceNormal = new Vector3D(surfaceNormal);
        if (oldHeading == null)
            throw new NullPointerException("Parent heading is null.");
        if (surfaceNormal == null)
            throw new NullPointerException("Surface normal is null.");
        if (reflectHeading && new Rotation(oldHeading, _surfaceNormal).getAngle() > Math.PI / 2.) {
            Vector3D newHeading = (_surfaceNormal.scalarMultiply(_surfaceNormal.dotProduct(oldHeading) * -2)
                    .add(oldHeading));
            parent.setHeading(newHeading);
            final Rotation resultingRotation = new Rotation(oldHeading, newHeading);
            Vector3D newTop = resultingRotation.applyTo(oldTop);
            //if(newTop.getY()<0)newTop=newTop.negate();
            parent.setTop(newTop);
        } //end if(should reflect)
          //if(parent instanceof Velocible){
        final Velocible velocible = (Velocible) parent.probeForBehavior(Velocible.class);
        Vector3D oldVelocity = velocible.getVelocity();
        if (oldVelocity.getNorm() == 0)
            oldVelocity = Vector3D.PLUS_I;
        if (new Rotation(oldVelocity.normalize(), _surfaceNormal).getAngle() > Math.PI / 2.) {
            velocible.setVelocity(
                    (_surfaceNormal.scalarMultiply(_surfaceNormal.dotProduct(oldVelocity) * -2).add(oldVelocity))
                            .scalarMultiply(velocityRetainmentCoefficient));
            //Nudge
            parent.setPosition(
                    new Vector3D(parent.getPosition()).add(_surfaceNormal.scalarMultiply(1000.)).toArray());
        } //end if(should bounce)
        //}//end if(Velocible)
    }//end collidedWithSurface(...)

    /**
     * @return the reflectHeading
     */
    public boolean isReflectHeading() {
        return reflectHeading;
    }

    /**
     * @param reflectHeading the reflectHeading to set
     */
    public BouncesOffSurfaces setReflectHeading(boolean reflectHeading) {
        this.reflectHeading = reflectHeading;
        return this;
    }

    /**
     * @return the velocityRetainmentCoefficient
     */
    public double getVelocityRetainmentCoefficient() {
        return velocityRetainmentCoefficient;
    }

    /**
     * @param velocityRetainmentCoefficient the velocityRetainmentCoefficient to set
     */
    public BouncesOffSurfaces setVelocityRetainmentCoefficient(double velocityRetainmentCoefficient) {
        this.velocityRetainmentCoefficient = velocityRetainmentCoefficient;
        return this;
    }

}