LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: bluenote10 on March 28, 2016, 21:08:53

Title: Oculus Rift SDK 1.3 released
Post by: bluenote10 on March 28, 2016, 21:08:53
Today Oculus has finally released the first official consumer version of their SDK:

https://developer.oculus.com/downloads/pc/1.3.0/Oculus_SDK_for_Windows/

I only had a brief look so far, but judging from the 0.8 to 1.3 migration guide (https://developer.oculus.com/documentation/pcsdk/latest/concepts/release-migration/) it looks like the change isn't as big as the version jump suggests. Mainly some renamed/removed functionality. Not sure if this new VR Focus Management requires any bigger changes though. Will have a closer look in the next days, maybe I can help porting LWJGL to the new version.
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on March 29, 2016, 09:58:55
I'm available for testing with my DK2.  Having tried some of the 1.3 demos I'm quite keen to see if we can still use Java for development :)
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 01, 2016, 11:18:33
relating to this, is LWJGL3 supporting xbox controllers?  The Rift ships with one and also with a seperate 'remote' that we may want to support...
Title: Re: Oculus Rift SDK 1.3 released
Post by: spasi on April 01, 2016, 11:30:26
Quote from: BrickFarmer on April 01, 2016, 11:18:33relating to this, is LWJGL3 supporting xbox controllers?

