/* 
 | 
 * Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz> 
 | 
 * 
 | 
 * Bullet Continuous Collision Detection and Physics Library 
 | 
 * Copyright (c) 2003-2008 Erwin Coumans  http://www.bulletphysics.com/ 
 | 
 * 
 | 
 * This software is provided 'as-is', without any express or implied warranty. 
 | 
 * In no event will the authors be held liable for any damages arising from 
 | 
 * the use of this software. 
 | 
 *  
 | 
 * Permission is granted to anyone to use this software for any purpose,  
 | 
 * including commercial applications, and to alter it and redistribute it 
 | 
 * freely, subject to the following restrictions: 
 | 
 *  
 | 
 * 1. The origin of this software must not be misrepresented; you must not 
 | 
 *    claim that you wrote the original software. If you use this software 
 | 
 *    in a product, an acknowledgment in the product documentation would be 
 | 
 *    appreciated but is not required. 
 | 
 * 2. Altered source versions must be plainly marked as such, and must not be 
 | 
 *    misrepresented as being the original software. 
 | 
 * 3. This notice may not be removed or altered from any source distribution. 
 | 
 */ 
 | 
  
 | 
/* 
 | 
2007-09-09 
 | 
btGeneric6DofConstraint Refactored by Francisco Le�n 
 | 
email: projectileman@yahoo.com 
 | 
http://gimpact.sf.net 
 | 
*/ 
 | 
  
 | 
package com.bulletphysics.dynamics.constraintsolver; 
 | 
  
 | 
import com.bulletphysics.dynamics.RigidBody; 
 | 
import com.bulletphysics.linearmath.VectorUtil; 
 | 
import cz.advel.stack.Stack; 
 | 
import cz.advel.stack.StaticAlloc; 
 | 
import javax.vecmath.Vector3f; 
 | 
  
 | 
/** 
 | 
 * 
 | 
 * @author jezek2 
 | 
 */ 
 | 
public class TranslationalLimitMotor  implements java.io.Serializable { 
 | 
     
 | 
    //protected final BulletStack stack = BulletStack.get(); 
 | 
     
 | 
    public final Vector3f lowerLimit = new Vector3f(); //!< the constraint lower limits 
 | 
    public final Vector3f upperLimit = new Vector3f(); //!< the constraint upper limits 
 | 
    public final Vector3f accumulatedImpulse = new Vector3f(); 
 | 
     
 | 
    public float limitSoftness; //!< Softness for linear limit 
 | 
    public float damping; //!< Damping for linear limit 
 | 
    public float restitution; //! Bounce parameter for linear limit 
 | 
  
 | 
    public TranslationalLimitMotor() { 
 | 
        lowerLimit.set(0f, 0f, 0f); 
 | 
        upperLimit.set(0f, 0f, 0f); 
 | 
        accumulatedImpulse.set(0f, 0f, 0f); 
 | 
  
 | 
        limitSoftness = 0.7f; 
 | 
        damping = 1.0f; 
 | 
        restitution = 0.5f; 
 | 
    } 
 | 
  
