001/**
002 * Copyright (c) 2008-2014 Ardor Labs, Inc.
003 *
004 * This file is part of Ardor3D.
005 *
006 * Ardor3D is free software: you can redistribute it and/or modify it 
007 * under the terms of its license which may be found in the accompanying
008 * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
009 */
010
011package com.ardor3d.math;
012
013import static org.junit.Assert.*;
014
015import org.junit.Test;
016
017public class TestVector3 {
018
019    @Test
020    public void testAdd() {
021        final Vector3 vec1 = new Vector3();
022        final Vector3 vec2 = new Vector3(Vector3.ONE);
023
024        vec1.addLocal(1, 2, 3);
025        assertEquals(new Vector3(1, 2, 3), vec1);
026        vec1.addLocal(-1, -2, -3);
027        assertEquals(Vector3.ZERO, vec1);
028
029        vec1.zero();
030        vec1.addLocal(vec2);
031        assertEquals(Vector3.ONE, vec1);
032
033        vec1.zero();
034        final Vector3 vec3 = vec1.add(vec2, new Vector3());
035        assertEquals(Vector3.ZERO, vec1);
036        assertEquals(Vector3.ONE, vec3);
037
038        final Vector3 vec4 = vec1.add(1, 0, 0, null);
039        assertEquals(Vector3.ZERO, vec1);
040        assertEquals(Vector3.UNIT_X, vec4);
041    }
042
043    @Test
044    public void testSubtract() {
045        final Vector3 vec1 = new Vector3();
046        final Vector3 vec2 = new Vector3(Vector3.ONE);
047
048        vec1.subtractLocal(1, 2, 3);
049        assertEquals(new Vector3(-1, -2, -3), vec1);
050        vec1.subtractLocal(-1, -2, -3);
051        assertEquals(Vector3.ZERO, vec1);
052
053        vec1.zero();
054        vec1.subtractLocal(vec2);
055        assertEquals(Vector3.NEG_ONE, vec1);
056
057        vec1.zero();
058        final Vector3 vec3 = vec1.subtract(vec2, new Vector3());
059        assertEquals(Vector3.ZERO, vec1);
060        assertEquals(Vector3.NEG_ONE, vec3);
061
062        final Vector3 vec4 = vec1.subtract(1, 0, 0, null);
063        assertEquals(Vector3.ZERO, vec1);
064        assertEquals(Vector3.NEG_UNIT_X, vec4);
065    }
066
067    @Test
068    public void testGetSet() {
069        final Vector3 vec1 = new Vector3();
070        vec1.setX(0);
071        assertTrue(vec1.getX() == 0.0);
072        vec1.setX(Double.POSITIVE_INFINITY);
073        assertTrue(vec1.getX() == Double.POSITIVE_INFINITY);
074        vec1.setX(Double.NEGATIVE_INFINITY);
075        assertTrue(vec1.getX() == Double.NEGATIVE_INFINITY);
076        assertTrue(vec1.getValue(0) == Double.NEGATIVE_INFINITY);
077
078        vec1.setY(0);
079        assertTrue(vec1.getY() == 0.0);
080        vec1.setY(Double.POSITIVE_INFINITY);
081        assertTrue(vec1.getY() == Double.POSITIVE_INFINITY);
082        vec1.setY(Double.NEGATIVE_INFINITY);
083        assertTrue(vec1.getY() == Double.NEGATIVE_INFINITY);
084        assertTrue(vec1.getValue(1) == Double.NEGATIVE_INFINITY);
085
086        vec1.setZ(0);
087        assertTrue(vec1.getZ() == 0.0);
088        vec1.setZ(Double.POSITIVE_INFINITY);
089        assertTrue(vec1.getZ() == Double.POSITIVE_INFINITY);
090        vec1.setZ(Double.NEGATIVE_INFINITY);
091        assertTrue(vec1.getZ() == Double.NEGATIVE_INFINITY);
092        assertTrue(vec1.getValue(2) == Double.NEGATIVE_INFINITY);
093
094        vec1.set(Math.PI, Math.PI, Math.PI);
095        assertTrue(vec1.getXf() == (float) Math.PI);
096        assertTrue(vec1.getYf() == (float) Math.PI);
097        assertTrue(vec1.getZf() == (float) Math.PI);
098
099        final Vector3 vec2 = new Vector3();
100        vec2.set(vec1);
101        assertEquals(vec1, vec2);
102
103        vec1.setValue(0, 0);
104        vec1.setValue(1, 0);
105        vec1.setValue(2, 0);
106        assertEquals(Vector3.ZERO, vec1);
107
108        // catch a few expected exceptions
109        try {
110            vec2.getValue(3);
111            fail("getValue(3) should have thrown IllegalArgumentException.");
112        } catch (final IllegalArgumentException e) {
113        }
114        try {
115            vec2.getValue(-1);
116            fail("getValue(-1) should have thrown IllegalArgumentException.");
117        } catch (final IllegalArgumentException e) {
118        }
119        try {
120            vec2.setValue(-1, 0);
121            fail("setValue(-1, 0) should have thrown IllegalArgumentException.");
122        } catch (final IllegalArgumentException e) {
123        }
124        try {
125            vec2.setValue(3, 0);
126            fail("setValue(3, 0) should have thrown IllegalArgumentException.");
127        } catch (final IllegalArgumentException e) {
128        }
129        // above exceptions shouldn't have altered vec2
130        assertEquals(new Vector3(Math.PI, Math.PI, Math.PI), vec2);
131    }
132
133    @Test
134    public void testToArray() {
135        final Vector3 vec1 = new Vector3();
136        vec1.set(Math.PI, Double.MAX_VALUE, 42);
137        final double[] array = vec1.toArray(null);
138        final double[] array2 = vec1.toArray(new double[3]);
139        assertNotNull(array);
140        assertTrue(array.length == 3);
141        assertTrue(array[0] == Math.PI);
142        assertTrue(array[1] == Double.MAX_VALUE);
143        assertTrue(array[2] == 42);
144        assertNotNull(array2);
145        assertTrue(array2.length == 3);
146        assertTrue(array2[0] == Math.PI);
147        assertTrue(array2[1] == Double.MAX_VALUE);
148        assertTrue(array2[2] == 42);
149
150        try {
151            vec1.toArray(new double[1]);
152            fail("toArray(d[1]) should have thrown ArrayIndexOutOfBoundsException.");
153        } catch (final ArrayIndexOutOfBoundsException e) {
154        }
155
156        final float[] farray = vec1.toFloatArray(null);
157        final float[] farray2 = vec1.toFloatArray(new float[3]);
158        assertNotNull(farray);
159        assertTrue(farray.length == 3);
160        assertTrue(farray[0] == (float) Math.PI);
161        assertTrue(farray[1] == (float) Double.MAX_VALUE);
162        assertTrue(farray[2] == 42f);
163        assertNotNull(farray2);
164        assertTrue(farray2.length == 3);
165        assertTrue(farray2[0] == (float) Math.PI);
166        assertTrue(farray2[1] == (float) Double.MAX_VALUE);
167        assertTrue(farray2[2] == 42f);
168
169        try {
170            vec1.toFloatArray(new float[1]);
171            fail("toFloatArray(d[1]) should have thrown ArrayIndexOutOfBoundsException.");
172        } catch (final ArrayIndexOutOfBoundsException e) {
173        }
174    }
175
176    @Test
177    public void testMultiply() {
178        final Vector3 vec1 = new Vector3(1, -1, 2);
179        final Vector3 vec2 = vec1.multiply(2.0, null);
180        final Vector3 vec2B = vec1.multiply(2.0, new Vector3());
181        assertEquals(new Vector3(2.0, -2.0, 4.0), vec2);
182        assertEquals(new Vector3(2.0, -2.0, 4.0), vec2B);
183
184        vec2.multiplyLocal(0.5);
185        assertEquals(new Vector3(1.0, -1.0, 2.0), vec2);
186
187        final Vector3 vec3 = vec1.multiply(vec2, null);
188        final Vector3 vec3B = vec1.multiply(vec2, new Vector3());
189        assertEquals(new Vector3(1, 1, 4), vec3);
190        assertEquals(new Vector3(1, 1, 4), vec3B);
191
192        final Vector3 vec4 = vec1.multiply(2, 3, 2, null);
193        final Vector3 vec4B = vec1.multiply(2, 3, 2, new Vector3());
194        assertEquals(new Vector3(2, -3, 4), vec4);
195        assertEquals(new Vector3(2, -3, 4), vec4B);
196
197        vec1.multiplyLocal(0.5, 0.5, 0.5);
198        assertEquals(new Vector3(0.5, -0.5, 1.0), vec1);
199
200        vec1.multiplyLocal(vec2);
201        assertEquals(new Vector3(0.5, 0.5, 2.0), vec1);
202    }
203
204    @Test
205    public void testDivide() {
206        final Vector3 vec1 = new Vector3(1, -1, 2);
207        final Vector3 vec2 = vec1.divide(2.0, null);
208        final Vector3 vec2B = vec1.divide(2.0, new Vector3());
209        assertEquals(new Vector3(0.5, -0.5, 1.0), vec2);
210        assertEquals(new Vector3(0.5, -0.5, 1.0), vec2B);
211
212        vec2.divideLocal(0.5);
213        assertEquals(new Vector3(1.0, -1.0, 2.0), vec2);
214
215        final Vector3 vec3 = vec1.divide(vec2, null);
216        final Vector3 vec3B = vec1.divide(vec2, new Vector3());
217        assertEquals(Vector3.ONE, vec3);
218        assertEquals(Vector3.ONE, vec3B);
219
220        final Vector3 vec4 = vec1.divide(2, 3, 4, null);
221        final Vector3 vec4B = vec1.divide(2, 3, 4, new Vector3());
222        assertEquals(new Vector3(0.5, -1 / 3., 0.5), vec4);
223        assertEquals(new Vector3(0.5, -1 / 3., 0.5), vec4B);
224
225        vec1.divideLocal(0.5, 0.5, 0.5);
226        assertEquals(new Vector3(2, -2, 4), vec1);
227
228        vec1.divideLocal(vec2);
229        assertEquals(new Vector3(2, 2, 2), vec1);
230    }
231
232    @Test
233    public void testScaleAdd() {
234        final Vector3 vec1 = new Vector3(1, 1, 1);
235        final Vector3 vec2 = vec1.scaleAdd(2.0, new Vector3(1, 2, 3), null);
236        final Vector3 vec2B = vec1.scaleAdd(2.0, new Vector3(1, 2, 3), new Vector3());
237        assertEquals(new Vector3(3.0, 4.0, 5.0), vec2);
238        assertEquals(new Vector3(3.0, 4.0, 5.0), vec2B);
239
240        vec1.scaleAddLocal(2.0, new Vector3(1, 2, 3));
241        assertEquals(vec2, vec1);
242    }
243
244    @Test
245    public void testNegate() {
246        final Vector3 vec1 = new Vector3(3, 2, -1);
247        final Vector3 vec2 = vec1.negate(null);
248        assertEquals(new Vector3(-3, -2, 1), vec2);
249
250        vec1.negateLocal();
251        assertEquals(vec2, vec1);
252    }
253
254    @Test
255    public void testNormalize() {
256        final Vector3 vec1 = new Vector3(2, 1, 3);
257        assertTrue(vec1.length() == Math.sqrt(14));
258
259        final Vector3 vec2 = vec1.normalize(null);
260        final double invLength = MathUtils.inverseSqrt(2 * 2 + 1 * 1 + 3 * 3);
261        assertEquals(new Vector3(2 * invLength, 1 * invLength, 3 * invLength), vec2);
262
263        vec1.normalizeLocal();
264        assertEquals(new Vector3(2 * invLength, 1 * invLength, 3 * invLength), vec1);
265
266        vec1.zero();
267        vec1.normalize(vec2);
268        assertEquals(vec1, vec2);
269
270        // ensure no exception thrown
271        vec1.normalizeLocal();
272        vec1.normalize(null);
273    }
274
275    @Test
276    public void testDistance() {
277        final Vector3 vec1 = new Vector3(0, 0, 0);
278        assertTrue(4.0 == vec1.distance(4, 0, 0));
279        assertTrue(3.0 == vec1.distance(0, 3, 0));
280        assertTrue(2.0 == vec1.distance(0, 0, 2));
281
282        final Vector3 vec2 = new Vector3(1, 1, 1);
283        assertTrue(Math.sqrt(3) == vec1.distance(vec2));
284    }
285
286    @Test
287    public void testLerp() {
288        final Vector3 vec1 = new Vector3(8, 3, -2);
289        final Vector3 vec2 = new Vector3(2, 1, 0);
290        assertEquals(new Vector3(5, 2, -1), vec1.lerp(vec2, 0.5, null));
291        assertEquals(new Vector3(5, 2, -1), vec1.lerp(vec2, 0.5, new Vector3()));
292        assertEquals(new Vector3(5, 2, -1), Vector3.lerp(vec1, vec2, 0.5, null));
293        assertEquals(new Vector3(5, 2, -1), Vector3.lerp(vec1, vec2, 0.5, new Vector3()));
294
295        vec1.set(14, 5, 4);
296        vec1.lerpLocal(vec2, 0.25);
297        assertEquals(new Vector3(11, 4, 3), vec1);
298
299        vec1.set(15, 7, 6);
300        final Vector3 vec3 = new Vector3(-1, -1, -1);
301        vec3.lerpLocal(vec1, vec2, 0.5);
302        assertEquals(new Vector3(8.5, 4.0, 3.0), vec3);
303
304        // coverage
305        assertEquals(vec1.lerp(vec1, .25, null), vec1);
306        assertEquals(vec2.lerpLocal(vec2, .25), vec2);
307        assertEquals(vec2.lerpLocal(vec2, vec2, .25), vec2);
308        assertEquals(Vector3.lerp(vec1, vec1, .25, null), vec1);
309    }
310
311    @Test
312    public void testCross() {
313        final Vector3 vec1 = new Vector3(1, 0, 0);
314        final Vector3 vec2 = new Vector3(0, 1, 0);
315        assertEquals(Vector3.UNIT_Z, vec1.cross(vec2, null));
316        assertEquals(Vector3.UNIT_Z, vec1.cross(vec2, new Vector3()));
317
318        assertEquals(Vector3.UNIT_Z, vec1.cross(0, 1, 0, null));
319        assertEquals(Vector3.UNIT_Z, vec1.cross(0, 1, 0, new Vector3()));
320
321        vec1.crossLocal(vec2);
322        assertEquals(Vector3.UNIT_Z, vec1);
323        vec2.crossLocal(1, 0, 0);
324        assertEquals(Vector3.NEG_UNIT_Z, vec2);
325    }
326
327    @Test
328    public void testAngle() {
329        final Vector3 vec1 = new Vector3(1, 0, 0);
330
331        assertTrue(MathUtils.HALF_PI == vec1.smallestAngleBetween(new Vector3(0, -1, 0)));
332    }
333
334    @Test
335    public void testDot() {
336        final Vector3 vec1 = new Vector3(7, 2, 5);
337        assertTrue(33.0 == vec1.dot(3, 1, 2));
338
339        assertTrue(-10.0 == vec1.dot(new Vector3(-1, 1, -1)));
340    }
341
342    @Test
343    public void testClone() {
344        final Vector3 vec1 = new Vector3(0, 0, 0);
345        final Vector3 vec2 = vec1.clone();
346        assertEquals(vec1, vec2);
347        assertNotSame(vec1, vec2);
348    }
349
350    @Test
351    public void testValid() {
352        final Vector3 vec1 = new Vector3(0, 0, 0);
353        final Vector3 vec2A = new Vector3(Double.POSITIVE_INFINITY, 0, 0);
354        final Vector3 vec2B = new Vector3(0, Double.NEGATIVE_INFINITY, 0);
355        final Vector3 vec2C = new Vector3(0, 0, Double.POSITIVE_INFINITY);
356        final Vector3 vec3A = new Vector3(Double.NaN, 0, 0);
357        final Vector3 vec3B = new Vector3(0, Double.NaN, 0);
358        final Vector3 vec3C = new Vector3(0, 0, Double.NaN);
359
360        assertTrue(Vector3.isValid(vec1));
361        assertFalse(Vector3.isValid(vec2A));
362        assertFalse(Vector3.isValid(vec2B));
363        assertFalse(Vector3.isValid(vec2C));
364        assertFalse(Vector3.isValid(vec3A));
365        assertFalse(Vector3.isValid(vec3B));
366        assertFalse(Vector3.isValid(vec3C));
367
368        assertFalse(Vector3.isInfinite(vec1));
369        assertTrue(Vector3.isInfinite(vec2A));
370
371        vec3C.zero();
372        assertTrue(Vector3.isValid(vec3C));
373
374        assertFalse(Vector3.isValid(null));
375        assertFalse(Vector3.isInfinite(null));
376
377        // couple of equals validity tests
378        assertEquals(vec1, vec1);
379        assertFalse(vec1.equals(null));
380        assertFalse(vec1.equals(new Vector4()));
381
382        // throw in a couple pool accesses for coverage
383        final Vector3 vec6 = Vector3.fetchTempInstance();
384        vec6.set(vec1);
385        assertEquals(vec1, vec6);
386        assertNotSame(vec1, vec6);
387        Vector3.releaseTempInstance(vec6);
388
389        // cover more of equals
390        vec1.set(0, 1, 2);
391        assertFalse(vec1.equals(new Vector3(0, 2, 3)));
392        assertFalse(vec1.equals(new Vector3(0, 1, 3)));
393    }
394
395    @Test
396    public void testSimpleHash() {
397        // Just a simple sanity check.
398        final Vector3 vec1 = new Vector3(1, 2, 3);
399        final Vector3 vec2 = new Vector3(1, 2, 3);
400        final Vector3 vec3 = new Vector3(2, 2, 2);
401
402        assertTrue(vec1.hashCode() == vec2.hashCode());
403        assertTrue(vec1.hashCode() != vec3.hashCode());
404    }
405}