Yes, via GLFW. Actually, this issue (https://github.com/glfw/glfw/issues/232) was closed yesterday, so controller support should be great now.

On topic, I'll update the LibOVR bindings to 1.3.0 today or tomorrow. Sorry for the delay.
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 01, 2016, 12:35:52
Awesome! always one step ahead of us :)
Title: Re: Oculus Rift SDK 1.3 released
Post by: spasi on April 04, 2016, 13:37:44
The latest nightly build (3.0.0 #64) supports Oculus SDK 1.3.0.
Title: Re: Oculus Rift SDK 1.3 released
Post by: bluenote10 on April 04, 2016, 15:21:15
Wow, thanks a lot for solving this so quickly -- awesome job! I got hold back by some other tasks and was just about to dig into this.

I'm now experimenting with the new build and there is one thing that isn't quite clear to me. What has changed from 0.8 to 1.3 is that the texture swap chain is now an opaque pointer. So it is no longer possible to extract the textures / textures count / current index directly but by means of calling ovr_GetTextureSwapChainBufferGL / ovr_GetTextureSwapChainLength /     ovr_GetTextureSwapChainCurrentIndex. I can see the latter two in class OVR. ovr_GetTextureSwapChainBufferGL should probably live in class OVRGL, but I can't see it. Did I somehow overlook it or is there some other way to get texture IDs stored in the swap chain?
Title: Re: Oculus Rift SDK 1.3 released
Post by: spasi on April 04, 2016, 15:25:21
Quote from: bluenote10 on April 04, 2016, 15:21:15Did I somehow overlook it?

No, you didn't, I missed it in the 0.8-1.3.0 diff. Adding now, it will appear in the next build. Thanks!
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 04, 2016, 15:31:49
Hi,  Thanks for the update, I'm also just porting my 'demo' over and it seems to be pulling in the old sources from maven nightly, for example ovrEye_Count which I think has been removed, but shows up in my sources, or do I need to manually place a new nightly sources jar into the .m2 local repo?  Sorry it's been a while since I touched this code.
Title: Re: Oculus Rift SDK 1.3 released
Post by: Kai on April 04, 2016, 15:52:58
I always use this dependency for the Java jar, which works just fine and pulls the latest with `mvn -U clean package`:

<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl</artifactId>
<version>3.0.0-SNAPSHOT</version>
</dependency>

Make sure to not use any 'A' or 'B' suffix in the version.
Title: Re: Oculus Rift SDK 1.3 released
Post by: spasi on April 04, 2016, 15:58:54
Build #65 is up.

The latest snapshot sources (https://oss.sonatype.org/content/repositories/snapshots/org/lwjgl/lwjgl/3.0.0-SNAPSHOT/) look fine.
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 04, 2016, 16:58:52
thanks! I got maven to pull the sources in, but the name of the jar had changed, so on with my migration and I'm going to hard code it with 2 eyes :)
Title: Re: Oculus Rift SDK 1.3 released
Post by: bluenote10 on April 04, 2016, 18:35:43
That was again super quick, thanks a lot! Migration to 1.3.0 worked very well for me, and everything seems to be running perfectly so far.

@BrickFarmer: I had a look in your code and there is one potential bug when moving to 1.3: In this line (https://github.com/WhiteHexagon/example-lwjgl3-rift/blob/3412fd1bad7ac3cf0f45416f46004f95588f9a6f/src/main/java/com/sunshineapps/rift/experimental/RiftWindow0800.java#L289) you are iterating over "eyes", but the loop should rather go over the number of textures in the swap chain (so using ovr_GetTextureSwapChainLength for the loop length; and it would make more sense to rename "eye" in just "i"). In 0.8 the number of textures in the swap chain happened to be 2 like the number of eyes. With the 1.3 SDK I now get 3 textures, probably due to asynchronous timewarp.
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 04, 2016, 20:51:06
@bluenote10 Thanks!!  It seems like they changed quite a bit more than I thought! but well done on getting yours working so fast :) do you DK2 or CV1?
Title: Re: Oculus Rift SDK 1.3 released
Post by: bluenote10 on April 04, 2016, 22:08:11
If it is of any help, this is my Scala code (still WIP, not cleaned up -- but since it was inspired by your example you should get the idea):


import org.lwjgl.glfw.GLFW._
import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL11._
import org.lwjgl.opengl.GL12._
import org.lwjgl.opengl.GL21._
import org.lwjgl.opengl.GL14._
import org.lwjgl.opengl.GL20._
import org.lwjgl.opengl.GL30._

import org.lwjgl.ovr._
import org.lwjgl.ovr.OVR._
import org.lwjgl.ovr.OVRUtil._
import org.lwjgl.ovr.OVRGL._
import org.lwjgl.ovr.OVRErrorCode._
import org.lwjgl.system.MemoryUtil
import org.lwjgl.BufferUtils


trait OvrWrapper {
 
  def updateCamera(): CameraState
  def render(renderFunction: MatrixSet => Unit, clearColor: Color)
 
  def resetPosition()
  def toggleHud()

  def isCloseRequested(): Boolean
  def processMessages()
 
  def destroy()
}


class OvrWrapperWindows(Boolean, useSRGB: Boolean = false) extends OvrWrapper {

  private val logger = Logger(LoggerFactory getLogger getClass)
 
  OvrWrapperWindows.init()
  OvrWrapperWindows.detect()
 
  val (session, luid) = OvrWrapperWindows.createSession()

  // Usage of ovr_ConfigureTracking is no longer needed unless you want to disable tracking features.
  // ovr_ConfigureTracking(session, 0, 0)

  val window = OvrWrapperWindows.initGlContext()
 
 
  // get hmd desc
  val hmdDesc = OVRHmdDesc.malloc()
  ovr_GetHmdDesc(session, hmdDesc)
  val resolution = hmdDesc.Resolution()
 
  // prepare projection matrices
  val projections = Array.tabulate(2){ eye =>
    val m = OVRMatrix4f.calloc()
    OVRUtil.ovrMatrix4f_Projection(hmdDesc.DefaultEyeFov(eye), 0.05f, 1000f, ovrProjection_ClipRangeOpenGL, m)
    val valuesArray = Array.tabulate(16)(i => m.M(i))
    val mConverted = Mat4f.createFromRowMajorArray(valuesArray)
    m.free()
    mConverted
  }
 
  // determine backbuffer size
  val recommenedTex0Size = OVRSizei.calloc()
  val recommenedTex1Size = OVRSizei.calloc()
  ovr_GetFovTextureSize(session, ovrEye_Left, hmdDesc.DefaultEyeFov(0), 2.0f, recommenedTex0Size)   
  ovr_GetFovTextureSize(session, ovrEye_Right, hmdDesc.DefaultEyeFov(1), 2.0f, recommenedTex1Size)   
 
  val wTotal = recommenedTex0Size.w + recommenedTex1Size.w
  val hTotal = recommenedTex0Size.h max recommenedTex1Size.h
  logger.debug(f"recommenedTex0Size = ${recommenedTex0Size.w} x ${recommenedTex0Size.h}")
  logger.debug(f"recommenedTex1Size = ${recommenedTex1Size.w} x ${recommenedTex1Size.h}")
  logger.debug(f"total = $wTotal x $hTotal")
 
  // create fbo
  val fbo = glGenFramebuffers()
  GlWrapper.checkGlError("after glGenFramebuffers", false)

  val renderBuffer = glGenRenderbuffers()
  glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer)
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, wTotal, hTotal)
  glBindRenderbuffer(GL_RENDERBUFFER, 0)
  GlWrapper.checkGlError("after glRenderbufferStorage", false)
 
  glBindFramebuffer(GL_FRAMEBUFFER, fbo)
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer)
  glBindFramebuffer(GL_FRAMEBUFFER, 0)
  GlWrapper.checkGlError("after glFramebufferRenderbuffer", false)
 
  // create swap texture set
  val textureSwapChainPB = BufferUtils.createPointerBuffer(1)
  // It looks like that in order to disable sRGB we have to
  // set the texture format to sRGB but omit the call the
  // enabling sRGB in the framebuffer. Info here:
  // https://forums.oculus.com/community/discussion/24347/srgb-and-sdk-0-6-0-0
  val colorSpace = ovrFORMAT_R8G8B8A8_UNORM_SRGB
  val textureSwapChainDesc = OVRTextureSwapChainDesc.calloc()
  textureSwapChainDesc.Type(ovrTexture_2D)
  textureSwapChainDesc.ArraySize(1)
  textureSwapChainDesc.Format(colorSpace)
  textureSwapChainDesc.Width(wTotal)
  textureSwapChainDesc.Height(hTotal)
  textureSwapChainDesc.MipLevels(1) // TODO: what do I need here -- looks like values > 1 result in black screen...
  textureSwapChainDesc.SampleCount(1)
  textureSwapChainDesc.StaticImage(false)
  textureSwapChainDesc.MiscFlags(ovrTextureMisc_None) // TODO: what do I need here
  if (ovr_CreateTextureSwapChainGL(session, textureSwapChainDesc, textureSwapChainPB) != ovrSuccess) {
    throw new IllegalStateException("Failed to create Swap Texture Set")
  }
  textureSwapChainDesc.free()
 
  val textureSwapChain = textureSwapChainPB.get(0)
  val texturesPerEyeCount = OvrWrapperWindows.getTextureSwapChainLength(session, textureSwapChain)
  logger.debug("texturesPerEyeCount = " + texturesPerEyeCount)
 
  val textures = Range(0, texturesPerEyeCount).map{ i =>
    val textureID = OvrWrapperWindows.getTextureSwapChainBufferGL(session, textureSwapChain, i)
    logger.debug(f"textureId = ${textureID}")
    glBindTexture(GL_TEXTURE_2D, textureID)
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
    glGenerateMipmap(GL_TEXTURE_2D)
  }
  // important: we have to commit once before rendering the first frame
  ovr_CommitTextureSwapChain(session, textureSwapChain)
 
 
  // get eye render desc
  val eyeRenderDesc = Array.tabulate(2){ eye =>
    val eyeRenderDesc = OVREyeRenderDesc.malloc()
    ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov(eye), eyeRenderDesc)
    eyeRenderDesc
  }
 
  // prepare layer
  val layer0 = OVRLayerEyeFov.calloc()
  layer0.Header().Type(ovrLayerType_EyeFov)
  layer0.Header().Flags(ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality)
  layer0.ColorTexture(0, textureSwapChain)
  layer0.ColorTexture(1, textureSwapChain)
  layer0.Fov(0, eyeRenderDesc(0).Fov())
  layer0.Fov(1, eyeRenderDesc(1).Fov())
  layer0.Viewport(0).Size(recommenedTex0Size)
  layer0.Viewport(1).Size(recommenedTex1Size)
  layer0.Viewport(0).Pos.x(0)
  layer0.Viewport(0).Pos.y(0)
  layer0.Viewport(1).Pos.x(recommenedTex0Size.w)
  layer0.Viewport(1).Pos.y(0)
 
  val layers = BufferUtils.createPointerBuffer(1)
  layers.put(0, layer0.Header())
 
  hmdDesc.free()
  recommenedTex0Size.free()
  recommenedTex1Size.free()
 
  // prepare hmdToEyeViewOffsets (required for the call to ovr_CalcEyePoses)
  val hmdToEyeViewOffsets = OVRVector3f.calloc(2)
  hmdToEyeViewOffsets.put(0, eyeRenderDesc(ovrEye_Left).HmdToEyeOffset())
  hmdToEyeViewOffsets.put(1, eyeRenderDesc(ovrEye_Right).HmdToEyeOffset())   

  // prepare outEyePoses (required for the call to ovr_CalcEyePoses)
  val outEyePoses = OVRPosef.create(2)
 
  val tracking = OVRTrackingState.calloc()
  var headPose: OVRPosef = null
 
  val hudModes = Array(
    ovrPerfHud_Off,
    ovrPerfHud_PerfSummary,
    ovrPerfHud_LatencyTiming,
    ovrPerfHud_AppRenderTiming,
    ovrPerfHud_CompRenderTiming,
    ovrPerfHud_VersionInfo
  )
  var hudModeIndex = 0
 
 
  def updateCamera(): CameraState = {
    val timeDisplayMidpointSeconds = ovr_GetPredictedDisplayTime(session, 0)
    ovr_GetTrackingState(session, timeDisplayMidpointSeconds, true, tracking)
   
    headPose = tracking.HeadPose.ThePose
   
    val worldToCamera = OvrWrapperWindows.convertPoseToMatrix(headPose)
    val yaw = 0f
    val pitch = 0f
    val roll = 0f
    CameraState(worldToCamera, yaw, pitch, roll)
  }
 

  def render(renderFunction: MatrixSet => Unit, clearColor: Color) {
   
    GlWrapper.checkGlError("render start", false)
   
    val textureCurrentIndex = OvrWrapperWindows.getTextureSwapChainCurrentIndex(session, textureSwapChain)
    val textureID = OvrWrapperWindows.getTextureSwapChainBufferGL(session, textureSwapChain, textureCurrentIndex)
    // println(f"Rendering to index = ${textureCurrentIndex}, textureID = ${textureID}")
   
    OVRUtil.ovr_CalcEyePoses(headPose, hmdToEyeViewOffsets, outEyePoses)

    // Bind framebuffer and switch the binding to the current textureID.
    // Note that the renderbuffer binding does not have to be changed, i.e.,
    // we can bind it statically above. This is because LibOVR does not do
    // anything with the depth buffer in ATW.
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo)
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0)
    glDrawBuffers(GL_COLOR_ATTACHMENT0)
    if (useSRGB) {
      glEnable(GL_FRAMEBUFFER_SRGB)
    } else {
      glDisable(GL_FRAMEBUFFER_SRGB)
    }
    GlWrapper.checkGlError("after binding fbo", false)

    GlWrapper.ClearColor.set(clearColor)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)   
    GlWrapper.checkGlError("after clear", false)
   
    // loop over eyes
    cforRange(0 until 2){ i =>
      // update the eye pose in the layer
      val eyePose = outEyePoses.get(i)
      layer0.RenderPose(i, eyePose)
     
      // set the viewport -- since we have stored the required information already
      // in the layer description we can use it from there...
      glViewport(
        layer0.Viewport(i).Pos().x(),
        layer0.Viewport(i).Pos().y(),
        layer0.Viewport(i).Size().w(),
        layer0.Viewport(i).Size().h()
      )

      val V = OvrWrapperWindows.convertPoseToMatrix(eyePose)
      val P = projections(i)
      val mset = new MatrixSet(P, V)
      renderFunction(mset)
    }
    GlWrapper.checkGlError("after rendering", false)
   
    // we finally have to regenerate the mipmaps of the framebuffer texture
    glGenerateMipmap(GL_TEXTURE_2D)
   
    // cleanup: un-attach the texture from the framebuffer and unbind the framebuffer
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0)
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0)
    GlWrapper.checkGlError("after unbinding fbo", false)
   
    // submit frame
    val result = ovr_SubmitFrame(session, 0, null, layers)
    if (result == ovrSuccess_NotVisible) {
      System.out.println("TODO not vis!!");
    } else if (result != ovrSuccess) {
      System.out.println("TODO failed submit");
    }
    GlWrapper.checkGlError("after ovr_SubmitFrame", false)
   
    // this switches the current index of the texture swap chain
    ovr_CommitTextureSwapChain(session, textureSwapChain)
  }

  def resetPosition() {
    ovr_RecenterTrackingOrigin(session)
  }
 
  def toggleHud() {
    hudModeIndex = (hudModeIndex + 1) % hudModes.length
    val hudMode = hudModes(hudModeIndex)
    ovr_SetInt(session, "PerfHudMode", hudMode)
  }
 
  def isCloseRequested(): Boolean = {
    glfwWindowShouldClose(window) == GL_TRUE
  }

  def processMessages() {
    glfwPollEvents()
  }
 
  def destroy() {
    // terminating GLFW before ovr_DestroyTextureSwapChain leads to a crash -- looks like we need this order...
    logger.debug("calling ovr_DestroyTextureSwapChain")
    ovr_DestroyTextureSwapChain(session, textureSwapChain)
    logger.debug("calling ovr_Destroy")
    ovr_Destroy(session)
    logger.debug("calling ovr_Shutdown")
    ovr_Shutdown()

    glfwDestroyWindow(window)
    glfwTerminate()     
   
    logger.debug("freeing eyeRenderDesc")
    eyeRenderDesc.foreach(_.free())
   
    logger.debug("freeing layer")
    layer0.free()
    logger.debug("freeing tracking")
    tracking.free()
    logger.debug("freeing luid")
    luid.free()
   
    logger.debug("freeing callback")
    OvrWrapperWindows.freeCallback()
  }
}


