/* * Copyright 2013 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.logic.location; import org.junit.Before; import org.junit.Test; import org.terasology.TerasologyTestingEnvironment; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.entitySystem.entity.lifecycleEvents.BeforeRemoveComponent; import org.terasology.math.TeraMath; import org.terasology.math.geom.Quat4f; import org.terasology.math.geom.Vector3f; import org.terasology.testUtil.TeraAssert; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** */ public class LocationComponentTest extends TerasologyTestingEnvironment { LocationComponent loc; EntityRef entity; Vector3f pos1 = new Vector3f(1, 2, 3); Vector3f pos2 = new Vector3f(2, 3, 4); Vector3f pos1plus2 = new Vector3f(3, 5, 7); Quat4f yawRotation; Quat4f pitchRotation; Quat4f yawPitch; long nextFakeEntityId = 1; @Before public void setup() { loc = new LocationComponent(); entity = createFakeEntityWith(loc); yawRotation = new Quat4f(TeraMath.DEG_TO_RAD * 90, 0, 0); pitchRotation = new Quat4f(0, TeraMath.DEG_TO_RAD * 45, 0); yawPitch = new Quat4f(TeraMath.DEG_TO_RAD * 90, TeraMath.DEG_TO_RAD * 45, 0); } private EntityRef createFakeEntityWith(LocationComponent locationComponent) { EntityRef entRef = mock(EntityRef.class); when(entRef.getComponent(LocationComponent.class)).thenReturn(locationComponent); when(entRef.exists()).thenReturn(true); when(entRef.getId()).thenReturn(nextFakeEntityId++); return entRef; } @Test public void testSetLocalPosition() { loc.setLocalPosition(pos1); assertEquals(pos1, loc.getLocalPosition()); } @Test public void testSetLocalRotation() { loc.setLocalRotation(yawRotation); assertEquals(yawRotation, loc.getLocalRotation()); } @Test public void testUnparentedWorldLocationSameAsLocal() { loc.setLocalPosition(pos1); assertEquals(loc.getLocalPosition(), loc.getWorldPosition()); } @Test public void testOffsetParentAddsToWorldLocation() { LocationComponent parent = giveParent(); loc.setLocalPosition(pos1); parent.setLocalPosition(pos2); assertEquals(pos1plus2, loc.getWorldPosition()); } @Test public void testParentRotatesWorldLocation() { LocationComponent parent = giveParent(); loc.setLocalPosition(pos1); parent.setLocalRotation(yawRotation); TeraAssert.assertEquals(new Vector3f(pos1.z, pos1.y, -pos1.x), loc.getWorldPosition(), 0.00001f); } @Test public void testParentScalesWorldLocation() { LocationComponent parent = giveParent(); loc.setLocalPosition(pos1); parent.setLocalScale(2.0f); assertEquals(new Vector3f(2, 4, 6), loc.getWorldPosition()); } @Test public void testScaleRotateAndOffsetCombineCorrectlyForWorldPosition() { LocationComponent parent = giveParent(); loc.setLocalPosition(pos1); parent.setLocalScale(2.0f); parent.setLocalPosition(pos2); parent.setLocalRotation(yawRotation); TeraAssert.assertEquals(new Vector3f(8, 7, 2), loc.getWorldPosition(), 0.00001f); } @Test public void testWorldRotationSameAsLocalRotationWhenNoParent() { loc.setLocalRotation(yawRotation); assertEquals(loc.getLocalRotation(), loc.getWorldRotation()); } @Test public void testWorldRotationCombinedWithParent() { LocationComponent parent = giveParent(); loc.setLocalRotation(pitchRotation); parent.setLocalRotation(yawRotation); assertEquals(yawPitch, loc.getWorldRotation()); } @Test public void testWorldScaleSameAsLocalWhenNoParent() { loc.setLocalScale(2.0f); assertEquals(loc.getLocalScale(), loc.getWorldScale(), 0.00001f); } @Test public void testWorldScaleStacksWithParent() { LocationComponent parent = giveParent(); loc.setLocalScale(2.f); parent.setLocalScale(2.f); assertEquals(4.f, loc.getWorldScale(), 0.000001f); } @Test public void testSetWorldPositionWorksWithNoParent() { loc.setWorldPosition(pos1); assertEquals(pos1, loc.getWorldPosition()); } @Test public void testSetWorldPositionWorksWithOffsetParent() { LocationComponent parent = giveParent(); parent.setLocalPosition(pos1); loc.setWorldPosition(pos1plus2); assertEquals(pos2, loc.getLocalPosition()); assertEquals(pos1plus2, loc.getWorldPosition()); } @Test public void testSetWorldPositionWorksWithScaledParent() { LocationComponent parent = giveParent(); parent.setLocalScale(2.0f); loc.setWorldPosition(pos1); assertEquals(pos1, loc.getWorldPosition()); } @Test public void testSetWorldPositionWorksWithRotatedParent() { LocationComponent parent = giveParent(); parent.setLocalRotation(yawRotation); loc.setWorldPosition(pos1); TeraAssert.assertEquals(pos1, loc.getWorldPosition(), 0.000001f); } @Test public void testSetWorldPositionWorksWithNestedRotatedParent() { LocationComponent first = new LocationComponent(); EntityRef firstEntity = createFakeEntityWith(first); LocationComponent second = new LocationComponent(); EntityRef secondEntity = createFakeEntityWith(second); LocationComponent third = new LocationComponent(); EntityRef thirdEntity = createFakeEntityWith(third); Location.attachChild(firstEntity, secondEntity); second.setLocalPosition(new Vector3f(1, 0, 0)); first.setLocalRotation(yawRotation); TeraAssert.assertEquals(new Vector3f(0, 0, -1), second.getWorldPosition(), 0.000001f); Location.attachChild(secondEntity, thirdEntity); second.setLocalRotation(pitchRotation); third.setLocalPosition(new Vector3f(0, 0, 0)); TeraAssert.assertEquals(new Vector3f(0, 0, -1), third.getWorldPosition(), 0.000001f); third.setLocalPosition(new Vector3f(0, 0, 1)); TeraAssert.assertEquals(new Vector3f(0.5f * (float) Math.sqrt(2), -0.5f * (float) Math.sqrt(2), -1), third.getWorldPosition(), 0.000001f); } @Test public void testSetWorldPositionWorksWithComplexParent() { LocationComponent parent = giveParent(); parent.setLocalRotation(yawRotation); parent.setLocalScale(2.0f); parent.setLocalPosition(pos2); loc.setWorldPosition(pos1); TeraAssert.assertEquals(pos1, loc.getWorldPosition(), 0.000001f); } @Test public void testSetWorldScaleWorksWithNoParent() { loc.setWorldScale(4.0f); assertEquals(4.0f, loc.getWorldScale(), 0.000001f); assertEquals(4.0f, loc.getLocalScale(), 0.000001f); } @Test public void testSetWorldScaleWorksWithScaledParent() { LocationComponent parent = giveParent(); parent.setLocalScale(4.0f); loc.setWorldScale(2.0f); assertEquals(2.0f, loc.getWorldScale(), 0.000001f); } @Test public void testSetWorldRotationWorksWithNoParent() { loc.setWorldRotation(yawRotation); assertEquals(yawRotation, loc.getWorldRotation()); assertEquals(yawRotation, loc.getLocalRotation()); } @Test public void testSetWorldRotationWithRotatedParent() { LocationComponent parent = giveParent(); parent.setLocalRotation(yawRotation); loc.setWorldRotation(yawPitch); TeraAssert.assertEquals(yawPitch, loc.getWorldRotation(), 0.0000001f); } @Test public void testPositionMaintainedWhenAttachedToParent() { LocationComponent parent = new LocationComponent(); EntityRef parentEntity = createFakeEntityWith(parent); parent.setWorldPosition(new Vector3f(1, 0, 0)); loc.setWorldPosition(new Vector3f(2, 0, 0)); Location.attachChild(parentEntity, entity); TeraAssert.assertEquals(new Vector3f(2, 0, 0), loc.getWorldPosition(), 0.000001f); } @Test public void testPositionMaintainedWhenRemovedFromParent() { LocationComponent parent = new LocationComponent(); EntityRef parentEntity = createFakeEntityWith(parent); parent.setWorldPosition(new Vector3f(1, 0, 0)); loc.setWorldPosition(new Vector3f(2, 0, 0)); Location.attachChild(parentEntity, entity); Location.removeChild(parentEntity, entity); TeraAssert.assertEquals(new Vector3f(2, 0, 0), loc.getWorldPosition(), 0.000001f); } @Test public void testPositionMaintainedWhenParentDestroyed() { LocationComponent parent = new LocationComponent(); EntityRef parentEntity = createFakeEntityWith(parent); parent.setWorldPosition(new Vector3f(1, 0, 0)); loc.setWorldPosition(new Vector3f(2, 0, 0)); Location.attachChild(parentEntity, entity); Location locationSystem = new Location(); locationSystem.onDestroyed(BeforeRemoveComponent.newInstance(), parentEntity, parent); when(parentEntity.getComponent(LocationComponent.class)).thenReturn(null); when(parentEntity.exists()).thenReturn(false); TeraAssert.assertEquals(new Vector3f(2, 0, 0), loc.getWorldPosition(), 0.000001f); } private LocationComponent giveParent() { LocationComponent parent = new LocationComponent(); EntityRef parentEntity = createFakeEntityWith(parent); Location.attachChild(parentEntity, entity); return parent; } }