Skip to content

Commit

Permalink
Docstrings to PreTick, Fixes, and VRPoseHistory
Browse files Browse the repository at this point in the history
  • Loading branch information
hammy275 committed Sep 11, 2023
1 parent 452746f commit ac13bf5
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 13 deletions.
1 change: 0 additions & 1 deletion common/src/main/java/org/vivecraft/api/VivecraftAPI.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.vivecraft.api;

import com.google.common.annotations.Beta;
import net.minecraft.world.entity.player.Player;
import org.vivecraft.api.data.VRData;
import org.vivecraft.common.api_impl.APIImpl;
Expand Down
10 changes: 8 additions & 2 deletions common/src/main/java/org/vivecraft/api/client/Tracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

import net.minecraft.client.player.LocalPlayer;

/**
* A tracker is an object that is run for the local player during the game tick or before rendering a frame.
* Using trackers are one of the cleanest ways to interact with Vivecraft's data; it's how Vivecraft itself does.
* Trackers should generally use {@link VivecraftClientAPI#getPreTickWorldData()}, and are only run for
* the local player if they are in VR.
*/
public interface Tracker {

/**
Expand All @@ -19,8 +25,8 @@ public interface Tracker {

/**
* The ticking type for this tracker.
* If this is PER_FRAME, the tracker is called once with the local player per frame.
* If this is PER_TICK, the tracker is called once with the local player per game tick.
* If this is PER_FRAME, the tracker is called once with the local player per frame before the frame is rendered.
* If this is PER_TICK, the tracker is called once with the local player per game tick during the tick.
* @return The ticking type this tracker should use.
*/
TrackerTickType tickType();
Expand Down
88 changes: 88 additions & 0 deletions common/src/main/java/org/vivecraft/api/client/VRPoseHistory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.vivecraft.api.client;

import net.minecraft.world.phys.Vec3;
import org.vivecraft.api.data.VRPose;

import java.util.List;

/**
* Represents historical VRData associated with a player.
*/
public interface VRPoseHistory {

/**
* The maximum amount of ticks back data is held for.
* It is only guaranteed that historical data does not go beyond this number of ticks back. Functions do not
* guarantee that they will reference this many ticks, as, for example, this amount of ticks may not have gone
* by for the player this history represents.
* Passing a value larger than this number to any methods below in their maxTicksBack or ticksBack parameters
* will throw an {@link IllegalArgumentException}.
*/
int MAX_TICKS_BACK = 20;

/**
* @return The amount of ticks worth of history being held.
*/
int ticksOfHistory();

/**
* Gets a raw list of {@link VRPose} instances, with index 0 representing the least recent pose known.
* @return The aforementioned list of {@link VRPose} instances.
*/
List<VRPose> getAllHistoricalData() throws IllegalArgumentException;

/**
* Gets the historical data ticksBack ticks back. This will throw an IllegalStateException if the data cannot
* be retrieved due to not having enough history.
* @param ticksBack Ticks back to retrieve data.
* @return A {@link VRPose} instance from ticksBack ticks ago.
* @throws IllegalStateException If ticksBack references a tick that there is not yet data for.
* @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0.
*/
VRPose getHistoricalData(int ticksBack) throws IllegalArgumentException, IllegalStateException;

/**
* Gets the net movement between the most recent data in this instance and the oldest position that can be
* retrieved, going no farther back than maxTicksBack.
* @param maxTicksBack The maximum amount of ticks back to compare the most recent data with.
* @return The aforementioned net movement. Note that this will return zero change on all axes if only zero ticks
* can be looked back.
* @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0.
*/
Vec3 netMovement(int maxTicksBack) throws IllegalArgumentException;

/**
* Gets the average velocity in blocks/tick between the most recent data in this instance and the oldest position
* that can be retrieved, going no farther back than maxTicksBack.
* @param maxTicksBack The maximum amount of ticks back to calculate velocity with.
* @return The aforementioned average velocity on each axis. Note that this will return zero velocity on all axes
* if only zero ticks can be looked back.
* @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0.
*/
Vec3 averageVelocity(int maxTicksBack) throws IllegalArgumentException;

/**
* Gets the average speed in blocks/tick between the most recent data in this instance and the oldest position
* that can be retrieved, going no farther back than maxTicksBack.
* @param maxTicksBack The maximum amount of ticks back to calculate speed with.
* @return The aforementioned average speed on each axis. Note that this will return zero speed if only zero ticks
* can be looked back.
* @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0.
*/
default double averageSpeed(int maxTicksBack) throws IllegalArgumentException {
Vec3 averageVelocity = averageVelocity(maxTicksBack);
return Math.sqrt(averageVelocity.x() * averageVelocity.x() +
averageVelocity.y() * averageVelocity.y() +
averageVelocity.z() * averageVelocity.z());
}

/**
* Gets the average position between the most recent data in this instance and the oldest position that can be
* retrieved, going no farther back than maxTicksBack.
* @param maxTicksBack The maximum amount of ticks back to calculate velocity with.
* @return The aforementioned average position. Note that this will return the current position if only zero ticks
* can be looked back.
* @throws IllegalArgumentException Thrown when maxTicksBack is larger than {@value #MAX_TICKS_BACK} or less than 0.
*/
Vec3 averagePosition(int maxTicksBack) throws IllegalArgumentException;
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
package org.vivecraft.api.client;

import com.google.common.annotations.Beta;
import net.minecraft.world.InteractionHand;
import org.vivecraft.api.data.VRData;
import org.vivecraft.client.api_impl.ClientAPIImpl;

import javax.annotation.Nullable;

public interface VivecraftClientAPI {

static VivecraftClientAPI getInstance() {
return ClientAPIImpl.INSTANCE;
}

/**
* Gets data representing the devices as they exist in the room before the game tick. This is effectively
* the latest polling data from the VR devices.
* Adds the tracker to the list of all trackers to be run for the local player. See the documentation for
* {@link Tracker} for more information on what a tracker is.
* @param tracker Tracker to register.
*/
void addTracker(Tracker tracker);

/**
* Gets data representing the devices as they exist in the room before the game tick.
* Note that this data is gathered BEFORE mod loaders' pre-tick events.
* @return Data representing the devices in the room pre-tick.
* @throws IllegalStateException Thrown when the local player isn't in VR.
*/
VRData getPreTickRoomData() throws IllegalStateException;

/**
* Gets data representing the devices as they exist in the room after the game tick.
* Note that this data is gathered AFTER mod loaders' post-tick events.
* @return Data representing the devices in the room post-tick.
* @throws IllegalStateException Thrown when the local player isn't in VR.
*/
Expand All @@ -28,7 +38,9 @@ static VivecraftClientAPI getInstance() {
/**
* Gets data representing the devices as they exist in Minecraft coordinates before the game tick.
* This is the same as {@link #getPreTickRoomData()} with translation to Minecraft's coordinates as of the last
* tick.
* tick, and is the main data source used by Vivecraft. If you're unsure which {@link VRData} method to use, you
* likely want to use this one.
* Note that this data is gathered BEFORE mod loaders' pre-tick events.
* @return Data representing the devices in Minecraft space pre-tick.
* @throws IllegalStateException Thrown when the local player isn't in VR.
*/
Expand All @@ -37,7 +49,7 @@ static VivecraftClientAPI getInstance() {
/**
* Gets data representing the devices as they exist in Minecraft coordinates after the game tick.
* This is the data sent to the server, and also used to calculate the data in {@link #getWorldRenderData()}.
* If you're unsure which {@link VRData} method to use, you likely want to use this one.
* Note that this data is gathered AFTER mod loaders' post-tick events.
* @return Data representing the devices in Minecraft space post-tick.
* @throws IllegalStateException Thrown when the local player isn't in VR.
*/
Expand Down Expand Up @@ -111,8 +123,50 @@ default void triggerHapticPulse(int controllerNum, float duration) {
float getWorldScale();

/**
* Adds the tracker to the list of all trackers to be run for the local player.
* @param tracker Tracker to register.
* Returns the history of VR poses for the player for the HMD. Will return null if the player isn't
* in VR.
* @return The historical VR data for the player's HMD, or null if the player isn't in VR.
*/
void addTracker(Tracker tracker);
@Nullable
VRPoseHistory getHistoricalVRHMDPoses();

/**
* Returns the history of VR poses for the player for a controller. Will return null if the player isn't
* in VR.
* @param controller The controller number to get, with 0 being the primary controller.
* @return The historical VR data for the player's controller, or null if the player isn't in VR.
*/
@Nullable
VRPoseHistory getHistoricalVRControllerPoses(int controller);

/**
* Returns the history of VR poses for the player for a controller. Will return null if the player isn't
* in VR.
* @param hand The hand to get controller history for.
* @return The historical VR data for the player's controller, or null if the player isn't in VR.
*/
@Nullable
default VRPoseHistory getHistoricalVRControllerData(InteractionHand hand) {
return getHistoricalVRControllerPoses(hand.ordinal());
}

/**
* Returns the history of VR poses for the player for the primary controller. Will return null if the
* player isn't in VR.
* @return The historical VR data for the player's primary controller, or null if the player isn't in VR.
*/
@Nullable
default VRPoseHistory getHistoricalVRController0Data() {
return getHistoricalVRControllerPoses(0);
}

/**
* Returns the history of VR poses for the player for the secondary controller. Will return null if the
* player isn't in VR.
* @return The historical VR data for the player's secondary controller, or null if the player isn't in VR.
*/
@Nullable
default VRPoseHistory getHistoricalVRController1Data() {
return getHistoricalVRControllerPoses(1);
}
}
2 changes: 1 addition & 1 deletion common/src/main/java/org/vivecraft/api/data/VRData.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public interface VRData {
/**
* Gets the pose data for a given controller.
*
* @param controller The controller number to get.
* @param controller The controller number to get, with 0 being the primary controller.
* @return The specified controller's pose data.
*/
VRPose getController(int controller);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package org.vivecraft.client.api_impl;

import org.jetbrains.annotations.Nullable;
import org.vivecraft.api.client.Tracker;
import org.vivecraft.api.client.VRPoseHistory;
import org.vivecraft.api.client.VivecraftClientAPI;
import org.vivecraft.api.data.VRData;
import org.vivecraft.api.data.VRPose;
import org.vivecraft.client.api_impl.data.VRPoseHistoryImpl;
import org.vivecraft.client_vr.ClientDataHolderVR;
import org.vivecraft.client_vr.VRState;
import org.vivecraft.client_vr.provider.ControllerType;
Expand All @@ -12,9 +16,25 @@ public final class ClientAPIImpl implements VivecraftClientAPI {

public static final ClientAPIImpl INSTANCE = new ClientAPIImpl();

private final VRPoseHistoryImpl hmdHistory = new VRPoseHistoryImpl();
private VRPoseHistoryImpl c0History = new VRPoseHistoryImpl();
private VRPoseHistoryImpl c1History = new VRPoseHistoryImpl();

private ClientAPIImpl() {
}

public void clearHistories() {
this.hmdHistory.clear();
this.c0History.clear();
this.c1History.clear();
}

public void addPosesToHistory(VRData data) {
this.hmdHistory.addPose(data.getHMD());
this.c0History.addPose(data.getController0());
this.c1History.addPose(data.getController1());
}

@Override
public VRData getPreTickRoomData() throws IllegalStateException {
if (!isVrActive()) {
Expand Down Expand Up @@ -108,4 +128,24 @@ public float getWorldScale() {
public void addTracker(Tracker tracker) {
ClientDataHolderVR.getInstance().addTracker(tracker);
}

@Nullable
@Override
public VRPoseHistory getHistoricalVRHMDPoses() {
if (!isVrActive()) {
return null;
}
return this.hmdHistory;
}

@Nullable
@Override
public VRPoseHistory getHistoricalVRControllerPoses(int controller) {
if (controller != 0 && controller != 1) {
throw new IllegalArgumentException("Historical VR controller data only available for controllers 0 and 1.");
} else if (!isVrActive()) {
return null;
}
return controller == 0 ? this.c0History : this.c1History;
}
}
Loading

0 comments on commit ac13bf5

Please sign in to comment.