object OvrWrapperWindows {
 
  private val logger = Logger(LoggerFactory getLogger getClass)

  val callback = new OVRLogCallback() {
    override def invoke(userData: Long, level: Int, message: Long) {
      val strOrig = OVRLogCallback.getMessage(message)
      val strWithoutNewline = strOrig.filter(_ != '\n')
      logger.debug("LibOVR [" + level + "] " + strWithoutNewline)
    }
  }
 
  def freeCallback() {
    // the callback needs to be free'd -- last step in the destroy...
    callback.free()
  }
 
  def init() {
    val initParams = OVRInitParams.calloc()
    initParams.LogCallback(callback)
    initParams.Flags(ovrInit_Debug)

    logger.debug("ovr_Initialize = " + ovr_Initialize(initParams))
    initParams.free()
   
    logger.debug("ovr_GetVersionString = " + ovr_GetVersionString());
  }
 
  def detect() {
    val detect = OVRDetectResult.calloc()
    ovr_Detect(0, detect)

    logger.debug("OVRDetectResult.IsOculusHMDConnected = " + detect.IsOculusHMDConnected())
    logger.debug("OVRDetectResult.IsOculusServiceRunning = " + detect.IsOculusServiceRunning())
    // TODO: fail for both cases with appropriate messages boxes

    detect.free()
  }
 
