def main(): width = 1600 height = 1200 timelimit = 10 modeltranslation = 200 SDL_Init(SDL_INIT_VIDEO) window = SDL_CreateWindow(b"benchmark", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL) context = SDL_GL_CreateContext(window) SDL_GL_SetSwapInterval(0) #no v-sync #coin3d setup vpRegion = SbViewportRegion( width, height, ) m_sceneManager = SoSceneManager() m_sceneManager.setViewportRegion(vpRegion) m_sceneManager.setBackgroundColor(SbColor(0.0, 0.0, 0.8)) rootScene = SoSeparator() rootScene.ref() camera = SoFrustumCamera() basePosition = SbVec3f(0.0, 0.0, 0.0) camera.position.setValue(basePosition) camera.focalDistance.setValue(5.0) camera.viewportMapping.setValue(SoCamera.LEAVE_ALONE) camera.nearDistance.setValue(0.1) camera.farDistance.setValue(10000.0) rootScene.addChild(camera) light = SoDirectionalLight() light2 = SoDirectionalLight() rootScene.addChild(light) rootScene.addChild(light2) trans = SoTranslation() trans.translation.setValue([0, 0, -modeltranslation]) rotat = SoRotation() rotat.rotation.setValue(coin.SbVec3f(0, 1, 0), 0) rootScene.addChild( trans) #translation have to be earlier than translated object rootScene.addChild(rotat) sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() rootScene.addChild(sg) #get active scenegraph m_sceneManager.setSceneGraph(rootScene) notfinished = 1 angle = 0 frames = 0 start = time() # Loop until time limit happens while notfinished: glUseProgram(0) #coin3d rendering angle = angle + 0.001 frames = frames + 1 rotat.rotation.setValue(coin.SbVec3f(0, 1, 0), angle) glEnable(GL_CULL_FACE) glEnable(GL_DEPTH_TEST) m_sceneManager.render() glDisable(GL_CULL_FACE) glDisable(GL_DEPTH_TEST) glClearDepth(1.0) # Swap front and back buffers SDL_GL_SwapWindow(window) stop = time() elapsed = stop - start if elapsed > timelimit: notfinished = 0 print(frames, ' in ', elapsed, 'seconds, ', (frames / elapsed), 'fps') rootScene.unref() SDL_GL_DeleteContext(context) SDL_DestroyWindow(window) SDL_Quit()
class OpenVRTest(object): "FreeCAD OpenVR testing script" def __init__(self): self._running = True def setupscene(self): #coin3d setup vpRegion = SbViewportRegion(self.w, self.h) self.m_sceneManager = SoSceneManager() #scene manager overhead over render manager seems to be pretty #small self.m_sceneManager.setViewportRegion(vpRegion) self.m_sceneManager.setBackgroundColor(SbColor(0.0, 0.0, 0.8)) light = SoDirectionalLight() light2 = SoDirectionalLight() light2.direction.setValue(-1,-1,-1) light2.intensity.setValue(0.6) light2.color.setValue(0.8,0.8,1) self.scale = SoScale() self.scale.scaleFactor.setValue(0.001, 0.001, 0.001) #OpenVR uses meters not milimeters self.camtrans0 = SoTranslation() self.camtrans1 = SoTranslation() self.cgrp0 = SoGroup() self.cgrp1 = SoGroup() self.sgrp0 = SoGroup() self.sgrp1 = SoGroup() self.camtrans0.translation.setValue([self.camToHead[0][0][3],0,0]) self.camtrans1.translation.setValue([self.camToHead[1][0][3],0,0]) sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()#get active scenegraph #LEFT EYE self.rootScene0 = SoSeparator() self.rootScene0.ref() self.rootScene0.addChild(self.cgrp0) self.cgrp0.addChild(self.camtrans0) self.cgrp0.addChild(self.camera0) self.rootScene0.addChild(self.sgrp0) self.sgrp0.addChild(light) self.sgrp0.addChild(light2) self.sgrp0.addChild(self.scale) self.sgrp0.addChild(sg)#add scenegraph #RIGHT EYE self.rootScene1 = SoSeparator() self.rootScene1.ref() self.rootScene1.addChild(self.cgrp1) self.cgrp1.addChild(self.camtrans1) self.cgrp1.addChild(self.camera1) self.rootScene1.addChild(self.sgrp1) self.sgrp1.addChild(light) self.sgrp1.addChild(light2) self.sgrp1.addChild(self.scale) self.sgrp1.addChild(sg)#add scenegraph def setupcameras(self): nearZ = self.nearZ farZ = self.farZ #LEFT EYE self.camera0 = SoFrustumCamera() self.basePosition0 = SbVec3f(0.0, 0.0, 0.0) self.camera0.position.setValue(self.basePosition0) self.camera0.viewportMapping.setValue(SoCamera.LEAVE_ALONE) left = nearZ * self.proj_raw[0][0] right = nearZ * self.proj_raw[0][1] top = nearZ * self.proj_raw[0][3] #top and bottom are reversed https://github.com/ValveSoftware/openvr/issues/110 bottom = nearZ * self.proj_raw[0][2] aspect = (top - bottom) / (right - left) self.camera0.nearDistance.setValue(nearZ) self.camera0.farDistance.setValue(farZ) self.camera0.left.setValue(left) self.camera0.right.setValue(right) self.camera0.top.setValue(top) self.camera0.bottom.setValue(bottom) self.camera0.aspectRatio.setValue(aspect) #RIGHT EYE self.camera1 = SoFrustumCamera() self.basePosition1 = SbVec3f(0.0, 0.0, 0.0) self.camera1.position.setValue(self.basePosition1) self.camera1.viewportMapping.setValue(SoCamera.LEAVE_ALONE) left = nearZ * self.proj_raw[1][0] right = nearZ * self.proj_raw[1][1] top = nearZ * self.proj_raw[1][3] bottom = nearZ * self.proj_raw[1][2] aspect = (top - bottom) / (right - left) self.camera1.nearDistance.setValue(nearZ) self.camera1.farDistance.setValue(farZ) self.camera1.left.setValue(left) self.camera1.right.setValue(right) self.camera1.top.setValue(top) self.camera1.bottom.setValue(bottom) self.camera1.aspectRatio.setValue(aspect) def extractrotation(self, transfmat): #extract rotation quaternion qw = sqrt(numpy.fmax(0, 1 + transfmat[0][0] + transfmat[1][1] + transfmat[2][2])) / 2 qx = sqrt(numpy.fmax(0, 1 + transfmat[0][0] - transfmat[1][1] - transfmat[2][2])) / 2 qy = sqrt(numpy.fmax(0, 1 - transfmat[0][0] + transfmat[1][1] - transfmat[2][2])) / 2 qz = sqrt(numpy.fmax(0, 1 - transfmat[0][0] - transfmat[1][1] + transfmat[2][2])) / 2 qx = copysign(qx, transfmat[2][1] - transfmat[1][2]); qy = copysign(qy, transfmat[0][2] - transfmat[2][0]) qz = copysign(qz, transfmat[1][0] - transfmat[0][1]) hmdrot = SbRotation(qx, qy, qz, qw) return hmdrot def extracttranslation(self, transfmat): hmdpos = SbVec3f(transfmat[0][3], transfmat[1][3], transfmat[2][3]) return hmdpos def draw(self): #self.vr_compositor.waitGetPoses(self.poses, openvr.k_unMaxTrackedDeviceCount, None, 0) self.vr_compositor.waitGetPoses(self.poses, None) headPose = self.poses[openvr.k_unTrackedDeviceIndex_Hmd] if not headPose.bPoseIsValid: return True headToWorld = headPose.mDeviceToAbsoluteTracking transfmat = numpy.array([ [headToWorld.m[j][i] for i in range(4)] for j in range(3) ]) hmdrot = self.extractrotation(transfmat) hmdpos = self.extracttranslation(transfmat) self.camera0.orientation.setValue(hmdrot) self.camera0.position.setValue(self.basePosition0 + hmdpos) self.camera1.orientation.setValue(hmdrot) self.camera1.position.setValue(self.basePosition1 + hmdpos) for eye in range(2): glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffers[eye]) #coin3d rendering glUseProgram(0) if eye == 0: self.m_sceneManager.setSceneGraph(self.rootScene0) if eye == 1: self.m_sceneManager.setSceneGraph(self.rootScene1) glEnable(GL_CULL_FACE) glEnable(GL_DEPTH_TEST) self.m_sceneManager.render() glDisable(GL_CULL_FACE) glDisable(GL_DEPTH_TEST) glClearDepth(1.0) #end coin3d rendering self.vr_compositor.submit(self.eyes[eye], self.textures[eye]) return True def run(self): self.vr_system = openvr.init(openvr.VRApplication_Scene) self.vr_compositor = openvr.VRCompositor() poses_t = openvr.TrackedDevicePose_t * openvr.k_unMaxTrackedDeviceCount self.poses = poses_t() self.w, self.h = self.vr_system.getRecommendedRenderTargetSize() SDL_Init(SDL_INIT_VIDEO) self.window = SDL_CreateWindow (b"test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100, 100, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL) self.context = SDL_GL_CreateContext(self.window) SDL_GL_MakeCurrent(self.window, self.context) self.depth_buffer = glGenRenderbuffers(1) self.frame_buffers = glGenFramebuffers(2) self.texture_ids = glGenTextures(2) self.textures = [None] * 2 self.eyes = [openvr.Eye_Left, openvr.Eye_Right] self.camToHead = [None] * 2 self.proj_raw = [None] * 2 self.nearZ = 0.01 self.farZ = 500 for eye in range(2): glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffers[eye]) glBindRenderbuffer(GL_RENDERBUFFER, self.depth_buffer) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self.w, self.h) glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self.depth_buffer) glBindTexture(GL_TEXTURE_2D, self.texture_ids[eye]) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, self.w, self.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.texture_ids[eye], 0) texture = openvr.Texture_t() texture.handle = int(self.texture_ids[eye]) texture.eType = openvr.TextureType_OpenGL texture.eColorSpace = openvr.ColorSpace_Gamma self.textures[eye] = texture self.proj_raw[eye]= self.vr_system.getProjectionRaw(self.eyes[eye]) #void GetProjectionRaw( Hmd_Eye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) eyehead = self.vr_system.getEyeToHeadTransform(self.eyes[eye]) #[0][3] is eye-center distance self.camToHead[eye] = numpy.array([ [eyehead.m[j][i] for i in range(4)] for j in range(3) ]) self.setupcameras() self.setupscene() while self._running: self.draw() def terminate(self): self._running = False glDeleteBuffers(1, [self.depth_buffer]) for eye in range(2): glDeleteBuffers(1, [self.frame_buffers[eye]]) self.rootScene0.unref() self.rootScene1.unref() SDL_GL_DeleteContext(self.context) SDL_DestroyWindow(self.window) SDL_Quit() openvr.shutdown()