 | 
    public TranslationalLimitMotor(TranslationalLimitMotor other) { 
 | 
        lowerLimit.set(other.lowerLimit); 
 | 
        upperLimit.set(other.upperLimit); 
 | 
        accumulatedImpulse.set(other.accumulatedImpulse); 
 | 
  
 | 
        limitSoftness = other.limitSoftness; 
 | 
        damping = other.damping; 
 | 
        restitution = other.restitution; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * Test limit.<p> 
 | 
     * - free means upper < lower,<br> 
 | 
     * - locked means upper == lower<br> 
 | 
     * - limited means upper > lower<br> 
 | 
     * - limitIndex: first 3 are linear, next 3 are angular 
 | 
     */ 
 | 
    public boolean isLimited(int limitIndex) { 
 | 
        return (VectorUtil.getCoord(upperLimit, limitIndex) >= VectorUtil.getCoord(lowerLimit, limitIndex)); 
 | 
    } 
 | 
  
 | 
    @StaticAlloc 
 | 
    public float solveLinearAxis(float timeStep, float jacDiagABInv, RigidBody body1, Vector3f pointInA, RigidBody body2, Vector3f pointInB, int limit_index, Vector3f axis_normal_on_a, Vector3f anchorPos) { 
 | 
        Vector3f tmp = Stack.alloc(Vector3f.class); 
 | 
        Vector3f tmpVec = Stack.alloc(Vector3f.class); 
 | 
         
 | 
        // find relative velocity 
 | 
        Vector3f rel_pos1 = Stack.alloc(Vector3f.class); 
 | 
        //rel_pos1.sub(pointInA, body1.getCenterOfMassPosition(tmpVec)); 
 | 
        rel_pos1.sub(anchorPos, body1.getCenterOfMassPosition(tmpVec)); 
 | 
  
 | 
        Vector3f rel_pos2 = Stack.alloc(Vector3f.class); 
 | 
        //rel_pos2.sub(pointInB, body2.getCenterOfMassPosition(tmpVec)); 
 | 
        rel_pos2.sub(anchorPos, body2.getCenterOfMassPosition(tmpVec)); 
 | 
  
 | 
        Vector3f vel1 = body1.getVelocityInLocalPoint(rel_pos1, Stack.alloc(Vector3f.class)); 
 | 
        Vector3f vel2 = body2.getVelocityInLocalPoint(rel_pos2, Stack.alloc(Vector3f.class)); 
 | 
        Vector3f vel = Stack.alloc(Vector3f.class); 
 | 
        vel.sub(vel1, vel2); 
 | 
  
 | 
        float rel_vel = axis_normal_on_a.dot(vel); 
 | 
  
 | 
        // apply displacement correction 
 | 
  
 | 
        // positional error (zeroth order error) 
 | 
        tmp.sub(pointInA, pointInB); 
 | 
        float depth = -(tmp).dot(axis_normal_on_a); 
 | 
        float lo = -1e30f; 
 | 
        float hi = 1e30f; 
 | 
  
 | 
        float minLimit = VectorUtil.getCoord(lowerLimit, limit_index); 
 | 
        float maxLimit = VectorUtil.getCoord(upperLimit, limit_index); 
 | 
  
 | 
        // handle the limits 
 | 
        if (minLimit < maxLimit) { 
 | 
            { 
 | 
                if (depth > maxLimit) { 
 | 
                    depth -= maxLimit; 
 | 
                    lo = 0f; 
 | 
  
 | 
                } 
 | 
                else { 
 | 
                    if (depth < minLimit) { 
 | 
                        depth -= minLimit; 
 | 
                        hi = 0f; 
 | 
                    } 
 | 
                    else { 
 | 
                        return 0.0f; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
  
 | 
        float normalImpulse = limitSoftness * (restitution * depth / timeStep - damping * rel_vel) * jacDiagABInv; 
 | 
  
 | 
        float oldNormalImpulse = VectorUtil.getCoord(accumulatedImpulse, limit_index); 
 | 
        float sum = oldNormalImpulse + normalImpulse; 
 | 
        VectorUtil.setCoord(accumulatedImpulse, limit_index, sum > hi ? 0f : sum < lo ? 0f : sum); 
 | 
        normalImpulse = VectorUtil.getCoord(accumulatedImpulse, limit_index) - oldNormalImpulse; 
 | 
  
 | 
        Vector3f impulse_vector = Stack.alloc(Vector3f.class); 
 | 
        impulse_vector.scale(normalImpulse, axis_normal_on_a); 
 | 
        body1.applyImpulse(impulse_vector, rel_pos1); 
 | 
  
 | 
        tmp.negate(impulse_vector); 
 | 
        body2.applyImpulse(tmp, rel_pos2); 
 | 
        return normalImpulse; 
 | 
    } 
 | 
     
 | 
} 
 |