  def createSession(): (Long, OVRGraphicsLuid) = {
    val sessionPointerBuffer = MemoryUtil.memAllocPointer(1)
    val luid = OVRGraphicsLuid.calloc()
    val createResult = ovr_Create(sessionPointerBuffer, luid)
    logger.debug("ovr_Create = " + createResult)
 
    val session = sessionPointerBuffer.get(0)
    MemoryUtil.memFree(sessionPointerBuffer)
    return (session, luid)
  }
 
 
  def initGlContext(): Long = {
    // init GL context
    logger.debug(" *** Initializing GL context")
    glfwInit()
    glfwDefaultWindowHints()
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
    //glfwWindowHint(GLFW_VISIBLE, GL11.GL_FALSE)
    val window = glfwCreateWindow(640, 480, "Guitar Geeks VR", 0, 0)
    glfwSetKeyCallback(window, Keyboard.KeyCallback)
    glfwSetCharCallback(window, Keyboard.CharCallback)
   
    glfwMakeContextCurrent(window)
    GL.createCapabilities()
   
    logger.debug("     Initializing GL context [done]") 
    GlWrapper.checkGlError("after initializing context", false)
   
    return window
  }
 
  def getTextureSwapChainCurrentIndex(session: Long, chain: Long): Int = {
    val buffer = BufferUtils.createIntBuffer(1)
    ovr_GetTextureSwapChainCurrentIndex(session, chain, buffer)
    val currentIndex = buffer.get(0)
    return currentIndex
  }
  def getTextureSwapChainLength(session: Long, chain: Long): Int = {
    val buffer = BufferUtils.createIntBuffer(1)
    ovr_GetTextureSwapChainLength(session, chain, buffer)
    val textureCount = buffer.get(0)
    return textureCount
  } 
  def getTextureSwapChainBufferGL(session: Long, chain: Long, index: Int): Int = {
    val buffer = BufferUtils.createIntBuffer(1)
    ovr_GetTextureSwapChainBufferGL(session, chain, index, buffer)
    val textureID = buffer.get(0)
    return textureID
  }
 
 
  def convertPoseToMatrix(pose: OVRPosef): Mat4f = {
    val PcurInv = Mat4f.translate(-pose.Position.x, -pose.Position.y, -pose.Position.z)
    val QcurInv = new Quaternion(-pose.Orientation.x, -pose.Orientation.y, -pose.Orientation.z, pose.Orientation.w).castToOrientationMatrix
    QcurInv * PcurInv
  }
 
}


Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 04, 2016, 23:37:42
Awesome! I could not find the OVR_FORMAT_R8G8B8A8_UNORM_SRGB, and I also had a couple other bugs that I probably would have spent a whole day tracking down if it wasnt for your help, big thanks!  We have some code differences that I will investigate after some sleep, but at least my scene renders again :)

