Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New PoseFrame streaming format #1284

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
33 changes: 20 additions & 13 deletions server/core/src/main/java/dev/slimevr/autobone/AutoBone.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import dev.slimevr.SLIMEVR_IDENTIFIER
import dev.slimevr.VRServer
import dev.slimevr.autobone.errors.*
import dev.slimevr.config.AutoBoneConfig
import dev.slimevr.poseframeformat.PoseFrameIO
import dev.slimevr.poseframeformat.PfrIO
import dev.slimevr.poseframeformat.PfsIO
import dev.slimevr.poseframeformat.PoseFrames
import dev.slimevr.tracking.processor.BoneType
import dev.slimevr.tracking.processor.HumanPoseManager
Expand Down Expand Up @@ -713,7 +714,7 @@ class AutoBone(server: VRServer) {
if (saveDir.isDirectory || saveDir.mkdirs()) {
LogManager
.info("[AutoBone] Exporting frames to \"${recordingFile.path}\"...")
if (PoseFrameIO.tryWriteToFile(recordingFile, frames)) {
if (PfsIO.tryWriteToFile(recordingFile, frames)) {
LogManager
.info(
"[AutoBone] Done exporting! Recording can be found at \"${recordingFile.path}\".",
Expand All @@ -740,29 +741,35 @@ class AutoBone(server: VRServer) {
var recordingFile: File
var recordingIndex = 1
do {
recordingFile = File(saveDir, "ABRecording${recordingIndex++}.pfr")
recordingFile = File(saveDir, "ABRecording${recordingIndex++}.pfs")
} while (recordingFile.exists())
saveRecording(frames, recordingFile)
}

fun loadRecordings(): FastList<Pair<String, PoseFrames>> {
val recordings = FastList<Pair<String, PoseFrames>>()
if (!loadDir.isDirectory) return recordings
val files = loadDir.listFiles() ?: return recordings
for (file in files) {
if (!file.isFile || !file.name.endsWith(".pfr", ignoreCase = true)) continue

LogManager
.info(
"[AutoBone] Detected recording at \"${file.path}\", loading frames...",
)
val frames = PoseFrameIO.tryReadFromFile(file)
loadDir.listFiles()?.forEach { file ->
if (!file.isFile) return@forEach

val frames = if (file.name.endsWith(".pfs", ignoreCase = true)) {
LogManager.info("[AutoBone] Loading PFS recording from \"${file.path}\"...")
PfsIO.tryReadFromFile(file)
} else if (file.name.endsWith(".pfr", ignoreCase = true)) {
LogManager.info("[AutoBone] Loading PFR recording from \"${file.path}\"...")
PfrIO.tryReadFromFile(file)
} else {
return@forEach
}

if (frames == null) {
LogManager.severe("Reading frames from \"${file.path}\" failed...")
LogManager.severe("[AutoBone] Failed to load recording from \"${file.path}\".")
} else {
recordings.add(Pair.of(file.name, frames))
LogManager.info("[AutoBone] Loaded recording from \"${file.path}\".")
}
}

return recordings
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException

object PoseFrameIO {
object PfrIO {
@Throws(IOException::class)
private fun writeVector3f(outputStream: DataOutputStream, vector: Vector3) {
outputStream.writeFloat(vector.x)
Expand All @@ -34,41 +34,46 @@ object PoseFrameIO {
outputStream.writeFloat(quaternion.w)
}

fun writeFrame(outputStream: DataOutputStream, trackerFrame: TrackerFrame?) {
if (trackerFrame == null) {
outputStream.writeInt(0)
return
}

var dataFlags = trackerFrame.dataFlags

// Don't write destination strings anymore, replace with
// the enum
if (trackerFrame.hasData(TrackerFrameData.DESIGNATION_STRING)) {
dataFlags = TrackerFrameData.TRACKER_POSITION_ENUM
.add(TrackerFrameData.DESIGNATION_STRING.remove(dataFlags))
}
outputStream.writeInt(dataFlags)
if (trackerFrame.hasData(TrackerFrameData.ROTATION)) {
writeQuaternion(outputStream, trackerFrame.rotation!!)
}
if (trackerFrame.hasData(TrackerFrameData.POSITION)) {
writeVector3f(outputStream, trackerFrame.position!!)
}
if (TrackerFrameData.TRACKER_POSITION_ENUM.check(dataFlags)) {
// ID is offset by 1 for historical reasons
outputStream.writeInt(trackerFrame.trackerPosition!!.id - 1)
}
if (trackerFrame.hasData(TrackerFrameData.ACCELERATION)) {
writeVector3f(outputStream, trackerFrame.acceleration!!)
}
if (trackerFrame.hasData(TrackerFrameData.RAW_ROTATION)) {
writeQuaternion(outputStream, trackerFrame.rawRotation!!)
}
}

fun writeFrames(outputStream: DataOutputStream, frames: PoseFrames) {
outputStream.writeInt(frames.frameHolders.size)
for (tracker in frames.frameHolders) {
outputStream.writeUTF(tracker.name)
outputStream.writeInt(tracker.frames.size)
for (i in 0 until tracker.frames.size) {
val trackerFrame = tracker.tryGetFrame(i)
if (trackerFrame == null) {
outputStream.writeInt(0)
continue
}
var dataFlags = trackerFrame.dataFlags

// Don't write destination strings anymore, replace with
// the enum
if (trackerFrame.hasData(TrackerFrameData.DESIGNATION_STRING)) {
dataFlags = TrackerFrameData.TRACKER_POSITION_ENUM
.add(TrackerFrameData.DESIGNATION_STRING.remove(dataFlags))
}
outputStream.writeInt(dataFlags)
if (trackerFrame.hasData(TrackerFrameData.ROTATION)) {
writeQuaternion(outputStream, trackerFrame.rotation!!)
}
if (trackerFrame.hasData(TrackerFrameData.POSITION)) {
writeVector3f(outputStream, trackerFrame.position!!)
}
if (TrackerFrameData.TRACKER_POSITION_ENUM.check(dataFlags)) {
outputStream.writeInt(trackerFrame.trackerPosition!!.ordinal)
}
if (trackerFrame.hasData(TrackerFrameData.ACCELERATION)) {
writeVector3f(outputStream, trackerFrame.acceleration!!)
}
if (trackerFrame.hasData(TrackerFrameData.RAW_ROTATION)) {
writeQuaternion(outputStream, trackerFrame.rawRotation!!)
}
writeFrame(outputStream, tracker.tryGetFrame(i))
}
}
}
Expand Down Expand Up @@ -112,6 +117,43 @@ object PoseFrameIO {
return Quaternion(w, x, y, z)
}

fun readFrame(inputStream: DataInputStream): TrackerFrame {
val dataFlags = inputStream.readInt()

var designation: TrackerPosition? = null
if (TrackerFrameData.DESIGNATION_STRING.check(dataFlags)) {
designation = getByDesignation(inputStream.readUTF())
}
var rotation: Quaternion? = null
if (TrackerFrameData.ROTATION.check(dataFlags)) {
rotation = readQuaternion(inputStream)
}
var position: Vector3? = null
if (TrackerFrameData.POSITION.check(dataFlags)) {
position = readVector3f(inputStream)
}
if (TrackerFrameData.TRACKER_POSITION_ENUM.check(dataFlags)) {
// ID is offset by 1 for historical reasons
designation = TrackerPosition.getById(inputStream.readInt() + 1)
}
var acceleration: Vector3? = null
if (TrackerFrameData.ACCELERATION.check(dataFlags)) {
acceleration = readVector3f(inputStream)
}
var rawRotation: Quaternion? = null
if (TrackerFrameData.RAW_ROTATION.check(dataFlags)) {
rawRotation = readQuaternion(inputStream)
}

return TrackerFrame(
designation,
rotation,
position,
acceleration,
rawRotation,
)
}

fun readFrames(inputStream: DataInputStream): PoseFrames {
val trackerCount = inputStream.readInt()
val trackers = FastList<TrackerFrames>(trackerCount)
Expand All @@ -122,40 +164,7 @@ object PoseFrameIO {
trackerFrameCount,
)
for (j in 0 until trackerFrameCount) {
val dataFlags = inputStream.readInt()
var designation: TrackerPosition? = null
if (TrackerFrameData.DESIGNATION_STRING.check(dataFlags)) {
designation = getByDesignation(inputStream.readUTF())
}
var rotation: Quaternion? = null
if (TrackerFrameData.ROTATION.check(dataFlags)) {
rotation = readQuaternion(inputStream)
}
var position: Vector3? = null
if (TrackerFrameData.POSITION.check(dataFlags)) {
position = readVector3f(inputStream)
}
if (TrackerFrameData.TRACKER_POSITION_ENUM.check(dataFlags)) {
designation = TrackerPosition.values()[inputStream.readInt()]
}
var acceleration: Vector3? = null
if (TrackerFrameData.ACCELERATION.check(dataFlags)) {
acceleration = readVector3f(inputStream)
}
var rawRotation: Quaternion? = null
if (TrackerFrameData.RAW_ROTATION.check(dataFlags)) {
rawRotation = readQuaternion(inputStream)
}
trackerFrames
.add(
TrackerFrame(
designation,
rotation,
position,
acceleration,
rawRotation,
),
)
trackerFrames.add(readFrame(inputStream))
}
trackers.add(TrackerFrames(name, trackerFrames))
}
Expand Down
Loading
Loading