• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
32 
33 package com.jme3.math;
34 
35 import com.jme3.export.*;
36 import java.io.IOException;
37 
38 /**
39  * Started Date: Jul 16, 2004<br><br>
40  * Represents a translation, rotation and scale in one object.
41  *
42  * @author Jack Lindamood
43  * @author Joshua Slack
44  */
45 public final class Transform implements Savable, Cloneable, java.io.Serializable {
46 
47     static final long serialVersionUID = 1;
48 
49     public static final Transform IDENTITY = new Transform();
50 
51     private Quaternion rot = new Quaternion();
52     private Vector3f translation = new Vector3f();
53     private Vector3f scale = new Vector3f(1,1,1);
54 
Transform(Vector3f translation, Quaternion rot)55     public Transform(Vector3f translation, Quaternion rot){
56         this.translation.set(translation);
57         this.rot.set(rot);
58     }
59 
Transform(Vector3f translation, Quaternion rot, Vector3f scale)60     public Transform(Vector3f translation, Quaternion rot, Vector3f scale){
61         this(translation, rot);
62         this.scale.set(scale);
63     }
64 
Transform(Vector3f translation)65     public Transform(Vector3f translation){
66         this(translation, Quaternion.IDENTITY);
67     }
68 
Transform(Quaternion rot)69     public Transform(Quaternion rot){
70         this(Vector3f.ZERO, rot);
71     }
72 
Transform()73     public Transform(){
74         this(Vector3f.ZERO, Quaternion.IDENTITY);
75     }
76 
77     /**
78      * Sets this rotation to the given Quaternion value.
79      * @param rot The new rotation for this matrix.
80      * @return this
81      */
setRotation(Quaternion rot)82     public Transform setRotation(Quaternion rot) {
83         this.rot.set(rot);
84         return this;
85     }
86 
87     /**
88      * Sets this translation to the given value.
89      * @param trans The new translation for this matrix.
90      * @return this
91      */
setTranslation(Vector3f trans)92     public Transform setTranslation(Vector3f trans) {
93         this.translation.set(trans);
94         return this;
95     }
96 
97     /**
98      * Return the translation vector in this matrix.
99      * @return translation vector.
100      */
getTranslation()101     public Vector3f getTranslation() {
102         return translation;
103     }
104 
105     /**
106      * Sets this scale to the given value.
107      * @param scale The new scale for this matrix.
108      * @return this
109      */
setScale(Vector3f scale)110     public Transform setScale(Vector3f scale) {
111         this.scale.set(scale);
112         return this;
113     }
114 
115     /**
116      * Sets this scale to the given value.
117      * @param scale The new scale for this matrix.
118      * @return this
119      */
setScale(float scale)120     public Transform setScale(float scale) {
121         this.scale.set(scale, scale, scale);
122         return this;
123     }
124 
125     /**
126      * Return the scale vector in this matrix.
127      * @return scale vector.
128      */
getScale()129     public Vector3f getScale() {
130         return scale;
131     }
132 
133     /**
134      * Stores this translation value into the given vector3f.  If trans is null, a new vector3f is created to
135      * hold the value.  The value, once stored, is returned.
136      * @param trans The store location for this matrix's translation.
137      * @return The value of this matrix's translation.
138      */
getTranslation(Vector3f trans)139     public Vector3f getTranslation(Vector3f trans) {
140         if (trans==null) trans=new Vector3f();
141         trans.set(this.translation);
142         return trans;
143     }
144 
145     /**
146      * Stores this rotation value into the given Quaternion.  If quat is null, a new Quaternion is created to
147      * hold the value.  The value, once stored, is returned.
148      * @param quat The store location for this matrix's rotation.
149      * @return The value of this matrix's rotation.
150      */
getRotation(Quaternion quat)151     public Quaternion getRotation(Quaternion quat) {
152         if (quat==null) quat=new Quaternion();
153         quat.set(rot);
154         return quat;
155     }
156 
157     /**
158      * Return the rotation quaternion in this matrix.
159      * @return rotation quaternion.
160      */
getRotation()161     public Quaternion getRotation() {
162         return rot;
163     }
164 
165     /**
166      * Stores this scale value into the given vector3f.  If scale is null, a new vector3f is created to
167      * hold the value.  The value, once stored, is returned.
168      * @param scale The store location for this matrix's scale.
169      * @return The value of this matrix's scale.
170      */
getScale(Vector3f scale)171     public Vector3f getScale(Vector3f scale) {
172         if (scale==null) scale=new Vector3f();
173         scale.set(this.scale);
174         return scale;
175     }
176 
177     /**
178      * Sets this matrix to the interpolation between the first matrix and the second by delta amount.
179      * @param t1 The begining transform.
180      * @param t2 The ending transform.
181      * @param delta An amount between 0 and 1 representing how far to interpolate from t1 to t2.
182      */
interpolateTransforms(Transform t1, Transform t2, float delta)183     public void interpolateTransforms(Transform t1, Transform t2, float delta) {
184         this.rot.slerp(t1.rot,t2.rot,delta);
185         this.translation.interpolate(t1.translation,t2.translation,delta);
186         this.scale.interpolate(t1.scale,t2.scale,delta);
187     }
188 
189     /**
190      * Changes the values of this matrix acording to it's parent.  Very similar to the concept of Node/Spatial transforms.
191      * @param parent The parent matrix.
192      * @return This matrix, after combining.
193      */
combineWithParent(Transform parent)194     public Transform combineWithParent(Transform parent) {
195         scale.multLocal(parent.scale);
196 //        rot.multLocal(parent.rot);
197         parent.rot.mult(rot, rot);
198 
199         // This here, is evil code
200 //        parent
201 //            .rot
202 //            .multLocal(translation)
203 //            .multLocal(parent.scale)
204 //            .addLocal(parent.translation);
205 
206         translation.multLocal(parent.scale);
207         parent
208             .rot
209             .multLocal(translation)
210             .addLocal(parent.translation);
211         return this;
212     }
213 
214     /**
215      * Sets this matrix's translation to the given x,y,z values.
216      * @param x This matrix's new x translation.
217      * @param y This matrix's new y translation.
218      * @param z This matrix's new z translation.
219      * @return this
220      */
setTranslation(float x,float y, float z)221     public Transform setTranslation(float x,float y, float z) {
222         translation.set(x,y,z);
223         return this;
224     }
225 
226     /**
227      * Sets this matrix's scale to the given x,y,z values.
228      * @param x This matrix's new x scale.
229      * @param y This matrix's new y scale.
230      * @param z This matrix's new z scale.
231      * @return this
232      */
setScale(float x, float y, float z)233     public Transform setScale(float x, float y, float z) {
234         scale.set(x,y,z);
235         return this;
236     }
237 
transformVector(final Vector3f in, Vector3f store)238     public Vector3f transformVector(final Vector3f in, Vector3f store){
239         if (store == null)
240             store = new Vector3f();
241 
242         // multiply with scale first, then rotate, finally translate (cf.
243         // Eberly)
244         return rot.mult(store.set(in).multLocal(scale), store).addLocal(translation);
245     }
246 
transformInverseVector(final Vector3f in, Vector3f store)247     public Vector3f transformInverseVector(final Vector3f in, Vector3f store){
248         if (store == null)
249             store = new Vector3f();
250 
251         // The author of this code should look above and take the inverse of that
252         // But for some reason, they didnt ..
253 //        in.subtract(translation, store).divideLocal(scale);
254 //        rot.inverse().mult(store, store);
255 
256         in.subtract(translation, store);
257         rot.inverse().mult(store, store);
258         store.divideLocal(scale);
259 
260         return store;
261     }
262 
263     /**
264      * Loads the identity.  Equal to translation=0,0,0 scale=1,1,1 rot=0,0,0,1.
265      */
loadIdentity()266     public void loadIdentity() {
267         translation.set(0,0,0);
268         scale.set(1,1,1);
269         rot.set(0,0,0,1);
270     }
271 
272     @Override
toString()273     public String toString(){
274         return getClass().getSimpleName() + "[ " + translation.x + ", " + translation.y + ", " + translation.z + "]\n"
275                                           + "[ " + rot.x + ", " + rot.y + ", " + rot.z + ", " + rot.w + "]\n"
276                                           + "[ " + scale.x + " , " + scale.y + ", " + scale.z + "]";
277     }
278 
279     /**
280      * Sets this matrix to be equal to the given matrix.
281      * @param matrixQuat The matrix to be equal to.
282      * @return this
283      */
set(Transform matrixQuat)284     public Transform set(Transform matrixQuat) {
285         this.translation.set(matrixQuat.translation);
286         this.rot.set(matrixQuat.rot);
287         this.scale.set(matrixQuat.scale);
288         return this;
289     }
290 
write(JmeExporter e)291     public void write(JmeExporter e) throws IOException {
292         OutputCapsule capsule = e.getCapsule(this);
293         capsule.write(rot, "rot", new Quaternion());
294         capsule.write(translation, "translation", Vector3f.ZERO);
295         capsule.write(scale, "scale", Vector3f.UNIT_XYZ);
296     }
297 
read(JmeImporter e)298     public void read(JmeImporter e) throws IOException {
299         InputCapsule capsule = e.getCapsule(this);
300 
301         rot = (Quaternion)capsule.readSavable("rot", new Quaternion());
302         translation = (Vector3f)capsule.readSavable("translation", Vector3f.ZERO);
303         scale = (Vector3f)capsule.readSavable("scale", Vector3f.UNIT_XYZ);
304     }
305 
306     @Override
clone()307     public Transform clone() {
308         try {
309             Transform tq = (Transform) super.clone();
310             tq.rot = rot.clone();
311             tq.scale = scale.clone();
312             tq.translation = translation.clone();
313             return tq;
314         } catch (CloneNotSupportedException e) {
315             throw new AssertionError();
316         }
317     }
318 }
319