https://github.com/WhiteHexagon/example-lwjgl3-rift/blob/master/src/main/java/com/sunshineapps/rift/experimental/RiftWindow130.java
Title: Re: Oculus Rift SDK 1.3 released
Post by: spasi on April 05, 2016, 06:51:31
Reminder: struct setters return the struct instance, so you could change code like this:

OVRTextureSwapChainDesc swapChainDesc = OVRTextureSwapChainDesc.calloc();
swapChainDesc.Type(ovrTexture_2D);
swapChainDesc.ArraySize(1);
swapChainDesc.Format(ovrFORMAT_R8G8B8A8_UNORM_SRGB);
swapChainDesc.Width(textureW);
swapChainDesc.Height(textureH);
swapChainDesc.MipLevels(1);
swapChainDesc.SampleCount(1);
swapChainDesc.StaticImage(false);

to this:

OVRTextureSwapChainDesc swapChainDesc = OVRTextureSwapChainDesc.calloc()
.Type(ovrTexture_2D)
.ArraySize(1)
.Format(ovrFORMAT_R8G8B8A8_UNORM_SRGB)
.Width(textureW)
.Height(textureH)
.MipLevels(1)
.SampleCount(1)
.StaticImage(false);

Also, the format tokens have a wrong prefix, e.g. ovrFORMAT_R8G8B8A8_UNORM_SRGB should be OVR_FORMAT_R8G8B8A8_UNORM_SRGB. Will be fixed in the next build.
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 05, 2016, 15:21:18
thanks, the struct thing is nice, more like a streams/DSL approach I see Java using more and more, although an eclipse reformat messed it up.

