/* * Copyright 2015 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.players; import jopenvr.VRControllerState_t; import org.joml.Matrix4f; import org.terasology.entitySystem.Component; import org.terasology.entitySystem.Owns; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.math.TeraMath; import org.terasology.math.geom.Vector3f; import org.terasology.rendering.openvrprovider.ControllerListener; import org.terasology.math.geom.Quat4f; import org.terasology.rendering.openvrprovider.OpenVRProvider; /** * Only used by the client side so that held items can be positioned in line with the camera */ public class FirstPersonHeldItemMountPointComponent implements Component, ControllerListener { @Owns public EntityRef mountPointEntity = EntityRef.NULL; public Vector3f rotateDegrees = Vector3f.zero(); public Vector3f translate = Vector3f.zero(); public Quat4f rotationQuaternion; public float scale = 1f; // TODO: @In private final OpenVRProvider vrProvider = OpenVRProvider.getInstance(); // The hand/tool models seem to have an origin other than the pivot point. This is a best-effort correction, // in the form of a 4x4 homogeneous transformation matrix private Matrix4f toolAdjustmentMatrix = new Matrix4f( 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, (float) Math.cos(230.* TeraMath.DEG_TO_RAD), (float) Math.sin(230. * TeraMath.DEG_TO_RAD), 0.0f, 0.0f, (float) -Math.sin(230. * TeraMath.DEG_TO_RAD), (float) Math.cos(230. * TeraMath.DEG_TO_RAD), 0.0f, 0.0f, -0.05f, -0.2f, 1.0f ); /** * If possible, make this object listen for controller pose updates. If the vrProvider is not active (i.e. no headset * is connected), then the callback methods will not get called for the first time, and this component will act as * it would in its default state (static location, activation triggered upon use of equipped object). */ public void trySubscribeToControllerPoses() { vrProvider.getState().addControllerListener(this); } /** * A callback target for the controller listener. This callback triggers when a button is pressed on the controllers. * It's currently ignored by this class. This method and the below method are both designed to be called in their * roles as listeners, and not really part of the public interface of this class. * @param stateBefore - the state before the state change. * @param stateAfter - the state after the state change. * @param nController - the hand index, 0 for left and 1 for right. */ public void buttonStateChanged(VRControllerState_t stateBefore, VRControllerState_t stateAfter, int nController) { // nothing for now } /** * A callback target for the controller listener. When this callback triggers, the pos of the mount point will * cuange to the value of the pose parameter. This is mainly designed as a callback, and not intended to be part * of the public interface of this class. * @param pose - the controller pose - a homogenous transformation matrix. * @param handIndex - the hand index - 0 for left and 1 for right. */ public void poseChanged(Matrix4f pose, int handIndex) { // do nothing for the second controller // TODO: put a hand for the second controller. if (handIndex != 0) { return; } Matrix4f adjustedPose = pose.mul(toolAdjustmentMatrix); translate = new Vector3f(adjustedPose.m30(), adjustedPose.m31(), adjustedPose.m32()); org.joml.Vector4f jomlQuaternion = org.terasology.rendering.openvrprovider.OpenVRUtil.convertToQuaternion(adjustedPose); if (rotationQuaternion == null) { rotationQuaternion = new Quat4f(jomlQuaternion.x, jomlQuaternion.y, jomlQuaternion.z, jomlQuaternion.w); } else { rotationQuaternion.set(jomlQuaternion.x, jomlQuaternion.y, jomlQuaternion.z, jomlQuaternion.w); } } }