1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32package com.jme3.bullet.joints;
33
34import com.bulletphysics.dynamics.constraintsolver.ConeTwistConstraint;
35import com.bulletphysics.linearmath.Transform;
36import com.jme3.bullet.objects.PhysicsRigidBody;
37import com.jme3.bullet.util.Converter;
38import com.jme3.export.InputCapsule;
39import com.jme3.export.JmeExporter;
40import com.jme3.export.JmeImporter;
41import com.jme3.export.OutputCapsule;
42import com.jme3.math.Matrix3f;
43import com.jme3.math.Vector3f;
44import java.io.IOException;
45
46/**
47 * <i>From bullet manual:</i><br>
48 * To create ragdolls, the conve twist constraint is very useful for limbs like the upper arm.
49 * It is a special point to point constraint that adds cone and twist axis limits.
50 * The x-axis serves as twist axis.
51 * @author normenhansen
52 */
53public class ConeJoint extends PhysicsJoint {
54
55    protected Matrix3f rotA, rotB;
56    protected float swingSpan1 = 1e30f;
57    protected float swingSpan2 = 1e30f;
58    protected float twistSpan = 1e30f;
59    protected boolean angularOnly = false;
60
61    public ConeJoint() {
62    }
63
64    /**
65     * @param pivotA local translation of the joint connection point in node A
66     * @param pivotB local translation of the joint connection point in node B
67     */
68    public ConeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB) {
69        super(nodeA, nodeB, pivotA, pivotB);
70        this.rotA = new Matrix3f();
71        this.rotB = new Matrix3f();
72        createJoint();
73    }
74
75    /**
76     * @param pivotA local translation of the joint connection point in node A
77     * @param pivotB local translation of the joint connection point in node B
78     */
79    public ConeJoint(PhysicsRigidBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB, Matrix3f rotA, Matrix3f rotB) {
80        super(nodeA, nodeB, pivotA, pivotB);
81        this.rotA = rotA;
82        this.rotB = rotB;
83        createJoint();
84    }
85
86    public void setLimit(float swingSpan1, float swingSpan2, float twistSpan) {
87        this.swingSpan1 = swingSpan1;
88        this.swingSpan2 = swingSpan2;
89        this.twistSpan = twistSpan;
90        ((ConeTwistConstraint) constraint).setLimit(swingSpan1, swingSpan2, twistSpan);
91    }
92
93    public void setAngularOnly(boolean value) {
94        angularOnly = value;
95        ((ConeTwistConstraint) constraint).setAngularOnly(value);
96    }
97
98    @Override
99    public void write(JmeExporter ex) throws IOException {
100        super.write(ex);
101        OutputCapsule capsule = ex.getCapsule(this);
102        capsule.write(rotA, "rotA", new Matrix3f());
103        capsule.write(rotB, "rotB", new Matrix3f());
104
105        capsule.write(angularOnly, "angularOnly", false);
106        capsule.write(swingSpan1, "swingSpan1", 1e30f);
107        capsule.write(swingSpan2, "swingSpan2", 1e30f);
108        capsule.write(twistSpan, "twistSpan", 1e30f);
109    }
110
111    @Override
112    public void read(JmeImporter im) throws IOException {
113        super.read(im);
114        InputCapsule capsule = im.getCapsule(this);
115        this.rotA = (Matrix3f) capsule.readSavable("rotA", new Matrix3f());
116        this.rotB = (Matrix3f) capsule.readSavable("rotB", new Matrix3f());
117
118        this.angularOnly = capsule.readBoolean("angularOnly", false);
119        this.swingSpan1 = capsule.readFloat("swingSpan1", 1e30f);
120        this.swingSpan2 = capsule.readFloat("swingSpan2", 1e30f);
121        this.twistSpan = capsule.readFloat("twistSpan", 1e30f);
122        createJoint();
123    }
124
125    protected void createJoint() {
126        Transform transA = new Transform(Converter.convert(rotA));
127        Converter.convert(pivotA, transA.origin);
128        Converter.convert(rotA, transA.basis);
129
130        Transform transB = new Transform(Converter.convert(rotB));
131        Converter.convert(pivotB, transB.origin);
132        Converter.convert(rotB, transB.basis);
133
134        constraint = new ConeTwistConstraint(nodeA.getObjectId(), nodeB.getObjectId(), transA, transB);
135        ((ConeTwistConstraint) constraint).setLimit(swingSpan1, swingSpan2, twistSpan);
136        ((ConeTwistConstraint) constraint).setAngularOnly(angularOnly);
137    }
138}
139