I fixed some memory leaks and cleaned up how the app responds to being started with oculus home, ie not visible.  I still have a couple issues, I get a hard VM crash upon exit that I'm trying to track down, and I'm not sure that I have my math correct for looking into the scene.  Looking around is fine, but when I try to look closer at an object by moving my head forwards, I'm not sure that is working, or maybe its just my scene is too far away.  I have to experiment some more, but otherwise LWJGL seems to be working really well with the Rift SDK.  Thanks to you both for your help!
Title: Re: Oculus Rift SDK 1.3 released
Post by: bluenote10 on April 05, 2016, 17:33:53
Oh yes, that is something I forgot to mention yesterday: I think you have to get rid of this offset (https://github.com/WhiteHexagon/example-lwjgl3-rift/blob/6abda0aa5438a8915af374bf681de60a3b4d105f/src/main/java/com/sunshineapps/rift/experimental/RiftWindow130.java#L439). When you compute the eye poses from the main head pose by using ovr_CalcEyePoses, they already incorporate the eye separation offset. In older SDK versions you had to do that manually, now you can just use them directly. Since you add the eye offsets on top of that, you probably end up with twice the IPD, which may cause these scale issues.

If you are (like me) still using DK2, note that the 1.3 no longer has a software configuration for the IPD, so it will by 64mm anyway. If I understand it correctly, the IPD of the CV1 will be reported according to the physical IPD slider on the HMD. That is actually something I still have to change in the above example: The hmdToEyeOffsets should be queried every frame, exactly like you already do.

Regarding the VM crash: I also had problems with this if I shutdown GLFW before destroying the texture swap chain (I somewhere read that it should be like that -- exact inverse of the initialization). I have now switched to shutting down LibOVR first, which seems to work for me.
Title: Re: Oculus Rift SDK 1.3 released
Post by: BrickFarmer on April 05, 2016, 21:09:37
Thanks for the tips and explanation.  I'm also on the DK2 so I'm missing the IPD override.

crash was exactly as you mentioned, just the order of shutdown, but I also found a couple of my bugs whilst trying to fix that :)

I also added some code to check the SessionStatus, and I found that on the first 2 frames IsVisible() returns true, then I get a frame submit error and then isVisible() returns the expected false, until the HSW has been 'clicked'.  What I would expect is that the isVisible call always return false until HSW has been clicked.  Is that the reason you do an early comit (line 129 in your posted code)?
Title: Re: Oculus Rift SDK 1.3 released
Post by: bluenote10 on April 16, 2016, 15:20:59
@BrickFarmer: I do this early commit because the documentation says that every submitFrame must be preceded by a commit. Actually I think I can just place it at the top of the loop.

One question: Do you think that Asynchronous Timewarp (ATW) is working for you? I had a feeling that my (rare) "application dropped frame" in fact do cause judder, which they should not if ATW would do its thing. I just ran a worst case test and put a Thread.sleep(50) in my rendering loop. Unfortunately, the result is nothing like the native Oculus examples, where even not re-rendering at all is still smooth thanks to re-projection. So it looks like ATW is not yet really working.

@spasi: Do you happen to have any idea what could cause this? ATW requires asynchronous context handling and I'm wondering there is something obvious in the context handling which could prevent this?
Title: Re: Oculus Rift SDK 1.3 released
Post by: spasi on April 16, 2016, 15:26:37
Sorry, can't think of anything that would affect ATW.

Have you tried running with ovrInit_Debug? It may produce ovrLogCallback output related to ATW.
Title: Re: Oculus Rift SDK 1.3 released
Post by: bluenote10 on April 16, 2016, 16:55:40
Thanks for the quick feedback. Now I can confirm: ATW itself definitely works. When I set the sleep to like 5 seconds, I do get reprojection during these 5 seconds (i.e., the world feels stationary while turning the head). The actual problem is that when the frame refreshes, it somehow uses the old view pose. This means that if the view direction has changed in these 5 seconds, the world suddenly "jumps", centering the old view direction in the new view direction. After the next frame update, the new position will be used, so the world jumps back to where it was before. So it looks like ATW simply trails by one frame, which causes the world to jump back and forth each frame. I hope it is just a bug in my wrapper code above or maybe some frame queuing issue.

Update:

Okay, found my mistake. This behavior is caused by having a calling order of ovr_GetTextureSwapChainCurrentIndex --> ovr_SubmitFrame --> ovr_CommitTextureSwapChain. In fact, this is probably a common pitfall when migration from 0.8. In most 0.8 examples, the last step of the rendering loop was incrementing the texture index. Since the migration guide suggests that ovr_CommitTextureSwapChain essentially replaces this texture index increment, I kept it at the end of the loop. However, ovr_CommitTextureSwapChain must be called between the other two calls, so the correct order is ovr_GetTextureSwapChainCurrentIndex --> ovr_CommitTextureSwapChain --> ovr_SubmitFrame.