diff --git a/data/multibody.bullet b/data/multibody.bullet index 4cb146f2f..f71d00473 100644 Binary files a/data/multibody.bullet and b/data/multibody.bullet differ diff --git a/examples/BasicDemo/premake4.lua b/examples/BasicDemo/premake4.lua index a480b82c9..cb16d4b79 100644 --- a/examples/BasicDemo/premake4.lua +++ b/examples/BasicDemo/premake4.lua @@ -187,6 +187,7 @@ files { "../ThirdPartyLibs/openvr/samples/shared/lodepng.h", "../ThirdPartyLibs/openvr/samples/shared/Matrices.cpp", "../ThirdPartyLibs/openvr/samples/shared/Matrices.h", + "../ThirdPartyLibs/openvr/samples/shared/strtools.cpp", "../ThirdPartyLibs/openvr/samples/shared/pathtools.cpp", "../ThirdPartyLibs/openvr/samples/shared/pathtools.h", "../ThirdPartyLibs/openvr/samples/shared/Vectors.h", diff --git a/examples/CommonInterfaces/CommonGUIHelperInterface.h b/examples/CommonInterfaces/CommonGUIHelperInterface.h index fd34803d1..6e9fd7aeb 100644 --- a/examples/CommonInterfaces/CommonGUIHelperInterface.h +++ b/examples/CommonInterfaces/CommonGUIHelperInterface.h @@ -37,7 +37,8 @@ struct GUIHelperInterface virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType, int textureId) = 0; virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) =0; virtual void removeAllGraphicsInstances()=0; - + virtual void removeGraphicsInstance(int graphicsUid)=0; + virtual Common2dCanvasInterface* get2dCanvasInterface()=0; virtual CommonParameterInterface* getParameterInterface()=0; @@ -123,7 +124,8 @@ struct DummyGUIHelper : public GUIHelperInterface virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType, int textureId){return -1;} virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) {return -1;} virtual void removeAllGraphicsInstances(){} - + virtual void removeGraphicsInstance(int graphicsUid){} + virtual Common2dCanvasInterface* get2dCanvasInterface() { return 0; diff --git a/examples/CommonInterfaces/CommonRenderInterface.h b/examples/CommonInterfaces/CommonRenderInterface.h index 69ee16117..bbc20c6f9 100644 --- a/examples/CommonInterfaces/CommonRenderInterface.h +++ b/examples/CommonInterfaces/CommonRenderInterface.h @@ -23,7 +23,8 @@ struct CommonRenderInterface virtual void init()=0; virtual void updateCamera(int upAxis)=0; virtual void removeAllInstances() = 0; - + virtual void removeGraphicsInstance(int instanceUid) = 0; + virtual const CommonCameraInterface* getActiveCamera() const =0; virtual CommonCameraInterface* getActiveCamera()=0; virtual void setActiveCamera(CommonCameraInterface* cam)=0; diff --git a/examples/CommonInterfaces/CommonRigidBodyBase.h b/examples/CommonInterfaces/CommonRigidBodyBase.h index 07175ca25..8bab88a9d 100644 --- a/examples/CommonInterfaces/CommonRigidBodyBase.h +++ b/examples/CommonInterfaces/CommonRigidBodyBase.h @@ -410,6 +410,18 @@ struct CommonRigidBodyBase : public CommonExampleInterface return box; } + void deleteRigidBody(btRigidBody* body) + { + int graphicsUid = body->getUserIndex(); + m_guiHelper->removeGraphicsInstance(graphicsUid); + + m_dynamicsWorld->removeRigidBody(body); + btMotionState* ms = body->getMotionState(); + delete body; + delete ms; + + } + btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1)) { btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE)); diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp index 2d9f8499f..b26dfbf59 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp +++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp @@ -241,6 +241,12 @@ void OpenGLGuiHelper::removeAllGraphicsInstances() m_data->m_glApp->m_renderer->removeAllInstances(); } +void OpenGLGuiHelper::removeGraphicsInstance(int graphicsUid) +{ + m_data->m_glApp->m_renderer->removeGraphicsInstance(graphicsUid); +} + + void OpenGLGuiHelper::createCollisionShapeGraphicsObject(btCollisionShape* collisionShape) { //already has a graphics object? @@ -587,7 +593,7 @@ void OpenGLGuiHelper::autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWor btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i]; sortedObjects.push_back(colObj); } - sortedObjects.quickSort(shapePointerCompareFunc); + //sortedObjects.quickSort(shapePointerCompareFunc); for (int i=0;i m_tempObjectUids; int m_instanceOffset; int m_vertexArrayOffset; int m_primitiveType; @@ -144,7 +146,22 @@ struct InternalTextureHandle int m_height; }; +struct b3PublicGraphicsInstanceData +{ + int m_shapeIndex; + int m_internalInstanceIndex; + GLfloat m_position[4]; + GLfloat m_orientation[4]; + GLfloat m_color[4]; + GLfloat m_scale[4]; + void clear() + { + } + +}; + +typedef b3PoolBodyHandle b3PublicGraphicsInstance; struct InternalDataRenderer : public GLInstanceRendererInternalData { @@ -165,7 +182,10 @@ struct InternalDataRenderer : public GLInstanceRendererInternalData GLuint m_renderFrameBuffer; - + + + b3ResizablePool< b3PublicGraphicsInstance> m_publicGraphicsInstances; + InternalDataRenderer() : m_activeCamera(&m_defaultCamera1), m_shadowMap(0), @@ -284,6 +304,8 @@ void GLInstancingRenderer::removeAllInstances() delete m_graphicsInstances[i]; } m_graphicsInstances.clear(); + m_data->m_publicGraphicsInstances.exitHandles(); + m_data->m_publicGraphicsInstances.initHandles(); } @@ -313,8 +335,13 @@ GLInstancingRenderer::~GLInstancingRenderer() -void GLInstancingRenderer::writeSingleInstanceTransformToCPU(const float* position, const float* orientation, int srcIndex) +void GLInstancingRenderer::writeSingleInstanceTransformToCPU(const float* position, const float* orientation, int bodyUniqueId) { + + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; + b3Assert(srcIndexm_totalNumInstances); b3Assert(srcIndex>=0); m_data->m_instance_positions_ptr[srcIndex*4+0]=position[0]; @@ -327,16 +354,16 @@ void GLInstancingRenderer::writeSingleInstanceTransformToCPU(const float* positi m_data->m_instance_quaternion_ptr[srcIndex*4+2]=orientation[2]; m_data->m_instance_quaternion_ptr[srcIndex*4+3]=orientation[3]; -/* m_data->m_instance_colors_ptr[srcIndex*4+0]=color[0]; - m_data->m_instance_colors_ptr[srcIndex*4+1]=color[1]; - m_data->m_instance_colors_ptr[srcIndex*4+2]=color[2]; - m_data->m_instance_colors_ptr[srcIndex*4+3]=color[3]; - */ } -void GLInstancingRenderer::readSingleInstanceTransformFromCPU(int srcIndex, float* position, float* orientation) +void GLInstancingRenderer::readSingleInstanceTransformFromCPU(int bodyUniqueId, float* position, float* orientation) { + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; + + b3Assert(srcIndexm_totalNumInstances); b3Assert(srcIndex>=0); position[0] = m_data->m_instance_positions_ptr[srcIndex*4+0]; @@ -348,16 +375,23 @@ void GLInstancingRenderer::readSingleInstanceTransformFromCPU(int srcIndex, floa orientation[2] = m_data->m_instance_quaternion_ptr[srcIndex*4+2]; orientation[3] = m_data->m_instance_quaternion_ptr[srcIndex*4+3]; } -void GLInstancingRenderer::writeSingleInstanceColorToCPU(double* color, int srcIndex) +void GLInstancingRenderer::writeSingleInstanceColorToCPU(double* color, int bodyUniqueId) { + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; + m_data->m_instance_colors_ptr[srcIndex*4+0]=float(color[0]); m_data->m_instance_colors_ptr[srcIndex*4+1]=float(color[1]); m_data->m_instance_colors_ptr[srcIndex*4+2]=float(color[2]); m_data->m_instance_colors_ptr[srcIndex*4+3]=float(color[3]); } -void GLInstancingRenderer::writeSingleInstanceColorToCPU(float* color, int srcIndex) +void GLInstancingRenderer::writeSingleInstanceColorToCPU(float* color, int bodyUniqueId) { + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; m_data->m_instance_colors_ptr[srcIndex*4+0]=color[0]; m_data->m_instance_colors_ptr[srcIndex*4+1]=color[1]; @@ -365,25 +399,37 @@ void GLInstancingRenderer::writeSingleInstanceColorToCPU(float* color, int srcIn m_data->m_instance_colors_ptr[srcIndex*4+3]=color[3]; } -void GLInstancingRenderer::writeSingleInstanceScaleToCPU(float* scale, int srcIndex) +void GLInstancingRenderer::writeSingleInstanceScaleToCPU(float* scale, int bodyUniqueId) { + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; + m_data->m_instance_scale_ptr[srcIndex*3+0]=scale[0]; m_data->m_instance_scale_ptr[srcIndex*3+1]=scale[1]; m_data->m_instance_scale_ptr[srcIndex*3+2]=scale[2]; } -void GLInstancingRenderer::writeSingleInstanceScaleToCPU(double* scale, int srcIndex) +void GLInstancingRenderer::writeSingleInstanceScaleToCPU(double* scale, int bodyUniqueId) { + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; + m_data->m_instance_scale_ptr[srcIndex*3+0]=scale[0]; m_data->m_instance_scale_ptr[srcIndex*3+1]=scale[1]; m_data->m_instance_scale_ptr[srcIndex*3+2]=scale[2]; } -void GLInstancingRenderer::writeSingleInstanceTransformToGPU(float* position, float* orientation, int objectIndex) +void GLInstancingRenderer::writeSingleInstanceTransformToGPU(float* position, float* orientation, int objectUniqueId) { glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo); //glFlush(); + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(objectUniqueId); + b3Assert(pg); + int objectIndex = pg->m_internalInstanceIndex; + char* orgBase = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE); //b3GraphicsInstance* gfxObj = m_graphicsInstances[k]; int totalNumInstances= 0; @@ -574,15 +620,92 @@ int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const double* return registerGraphicsInstance(shapeIndex,pos,orn,color,scaling); } - -int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) +void GLInstancingRenderer::rebuildGraphicsInstances() { - b3Assert(shapeIndex == (m_graphicsInstances.size()-1)); - b3Assert(m_graphicsInstances.size()m_maxNumObjectCapacity-1); + m_data->m_totalNumInstances = 0; + + b3AlignedObjectArray usedObjects; + m_data->m_publicGraphicsInstances.getUsedHandles(usedObjects); + + for (int i=0;im_publicGraphicsInstances.getHandle(bodyUniqueId); + b3Assert(pg); + int srcIndex = pg->m_internalInstanceIndex; + + pg->m_position[0] = m_data->m_instance_positions_ptr[srcIndex*4+0]; + pg->m_position[1] = m_data->m_instance_positions_ptr[srcIndex*4+1]; + pg->m_position[2] = m_data->m_instance_positions_ptr[srcIndex*4+2]; + pg->m_orientation[0] = m_data->m_instance_quaternion_ptr[srcIndex*4+0]; + pg->m_orientation[1] = m_data->m_instance_quaternion_ptr[srcIndex*4+1]; + pg->m_orientation[2] = m_data->m_instance_quaternion_ptr[srcIndex*4+2]; + pg->m_orientation[3] = m_data->m_instance_quaternion_ptr[srcIndex*4+3]; + pg->m_color[0] = m_data->m_instance_colors_ptr[srcIndex*4+0]; + pg->m_color[1] = m_data->m_instance_colors_ptr[srcIndex*4+1]; + pg->m_color[2] = m_data->m_instance_colors_ptr[srcIndex*4+2]; + pg->m_color[3] = m_data->m_instance_colors_ptr[srcIndex*4+3]; + pg->m_scale[0] = m_data->m_instance_scale_ptr[srcIndex*3+0]; + pg->m_scale[1] = m_data->m_instance_scale_ptr[srcIndex*3+1]; + pg->m_scale[2] = m_data->m_instance_scale_ptr[srcIndex*3+2]; + } + for (int i=0;im_numGraphicsInstances = 0; + m_graphicsInstances[i]->m_instanceOffset = 0; + m_graphicsInstances[i]->m_tempObjectUids.clear(); + } + for (int i=0;im_publicGraphicsInstances.getHandle(bodyUniqueId); + m_graphicsInstances[pg->m_shapeIndex]->m_tempObjectUids.push_back(bodyUniqueId); + } + + int curOffset = 0; + m_data->m_totalNumInstances = 0; + + for (int i=0;im_instanceOffset = curOffset; + m_graphicsInstances[i]->m_numGraphicsInstances = 0; + + for (int g=0;gm_tempObjectUids.size();g++) + { + curOffset++; + int objectUniqueId = m_graphicsInstances[i]->m_tempObjectUids[g]; + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(objectUniqueId); + + registerGraphicsInstanceInternal(objectUniqueId,pg->m_position,pg->m_orientation,pg->m_color,pg->m_scale); + } + } + +} + +void GLInstancingRenderer::removeGraphicsInstance(int instanceUid) +{ + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(instanceUid); + b3Assert(pg); + if (pg) + { + m_data->m_publicGraphicsInstances.freeHandle(instanceUid); + rebuildGraphicsInstances(); + } +} + + +int GLInstancingRenderer::registerGraphicsInstanceInternal(int newUid, const float* position, const float* quaternion, const float* color, const float* scaling) +{ + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(newUid); + int shapeIndex = pg->m_shapeIndex; +// b3Assert(pg); +// int objectIndex = pg->m_internalInstanceIndex; + + b3GraphicsInstance* gfxObj = m_graphicsInstances[shapeIndex]; - int index = gfxObj->m_numGraphicsInstances + gfxObj->m_instanceOffset; + pg->m_internalInstanceIndex = index; int maxElements = m_data->m_instance_positions_ptr.size(); if (index*4m_numGraphicsInstances; + return newUid;//gfxObj->m_numGraphicsInstances; +} + +int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) +{ + int newUid = m_data->m_publicGraphicsInstances.allocHandle(); + b3PublicGraphicsInstance* pg = m_data->m_publicGraphicsInstances.getHandle(newUid); + pg->m_shapeIndex = shapeIndex; + + //b3Assert(shapeIndex == (m_graphicsInstances.size()-1)); + b3Assert(m_graphicsInstances.size()m_maxNumObjectCapacity-1); + if (shapeIndex == (m_graphicsInstances.size()-1)) + { + registerGraphicsInstanceInternal(newUid, position,quaternion,color,scaling); + } else + { + + int srcIndex = m_data->m_totalNumInstances++; + pg->m_internalInstanceIndex = srcIndex; + + m_data->m_instance_positions_ptr[srcIndex*4+0] = position[0]; + m_data->m_instance_positions_ptr[srcIndex*4+1] = position[1]; + m_data->m_instance_positions_ptr[srcIndex*4+2] = position[2]; + m_data->m_instance_positions_ptr[srcIndex*4+3] = 1.; + + m_data->m_instance_quaternion_ptr[srcIndex*4+0] = quaternion[0]; + m_data->m_instance_quaternion_ptr[srcIndex*4+1] = quaternion[1]; + m_data->m_instance_quaternion_ptr[srcIndex*4+2] = quaternion[2]; + m_data->m_instance_quaternion_ptr[srcIndex*4+3] = quaternion[3]; + + m_data->m_instance_colors_ptr[srcIndex*4+0] = color[0]; + m_data->m_instance_colors_ptr[srcIndex*4+1] = color[1]; + m_data->m_instance_colors_ptr[srcIndex*4+2] = color[2]; + m_data->m_instance_colors_ptr[srcIndex*4+3] = color[3]; + + m_data->m_instance_scale_ptr[srcIndex*3+0] = scaling[0]; + m_data->m_instance_scale_ptr[srcIndex*3+1] = scaling[1]; + m_data->m_instance_scale_ptr[srcIndex*3+2] = scaling[2]; + + + rebuildGraphicsInstances(); + } + + return newUid; } diff --git a/examples/OpenGLWindow/GLInstancingRenderer.h b/examples/OpenGLWindow/GLInstancingRenderer.h index d42512280..b49cf2107 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.h +++ b/examples/OpenGLWindow/GLInstancingRenderer.h @@ -41,10 +41,10 @@ class GLInstancingRenderer : public CommonRenderInterface int m_upAxis; bool m_enableBlend; - + int registerGraphicsInstanceInternal(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); + void rebuildGraphicsInstances(); - public: GLInstancingRenderer(int m_maxObjectCapacity, int maxShapeCapacityInBytes = 56*1024*1024); virtual ~GLInstancingRenderer(); @@ -57,7 +57,8 @@ public: void InitShaders(); void CleanupShaders(); virtual void removeAllInstances(); - + virtual void removeGraphicsInstance(int instanceUid); + virtual void updateShape(int shapeIndex, const float* vertices); ///vertices must be in the format x,y,z, nx,ny,nz, u,v @@ -72,6 +73,7 @@ public: virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); virtual int registerGraphicsInstance(int shapeIndex, const double* position, const double* quaternion, const double* color, const double* scaling); + void writeTransforms(); diff --git a/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp b/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp index d39622e35..564212f9d 100644 --- a/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp +++ b/examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp @@ -6,6 +6,7 @@ #include "GLInstanceGraphicsShape.h" #include "Bullet3Common/b3Quaternion.h" #include "Bullet3Common/b3Transform.h" +#include "Bullet3Common/b3ResizablePool.h" B3_ATTRIBUTE_ALIGNED16(struct) SimpleGL2Shape { @@ -27,6 +28,9 @@ B3_ATTRIBUTE_ALIGNED16(struct) SimpleGL2Instance b3Quaternion orn; b3Vector3 m_rgbColor; b3Vector3 m_scaling; + void clear() + { + } }; @@ -38,13 +42,18 @@ struct InternalTextureHandle2 int m_height; }; +typedef b3PoolBodyHandle SimpleGL2InstanceHandle; + struct SimpleOpenGL2RendererInternalData { int m_width; int m_height; SimpleCamera m_camera; b3AlignedObjectArray m_shapes; - b3AlignedObjectArray m_graphicsInstances; + //b3AlignedObjectArray m_graphicsInstances1; + + b3ResizablePool m_graphicsInstancesPool; + b3AlignedObjectArray m_textureHandles; }; @@ -118,11 +127,17 @@ void SimpleOpenGL2Renderer::removeAllInstances() delete m_data->m_shapes[i]; } m_data->m_shapes.clear(); - m_data->m_graphicsInstances.clear(); + m_data->m_graphicsInstancesPool.exitHandles(); + m_data->m_graphicsInstancesPool.initHandles(); + //also destroy textures? m_data->m_textureHandles.clear(); } +void SimpleOpenGL2Renderer::removeGraphicsInstance(int instanceUid) +{ + m_data->m_graphicsInstancesPool.freeHandle(instanceUid); +} void SimpleOpenGL2Renderer::writeSingleInstanceColorToCPU(float* color, int srcIndex) { @@ -142,7 +157,7 @@ void SimpleOpenGL2Renderer::writeSingleInstanceScaleToCPU(double* scale, int src int SimpleOpenGL2Renderer::getTotalNumInstances() const { - return m_data->m_graphicsInstances.size(); + return m_data->m_graphicsInstancesPool.getNumHandles(); } void SimpleOpenGL2Renderer::getCameraViewMatrix(float viewMat[16]) const @@ -158,7 +173,13 @@ void SimpleOpenGL2Renderer::getCameraProjectionMatrix(float projMat[16]) const void SimpleOpenGL2Renderer::drawOpenGL(int instanceIndex) { - const SimpleGL2Instance& inst = m_data->m_graphicsInstances[instanceIndex]; + const SimpleGL2Instance* instPtr = m_data->m_graphicsInstancesPool.getHandle(instanceIndex); + if (0==instPtr) + { + b3Assert(0); + return; + } + const SimpleGL2Instance& inst = *instPtr; const SimpleGL2Shape* shape = m_data->m_shapes[inst.m_shapeIndex]; @@ -244,9 +265,11 @@ void SimpleOpenGL2Renderer::drawOpenGL(int instanceIndex) void SimpleOpenGL2Renderer::drawSceneInternal(int pass, int cameraUpAxis) { - for (int i=0;im_graphicsInstances.size();i++) + b3AlignedObjectArray usedHandles; + m_data->m_graphicsInstancesPool.getUsedHandles(usedHandles); + for (int i=0;im_graphicsInstances.size(); - SimpleGL2Instance& instance = m_data->m_graphicsInstances.expand(); + int newHandle = m_data->m_graphicsInstancesPool.allocHandle(); + + +// int sz = m_data->m_graphicsInstances.size(); + + SimpleGL2Instance& instance = *m_data->m_graphicsInstancesPool.getHandle(newHandle); instance.m_shapeIndex = shapeIndex; instance.m_position[0] = position[0]; instance.m_position[1] = position[1]; @@ -451,13 +478,13 @@ int SimpleOpenGL2Renderer::registerGraphicsInstance(int shapeIndex, const double instance.m_scaling[0] = scaling[0]; instance.m_scaling[1] = scaling[1]; instance.m_scaling[2] = scaling[2]; - return sz; + return newHandle; } int SimpleOpenGL2Renderer::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) { - int sz = m_data->m_graphicsInstances.size(); - SimpleGL2Instance& instance = m_data->m_graphicsInstances.expand(); + int newHandle = m_data->m_graphicsInstancesPool.allocHandle(); + SimpleGL2Instance& instance = *m_data->m_graphicsInstancesPool.getHandle(newHandle); instance.m_shapeIndex = shapeIndex; instance.m_position[0] = position[0]; instance.m_position[1] = position[1]; @@ -472,7 +499,7 @@ int SimpleOpenGL2Renderer::registerGraphicsInstance(int shapeIndex, const float* instance.m_scaling[0] = scaling[0]; instance.m_scaling[1] = scaling[1]; instance.m_scaling[2] = scaling[2]; - return sz; + return newHandle; } void SimpleOpenGL2Renderer::drawLines(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, const unsigned int* indices, int numIndices, float pointDrawSize) @@ -545,26 +572,30 @@ int SimpleOpenGL2Renderer::registerShape(const float* vertices, int numvertices, void SimpleOpenGL2Renderer::writeSingleInstanceTransformToCPU(const float* position, const float* orientation, int srcIndex) { - m_data->m_graphicsInstances[srcIndex].m_position[0] = position[0]; - m_data->m_graphicsInstances[srcIndex].m_position[1] = position[1]; - m_data->m_graphicsInstances[srcIndex].m_position[2] = position[2]; + SimpleGL2Instance& graphicsInstance = *m_data->m_graphicsInstancesPool.getHandle(srcIndex); + + graphicsInstance.m_position[0] = position[0]; + graphicsInstance.m_position[1] = position[1]; + graphicsInstance.m_position[2] = position[2]; - m_data->m_graphicsInstances[srcIndex].orn[0] = orientation[0]; - m_data->m_graphicsInstances[srcIndex].orn[1] = orientation[1]; - m_data->m_graphicsInstances[srcIndex].orn[2] = orientation[2]; - m_data->m_graphicsInstances[srcIndex].orn[3] = orientation[3]; + graphicsInstance.orn[0] = orientation[0]; + graphicsInstance.orn[1] = orientation[1]; + graphicsInstance.orn[2] = orientation[2]; + graphicsInstance.orn[3] = orientation[3]; } void SimpleOpenGL2Renderer::writeSingleInstanceTransformToCPU(const double* position, const double* orientation, int srcIndex) { - m_data->m_graphicsInstances[srcIndex].m_position[0] = position[0]; - m_data->m_graphicsInstances[srcIndex].m_position[1] = position[1]; - m_data->m_graphicsInstances[srcIndex].m_position[2] = position[2]; + SimpleGL2Instance& graphicsInstance = *m_data->m_graphicsInstancesPool.getHandle(srcIndex); + + graphicsInstance.m_position[0] = position[0]; + graphicsInstance.m_position[1] = position[1]; + graphicsInstance.m_position[2] = position[2]; - m_data->m_graphicsInstances[srcIndex].orn[0] = orientation[0]; - m_data->m_graphicsInstances[srcIndex].orn[1] = orientation[1]; - m_data->m_graphicsInstances[srcIndex].orn[2] = orientation[2]; - m_data->m_graphicsInstances[srcIndex].orn[3] = orientation[3]; + graphicsInstance.orn[0] = orientation[0]; + graphicsInstance.orn[1] = orientation[1]; + graphicsInstance.orn[2] = orientation[2]; + graphicsInstance.orn[3] = orientation[3]; } void SimpleOpenGL2Renderer::writeTransforms() { diff --git a/examples/OpenGLWindow/SimpleOpenGL2Renderer.h b/examples/OpenGLWindow/SimpleOpenGL2Renderer.h index 57798e35b..3a94a3783 100644 --- a/examples/OpenGLWindow/SimpleOpenGL2Renderer.h +++ b/examples/OpenGLWindow/SimpleOpenGL2Renderer.h @@ -32,7 +32,7 @@ public: virtual void resize(int width, int height); virtual void removeAllInstances(); - + virtual void removeGraphicsInstance(int instanceUid); virtual void writeSingleInstanceColorToCPU(float* color, int srcIndex); virtual void writeSingleInstanceColorToCPU(double* color, int srcIndex); diff --git a/examples/RoboticsLearning/b3RobotSimAPI.cpp b/examples/RoboticsLearning/b3RobotSimAPI.cpp index 3b8948761..f0e4224ac 100644 --- a/examples/RoboticsLearning/b3RobotSimAPI.cpp +++ b/examples/RoboticsLearning/b3RobotSimAPI.cpp @@ -50,6 +50,7 @@ enum MultiThreadedGUIHelperCommunicationEnums eRobotSimGUIHelperCreateCollisionObjectGraphicsObject, eRobotSimGUIHelperRemoveAllGraphicsInstances, eRobotSimGUIHelperCopyCameraImageData, + eRobotSimGUIHelperRemoveGraphicsInstance, }; #include @@ -320,6 +321,17 @@ public: { } } + int m_graphicsInstanceRemove; + virtual void removeGraphicsInstance(int instanceUid) + { + m_cs->lock(); + m_cs->setSharedParam(1,eRobotSimGUIHelperRemoveGraphicsInstance); + m_graphicsInstanceRemove = instanceUid; + m_cs->unlock(); + while (m_cs->getSharedParam(1)!=eRobotSimGUIHelperIdle) + { + } + } virtual Common2dCanvasInterface* get2dCanvasInterface() { @@ -639,6 +651,14 @@ void b3RobotSimAPI::processMultiThreadedGraphicsRequests() m_data->m_multiThreadedHelper->getCriticalSection()->unlock(); break; } + case eRobotSimGUIHelperRemoveGraphicsInstance: + { + m_data->m_multiThreadedHelper->m_childGuiHelper->removeGraphicsInstance(m_data->m_multiThreadedHelper->m_graphicsInstanceRemove); + m_data->m_multiThreadedHelper->getCriticalSection()->lock(); + m_data->m_multiThreadedHelper->getCriticalSection()->setSharedParam(1,eRobotSimGUIHelperIdle); + m_data->m_multiThreadedHelper->getCriticalSection()->unlock(); + break; + } case eRobotSimGUIHelperCopyCameraImageData: { m_data->m_multiThreadedHelper->m_childGuiHelper->copyCameraImageData(m_data->m_multiThreadedHelper->m_viewMatrix, diff --git a/examples/SharedMemory/CMakeLists.txt b/examples/SharedMemory/CMakeLists.txt index dc848abec..1bd626572 100644 --- a/examples/SharedMemory/CMakeLists.txt +++ b/examples/SharedMemory/CMakeLists.txt @@ -249,6 +249,8 @@ LINK_LIBRARIES( ../ThirdPartyLibs/openvr/samples/shared/Matrices.h ../ThirdPartyLibs/openvr/samples/shared/pathtools.cpp ../ThirdPartyLibs/openvr/samples/shared/pathtools.h + ../ThirdPartyLibs/openvr/samples/shared/strtools.cpp + ../ThirdPartyLibs/openvr/samples/shared/strtools.h ../ThirdPartyLibs/openvr/samples/shared/Vectors.h ../MultiThreading/b3Win32ThreadSupport.cpp ../MultiThreading/b3Win32ThreadSupport.h @@ -261,7 +263,7 @@ IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES) ADD_CUSTOM_COMMAND( TARGET App_PhysicsServer_SharedMemory_VR POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/openvr/bin/win64/openvr_api.dll ${CMAKE_CURRENT_BINARY_DIR}/openvr_api.dll + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/openvr/bin/win64/openvr_api.dll ${CMAKE_CURRENT_BINARY_DIR}/openvr64pi.dll ) ELSE(CMAKE_CL_64) ADD_CUSTOM_COMMAND( diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index 61e3a69d6..150c6a242 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -1349,6 +1349,24 @@ b3SharedMemoryCommandHandle b3InitRemoveUserConstraintCommand(b3PhysicsClientHa command->m_userConstraintArguments.m_userConstraintUniqueId = userConstraintUniqueId; return (b3SharedMemoryCommandHandle)command; } + +b3SharedMemoryCommandHandle b3InitRemoveBodyCommand(b3PhysicsClientHandle physClient, int bodyUniqueId) +{ + PhysicsClient* cl = (PhysicsClient* ) physClient; + b3Assert(cl); + b3Assert(cl->canSubmitCommand()); + struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand(); + b3Assert(command); + + command->m_type = CMD_REMOVE_BODY; + command->m_updateFlags = BODY_DELETE_FLAG; + command->m_removeObjectArgs.m_numBodies = 1; + command->m_removeObjectArgs.m_bodyUniqueIds[0] = bodyUniqueId; + command->m_removeObjectArgs.m_numUserConstraints = 0; + + return (b3SharedMemoryCommandHandle)command; +} + int b3GetStatusUserConstraintUniqueId(b3SharedMemoryStatusHandle statusHandle) { const SharedMemoryStatus* status = (const SharedMemoryStatus* ) statusHandle; diff --git a/examples/SharedMemory/PhysicsClientC_API.h b/examples/SharedMemory/PhysicsClientC_API.h index f57ffdcee..61db28054 100644 --- a/examples/SharedMemory/PhysicsClientC_API.h +++ b/examples/SharedMemory/PhysicsClientC_API.h @@ -60,6 +60,8 @@ int b3GetStatusActualState(b3SharedMemoryStatusHandle statusHandle, ///If you re-connected to an existing server, or server changed otherwise, sync the body info and user constraints etc. b3SharedMemoryCommandHandle b3InitSyncBodyInfoCommand(b3PhysicsClientHandle physClient); +b3SharedMemoryCommandHandle b3InitRemoveBodyCommand(b3PhysicsClientHandle physClient, int bodyUniqueId); + ///return the total number of bodies in the simulation int b3GetNumBodies(b3PhysicsClientHandle physClient); diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.cpp b/examples/SharedMemory/PhysicsClientSharedMemory.cpp index dcac6541b..27262685f 100644 --- a/examples/SharedMemory/PhysicsClientSharedMemory.cpp +++ b/examples/SharedMemory/PhysicsClientSharedMemory.cpp @@ -199,6 +199,28 @@ PhysicsClientSharedMemory::~PhysicsClientSharedMemory() { delete m_data; } +void PhysicsClientSharedMemory::removeCachedBody(int bodyUniqueId) +{ + BodyJointInfoCache** bodyJointsPtr = m_data->m_bodyJointMap[bodyUniqueId]; + if (bodyJointsPtr && *bodyJointsPtr) + { + + BodyJointInfoCache* bodyJoints = *bodyJointsPtr; + for (int j=0;jm_jointInfo.size();j++) + { + if (bodyJoints->m_jointInfo[j].m_jointName) + { + free(bodyJoints->m_jointInfo[j].m_jointName); + } + if (bodyJoints->m_jointInfo[j].m_linkName) + { + free(bodyJoints->m_jointInfo[j].m_linkName); + } + } + delete (*bodyJointsPtr); + m_data->m_bodyJointMap.remove(bodyUniqueId); + } +} void PhysicsClientSharedMemory::resetData() { m_data->m_debugLinesFrom.clear(); @@ -1008,7 +1030,15 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() { { break; } - + case CMD_REMOVE_BODY_COMPLETED: + { + break; + } + case CMD_REMOVE_BODY_FAILED: + { + b3Warning("Removing body failed"); + break; + } default: { b3Error("Unknown server status %d\n", serverCmd.m_type); btAssert(0); @@ -1059,7 +1089,21 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() { return 0; } } - + + if (serverCmd.m_type == CMD_REMOVE_BODY_COMPLETED) + { + for (int i=0;im_userConstraintInfoMap.remove(key); + } + } + if (serverCmd.m_type == CMD_USER_CONSTRAINT_INFO_COMPLETED) { B3_PROFILE("CMD_USER_CONSTRAINT_INFO_COMPLETED"); diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.h b/examples/SharedMemory/PhysicsClientSharedMemory.h index 163ea55fb..b436a9fef 100644 --- a/examples/SharedMemory/PhysicsClientSharedMemory.h +++ b/examples/SharedMemory/PhysicsClientSharedMemory.h @@ -13,6 +13,7 @@ protected: virtual void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem); void processBodyJointInfo(int bodyUniqueId, const struct SharedMemoryStatus& serverCmd); void resetData(); + void removeCachedBody(int bodyUniqueId); public: PhysicsClientSharedMemory(); diff --git a/examples/SharedMemory/PhysicsDirect.cpp b/examples/SharedMemory/PhysicsDirect.cpp index ef1d70aba..8a5ec6c8d 100644 --- a/examples/SharedMemory/PhysicsDirect.cpp +++ b/examples/SharedMemory/PhysicsDirect.cpp @@ -724,6 +724,26 @@ void PhysicsDirect::postProcessStatus(const struct SharedMemoryStatus& serverCmd m_data->m_userConstraintInfoMap.remove(cid); break; } + case CMD_REMOVE_BODY_FAILED: + { + b3Warning("Remove body failed\n"); + break; + } + case CMD_REMOVE_BODY_COMPLETED: + { + for (int i=0;im_userConstraintInfoMap.remove(key); + } + + break; + } case CMD_CHANGE_USER_CONSTRAINT_COMPLETED: { int cid = serverCmd.m_userConstraintResultArgs.m_userConstraintUniqueId; @@ -909,6 +929,28 @@ int PhysicsDirect::getNumBodies() const return m_data->m_bodyJointMap.size(); } +void PhysicsDirect::removeCachedBody(int bodyUniqueId) +{ + BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap[bodyUniqueId]; + if (bodyJointsPtr && *bodyJointsPtr) + { + BodyJointInfoCache2* bodyJoints = *bodyJointsPtr; + for (int j=0;jm_jointInfo.size();j++) { + if (bodyJoints->m_jointInfo[j].m_jointName) + { + free(bodyJoints->m_jointInfo[j].m_jointName); + } + if (bodyJoints->m_jointInfo[j].m_linkName) + { + free(bodyJoints->m_jointInfo[j].m_linkName); + } + } + delete (*bodyJointsPtr); + m_data->m_bodyJointMap.remove(bodyUniqueId); + } +} + + int PhysicsDirect::getNumUserConstraints() const { return m_data->m_userConstraintInfoMap.size(); diff --git a/examples/SharedMemory/PhysicsDirect.h b/examples/SharedMemory/PhysicsDirect.h index 18e08477d..64ea073eb 100644 --- a/examples/SharedMemory/PhysicsDirect.h +++ b/examples/SharedMemory/PhysicsDirect.h @@ -29,6 +29,9 @@ protected: void postProcessStatus(const struct SharedMemoryStatus& serverCmd); void resetData(); + + void removeCachedBody(int bodyUniqueId); + public: PhysicsDirect(class PhysicsCommandProcessorInterface* physSdk, bool passSdkOwnership); diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp index 223210e73..2883b3b92 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp @@ -27,6 +27,8 @@ #include "../CommonInterfaces/CommonGUIHelperInterface.h" #include "SharedMemoryCommands.h" #include "LinearMath/btRandom.h" +#include "Bullet3Common/b3ResizablePool.h" + #ifdef B3_ENABLE_TINY_AUDIO #include "../TinyAudio/b3SoundEngine.h" #endif @@ -133,13 +135,21 @@ struct InteralBodyData btHashMap m_audioSources; #endif //B3_ENABLE_TINY_AUDIO - InteralBodyData() - :m_multiBody(0), - m_rigidBody(0), - m_testData(0) + InteralBodyData() { - m_rootLocalInertialFrame.setIdentity(); + clear(); } + + void clear() + { + m_multiBody=0; + m_rigidBody=0; + m_testData=0; + m_bodyName=""; + m_rootLocalInertialFrame.setIdentity(); + m_linkLocalInertialFrames.clear(); + } + }; struct InteralUserConstraintData @@ -156,21 +166,8 @@ struct InteralUserConstraintData } }; -///todo: templatize this -struct InternalBodyHandle : public InteralBodyData -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); +typedef b3PoolBodyHandle InternalBodyHandle; - int m_nextFreeHandle; - void SetNextFree(int next) - { - m_nextFreeHandle = next; - } - int GetNextFree() const - { - return m_nextFreeHandle; - } -}; class btCommandChunk { @@ -1131,95 +1128,8 @@ struct ContactPointsStateLogger : public InternalStateLogger struct PhysicsServerCommandProcessorInternalData { ///handle management - btAlignedObjectArray m_bodyHandles; - int m_numUsedHandles; // number of active handles - int m_firstFreeHandle; // free handles list + b3ResizablePool< InternalBodyHandle > m_bodyHandles; - int getNumHandles() const - { - return m_bodyHandles.size(); - } - - InternalBodyHandle* getHandle(int handle) - { - btAssert(handle>=0); - btAssert(handle=m_bodyHandles.size())) - { - return 0; - } - return &m_bodyHandles[handle]; - } - const InternalBodyHandle* getHandle(int handle) const - { - return &m_bodyHandles[handle]; - } - - void increaseHandleCapacity(int extraCapacity) - { - int curCapacity = m_bodyHandles.size(); - btAssert(curCapacity == m_numUsedHandles); - int newCapacity = curCapacity + extraCapacity; - m_bodyHandles.resize(newCapacity); - - { - for (int i = curCapacity; i < newCapacity; i++) - m_bodyHandles[i].SetNextFree(i + 1); - - - m_bodyHandles[newCapacity - 1].SetNextFree(-1); - } - m_firstFreeHandle = curCapacity; - } - void initHandles() - { - m_numUsedHandles = 0; - m_firstFreeHandle = -1; - - increaseHandleCapacity(1); - } - - void exitHandles() - { - m_bodyHandles.resize(0); - m_firstFreeHandle = -1; - m_numUsedHandles = 0; - } - - int allocHandle() - { - btAssert(m_firstFreeHandle>=0); - - int handle = m_firstFreeHandle; - m_firstFreeHandle = getHandle(handle)->GetNextFree(); - m_numUsedHandles++; - - if (m_firstFreeHandle<0) - { - //int curCapacity = m_bodyHandles.size(); - int additionalCapacity= m_bodyHandles.size(); - increaseHandleCapacity(additionalCapacity); - - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - } - - - return handle; - } - - - void freeHandle(int handle) - { - btAssert(handle >= 0); - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numUsedHandles--; - } - - ///end handle management bool m_allowRealTimeSimulation; bool m_hasGround; @@ -1346,7 +1256,8 @@ struct PhysicsServerCommandProcessorInternalData { m_vrControllerEvents.init(); - initHandles(); + m_bodyHandles.exitHandles(); + m_bodyHandles.initHandles(); #if 0 btAlignedObjectArray bla; @@ -1545,7 +1456,7 @@ void PhysicsServerCommandProcessor::processCollisionForces(btScalar timeStep) if ((uid0<0)||(linkIndex<-1)) continue; - InternalBodyHandle* bodyHandle0 = m_data->getHandle(uid0); + InternalBodyHandle* bodyHandle0 = m_data->m_bodyHandles.getHandle(uid0); SDFAudioSource* audioSrc = bodyHandle0->m_audioSources[linkIndex]; if (audioSrc==0) continue; @@ -1818,7 +1729,7 @@ void PhysicsServerCommandProcessor::deleteDynamicsWorld() delete m_data->m_collisionConfiguration; m_data->m_collisionConfiguration=0; - + m_userConstraintUIDGenerator = 1; } @@ -1882,9 +1793,9 @@ bool PhysicsServerCommandProcessor::processImportedObjects(const char* fileName, btRigidBody* rb = 0; //get a body index - int bodyUniqueId = m_data->allocHandle(); + int bodyUniqueId = m_data->m_bodyHandles.allocHandle(); - InternalBodyHandle* bodyHandle = m_data->getHandle(bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(bodyUniqueId); sd.m_bodyUniqueIds.push_back(bodyUniqueId); @@ -2062,7 +1973,7 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto if (loadOk) { //get a body index - int bodyUniqueId = m_data->allocHandle(); + int bodyUniqueId = m_data->m_bodyHandles.allocHandle(); if (bodyUniqueIdPtr) *bodyUniqueIdPtr= bodyUniqueId; @@ -2075,7 +1986,7 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto } u2b.setBodyUniqueId(bodyUniqueId); - InternalBodyHandle* bodyHandle = m_data->getHandle(bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(bodyUniqueId); @@ -2258,7 +2169,7 @@ int PhysicsServerCommandProcessor::createBodyInfoStream(int bodyUniqueId, char* int streamSizeInBytes = 0; //serialize the btMultiBody and send the data to the client. This is one way to get the link/joint names across the (shared memory) wire - InternalBodyHandle* bodyHandle = m_data->getHandle(bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(bodyUniqueId); btMultiBody* mb = bodyHandle->m_multiBody; if (mb) { @@ -2390,7 +2301,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if ((clientCmd.m_updateFlags & STATE_LOGGING_FILTER_OBJECT_UNIQUE_ID)&& (clientCmd.m_stateLoggingArguments.m_numBodyUniqueIds>0)) { int bodyUniqueId = clientCmd.m_stateLoggingArguments.m_bodyUniqueIds[0]; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body) { if (body->m_multiBody) @@ -2891,11 +2802,12 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm { BT_PROFILE("CMD_SYNC_BODY_INFO"); - int numHandles = m_data->getNumHandles(); + b3AlignedObjectArray usedHandles; + m_data->m_bodyHandles.getUsedHandles(usedHandles); int actualNumBodies = 0; - for (int i=0;igetHandle(i); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(usedHandles[i]); if (body && (body->m_multiBody || body->m_rigidBody)) { serverStatusOut.m_sdfLoadedArgs.m_bodyUniqueIds[actualNumBodies++] = i; @@ -2929,7 +2841,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverStatusOut.m_dataStreamArguments.m_bodyUniqueId = sdfInfoArgs.m_bodyUniqueId; serverStatusOut.m_dataStreamArguments.m_bodyName[0] = 0; - InternalBodyHandle* bodyHandle = m_data->getHandle(clientCmd.m_calculateJacobianArguments.m_bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(clientCmd.m_calculateJacobianArguments.m_bodyUniqueId); if (bodyHandle) { strcpy(serverStatusOut.m_dataStreamArguments.m_bodyName,bodyHandle->m_bodyName.c_str()); @@ -2946,7 +2858,6 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm ///this is a very rudimentary way to save the state of the world, for scene authoring ///many todo's, for example save the state of motor controllers etc. - { //saveWorld(clientCmd.m_sdfArguments.m_sdfFileName); @@ -2985,7 +2896,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm { { int bodyUniqueId = sd.m_bodyUniqueIds[i]; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body) { if (body->m_multiBody) @@ -3279,7 +3190,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverStatusOut.m_numDataStreamBytes = m_data->m_urdfLinkNameMapper.at(m_data->m_urdfLinkNameMapper.size()-1)->m_memSerializer->getCurrentBufferSize(); } serverStatusOut.m_dataStreamArguments.m_bodyUniqueId = bodyUniqueId; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); strcpy(serverStatusOut.m_dataStreamArguments.m_bodyName, body->m_bodyName.c_str()); hasStatus = true; @@ -3348,7 +3259,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm b3Printf("Processed CMD_CREATE_SENSOR"); } int bodyUniqueId = clientCmd.m_createSensorArguments.m_bodyUniqueId; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body && body->m_multiBody) { btMultiBody* mb = body->m_multiBody; @@ -3418,7 +3329,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm } int bodyUniqueId = clientCmd.m_sendDesiredStateCommandArgument.m_bodyUniqueId; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body && body->m_multiBody) { @@ -3610,7 +3521,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm b3Printf("Sending the actual state (Q,U)"); } int bodyUniqueId = clientCmd.m_requestActualStateInformationCommandArgument.m_bodyUniqueId; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body && body->m_multiBody) { @@ -3852,13 +3763,19 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm b3Printf("CMD_STEP_FORWARD_SIMULATION clientCmd = %d\n", clientCmd.m_sequenceNumber); } ///todo(erwincoumans) move this damping inside Bullet - for (int i=0;im_bodyHandles.size();i++) - { - applyJointDamping(i); - } - - - + for (int i=0;im_dynamicsWorld->getNumMultibodies();i++) + { + btMultiBody* mb = m_data->m_dynamicsWorld->getMultiBody(i); + for (int l=0;lgetNumLinks();l++) + { + for (int d=0;dgetLink(l).m_dofCount;d++) + { + double damping_coefficient = mb->getLink(l).m_jointDamping; + double damping = -damping_coefficient*mb->getJointVelMultiDof(l)[d]; + mb->addJointTorqueMultiDof(l, d, damping); + } + } + } btScalar deltaTimeScaled = m_data->m_physicsDeltaTime*simTimeScalingFactor; @@ -3913,7 +3830,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm btAssert(bodyUniqueId >= 0); btAssert(linkIndex >= -1); - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body && body->m_multiBody) { btMultiBody* mb = body->m_multiBody; @@ -3936,7 +3853,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm btAssert(bodyUniqueId >= 0); btAssert(linkIndex >= -1); - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body && body->m_multiBody) { btMultiBody* mb = body->m_multiBody; @@ -4044,7 +3961,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm b3Printf("Server Init Pose not implemented yet"); } int bodyUniqueId = clientCmd.m_initPoseArgs.m_bodyUniqueId; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); btVector3 baseLinVel(0, 0, 0); btVector3 baseAngVel(0, 0, 0); @@ -4324,8 +4241,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverCmd.m_type = CMD_RIGID_BODY_CREATION_COMPLETED; - int bodyUniqueId = m_data->allocHandle(); - InternalBodyHandle* bodyHandle = m_data->getHandle(bodyUniqueId); + int bodyUniqueId = m_data->m_bodyHandles.allocHandle(); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(bodyUniqueId); serverCmd.m_rigidBodyCreateArgs.m_bodyUniqueId = bodyUniqueId; rb->setUserIndex2(bodyUniqueId); bodyHandle->m_rootLocalInertialFrame.setIdentity(); @@ -4614,7 +4531,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if (bodyUniqueIdA >= 0) { - InteralBodyData* bodyA = m_data->getHandle(bodyUniqueIdA); + InteralBodyData* bodyA = m_data->m_bodyHandles.getHandle(bodyUniqueIdA); if (bodyA) { if (bodyA->m_multiBody) @@ -4648,7 +4565,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm } if (bodyUniqueIdB>=0) { - InteralBodyData* bodyB = m_data->getHandle(bodyUniqueIdB); + InteralBodyData* bodyB = m_data->m_bodyHandles.getHandle(bodyUniqueIdB); if (bodyB) { if (bodyB->m_multiBody) @@ -4802,7 +4719,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm { BT_PROFILE("CMD_CALCULATE_INVERSE_DYNAMICS"); SharedMemoryStatus& serverCmd = serverStatusOut; - InternalBodyHandle* bodyHandle = m_data->getHandle(clientCmd.m_calculateInverseDynamicsArguments.m_bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(clientCmd.m_calculateInverseDynamicsArguments.m_bodyUniqueId); if (bodyHandle && bodyHandle->m_multiBody) { serverCmd.m_type = CMD_CALCULATED_INVERSE_DYNAMICS_FAILED; @@ -4854,7 +4771,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm BT_PROFILE("CMD_CALCULATE_JACOBIAN"); SharedMemoryStatus& serverCmd = serverStatusOut; - InternalBodyHandle* bodyHandle = m_data->getHandle(clientCmd.m_calculateJacobianArguments.m_bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(clientCmd.m_calculateJacobianArguments.m_bodyUniqueId); if (bodyHandle && bodyHandle->m_multiBody) { serverCmd.m_type = CMD_CALCULATED_JACOBIAN_FAILED; @@ -4917,7 +4834,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm } for (int i = 0; i < clientCmd.m_externalForceArguments.m_numForcesAndTorques; ++i) { - InteralBodyData* body = m_data->getHandle(clientCmd.m_externalForceArguments.m_bodyUniqueIds[i]); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(clientCmd.m_externalForceArguments.m_bodyUniqueIds[i]); bool isLinkFrame = ((clientCmd.m_externalForceArguments.m_forceFlags[i] & EF_LINK_FRAME) != 0); if (body && body->m_multiBody) @@ -5008,6 +4925,95 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm hasStatus = true; break; } + case CMD_REMOVE_BODY: + { + SharedMemoryStatus& serverCmd =serverStatusOut; + serverCmd.m_type = CMD_REMOVE_BODY_FAILED; + serverCmd.m_removeObjectArgs.m_numBodies = 0; + serverCmd.m_removeObjectArgs.m_numUserConstraints = 0; + + for (int i=0;im_bodyHandles.getHandle(bodyUniqueId); + if (bodyHandle) + { + if (bodyHandle->m_multiBody) + { + serverCmd.m_removeObjectArgs.m_bodyUniqueIds[serverCmd.m_removeObjectArgs.m_numBodies++] = bodyUniqueId; + + //also remove user constraints... + for (int i=m_data->m_dynamicsWorld->getNumMultiBodyConstraints()-1;i>=0;i--) + { + btMultiBodyConstraint* mbc = m_data->m_dynamicsWorld->getMultiBodyConstraint(i); + if ((mbc->getMultiBodyA() == bodyHandle->m_multiBody)||(mbc->getMultiBodyB()==bodyHandle->m_multiBody)) + { + m_data->m_dynamicsWorld->removeMultiBodyConstraint(mbc); + + //also remove user constraint and submit it as removed + for (int c=m_data->m_userConstraints.size()-1;c>=0;c--) + { + InteralUserConstraintData* userConstraintPtr = m_data->m_userConstraints.getAtIndex(c); + int userConstraintKey = m_data->m_userConstraints.getKeyAtIndex(c).getUid1(); + + if (userConstraintPtr->m_mbConstraint == mbc) + { + m_data->m_userConstraints.remove(userConstraintKey); + serverCmd.m_removeObjectArgs.m_userConstraintUniqueIds[serverCmd.m_removeObjectArgs.m_numUserConstraints++]=userConstraintKey; + } + } + + delete mbc; + + + } + } + + if (bodyHandle->m_multiBody->getBaseCollider()) + { + m_data->m_dynamicsWorld->removeCollisionObject(bodyHandle->m_multiBody->getBaseCollider()); + int graphicsIndex = bodyHandle->m_multiBody->getBaseCollider()->getUserIndex(); + m_data->m_guiHelper->removeGraphicsInstance(graphicsIndex); + } + for (int link=0;linkm_multiBody->getNumLinks();link++) + { + + if (bodyHandle->m_multiBody->getLink(link).m_collider) + { + m_data->m_dynamicsWorld->removeCollisionObject(bodyHandle->m_multiBody->getLink(link).m_collider); + int graphicsIndex = bodyHandle->m_multiBody->getLink(link).m_collider->getUserIndex(); + m_data->m_guiHelper->removeGraphicsInstance(graphicsIndex); + } + } + int numCollisionObjects = m_data->m_dynamicsWorld->getNumCollisionObjects(); + m_data->m_dynamicsWorld->removeMultiBody(bodyHandle->m_multiBody); + numCollisionObjects = m_data->m_dynamicsWorld->getNumCollisionObjects(); + //todo: clear all other remaining data, release memory etc + + delete bodyHandle->m_multiBody; + bodyHandle->m_multiBody=0; + serverCmd.m_type = CMD_REMOVE_BODY_COMPLETED; + } + if (bodyHandle->m_rigidBody) + { + serverCmd.m_removeObjectArgs.m_bodyUniqueIds[serverCmd.m_removeObjectArgs.m_numBodies++] = bodyUniqueId; + //todo: clear all other remaining data... + m_data->m_dynamicsWorld->removeRigidBody(bodyHandle->m_rigidBody); + int graphicsInstance = bodyHandle->m_rigidBody->getUserIndex2(); + m_data->m_guiHelper->removeGraphicsInstance(graphicsInstance); + delete bodyHandle->m_rigidBody; + bodyHandle->m_rigidBody=0; + serverCmd.m_type = CMD_REMOVE_BODY_COMPLETED; + } + } + + m_data->m_bodyHandles.freeHandle(bodyUniqueId); + } + + + hasStatus = true; + break; + } case CMD_USER_CONSTRAINT: { BT_PROFILE("CMD_USER_CONSTRAINT"); @@ -5028,12 +5034,12 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if (clientCmd.m_updateFlags & USER_CONSTRAINT_ADD_CONSTRAINT) { btScalar defaultMaxForce = 500.0; - InteralBodyData* parentBody = m_data->getHandle(clientCmd.m_userConstraintArguments.m_parentBodyIndex); + InteralBodyData* parentBody = m_data->m_bodyHandles.getHandle(clientCmd.m_userConstraintArguments.m_parentBodyIndex); if (parentBody && parentBody->m_multiBody) { if ((clientCmd.m_userConstraintArguments.m_parentJointIndex>=-1) && clientCmd.m_userConstraintArguments.m_parentJointIndex < parentBody->m_multiBody->getNumLinks()) { - InteralBodyData* childBody = clientCmd.m_userConstraintArguments.m_childBodyIndex>=0 ? m_data->getHandle(clientCmd.m_userConstraintArguments.m_childBodyIndex):0; + InteralBodyData* childBody = clientCmd.m_userConstraintArguments.m_childBodyIndex>=0 ? m_data->m_bodyHandles.getHandle(clientCmd.m_userConstraintArguments.m_childBodyIndex):0; //also create a constraint with just a single multibody/rigid body without child //if (childBody) { @@ -5246,7 +5252,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm SharedMemoryStatus& serverCmd = serverStatusOut; serverCmd.m_type = CMD_CALCULATE_INVERSE_KINEMATICS_FAILED; - InternalBodyHandle* bodyHandle = m_data->getHandle(clientCmd.m_calculateInverseKinematicsArguments.m_bodyUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(clientCmd.m_calculateInverseKinematicsArguments.m_bodyUniqueId); if (bodyHandle && bodyHandle->m_multiBody) { IKTrajectoryHelper** ikHelperPtrPtr = m_data->m_inverseKinematicsHelpers.find(bodyHandle->m_multiBody); @@ -5519,8 +5525,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm btRigidBody* rb = btRigidBody::upcast(colObj); if (rb) { - int bodyUniqueId = m_data->allocHandle(); - InternalBodyHandle* bodyHandle = m_data->getHandle(bodyUniqueId); + int bodyUniqueId = m_data->m_bodyHandles.allocHandle(); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(bodyUniqueId); colObj->setUserIndex2(bodyUniqueId); bodyHandle->m_rigidBody = rb; @@ -5630,7 +5636,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if ((clientCmd.m_updateFlags & USER_DEBUG_SET_CUSTOM_OBJECT_COLOR) || (clientCmd.m_updateFlags & USER_DEBUG_REMOVE_CUSTOM_OBJECT_COLOR)) { int bodyUniqueId = clientCmd.m_userDebugDrawArgs.m_objectUniqueId; - InteralBodyData* body = m_data->getHandle(bodyUniqueId); + InteralBodyData* body = m_data->m_bodyHandles.getHandle(bodyUniqueId); if (body) { btCollisionObject* destColObj = 0; @@ -6014,7 +6020,7 @@ void PhysicsServerCommandProcessor::stepSimulationRealTime(double dtInSec, const if (gVRTrackingObjectUniqueId >= 0) { - InternalBodyHandle* bodyHandle = m_data->getHandle(gVRTrackingObjectUniqueId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(gVRTrackingObjectUniqueId); if (bodyHandle && bodyHandle->m_multiBody) { gVRTrackingObjectTr = bodyHandle->m_multiBody->getBaseWorldTransform(); @@ -6033,22 +6039,7 @@ void PhysicsServerCommandProcessor::stepSimulationRealTime(double dtInSec, const } } -void PhysicsServerCommandProcessor::applyJointDamping(int bodyUniqueId) -{ - InteralBodyData* body = m_data->getHandle(bodyUniqueId); - if (body) { - btMultiBody* mb = body->m_multiBody; - if (mb) { - for (int l=0;lgetNumLinks();l++) { - for (int d=0;dgetLink(l).m_dofCount;d++) { - double damping_coefficient = mb->getLink(l).m_jointDamping; - double damping = -damping_coefficient*mb->getJointVelMultiDof(l)[d]; - mb->addJointTorqueMultiDof(l, d, damping); - } - } - } - } -} + void PhysicsServerCommandProcessor::resetSimulation() { @@ -6069,8 +6060,8 @@ void PhysicsServerCommandProcessor::resetSimulation() deleteDynamicsWorld(); createEmptyDynamicsWorld(); - m_data->exitHandles(); - m_data->initHandles(); + m_data->m_bodyHandles.exitHandles(); + m_data->m_bodyHandles.initHandles(); m_data->m_hasGround = false; m_data->m_gripperRigidbodyFixed = 0; @@ -6095,7 +6086,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() loadUrdf("sphere_small.urdf", spawnPos, gVRGripperOrn, true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size(),0); //loadUrdf("lego/lego.urdf", spawnPos, gVRGripperOrn, true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size()); m_data->m_sphereId = bodyId; - InteralBodyData* parentBody = m_data->getHandle(bodyId); + InteralBodyData* parentBody = m_data->m_bodyHandles.getHandle(bodyId); if (parentBody->m_multiBody) { parentBody->m_multiBody->setBaseVel(spawnDir * 5); @@ -6116,7 +6107,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() if (loadUrdf("pr2_gripper.urdf", btVector3(-0.2, 0.15, 0.9), btQuaternion(0, 0, 0, 1), true, false, &bodyId, &gBufferServerToClient[0], gBufferServerToClient.size())) { - InteralBodyData* parentBody = m_data->getHandle(bodyId); + InteralBodyData* parentBody = m_data->m_bodyHandles.getHandle(bodyId); if (parentBody->m_multiBody) { parentBody->m_multiBody->setHasSelfCollision(0); @@ -6146,7 +6137,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() m_data->m_KukaId = bodyId; if (m_data->m_KukaId>=0) { - InteralBodyData* kukaBody = m_data->getHandle(m_data->m_KukaId); + InteralBodyData* kukaBody = m_data->m_bodyHandles.getHandle(m_data->m_KukaId); if (kukaBody->m_multiBody && kukaBody->m_multiBody->getNumDofs() == 7) { btScalar q[7]; @@ -6184,7 +6175,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() loadSdf("gripper/wsg50_one_motor_gripper_new_free_base.sdf", &gBufferServerToClient[0], gBufferServerToClient.size(), true,CUF_USE_SDF); m_data->m_gripperId = bodyId + 1; { - InteralBodyData* gripperBody = m_data->getHandle(m_data->m_gripperId); + InteralBodyData* gripperBody = m_data->m_bodyHandles.getHandle(m_data->m_gripperId); // Reset the default gripper motor maximum torque for damping to 0 for (int i = 0; i < gripperBody->m_multiBody->getNumLinks(); i++) @@ -6222,7 +6213,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() if (m_data->m_gripperId>=0) { - InteralBodyData* gripperBody = m_data->getHandle(m_data->m_gripperId); + InteralBodyData* gripperBody = m_data->m_bodyHandles.getHandle(m_data->m_gripperId); m_data->m_kukaGripperRevolute1 = new btMultiBodyPoint2Point(gripperBody->m_multiBody, 2, gripperBody->m_multiBody, 4, pivotInParent1, pivotInChild1); m_data->m_kukaGripperRevolute1->setMaxAppliedImpulse(5.0); m_data->m_kukaGripperRevolute2 = new btMultiBodyPoint2Point(gripperBody->m_multiBody, 3, gripperBody->m_multiBody, 6, pivotInParent2, pivotInChild2); @@ -6235,12 +6226,12 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() if (m_data->m_KukaId>=0) { - InteralBodyData* kukaBody = m_data->getHandle(m_data->m_KukaId); + InteralBodyData* kukaBody = m_data->m_bodyHandles.getHandle(m_data->m_KukaId); if (kukaBody->m_multiBody && kukaBody->m_multiBody->getNumDofs()==7) { if (m_data->m_gripperId>=0) { - InteralBodyData* gripperBody = m_data->getHandle(m_data->m_gripperId); + InteralBodyData* gripperBody = m_data->m_bodyHandles.getHandle(m_data->m_gripperId); gripperBody->m_multiBody->setHasSelfCollision(0); btVector3 pivotInParent(0, 0, 0.05); @@ -6331,7 +6322,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() if (m_data->m_kukaGripperFixed && m_data->m_kukaGripperMultiBody) { - InteralBodyData* childBody = m_data->getHandle(m_data->m_gripperId); + InteralBodyData* childBody = m_data->m_bodyHandles.getHandle(m_data->m_gripperId); // Add gripper controller btMultiBodyJointMotor* motor = (btMultiBodyJointMotor*)childBody->m_multiBody->getLink(1).m_userPtr; if (motor) @@ -6399,7 +6390,7 @@ void PhysicsServerCommandProcessor::createDefaultRobotAssets() // Inverse kinematics for KUKA if (m_data->m_KukaId>=0) { - InternalBodyHandle* bodyHandle = m_data->getHandle(m_data->m_KukaId); + InternalBodyHandle* bodyHandle = m_data->m_bodyHandles.getHandle(m_data->m_KukaId); if (bodyHandle && bodyHandle->m_multiBody && bodyHandle->m_multiBody->getNumDofs()==7) { btMultiBody* mb = bodyHandle->m_multiBody; diff --git a/examples/SharedMemory/PhysicsServerExample.cpp b/examples/SharedMemory/PhysicsServerExample.cpp index 05a38169a..d0f6269a5 100644 --- a/examples/SharedMemory/PhysicsServerExample.cpp +++ b/examples/SharedMemory/PhysicsServerExample.cpp @@ -179,6 +179,7 @@ enum MultiThreadedGUIHelperCommunicationEnums eGUIUserDebugRemoveItem, eGUIUserDebugRemoveAllItems, eGUIDumpFramesToVideo, + eGUIHelperRemoveGraphicsInstance, }; @@ -778,6 +779,15 @@ public: workerThreadWait(); } + int m_graphicsInstanceRemove; + virtual void removeGraphicsInstance(int graphicsUid) + { + m_graphicsInstanceRemove = graphicsUid; + m_cs->lock(); + m_cs->setSharedParam(1,eGUIHelperRemoveGraphicsInstance); + workerThreadWait(); + } + virtual Common2dCanvasInterface* get2dCanvasInterface() { return 0; @@ -1193,39 +1203,45 @@ public: printf("key[%d]=%d state = %d\n",i,m_args[0].m_keyboardEvents[i].m_keyCode,m_args[0].m_keyboardEvents[i].m_keyState); } */ + double shift=0.1; + + CommonWindowInterface* window = m_guiHelper->getAppInterface()->m_window; + if (window->isModifierKeyPressed(B3G_SHIFT)) + shift=0.01; + if (key=='w' && state) { - gVRTeleportPos1[0]+=0.1; + gVRTeleportPos1[0]+=shift; saveCurrentSettingsVR(); } if (key=='s' && state) { - gVRTeleportPos1[0]-=0.1; + gVRTeleportPos1[0]-=shift; saveCurrentSettingsVR(); } if (key=='a' && state) { - gVRTeleportPos1[1]-=0.1; + gVRTeleportPos1[1]-=shift; saveCurrentSettingsVR(); } if (key=='d' && state) { - gVRTeleportPos1[1]+=0.1; + gVRTeleportPos1[1]+=shift; saveCurrentSettingsVR(); } if (key=='q' && state) { - gVRTeleportPos1[2]+=0.1; + gVRTeleportPos1[2]+=shift; saveCurrentSettingsVR(); } if (key=='e' && state) { - gVRTeleportPos1[2]-=0.1; + gVRTeleportPos1[2]-=shift; saveCurrentSettingsVR(); } if (key=='z' && state) { - gVRTeleportRotZ+=0.1; + gVRTeleportRotZ+=shift; gVRTeleportOrn = btQuaternion(btVector3(0, 0, 1), gVRTeleportRotZ); saveCurrentSettingsVR(); } @@ -1551,7 +1567,15 @@ void PhysicsServerExample::updateGraphics() break; } - + case eGUIHelperRemoveGraphicsInstance: + { + m_multiThreadedHelper->m_childGuiHelper->removeGraphicsInstance(m_multiThreadedHelper->m_graphicsInstanceRemove); + m_multiThreadedHelper->mainThreadRelease(); + break; + } + + + case eGUIHelperCopyCameraImageData: { m_multiThreadedHelper->m_childGuiHelper->copyCameraImageData(m_multiThreadedHelper->m_viewMatrix, diff --git a/examples/SharedMemory/SharedMemoryCommands.h b/examples/SharedMemory/SharedMemoryCommands.h index 1c141e97d..299b1c804 100644 --- a/examples/SharedMemory/SharedMemoryCommands.h +++ b/examples/SharedMemory/SharedMemoryCommands.h @@ -451,6 +451,14 @@ struct CreateBoxShapeArgs double m_colorRGBA[4]; }; +struct b3ObjectArgs +{ + int m_numBodies; + int m_bodyUniqueIds[MAX_SDF_BODIES]; + int m_numUserConstraints; + int m_userConstraintUniqueIds[MAX_SDF_BODIES]; +}; + struct SdfLoadedArgs { int m_numBodies; @@ -572,6 +580,10 @@ enum EnumUserConstraintFlags }; +enum EnumBodyChangeFlags +{ + BODY_DELETE_FLAG=1, +}; @@ -745,6 +757,8 @@ struct SharedMemoryCommand struct VRCameraState m_vrCameraStateArguments; struct StateLoggingRequest m_stateLoggingArguments; struct ConfigureOpenGLVisualizerRequest m_configureOpenGLVisualizerArguments; + struct b3ObjectArgs m_removeObjectArgs; + }; }; @@ -808,6 +822,7 @@ struct SharedMemoryStatus struct SendRaycastHits m_raycastHits; struct StateLoggingResultArgs m_stateLoggingResultArgs; struct b3OpenGLVisualizerCameraInfo m_visualizerCameraResultArgs; + struct b3ObjectArgs m_removeObjectArgs; }; }; diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h index 4f1771a2d..57b44fef6 100644 --- a/examples/SharedMemory/SharedMemoryPublic.h +++ b/examples/SharedMemory/SharedMemoryPublic.h @@ -55,6 +55,7 @@ enum EnumSharedMemoryClientCommand CMD_CONFIGURE_OPENGL_VISUALIZER, CMD_REQUEST_KEYBOARD_EVENTS_DATA, CMD_REQUEST_OPENGL_VISUALIZER_CAMERA, + CMD_REMOVE_BODY, CMD_RESET_DYNAMIC_INFO, //don't go beyond this command! CMD_MAX_CLIENT_COMMANDS, @@ -137,6 +138,8 @@ enum EnumSharedMemoryServerStatus CMD_REQUEST_KEYBOARD_EVENTS_DATA_FAILED, CMD_REQUEST_OPENGL_VISUALIZER_CAMERA_FAILED, CMD_REQUEST_OPENGL_VISUALIZER_CAMERA_COMPLETED, + CMD_REMOVE_BODY_COMPLETED, + CMD_REMOVE_BODY_FAILED, //don't go beyond 'CMD_MAX_SERVER_COMMANDS! CMD_MAX_SERVER_COMMANDS }; diff --git a/examples/SharedMemory/premake4.lua b/examples/SharedMemory/premake4.lua index 20d97c36b..ff2ab709f 100644 --- a/examples/SharedMemory/premake4.lua +++ b/examples/SharedMemory/premake4.lua @@ -344,6 +344,7 @@ if os.is("Windows") then "../ThirdPartyLibs/openvr/samples/shared/lodepng.h", "../ThirdPartyLibs/openvr/samples/shared/Matrices.cpp", "../ThirdPartyLibs/openvr/samples/shared/Matrices.h", + "../ThirdPartyLibs/openvr/samples/shared/strtools.cpp", "../ThirdPartyLibs/openvr/samples/shared/pathtools.cpp", "../ThirdPartyLibs/openvr/samples/shared/pathtools.h", "../ThirdPartyLibs/openvr/samples/shared/Vectors.h", diff --git a/examples/ThirdPartyLibs/openvr/bin/linux32/libopenvr_api.so b/examples/ThirdPartyLibs/openvr/bin/linux32/libopenvr_api.so new file mode 100644 index 000000000..00825b982 Binary files /dev/null and b/examples/ThirdPartyLibs/openvr/bin/linux32/libopenvr_api.so differ diff --git a/examples/ThirdPartyLibs/openvr/bin/linux64/libopenvr_api.so b/examples/ThirdPartyLibs/openvr/bin/linux64/libopenvr_api.so index 7b6f2d2de..8d30531dc 100644 Binary files a/examples/ThirdPartyLibs/openvr/bin/linux64/libopenvr_api.so and b/examples/ThirdPartyLibs/openvr/bin/linux64/libopenvr_api.so differ diff --git a/examples/ThirdPartyLibs/openvr/bin/osx32/libopenvr_api.dylib b/examples/ThirdPartyLibs/openvr/bin/osx32/libopenvr_api.dylib index 647ec3fa9..5a20f3aae 100644 Binary files a/examples/ThirdPartyLibs/openvr/bin/osx32/libopenvr_api.dylib and b/examples/ThirdPartyLibs/openvr/bin/osx32/libopenvr_api.dylib differ diff --git a/examples/ThirdPartyLibs/openvr/bin/win32/openvr_api.dll b/examples/ThirdPartyLibs/openvr/bin/win32/openvr_api.dll index 7aa2b993a..aafef728c 100644 Binary files a/examples/ThirdPartyLibs/openvr/bin/win32/openvr_api.dll and b/examples/ThirdPartyLibs/openvr/bin/win32/openvr_api.dll differ diff --git a/examples/ThirdPartyLibs/openvr/bin/win64/openvr_api.dll b/examples/ThirdPartyLibs/openvr/bin/win64/openvr_api.dll index bbcccde55..ddda89700 100644 Binary files a/examples/ThirdPartyLibs/openvr/bin/win64/openvr_api.dll and b/examples/ThirdPartyLibs/openvr/bin/win64/openvr_api.dll differ diff --git a/examples/ThirdPartyLibs/openvr/headers/openvr.h b/examples/ThirdPartyLibs/openvr/headers/openvr.h index 6617b4d34..2020e9d3a 100644 --- a/examples/ThirdPartyLibs/openvr/headers/openvr.h +++ b/examples/ThirdPartyLibs/openvr/headers/openvr.h @@ -21,19 +21,13 @@ struct VkPhysicalDevice_T; struct VkInstance_T; struct VkQueue_T; +// Forward declarations to avoid requiring d3d12.h +struct ID3D12Resource; +struct ID3D12CommandQueue; + namespace vr { - -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. - #pragma pack( push, 4 ) -#else - #pragma pack( push, 8 ) -#endif +#pragma pack( push, 8 ) typedef void* glSharedTextureHandle_t; typedef int32_t glInt_t; @@ -116,6 +110,8 @@ enum ETextureType TextureType_DirectX = 0, // Handle is an ID3D11Texture TextureType_OpenGL = 1, // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure + TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurfaceRef + TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure }; enum EColorSpace @@ -164,6 +160,7 @@ enum ETrackedDeviceClass TrackedDeviceClass_Controller = 2, // Tracked controllers TrackedDeviceClass_GenericTracker = 3, // Generic trackers, similar to controllers TrackedDeviceClass_TrackingReference = 4, // Camera and base stations that serve as tracking reference points + TrackedDeviceClass_DisplayRedirect = 5, // Accessories that aren't necessarily tracked themselves, but may redirect video output from other tracked devices }; @@ -199,6 +196,30 @@ enum ETrackingUniverseOrigin TrackingUniverseRawAndUncalibrated = 2, // Poses are provided in the coordinate system defined by the driver. It has Y up and is unified for devices of the same driver. You usually don't want this one. }; +// Refers to a single container of properties +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + +static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0; +static const PropertyTypeTag_t k_unInvalidPropertyTag = 0; + +// Use these tags to set/get common types as struct properties +static const PropertyTypeTag_t k_unFloatPropertyTag = 1; +static const PropertyTypeTag_t k_unInt32PropertyTag = 2; +static const PropertyTypeTag_t k_unUint64PropertyTag = 3; +static const PropertyTypeTag_t k_unBoolPropertyTag = 4; +static const PropertyTypeTag_t k_unStringPropertyTag = 5; + +static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20; +static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21; +static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22; +static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23; + +static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30; + +static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000; +static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000; + /** Each entry in this enum represents a property that can be retrieved about a * tracked device. Many fields are only valid for one ETrackedDeviceClass. */ @@ -241,6 +262,8 @@ enum ETrackedDeviceProperty Prop_DriverVersion_String = 1031, Prop_Firmware_ForceUpdateRequired_Bool = 1032, Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + Prop_ResourceRoot_String = 1035, // Properties that are unique to TrackedDeviceClass_HMD Prop_ReportsTimeSinceVSync_Bool = 2000, @@ -281,6 +304,11 @@ enum ETrackedDeviceProperty Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, Prop_DisplaySuppressed_Bool = 2036, Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_SecondsFromPhotonsToVblank_Float = 2042, // Properties that are unique to TrackedDeviceClass_Controller Prop_AttachedDeviceId_String = 3000, @@ -312,6 +340,19 @@ enum ETrackedDeviceProperty Prop_NamedIconPathDeviceStandby_String = 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others Prop_NamedIconPathDeviceAlertLow_String = 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + // Properties that are used by helpers, but are opaque to applications + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + + // Properties that are unique to drivers + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + Prop_HasDisplayComponent_Bool = 6002, + Prop_HasControllerComponent_Bool = 6003, + Prop_HasCameraComponent_Bool = 6004, + Prop_HasDriverDirectModeComponent_Bool = 6005, + Prop_HasVirtualDisplayComponent_Bool = 6006, + // Vendors are free to expose private debug data in this reserved region Prop_VendorSpecific_Reserved_Start = 10000, Prop_VendorSpecific_Reserved_End = 10999, @@ -327,13 +368,14 @@ enum ETrackedPropertyError TrackedProp_WrongDataType = 1, TrackedProp_WrongDeviceClass = 2, TrackedProp_BufferTooSmall = 3, - TrackedProp_UnknownProperty = 4, + TrackedProp_UnknownProperty = 4, // Driver has not set the property (and may not ever). TrackedProp_InvalidDevice = 5, TrackedProp_CouldNotContactServer = 6, TrackedProp_ValueNotProvidedByDevice = 7, TrackedProp_StringExceedsMaximumLength = 8, TrackedProp_NotYetAvailable = 9, // The property value isn't known yet, but is expected soon. Call again later. TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, }; /** Allows the application to control what part of the provided texture will be used in the @@ -376,6 +418,14 @@ struct VRVulkanTextureData_t uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount; }; +/** Data required for passing D3D12 textures to IVRCompositor::Submit. +* Be sure to call OpenVR_Shutdown before destroying these resources. */ +struct D3D12TextureData_t +{ + ID3D12Resource *m_pResource; + ID3D12CommandQueue *m_pCommandQueue; + uint32_t m_nNodeMask; +}; /** Status of the overall system or tracked objects */ enum EVRState @@ -399,7 +449,7 @@ enum EVREventType VREvent_TrackedDeviceActivated = 100, VREvent_TrackedDeviceDeactivated = 101, VREvent_TrackedDeviceUpdated = 102, - VREvent_TrackedDeviceUserInteractionStarted = 103, + VREvent_TrackedDeviceUserInteractionStarted = 103, VREvent_TrackedDeviceUserInteractionEnded = 104, VREvent_IpdChanged = 105, VREvent_EnterStandbyMode = 106, @@ -407,6 +457,7 @@ enum EVREventType VREvent_TrackedDeviceRoleChanged = 108, VREvent_WatchdogWakeUpRequested = 109, VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, VREvent_ButtonPress = 200, // data is controller VREvent_ButtonUnpress = 201, // data is controller @@ -436,78 +487,83 @@ enum EVREventType VREvent_OverlayShown = 500, VREvent_OverlayHidden = 501, - VREvent_DashboardActivated = 502, - VREvent_DashboardDeactivated = 503, - VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay - VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay - VREvent_ResetDashboard = 506, // Send to the overlay manager - VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID - VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading - VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it - VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it - VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it - VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else + VREvent_DashboardActivated = 502, + VREvent_DashboardDeactivated = 503, + VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay + VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay + VREvent_ResetDashboard = 506, // Send to the overlay manager + VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID + VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading + VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it + VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it + VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it + VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else VREvent_OverlaySharedTextureChanged = 513, - VREvent_DashboardGuideButtonDown = 514, - VREvent_DashboardGuideButtonUp = 515, - VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot - VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load - VREvent_DashboardOverlayCreated = 518, + VREvent_DashboardGuideButtonDown = 514, + VREvent_DashboardGuideButtonUp = 515, + VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot + VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load + VREvent_DashboardOverlayCreated = 518, // Screenshot API - VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot - VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken - VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken - VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted - VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot + VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken + VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken + VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + + VREvent_PrimaryDashboardDeviceChanged = 525, VREvent_Notification_Shown = 600, VREvent_Notification_Hidden = 601, VREvent_Notification_BeginInteraction = 602, VREvent_Notification_Destroyed = 603, - VREvent_Quit = 700, // data is process - VREvent_ProcessQuit = 701, // data is process - VREvent_QuitAborted_UserPrompt = 702, // data is process - VREvent_QuitAcknowledged = 703, // data is process - VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down + VREvent_Quit = 700, // data is process + VREvent_ProcessQuit = 701, // data is process + VREvent_QuitAborted_UserPrompt = 702, // data is process + VREvent_QuitAcknowledged = 703, // data is process + VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down - VREvent_ChaperoneDataHasChanged = 800, - VREvent_ChaperoneUniverseHasChanged = 801, - VREvent_ChaperoneTempDataHasChanged = 802, - VREvent_ChaperoneSettingsHaveChanged = 803, - VREvent_SeatedZeroPoseReset = 804, + VREvent_ChaperoneDataHasChanged = 800, + VREvent_ChaperoneUniverseHasChanged = 801, + VREvent_ChaperoneTempDataHasChanged = 802, + VREvent_ChaperoneSettingsHaveChanged = 803, + VREvent_SeatedZeroPoseReset = 804, - VREvent_AudioSettingsHaveChanged = 820, + VREvent_AudioSettingsHaveChanged = 820, - VREvent_BackgroundSettingHasChanged = 850, - VREvent_CameraSettingsHaveChanged = 851, - VREvent_ReprojectionSettingHasChanged = 852, - VREvent_ModelSkinSettingsHaveChanged = 853, - VREvent_EnvironmentSettingsHaveChanged = 854, - VREvent_PowerSettingsHaveChanged = 855, + VREvent_BackgroundSettingHasChanged = 850, + VREvent_CameraSettingsHaveChanged = 851, + VREvent_ReprojectionSettingHasChanged = 852, + VREvent_ModelSkinSettingsHaveChanged = 853, + VREvent_EnvironmentSettingsHaveChanged = 854, + VREvent_PowerSettingsHaveChanged = 855, - VREvent_StatusUpdate = 900, + VREvent_StatusUpdate = 900, - VREvent_MCImageUpdated = 1000, + VREvent_MCImageUpdated = 1000, - VREvent_FirmwareUpdateStarted = 1100, - VREvent_FirmwareUpdateFinished = 1101, + VREvent_FirmwareUpdateStarted = 1100, + VREvent_FirmwareUpdateFinished = 1101, - VREvent_KeyboardClosed = 1200, - VREvent_KeyboardCharInput = 1201, - VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard + VREvent_KeyboardClosed = 1200, + VREvent_KeyboardCharInput = 1201, + VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard - VREvent_ApplicationTransitionStarted = 1300, - VREvent_ApplicationTransitionAborted = 1301, - VREvent_ApplicationTransitionNewAppStarted = 1302, - VREvent_ApplicationListUpdated = 1303, - VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionStarted = 1300, + VREvent_ApplicationTransitionAborted = 1301, + VREvent_ApplicationTransitionNewAppStarted = 1302, + VREvent_ApplicationListUpdated = 1303, + VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, + VREvent_ProcessConnected = 1306, + VREvent_ProcessDisconnected = 1307, - VREvent_Compositor_MirrorWindowShown = 1400, - VREvent_Compositor_MirrorWindowHidden = 1401, - VREvent_Compositor_ChaperoneBoundsShown = 1410, - VREvent_Compositor_ChaperoneBoundsHidden = 1411, + VREvent_Compositor_MirrorWindowShown = 1400, + VREvent_Compositor_MirrorWindowHidden = 1401, + VREvent_Compositor_ChaperoneBoundsShown = 1410, + VREvent_Compositor_ChaperoneBoundsHidden = 1411, VREvent_TrackedCamera_StartVideoStream = 1500, VREvent_TrackedCamera_StopVideoStream = 1501, @@ -515,26 +571,30 @@ enum EVREventType VREvent_TrackedCamera_ResumeVideoStream = 1503, VREvent_TrackedCamera_EditingSurface = 1550, - VREvent_PerformanceTest_EnableCapture = 1600, - VREvent_PerformanceTest_DisableCapture = 1601, - VREvent_PerformanceTest_FidelityLevel = 1602, + VREvent_PerformanceTest_EnableCapture = 1600, + VREvent_PerformanceTest_DisableCapture = 1601, + VREvent_PerformanceTest_FidelityLevel = 1602, - VREvent_MessageOverlay_Closed = 1650, + VREvent_MessageOverlay_Closed = 1650, // Vendors are free to expose private events in this reserved region - VREvent_VendorSpecific_Reserved_Start = 10000, - VREvent_VendorSpecific_Reserved_End = 19999, + VREvent_VendorSpecific_Reserved_Start = 10000, + VREvent_VendorSpecific_Reserved_End = 19999, }; /** Level of Hmd activity */ +// UserInteraction_Timeout means the device is in the process of timing out. +// InUse = ( k_EDeviceActivityLevel_UserInteraction || k_EDeviceActivityLevel_UserInteraction_Timeout ) +// VREvent_TrackedDeviceUserInteractionStarted fires when the devices transitions from Standby -> UserInteraction or Idle -> UserInteraction. +// VREvent_TrackedDeviceUserInteractionEnded fires when the devices transitions from UserInteraction_Timeout -> Idle enum EDeviceActivityLevel -{ - k_EDeviceActivityLevel_Unknown = -1, - k_EDeviceActivityLevel_Idle = 0, - k_EDeviceActivityLevel_UserInteraction = 1, - k_EDeviceActivityLevel_UserInteraction_Timeout = 2, - k_EDeviceActivityLevel_Standby = 3, +{ + k_EDeviceActivityLevel_Unknown = -1, + k_EDeviceActivityLevel_Idle = 0, // No activity for the last 10 seconds + k_EDeviceActivityLevel_UserInteraction = 1, // Activity (movement or prox sensor) is happening now + k_EDeviceActivityLevel_UserInteraction_Timeout = 2, // No activity for the last 0.5 seconds + k_EDeviceActivityLevel_Standby = 3, // Idle for at least 5 seconds (configurable in Settings -> Power Management) }; @@ -711,6 +771,12 @@ struct VREvent_MessageOverlay_t uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum }; +struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + ETrackedDeviceProperty prop; +}; + /** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */ typedef union { @@ -733,8 +799,16 @@ typedef union VREvent_ApplicationLaunch_t applicationLaunch; VREvent_EditingCameraSurface_t cameraSurface; VREvent_MessageOverlay_t messageOverlay; + VREvent_Property_t property; } VREvent_Data_t; + +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + /** An event posted by the server to all running applications */ struct VREvent_t { @@ -745,6 +819,9 @@ struct VREvent_t VREvent_Data_t data; }; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif /** The mesh to draw into the stencil (or depth) buffer to perform * early stencil (or depth) kills of pixels that will never appear on the HMD. @@ -764,6 +841,8 @@ enum EHiddenAreaMeshType k_eHiddenAreaMesh_Standard = 0, k_eHiddenAreaMesh_Inverse = 1, k_eHiddenAreaMesh_LineLoop = 2, + + k_eHiddenAreaMesh_Max = 3, }; @@ -791,6 +870,12 @@ struct VRControllerAxis_t static const uint32_t k_unControllerStateAxisCount = 5; +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + /** Holds all the state of a controller at one moment in time. */ struct VRControllerState001_t { @@ -805,6 +890,9 @@ struct VRControllerState001_t // Axis data for the controller's analog inputs VRControllerAxis_t rAxis[ k_unControllerStateAxisCount ]; }; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif typedef VRControllerState001_t VRControllerState_t; @@ -887,6 +975,7 @@ enum EVRApplicationType // interfaces (like IVRSettings and IVRApplications) but not hardware. VRApplication_VRMonitor = 5, // Reserved for vrmonitor VRApplication_SteamWatchdog = 6,// Reserved for Steam + VRApplication_Bootstrapper = 7, // Start up SteamVR VRApplication_Max }; @@ -1173,9 +1262,7 @@ public: /** [D3D10/11 Only] * Returns the adapter index that the user should pass into EnumAdapters to create the device - * and swap chain in DX10 and DX11. If an error occurs the index will be set to -1. The index will - * also be -1 if the headset is in direct mode on the driver side instead of using the compositor's - * builtin direct mode support. + * and swap chain in DX10 and DX11. If an error occurs the index will be set to -1. */ virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex ) = 0; @@ -1453,6 +1540,7 @@ namespace vr VRApplicationProperty_IsDashboardOverlay_Bool = 60, VRApplicationProperty_IsTemplate_Bool = 61, VRApplicationProperty_IsInstanced_Bool = 62, + VRApplicationProperty_IsInternal_Bool = 63, VRApplicationProperty_LastLaunchTime_Uint64 = 70, }; @@ -1600,6 +1688,11 @@ namespace vr * If working directory is NULL or "" the directory portion of the binary path will be * the working directory. */ virtual EVRApplicationError LaunchInternalProcess( const char *pchBinaryPath, const char *pchArguments, const char *pchWorkingDirectory ) = 0; + + /** Returns the current scene process ID according to the application system. A scene process will get scene + * focus once it starts rendering, but it will appear here once it calls VR_Init with the Scene application + * type. */ + virtual uint32_t GetCurrentSceneProcessId() = 0; }; static const char * const IVRApplications_Version = "IVRApplications_006"; @@ -1657,7 +1750,6 @@ namespace vr static const char * const k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd"; static const char * const k_pch_SteamVR_DisplayDebug_Bool = "displayDebug"; static const char * const k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe"; - static const char * const k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion"; static const char * const k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX"; static const char * const k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY"; static const char * const k_pch_SteamVR_SendSystemButtonToAllApps_Bool= "sendSystemButtonToAllApps"; @@ -1708,7 +1800,6 @@ namespace vr //----------------------------------------------------------------------------- // null keys static const char * const k_pch_Null_Section = "driver_null"; - static const char * const k_pch_Null_EnableNullDriver_Bool = "enable"; static const char * const k_pch_Null_SerialNumber_String = "serialNumber"; static const char * const k_pch_Null_ModelNumber_String = "modelNumber"; static const char * const k_pch_Null_WindowX_Int32 = "windowX"; @@ -1809,22 +1900,17 @@ namespace vr // model skin keys static const char * const k_pch_modelskin_Section = "modelskins"; + //----------------------------------------------------------------------------- + // driver keys - These could be checked in any driver_ section + static const char * const k_pch_Driver_Enable_Bool = "enable"; + } // namespace vr // ivrchaperone.h namespace vr { -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. - #pragma pack( push, 4 ) -#else - #pragma pack( push, 8 ) -#endif +#pragma pack( push, 8 ) enum ChaperoneCalibrationState { @@ -1985,16 +2071,7 @@ static const char * const IVRChaperoneSetup_Version = "IVRChaperoneSetup_005"; namespace vr { -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. - #pragma pack( push, 4 ) -#else - #pragma pack( push, 8 ) -#endif +#pragma pack( push, 8 ) /** Errors that can occur with the VR compositor */ enum EVRCompositorError @@ -2237,8 +2314,10 @@ public: /** Temporarily suspends rendering (useful for finer control over scene transitions). */ virtual void SuspendRendering( bool bSuspend ) = 0; - /** Opens a shared D3D11 texture with the undistorted composited image for each eye. */ + /** Opens a shared D3D11 texture with the undistorted composited image for each eye. Use ReleaseMirrorTextureD3D11 when finished + * instead of calling Release on the resource itself. */ virtual vr::EVRCompositorError GetMirrorTextureD3D11( vr::EVREye eEye, void *pD3D11DeviceOrResource, void **ppD3D11ShaderResourceView ) = 0; + virtual void ReleaseMirrorTextureD3D11( void *pD3D11ShaderResourceView ) = 0; /** Access to mirror textures from OpenGL. */ virtual vr::EVRCompositorError GetMirrorTextureGL( vr::EVREye eEye, vr::glUInt_t *pglTextureId, vr::glSharedTextureHandle_t *pglSharedTextureHandle ) = 0; @@ -2258,7 +2337,7 @@ public: }; -static const char * const IVRCompositor_Version = "IVRCompositor_019"; +static const char * const IVRCompositor_Version = "IVRCompositor_020"; } // namespace vr @@ -2268,16 +2347,7 @@ static const char * const IVRCompositor_Version = "IVRCompositor_019"; namespace vr { -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. - #pragma pack( push, 4 ) -#else - #pragma pack( push, 8 ) -#endif +#pragma pack( push, 8 ) // Used for passing graphic data struct NotificationBitmap_t @@ -2537,7 +2607,7 @@ namespace vr virtual EVROverlayError FindOverlay( const char *pchOverlayKey, VROverlayHandle_t * pOverlayHandle ) = 0; /** Creates a new named overlay. All overlays start hidden and with default settings. */ - virtual EVROverlayError CreateOverlay( const char *pchOverlayKey, const char *pchOverlayFriendlyName, VROverlayHandle_t * pOverlayHandle ) = 0; + virtual EVROverlayError CreateOverlay( const char *pchOverlayKey, const char *pchOverlayName, VROverlayHandle_t * pOverlayHandle ) = 0; /** Destroys the specified overlay. When an application calls VR_Shutdown all overlays created by that app are * automatically destroyed. */ @@ -2562,6 +2632,9 @@ namespace vr * the terminating null character. k_unVROverlayMaxNameLength will be enough bytes to fit the string. */ virtual uint32_t GetOverlayName( VROverlayHandle_t ulOverlayHandle, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, EVROverlayError *pError = 0L ) = 0; + /** set the name to use for this overlay */ + virtual EVROverlayError SetOverlayName( VROverlayHandle_t ulOverlayHandle, const char *pchName ) = 0; + /** Gets the raw image data from an overlay. Overlay image data is always returned as RGBA data, 4 bytes per pixel. If the buffer is not large enough, width and height * will be set and VROverlayError_ArrayTooSmall is returned. */ virtual EVROverlayError GetOverlayImageData( VROverlayHandle_t ulOverlayHandle, void *pvBuffer, uint32_t unBufferSize, uint32_t *punWidth, uint32_t *punHeight ) = 0; @@ -2570,7 +2643,6 @@ namespace vr * of the error enum value for all valid error codes */ virtual const char *GetOverlayErrorNameFromEnum( EVROverlayError error ) = 0; - // --------------------------------------------- // Overlay rendering methods // --------------------------------------------- @@ -2647,6 +2719,13 @@ namespace vr /** Gets the part of the texture to use for the overlay. UV Min is the upper left corner and UV Max is the lower right corner. */ virtual EVROverlayError GetOverlayTextureBounds( VROverlayHandle_t ulOverlayHandle, VRTextureBounds_t *pOverlayTextureBounds ) = 0; + /** Gets render model to draw behind this overlay */ + virtual uint32_t GetOverlayRenderModel( vr::VROverlayHandle_t ulOverlayHandle, char *pchValue, uint32_t unBufferSize, HmdColor_t *pColor, vr::EVROverlayError *pError ) = 0; + + /** Sets render model to draw behind this overlay and the vertex color to use, pass null for pColor to match the overlays vertex color. + The model is scaled by the same amount as the overlay, with a default of 1m. */ + virtual vr::EVROverlayError SetOverlayRenderModel( vr::VROverlayHandle_t ulOverlayHandle, const char *pchRenderModel, const HmdColor_t *pColor ) = 0; + /** Returns the transform type of this overlay. */ virtual EVROverlayError GetOverlayTransformType( VROverlayHandle_t ulOverlayHandle, VROverlayTransformType *peTransformType ) = 0; @@ -2669,6 +2748,12 @@ namespace vr /** Gets the transform information when the overlay is rendering on a component. */ virtual EVROverlayError GetOverlayTransformTrackedDeviceComponent( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t *punDeviceIndex, char *pchComponentName, uint32_t unComponentNameSize ) = 0; + /** Gets the transform if it is relative to another overlay. Returns an error if the transform is some other type. */ + virtual vr::EVROverlayError GetOverlayTransformOverlayRelative( VROverlayHandle_t ulOverlayHandle, VROverlayHandle_t *ulOverlayHandleParent, HmdMatrix34_t *pmatParentOverlayToOverlayTransform ) = 0; + + /** Sets the transform to relative to the transform of the specified overlay. This overlays visibility will also track the parents visibility */ + virtual vr::EVROverlayError SetOverlayTransformOverlayRelative( VROverlayHandle_t ulOverlayHandle, VROverlayHandle_t ulOverlayHandleParent, const HmdMatrix34_t *pmatParentOverlayToOverlayTransform ) = 0; + /** Shows the VR overlay. For dashboard overlays, only the Dashboard Manager is allowed to call this. */ virtual EVROverlayError ShowOverlay( VROverlayHandle_t ulOverlayHandle ) = 0; @@ -2839,7 +2924,7 @@ namespace vr virtual VRMessageOverlayResponse ShowMessageOverlay( const char* pchText, const char* pchCaption, const char* pchButton0Text, const char* pchButton1Text = nullptr, const char* pchButton2Text = nullptr, const char* pchButton3Text = nullptr ) = 0; }; - static const char * const IVROverlay_Version = "IVROverlay_014"; + static const char * const IVROverlay_Version = "IVROverlay_016"; } // namespace vr @@ -2853,16 +2938,7 @@ static const char * const k_pch_Controller_Component_Tip = "tip"; // F static const char * const k_pch_Controller_Component_HandGrip = "handgrip"; // Neutral, ambidextrous hand-pose when holding controller. On plane between neutrally posed index finger and thumb static const char * const k_pch_Controller_Component_Status = "status"; // 1:1 aspect ratio status area, with canonical [0,1] uv mapping -#if defined(__linux__) || defined(__APPLE__) -// The 32-bit version of gcc has the alignment requirement for uint64 and double set to -// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. -// The 64-bit version of gcc has the alignment requirement for these types set to -// 8 meaning that unless we use #pragma pack(4) our structures will get bigger. -// The 64-bit structure packing has to match the 32-bit structure packing for each platform. -#pragma pack( push, 4 ) -#else #pragma pack( push, 8 ) -#endif /** Errors that can occur with the VR compositor */ enum EVRRenderModelError @@ -2911,11 +2987,20 @@ struct RenderModel_Vertex_t }; /** A texture map for use on a render model */ +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + struct RenderModel_TextureMap_t { uint16_t unWidth, unHeight; // width and height of the texture map in pixels const uint8_t *rubTextureMapData; // Map texture data. All textures are RGBA with 8 bits per channel per pixel. Data size is width * height * 4ub }; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif /** Session unique texture identifier. Rendermodels which share the same texture will have the same id. IDs <0 denote the texture is not present */ @@ -2924,6 +3009,12 @@ typedef int32_t TextureID_t; const TextureID_t INVALID_TEXTURE_ID = -1; +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + struct RenderModel_t { const RenderModel_Vertex_t *rVertexData; // Vertex data for the mesh @@ -2932,6 +3023,10 @@ struct RenderModel_t uint32_t unTriangleCount; // Number of triangles in the mesh. Index count is 3 * TriangleCount TextureID_t diffuseTextureId; // Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present }; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif + struct RenderModel_ControllerMode_State_t { @@ -3168,7 +3263,7 @@ public: * once SubmitScreenshot() is called. * If Steam is not running, the paths will be in the user's * documents folder under Documents\SteamVR\Screenshots. - * Other VR applications can call this to initate a + * Other VR applications can call this to initiate a * screenshot outside of user control. * The destination file names do not need an extension, * will be replaced with the correct one for the format @@ -3206,7 +3301,7 @@ public: * submitted scene textures of the running application and * write them into the preview image and a side-by-side file * for the VR image. - * This is similiar to request screenshot, but doesn't ever + * This is similar to request screenshot, but doesn't ever * talk to the application, just takes the shot and submits. */ virtual vr::EVRScreenshotError TakeStereoScreenshot( vr::ScreenshotHandle_t *pOutScreenshotHandle, const char *pchPreviewFilename, const char *pchVRFilename ) = 0; @@ -3217,8 +3312,7 @@ public: * function will display a notification to the user that the * screenshot was taken. The paths should be full paths with * extensions. - * File paths should be absolute including - * exntensions. + * File paths should be absolute including extensions. * screenshotHandle can be k_unScreenshotHandleInvalid if this * was a new shot taking by the app to be saved and not * initiated by a user (achievement earned or something) */ @@ -3291,7 +3385,7 @@ namespace vr /** Returns the name of the enum value for an EVRInitError. This function may be called outside of VR_Init()/VR_Shutdown(). */ VR_INTERFACE const char *VR_CALLTYPE VR_GetVRInitErrorAsSymbol( EVRInitError error ); - /** Returns an english string for an EVRInitError. Applications should call VR_GetVRInitErrorAsSymbol instead and + /** Returns an English string for an EVRInitError. Applications should call VR_GetVRInitErrorAsSymbol instead and * use that as a key to look up their own localized error message. This function may be called outside of VR_Init()/VR_Shutdown(). */ VR_INTERFACE const char *VR_CALLTYPE VR_GetVRInitErrorAsEnglishDescription( EVRInitError error ); diff --git a/examples/ThirdPartyLibs/openvr/headers/openvr_api.cs b/examples/ThirdPartyLibs/openvr/headers/openvr_api.cs index 98e09ef0b..377d91a65 100644 --- a/examples/ThirdPartyLibs/openvr/headers/openvr_api.cs +++ b/examples/ThirdPartyLibs/openvr/headers/openvr_api.cs @@ -475,6 +475,11 @@ public struct IVRApplications [MarshalAs(UnmanagedType.FunctionPtr)] internal _LaunchInternalProcess LaunchInternalProcess; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate uint _GetCurrentSceneProcessId(); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _GetCurrentSceneProcessId GetCurrentSceneProcessId; + } [StructLayout(LayoutKind.Sequential)] @@ -800,6 +805,11 @@ public struct IVRCompositor [MarshalAs(UnmanagedType.FunctionPtr)] internal _GetMirrorTextureD3D11 GetMirrorTextureD3D11; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate void _ReleaseMirrorTextureD3D11(IntPtr pD3D11ShaderResourceView); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _ReleaseMirrorTextureD3D11 ReleaseMirrorTextureD3D11; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate EVRCompositorError _GetMirrorTextureGL(EVREye eEye, ref uint pglTextureId, IntPtr pglSharedTextureHandle); [MarshalAs(UnmanagedType.FunctionPtr)] @@ -841,7 +851,7 @@ public struct IVROverlay internal _FindOverlay FindOverlay; [UnmanagedFunctionPointer(CallingConvention.StdCall)] - internal delegate EVROverlayError _CreateOverlay(string pchOverlayKey, string pchOverlayFriendlyName, ref ulong pOverlayHandle); + internal delegate EVROverlayError _CreateOverlay(string pchOverlayKey, string pchOverlayName, ref ulong pOverlayHandle); [MarshalAs(UnmanagedType.FunctionPtr)] internal _CreateOverlay CreateOverlay; @@ -870,6 +880,11 @@ public struct IVROverlay [MarshalAs(UnmanagedType.FunctionPtr)] internal _GetOverlayName GetOverlayName; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate EVROverlayError _SetOverlayName(ulong ulOverlayHandle, string pchName); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _SetOverlayName SetOverlayName; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate EVROverlayError _GetOverlayImageData(ulong ulOverlayHandle, IntPtr pvBuffer, uint unBufferSize, ref uint punWidth, ref uint punHeight); [MarshalAs(UnmanagedType.FunctionPtr)] @@ -980,6 +995,16 @@ public struct IVROverlay [MarshalAs(UnmanagedType.FunctionPtr)] internal _GetOverlayTextureBounds GetOverlayTextureBounds; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate uint _GetOverlayRenderModel(ulong ulOverlayHandle, string pchValue, uint unBufferSize, ref HmdColor_t pColor, ref EVROverlayError pError); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _GetOverlayRenderModel GetOverlayRenderModel; + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate EVROverlayError _SetOverlayRenderModel(ulong ulOverlayHandle, string pchRenderModel, ref HmdColor_t pColor); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _SetOverlayRenderModel SetOverlayRenderModel; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate EVROverlayError _GetOverlayTransformType(ulong ulOverlayHandle, ref VROverlayTransformType peTransformType); [MarshalAs(UnmanagedType.FunctionPtr)] @@ -1015,6 +1040,16 @@ public struct IVROverlay [MarshalAs(UnmanagedType.FunctionPtr)] internal _GetOverlayTransformTrackedDeviceComponent GetOverlayTransformTrackedDeviceComponent; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate EVROverlayError _GetOverlayTransformOverlayRelative(ulong ulOverlayHandle, ref ulong ulOverlayHandleParent, ref HmdMatrix34_t pmatParentOverlayToOverlayTransform); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _GetOverlayTransformOverlayRelative GetOverlayTransformOverlayRelative; + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate EVROverlayError _SetOverlayTransformOverlayRelative(ulong ulOverlayHandle, ulong ulOverlayHandleParent, ref HmdMatrix34_t pmatParentOverlayToOverlayTransform); + [MarshalAs(UnmanagedType.FunctionPtr)] + internal _SetOverlayTransformOverlayRelative SetOverlayTransformOverlayRelative; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate EVROverlayError _ShowOverlay(ulong ulOverlayHandle); [MarshalAs(UnmanagedType.FunctionPtr)] @@ -1593,8 +1628,32 @@ public class CVRSystem IntPtr result = FnTable.GetPropErrorNameFromEnum(error); return Marshal.PtrToStringAnsi(result); } +// This is a terrible hack to workaround the fact that VRControllerState_t and VREvent_t were +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _PollNextEventPacked(ref VREvent_t_Packed pEvent,uint uncbVREvent); + [StructLayout(LayoutKind.Explicit)] + struct PollNextEventUnion + { + [FieldOffset(0)] + public IVRSystem._PollNextEvent pPollNextEvent; + [FieldOffset(0)] + public _PollNextEventPacked pPollNextEventPacked; + } public bool PollNextEvent(ref VREvent_t pEvent,uint uncbVREvent) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + PollNextEventUnion u; + VREvent_t_Packed event_packed = new VREvent_t_Packed(); + u.pPollNextEventPacked = null; + u.pPollNextEvent = FnTable.PollNextEvent; + bool packed_result = u.pPollNextEventPacked(ref event_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VREvent_t_Packed))); + + event_packed.Unpack(ref pEvent); + return packed_result; + } bool result = FnTable.PollNextEvent(ref pEvent,uncbVREvent); return result; } @@ -1613,13 +1672,61 @@ public class CVRSystem HiddenAreaMesh_t result = FnTable.GetHiddenAreaMesh(eEye,type); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t and VREvent_t were +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _GetControllerStatePacked(uint unControllerDeviceIndex,ref VRControllerState_t_Packed pControllerState,uint unControllerStateSize); + [StructLayout(LayoutKind.Explicit)] + struct GetControllerStateUnion + { + [FieldOffset(0)] + public IVRSystem._GetControllerState pGetControllerState; + [FieldOffset(0)] + public _GetControllerStatePacked pGetControllerStatePacked; + } public bool GetControllerState(uint unControllerDeviceIndex,ref VRControllerState_t pControllerState,uint unControllerStateSize) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + GetControllerStateUnion u; + VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(pControllerState); + u.pGetControllerStatePacked = null; + u.pGetControllerState = FnTable.GetControllerState; + bool packed_result = u.pGetControllerStatePacked(unControllerDeviceIndex,ref state_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed))); + + state_packed.Unpack(ref pControllerState); + return packed_result; + } bool result = FnTable.GetControllerState(unControllerDeviceIndex,ref pControllerState,unControllerStateSize); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t and VREvent_t were +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _GetControllerStateWithPosePacked(ETrackingUniverseOrigin eOrigin,uint unControllerDeviceIndex,ref VRControllerState_t_Packed pControllerState,uint unControllerStateSize,ref TrackedDevicePose_t pTrackedDevicePose); + [StructLayout(LayoutKind.Explicit)] + struct GetControllerStateWithPoseUnion + { + [FieldOffset(0)] + public IVRSystem._GetControllerStateWithPose pGetControllerStateWithPose; + [FieldOffset(0)] + public _GetControllerStateWithPosePacked pGetControllerStateWithPosePacked; + } public bool GetControllerStateWithPose(ETrackingUniverseOrigin eOrigin,uint unControllerDeviceIndex,ref VRControllerState_t pControllerState,uint unControllerStateSize,ref TrackedDevicePose_t pTrackedDevicePose) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + GetControllerStateWithPoseUnion u; + VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(pControllerState); + u.pGetControllerStateWithPosePacked = null; + u.pGetControllerStateWithPose = FnTable.GetControllerStateWithPose; + bool packed_result = u.pGetControllerStateWithPosePacked(eOrigin,unControllerDeviceIndex,ref state_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed)),ref pTrackedDevicePose); + + state_packed.Unpack(ref pControllerState); + return packed_result; + } bool result = FnTable.GetControllerStateWithPose(eOrigin,unControllerDeviceIndex,ref pControllerState,unControllerStateSize,ref pTrackedDevicePose); return result; } @@ -1939,6 +2046,11 @@ public class CVRApplications EVRApplicationError result = FnTable.LaunchInternalProcess(pchBinaryPath,pchArguments,pchWorkingDirectory); return result; } + public uint GetCurrentSceneProcessId() + { + uint result = FnTable.GetCurrentSceneProcessId(); + return result; + } } @@ -2269,6 +2381,10 @@ public class CVRCompositor EVRCompositorError result = FnTable.GetMirrorTextureD3D11(eEye,pD3D11DeviceOrResource,ref ppD3D11ShaderResourceView); return result; } + public void ReleaseMirrorTextureD3D11(IntPtr pD3D11ShaderResourceView) + { + FnTable.ReleaseMirrorTextureD3D11(pD3D11ShaderResourceView); + } public EVRCompositorError GetMirrorTextureGL(EVREye eEye,ref uint pglTextureId,IntPtr pglSharedTextureHandle) { pglTextureId = 0; @@ -2314,10 +2430,10 @@ public class CVROverlay EVROverlayError result = FnTable.FindOverlay(pchOverlayKey,ref pOverlayHandle); return result; } - public EVROverlayError CreateOverlay(string pchOverlayKey,string pchOverlayFriendlyName,ref ulong pOverlayHandle) + public EVROverlayError CreateOverlay(string pchOverlayKey,string pchOverlayName,ref ulong pOverlayHandle) { pOverlayHandle = 0; - EVROverlayError result = FnTable.CreateOverlay(pchOverlayKey,pchOverlayFriendlyName,ref pOverlayHandle); + EVROverlayError result = FnTable.CreateOverlay(pchOverlayKey,pchOverlayName,ref pOverlayHandle); return result; } public EVROverlayError DestroyOverlay(ulong ulOverlayHandle) @@ -2345,6 +2461,11 @@ public class CVROverlay uint result = FnTable.GetOverlayName(ulOverlayHandle,pchValue,unBufferSize,ref pError); return result; } + public EVROverlayError SetOverlayName(ulong ulOverlayHandle,string pchName) + { + EVROverlayError result = FnTable.SetOverlayName(ulOverlayHandle,pchName); + return result; + } public EVROverlayError GetOverlayImageData(ulong ulOverlayHandle,IntPtr pvBuffer,uint unBufferSize,ref uint punWidth,ref uint punHeight) { punWidth = 0; @@ -2467,6 +2588,16 @@ public class CVROverlay EVROverlayError result = FnTable.GetOverlayTextureBounds(ulOverlayHandle,ref pOverlayTextureBounds); return result; } + public uint GetOverlayRenderModel(ulong ulOverlayHandle,string pchValue,uint unBufferSize,ref HmdColor_t pColor,ref EVROverlayError pError) + { + uint result = FnTable.GetOverlayRenderModel(ulOverlayHandle,pchValue,unBufferSize,ref pColor,ref pError); + return result; + } + public EVROverlayError SetOverlayRenderModel(ulong ulOverlayHandle,string pchRenderModel,ref HmdColor_t pColor) + { + EVROverlayError result = FnTable.SetOverlayRenderModel(ulOverlayHandle,pchRenderModel,ref pColor); + return result; + } public EVROverlayError GetOverlayTransformType(ulong ulOverlayHandle,ref VROverlayTransformType peTransformType) { EVROverlayError result = FnTable.GetOverlayTransformType(ulOverlayHandle,ref peTransformType); @@ -2504,6 +2635,17 @@ public class CVROverlay EVROverlayError result = FnTable.GetOverlayTransformTrackedDeviceComponent(ulOverlayHandle,ref punDeviceIndex,pchComponentName,unComponentNameSize); return result; } + public EVROverlayError GetOverlayTransformOverlayRelative(ulong ulOverlayHandle,ref ulong ulOverlayHandleParent,ref HmdMatrix34_t pmatParentOverlayToOverlayTransform) + { + ulOverlayHandleParent = 0; + EVROverlayError result = FnTable.GetOverlayTransformOverlayRelative(ulOverlayHandle,ref ulOverlayHandleParent,ref pmatParentOverlayToOverlayTransform); + return result; + } + public EVROverlayError SetOverlayTransformOverlayRelative(ulong ulOverlayHandle,ulong ulOverlayHandleParent,ref HmdMatrix34_t pmatParentOverlayToOverlayTransform) + { + EVROverlayError result = FnTable.SetOverlayTransformOverlayRelative(ulOverlayHandle,ulOverlayHandleParent,ref pmatParentOverlayToOverlayTransform); + return result; + } public EVROverlayError ShowOverlay(ulong ulOverlayHandle) { EVROverlayError result = FnTable.ShowOverlay(ulOverlayHandle); @@ -2524,8 +2666,32 @@ public class CVROverlay EVROverlayError result = FnTable.GetTransformForOverlayCoordinates(ulOverlayHandle,eTrackingOrigin,coordinatesInOverlay,ref pmatTransform); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t and VREvent_t were +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _PollNextOverlayEventPacked(ulong ulOverlayHandle,ref VREvent_t_Packed pEvent,uint uncbVREvent); + [StructLayout(LayoutKind.Explicit)] + struct PollNextOverlayEventUnion + { + [FieldOffset(0)] + public IVROverlay._PollNextOverlayEvent pPollNextOverlayEvent; + [FieldOffset(0)] + public _PollNextOverlayEventPacked pPollNextOverlayEventPacked; + } public bool PollNextOverlayEvent(ulong ulOverlayHandle,ref VREvent_t pEvent,uint uncbVREvent) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + PollNextOverlayEventUnion u; + VREvent_t_Packed event_packed = new VREvent_t_Packed(); + u.pPollNextOverlayEventPacked = null; + u.pPollNextOverlayEvent = FnTable.PollNextOverlayEvent; + bool packed_result = u.pPollNextOverlayEventPacked(ulOverlayHandle,ref event_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VREvent_t_Packed))); + + event_packed.Unpack(ref pEvent); + return packed_result; + } bool result = FnTable.PollNextOverlayEvent(ulOverlayHandle,ref pEvent,uncbVREvent); return result; } @@ -2776,8 +2942,32 @@ public class CVRRenderModels uint result = FnTable.GetComponentRenderModelName(pchRenderModelName,pchComponentName,pchComponentRenderModelName,unComponentRenderModelNameLen); return result; } +// This is a terrible hack to workaround the fact that VRControllerState_t and VREvent_t were +// originally mis-compiled with the wrong packing for Linux and OSX. + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool _GetComponentStatePacked(string pchRenderModelName,string pchComponentName,ref VRControllerState_t_Packed pControllerState,ref RenderModel_ControllerMode_State_t pState,ref RenderModel_ComponentState_t pComponentState); + [StructLayout(LayoutKind.Explicit)] + struct GetComponentStateUnion + { + [FieldOffset(0)] + public IVRRenderModels._GetComponentState pGetComponentState; + [FieldOffset(0)] + public _GetComponentStatePacked pGetComponentStatePacked; + } public bool GetComponentState(string pchRenderModelName,string pchComponentName,ref VRControllerState_t pControllerState,ref RenderModel_ControllerMode_State_t pState,ref RenderModel_ComponentState_t pComponentState) { + if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) || + (System.Environment.OSVersion.Platform == System.PlatformID.Unix)) + { + GetComponentStateUnion u; + VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(pControllerState); + u.pGetComponentStatePacked = null; + u.pGetComponentState = FnTable.GetComponentState; + bool packed_result = u.pGetComponentStatePacked(pchRenderModelName,pchComponentName,ref state_packed,ref pState,ref pComponentState); + + state_packed.Unpack(ref pControllerState); + return packed_result; + } bool result = FnTable.GetComponentState(pchRenderModelName,pchComponentName,ref pControllerState,ref pState,ref pComponentState); return result; } @@ -2986,6 +3176,8 @@ public enum ETextureType DirectX = 0, OpenGL = 1, Vulkan = 2, + IOSurface = 3, + DirectX12 = 4, } public enum EColorSpace { @@ -3008,6 +3200,7 @@ public enum ETrackedDeviceClass Controller = 2, GenericTracker = 3, TrackingReference = 4, + DisplayRedirect = 5, } public enum ETrackedControllerRole { @@ -3058,6 +3251,8 @@ public enum ETrackedDeviceProperty Prop_DriverVersion_String = 1031, Prop_Firmware_ForceUpdateRequired_Bool = 1032, Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + Prop_ResourceRoot_String = 1035, Prop_ReportsTimeSinceVSync_Bool = 2000, Prop_SecondsFromVsyncToPhotons_Float = 2001, Prop_DisplayFrequency_Float = 2002, @@ -3096,6 +3291,11 @@ public enum ETrackedDeviceProperty Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, Prop_DisplaySuppressed_Bool = 2036, Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_SecondsFromPhotonsToVblank_Float = 2042, Prop_AttachedDeviceId_String = 3000, Prop_SupportedButtons_Uint64 = 3001, Prop_Axis0Type_Int32 = 3002, @@ -3120,6 +3320,15 @@ public enum ETrackedDeviceProperty Prop_NamedIconPathDeviceNotReady_String = 5006, Prop_NamedIconPathDeviceStandby_String = 5007, Prop_NamedIconPathDeviceAlertLow_String = 5008, + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + Prop_HasDisplayComponent_Bool = 6002, + Prop_HasControllerComponent_Bool = 6003, + Prop_HasCameraComponent_Bool = 6004, + Prop_HasDriverDirectModeComponent_Bool = 6005, + Prop_HasVirtualDisplayComponent_Bool = 6006, Prop_VendorSpecific_Reserved_Start = 10000, Prop_VendorSpecific_Reserved_End = 10999, } @@ -3136,6 +3345,7 @@ public enum ETrackedPropertyError TrackedProp_StringExceedsMaximumLength = 8, TrackedProp_NotYetAvailable = 9, TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, } public enum EVRSubmitFlags { @@ -3170,6 +3380,7 @@ public enum EVREventType VREvent_TrackedDeviceRoleChanged = 108, VREvent_WatchdogWakeUpRequested = 109, VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, VREvent_ButtonPress = 200, VREvent_ButtonUnpress = 201, VREvent_ButtonTouch = 202, @@ -3216,6 +3427,7 @@ public enum EVREventType VREvent_ScreenshotFailed = 522, VREvent_SubmitScreenshotToDashboard = 523, VREvent_ScreenshotProgressToDashboard = 524, + VREvent_PrimaryDashboardDeviceChanged = 525, VREvent_Notification_Shown = 600, VREvent_Notification_Hidden = 601, VREvent_Notification_BeginInteraction = 602, @@ -3249,6 +3461,9 @@ public enum EVREventType VREvent_ApplicationTransitionNewAppStarted = 1302, VREvent_ApplicationListUpdated = 1303, VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, + VREvent_ProcessConnected = 1306, + VREvent_ProcessDisconnected = 1307, VREvent_Compositor_MirrorWindowShown = 1400, VREvent_Compositor_MirrorWindowHidden = 1401, VREvent_Compositor_ChaperoneBoundsShown = 1410, @@ -3305,6 +3520,7 @@ public enum EHiddenAreaMeshType k_eHiddenAreaMesh_Standard = 0, k_eHiddenAreaMesh_Inverse = 1, k_eHiddenAreaMesh_LineLoop = 2, + k_eHiddenAreaMesh_Max = 3, } public enum EVRControllerAxisType { @@ -3360,7 +3576,8 @@ public enum EVRApplicationType VRApplication_Utility = 4, VRApplication_VRMonitor = 5, VRApplication_SteamWatchdog = 6, - VRApplication_Max = 7, + VRApplication_Bootstrapper = 7, + VRApplication_Max = 8, } public enum EVRFirmwareError { @@ -3536,6 +3753,7 @@ public enum EVRApplicationProperty IsDashboardOverlay_Bool = 60, IsTemplate_Bool = 61, IsInstanced_Bool = 62, + IsInternal_Bool = 63, LastLaunchTime_Uint64 = 70, } public enum EVRApplicationTransitionState @@ -3863,6 +4081,12 @@ public enum EVRScreenshotError public uint m_nFormat; public uint m_nSampleCount; } +[StructLayout(LayoutKind.Sequential)] public struct D3D12TextureData_t +{ + public IntPtr m_pResource; // struct ID3D12Resource * + public IntPtr m_pCommandQueue; // struct ID3D12CommandQueue * + public uint m_nNodeMask; +} [StructLayout(LayoutKind.Sequential)] public struct VREvent_Controller_t { public uint button; @@ -3960,6 +4184,11 @@ public enum EVRScreenshotError { public uint unVRMessageOverlayResponse; } +[StructLayout(LayoutKind.Sequential)] public struct VREvent_Property_t +{ + public ulong container; + public ETrackedDeviceProperty prop; +} [StructLayout(LayoutKind.Sequential)] public struct VREvent_t { public uint eventType; @@ -3967,6 +4196,28 @@ public enum EVRScreenshotError public float eventAgeSeconds; public VREvent_Data_t data; } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct VREvent_t_Packed +{ + public uint eventType; + public uint trackedDeviceIndex; + public float eventAgeSeconds; + public VREvent_Data_t data; + public VREvent_t_Packed(VREvent_t unpacked) + { + this.eventType = unpacked.eventType; + this.trackedDeviceIndex = unpacked.trackedDeviceIndex; + this.eventAgeSeconds = unpacked.eventAgeSeconds; + this.data = unpacked.data; + } + public void Unpack(ref VREvent_t unpacked) + { + unpacked.eventType = this.eventType; + unpacked.trackedDeviceIndex = this.trackedDeviceIndex; + unpacked.eventAgeSeconds = this.eventAgeSeconds; + unpacked.data = this.data; + } +} [StructLayout(LayoutKind.Sequential)] public struct HiddenAreaMesh_t { public IntPtr pVertexData; // const struct vr::HmdVector2_t * @@ -3988,6 +4239,40 @@ public enum EVRScreenshotError public VRControllerAxis_t rAxis3; public VRControllerAxis_t rAxis4; } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct VRControllerState_t_Packed +{ + public uint unPacketNum; + public ulong ulButtonPressed; + public ulong ulButtonTouched; + public VRControllerAxis_t rAxis0; //VRControllerAxis_t[5] + public VRControllerAxis_t rAxis1; + public VRControllerAxis_t rAxis2; + public VRControllerAxis_t rAxis3; + public VRControllerAxis_t rAxis4; + public VRControllerState_t_Packed(VRControllerState_t unpacked) + { + this.unPacketNum = unpacked.unPacketNum; + this.ulButtonPressed = unpacked.ulButtonPressed; + this.ulButtonTouched = unpacked.ulButtonTouched; + this.rAxis0 = unpacked.rAxis0; + this.rAxis1 = unpacked.rAxis1; + this.rAxis2 = unpacked.rAxis2; + this.rAxis3 = unpacked.rAxis3; + this.rAxis4 = unpacked.rAxis4; + } + public void Unpack(ref VRControllerState_t unpacked) + { + unpacked.unPacketNum = this.unPacketNum; + unpacked.ulButtonPressed = this.ulButtonPressed; + unpacked.ulButtonTouched = this.ulButtonTouched; + unpacked.rAxis0 = this.rAxis0; + unpacked.rAxis1 = this.rAxis1; + unpacked.rAxis2 = this.rAxis2; + unpacked.rAxis3 = this.rAxis3; + unpacked.rAxis4 = this.rAxis4; + } +} [StructLayout(LayoutKind.Sequential)] public struct Compositor_OverlaySettings { public uint size; @@ -4116,6 +4401,25 @@ public enum EVRScreenshotError public char unHeight; public IntPtr rubTextureMapData; // const uint8_t * } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct RenderModel_TextureMap_t_Packed +{ + public char unWidth; + public char unHeight; + public IntPtr rubTextureMapData; // const uint8_t * + public RenderModel_TextureMap_t_Packed(RenderModel_TextureMap_t unpacked) + { + this.unWidth = unpacked.unWidth; + this.unHeight = unpacked.unHeight; + this.rubTextureMapData = unpacked.rubTextureMapData; + } + public void Unpack(ref RenderModel_TextureMap_t unpacked) + { + unpacked.unWidth = this.unWidth; + unpacked.unHeight = this.unHeight; + unpacked.rubTextureMapData = this.rubTextureMapData; + } +} [StructLayout(LayoutKind.Sequential)] public struct RenderModel_t { public IntPtr rVertexData; // const struct vr::RenderModel_Vertex_t * @@ -4124,6 +4428,31 @@ public enum EVRScreenshotError public uint unTriangleCount; public int diffuseTextureId; } +// This structure is for backwards binary compatibility on Linux and OSX only +[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct RenderModel_t_Packed +{ + public IntPtr rVertexData; // const struct vr::RenderModel_Vertex_t * + public uint unVertexCount; + public IntPtr rIndexData; // const uint16_t * + public uint unTriangleCount; + public int diffuseTextureId; + public RenderModel_t_Packed(RenderModel_t unpacked) + { + this.rVertexData = unpacked.rVertexData; + this.unVertexCount = unpacked.unVertexCount; + this.rIndexData = unpacked.rIndexData; + this.unTriangleCount = unpacked.unTriangleCount; + this.diffuseTextureId = unpacked.diffuseTextureId; + } + public void Unpack(ref RenderModel_t unpacked) + { + unpacked.rVertexData = this.rVertexData; + unpacked.unVertexCount = this.unVertexCount; + unpacked.rIndexData = this.rIndexData; + unpacked.unTriangleCount = this.unTriangleCount; + unpacked.diffuseTextureId = this.diffuseTextureId; + } +} [StructLayout(LayoutKind.Sequential)] public struct RenderModel_ControllerMode_State_t { [MarshalAs(UnmanagedType.I1)] @@ -4200,6 +4529,20 @@ public class OpenVR public const uint k_unMaxTrackedDeviceCount = 16; public const uint k_unTrackedDeviceIndexOther = 4294967294; public const uint k_unTrackedDeviceIndexInvalid = 4294967295; + public const ulong k_ulInvalidPropertyContainer = 0; + public const uint k_unInvalidPropertyTag = 0; + public const uint k_unFloatPropertyTag = 1; + public const uint k_unInt32PropertyTag = 2; + public const uint k_unUint64PropertyTag = 3; + public const uint k_unBoolPropertyTag = 4; + public const uint k_unStringPropertyTag = 5; + public const uint k_unHmdMatrix34PropertyTag = 20; + public const uint k_unHmdMatrix44PropertyTag = 21; + public const uint k_unHmdVector3PropertyTag = 22; + public const uint k_unHmdVector4PropertyTag = 23; + public const uint k_unHiddenAreaPropertyTag = 30; + public const uint k_unOpenVRInternalReserved_Start = 1000; + public const uint k_unOpenVRInternalReserved_End = 10000; public const uint k_unMaxPropertyStringSize = 32768; public const uint k_unControllerStateAxisCount = 5; public const ulong k_ulOverlayHandleInvalid = 0; @@ -4213,12 +4556,12 @@ public class OpenVR public const string IVRApplications_Version = "IVRApplications_006"; public const string IVRChaperone_Version = "IVRChaperone_003"; public const string IVRChaperoneSetup_Version = "IVRChaperoneSetup_005"; - public const string IVRCompositor_Version = "IVRCompositor_019"; + public const string IVRCompositor_Version = "IVRCompositor_020"; public const uint k_unVROverlayMaxKeyLength = 128; public const uint k_unVROverlayMaxNameLength = 128; public const uint k_unMaxOverlayCount = 64; public const uint k_unMaxOverlayIntersectionMaskPrimitivesCount = 32; - public const string IVROverlay_Version = "IVROverlay_014"; + public const string IVROverlay_Version = "IVROverlay_016"; public const string k_pch_Controller_Component_GDC2015 = "gdc2015"; public const string k_pch_Controller_Component_Base = "base"; public const string k_pch_Controller_Component_Tip = "tip"; @@ -4235,7 +4578,6 @@ public class OpenVR public const string k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd"; public const string k_pch_SteamVR_DisplayDebug_Bool = "displayDebug"; public const string k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe"; - public const string k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion"; public const string k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX"; public const string k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY"; public const string k_pch_SteamVR_SendSystemButtonToAllApps_Bool = "sendSystemButtonToAllApps"; @@ -4280,7 +4622,6 @@ public class OpenVR public const string k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation"; public const string k_pch_Lighthouse_DBHistory_Bool = "dbhistory"; public const string k_pch_Null_Section = "driver_null"; - public const string k_pch_Null_EnableNullDriver_Bool = "enable"; public const string k_pch_Null_SerialNumber_String = "serialNumber"; public const string k_pch_Null_ModelNumber_String = "modelNumber"; public const string k_pch_Null_WindowX_Int32 = "windowX"; @@ -4350,6 +4691,7 @@ public class OpenVR public const string k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard"; public const string k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode"; public const string k_pch_modelskin_Section = "modelskins"; + public const string k_pch_Driver_Enable_Bool = "enable"; public const string IVRScreenshots_Version = "IVRScreenshots_001"; public const string IVRResources_Version = "IVRResources_001"; diff --git a/examples/ThirdPartyLibs/openvr/headers/openvr_api.json b/examples/ThirdPartyLibs/openvr/headers/openvr_api.json index 24509ee00..43c3bf958 100644 --- a/examples/ThirdPartyLibs/openvr/headers/openvr_api.json +++ b/examples/ThirdPartyLibs/openvr/headers/openvr_api.json @@ -3,6 +3,8 @@ ,{"typedef": "vr::glUInt_t","type": "uint32_t"} ,{"typedef": "vr::SharedTextureHandle_t","type": "uint64_t"} ,{"typedef": "vr::TrackedDeviceIndex_t","type": "uint32_t"} +,{"typedef": "vr::PropertyContainerHandle_t","type": "uint64_t"} +,{"typedef": "vr::PropertyTypeTag_t","type": "uint32_t"} ,{"typedef": "vr::VREvent_Data_t","type": "union VREvent_Data_t"} ,{"typedef": "vr::VRControllerState_t","type": "struct vr::VRControllerState001_t"} ,{"typedef": "vr::VROverlayHandle_t","type": "uint64_t"} @@ -37,6 +39,8 @@ {"name": "TextureType_DirectX","value": "0"} ,{"name": "TextureType_OpenGL","value": "1"} ,{"name": "TextureType_Vulkan","value": "2"} + ,{"name": "TextureType_IOSurface","value": "3"} + ,{"name": "TextureType_DirectX12","value": "4"} ]} , {"enumname": "vr::EColorSpace","values": [ {"name": "ColorSpace_Auto","value": "0"} @@ -56,6 +60,7 @@ ,{"name": "TrackedDeviceClass_Controller","value": "2"} ,{"name": "TrackedDeviceClass_GenericTracker","value": "3"} ,{"name": "TrackedDeviceClass_TrackingReference","value": "4"} + ,{"name": "TrackedDeviceClass_DisplayRedirect","value": "5"} ]} , {"enumname": "vr::ETrackedControllerRole","values": [ {"name": "TrackedControllerRole_Invalid","value": "0"} @@ -103,6 +108,8 @@ ,{"name": "Prop_DriverVersion_String","value": "1031"} ,{"name": "Prop_Firmware_ForceUpdateRequired_Bool","value": "1032"} ,{"name": "Prop_ViveSystemButtonFixRequired_Bool","value": "1033"} + ,{"name": "Prop_ParentDriver_Uint64","value": "1034"} + ,{"name": "Prop_ResourceRoot_String","value": "1035"} ,{"name": "Prop_ReportsTimeSinceVSync_Bool","value": "2000"} ,{"name": "Prop_SecondsFromVsyncToPhotons_Float","value": "2001"} ,{"name": "Prop_DisplayFrequency_Float","value": "2002"} @@ -141,6 +148,11 @@ ,{"name": "Prop_ScreenshotVerticalFieldOfViewDegrees_Float","value": "2035"} ,{"name": "Prop_DisplaySuppressed_Bool","value": "2036"} ,{"name": "Prop_DisplayAllowNightMode_Bool","value": "2037"} + ,{"name": "Prop_DisplayMCImageWidth_Int32","value": "2038"} + ,{"name": "Prop_DisplayMCImageHeight_Int32","value": "2039"} + ,{"name": "Prop_DisplayMCImageNumChannels_Int32","value": "2040"} + ,{"name": "Prop_DisplayMCImageData_Binary","value": "2041"} + ,{"name": "Prop_SecondsFromPhotonsToVblank_Float","value": "2042"} ,{"name": "Prop_AttachedDeviceId_String","value": "3000"} ,{"name": "Prop_SupportedButtons_Uint64","value": "3001"} ,{"name": "Prop_Axis0Type_Int32","value": "3002"} @@ -165,6 +177,15 @@ ,{"name": "Prop_NamedIconPathDeviceNotReady_String","value": "5006"} ,{"name": "Prop_NamedIconPathDeviceStandby_String","value": "5007"} ,{"name": "Prop_NamedIconPathDeviceAlertLow_String","value": "5008"} + ,{"name": "Prop_DisplayHiddenArea_Binary_Start","value": "5100"} + ,{"name": "Prop_DisplayHiddenArea_Binary_End","value": "5150"} + ,{"name": "Prop_UserConfigPath_String","value": "6000"} + ,{"name": "Prop_InstallPath_String","value": "6001"} + ,{"name": "Prop_HasDisplayComponent_Bool","value": "6002"} + ,{"name": "Prop_HasControllerComponent_Bool","value": "6003"} + ,{"name": "Prop_HasCameraComponent_Bool","value": "6004"} + ,{"name": "Prop_HasDriverDirectModeComponent_Bool","value": "6005"} + ,{"name": "Prop_HasVirtualDisplayComponent_Bool","value": "6006"} ,{"name": "Prop_VendorSpecific_Reserved_Start","value": "10000"} ,{"name": "Prop_VendorSpecific_Reserved_End","value": "10999"} ]} @@ -180,6 +201,7 @@ ,{"name": "TrackedProp_StringExceedsMaximumLength","value": "8"} ,{"name": "TrackedProp_NotYetAvailable","value": "9"} ,{"name": "TrackedProp_PermissionDenied","value": "10"} + ,{"name": "TrackedProp_InvalidOperation","value": "11"} ]} , {"enumname": "vr::EVRSubmitFlags","values": [ {"name": "Submit_Default","value": "0"} @@ -211,6 +233,7 @@ ,{"name": "VREvent_TrackedDeviceRoleChanged","value": "108"} ,{"name": "VREvent_WatchdogWakeUpRequested","value": "109"} ,{"name": "VREvent_LensDistortionChanged","value": "110"} + ,{"name": "VREvent_PropertyChanged","value": "111"} ,{"name": "VREvent_ButtonPress","value": "200"} ,{"name": "VREvent_ButtonUnpress","value": "201"} ,{"name": "VREvent_ButtonTouch","value": "202"} @@ -257,6 +280,7 @@ ,{"name": "VREvent_ScreenshotFailed","value": "522"} ,{"name": "VREvent_SubmitScreenshotToDashboard","value": "523"} ,{"name": "VREvent_ScreenshotProgressToDashboard","value": "524"} + ,{"name": "VREvent_PrimaryDashboardDeviceChanged","value": "525"} ,{"name": "VREvent_Notification_Shown","value": "600"} ,{"name": "VREvent_Notification_Hidden","value": "601"} ,{"name": "VREvent_Notification_BeginInteraction","value": "602"} @@ -290,6 +314,9 @@ ,{"name": "VREvent_ApplicationTransitionNewAppStarted","value": "1302"} ,{"name": "VREvent_ApplicationListUpdated","value": "1303"} ,{"name": "VREvent_ApplicationMimeTypeLoad","value": "1304"} + ,{"name": "VREvent_ApplicationTransitionNewAppLaunchComplete","value": "1305"} + ,{"name": "VREvent_ProcessConnected","value": "1306"} + ,{"name": "VREvent_ProcessDisconnected","value": "1307"} ,{"name": "VREvent_Compositor_MirrorWindowShown","value": "1400"} ,{"name": "VREvent_Compositor_MirrorWindowHidden","value": "1401"} ,{"name": "VREvent_Compositor_ChaperoneBoundsShown","value": "1410"} @@ -342,6 +369,7 @@ {"name": "k_eHiddenAreaMesh_Standard","value": "0"} ,{"name": "k_eHiddenAreaMesh_Inverse","value": "1"} ,{"name": "k_eHiddenAreaMesh_LineLoop","value": "2"} + ,{"name": "k_eHiddenAreaMesh_Max","value": "3"} ]} , {"enumname": "vr::EVRControllerAxisType","values": [ {"name": "k_eControllerAxis_None","value": "0"} @@ -392,7 +420,8 @@ ,{"name": "VRApplication_Utility","value": "4"} ,{"name": "VRApplication_VRMonitor","value": "5"} ,{"name": "VRApplication_SteamWatchdog","value": "6"} - ,{"name": "VRApplication_Max","value": "7"} + ,{"name": "VRApplication_Bootstrapper","value": "7"} + ,{"name": "VRApplication_Max","value": "8"} ]} , {"enumname": "vr::EVRFirmwareError","values": [ {"name": "VRFirmwareError_None","value": "0"} @@ -559,6 +588,7 @@ ,{"name": "VRApplicationProperty_IsDashboardOverlay_Bool","value": "60"} ,{"name": "VRApplicationProperty_IsTemplate_Bool","value": "61"} ,{"name": "VRApplicationProperty_IsInstanced_Bool","value": "62"} + ,{"name": "VRApplicationProperty_IsInternal_Bool","value": "63"} ,{"name": "VRApplicationProperty_LastLaunchTime_Uint64","value": "70"} ]} , {"enumname": "vr::EVRApplicationTransitionState","values": [ @@ -717,6 +747,34 @@ "constname": "k_unTrackedDeviceIndexOther","consttype": "const uint32_t", "constval": "4294967294"} ,{ "constname": "k_unTrackedDeviceIndexInvalid","consttype": "const uint32_t", "constval": "4294967295"} +,{ + "constname": "k_ulInvalidPropertyContainer","consttype": "const PropertyContainerHandle_t", "constval": "0"} +,{ + "constname": "k_unInvalidPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "0"} +,{ + "constname": "k_unFloatPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "1"} +,{ + "constname": "k_unInt32PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "2"} +,{ + "constname": "k_unUint64PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "3"} +,{ + "constname": "k_unBoolPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "4"} +,{ + "constname": "k_unStringPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "5"} +,{ + "constname": "k_unHmdMatrix34PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "20"} +,{ + "constname": "k_unHmdMatrix44PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "21"} +,{ + "constname": "k_unHmdVector3PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "22"} +,{ + "constname": "k_unHmdVector4PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "23"} +,{ + "constname": "k_unHiddenAreaPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "30"} +,{ + "constname": "k_unOpenVRInternalReserved_Start","consttype": "const PropertyTypeTag_t", "constval": "1000"} +,{ + "constname": "k_unOpenVRInternalReserved_End","consttype": "const PropertyTypeTag_t", "constval": "10000"} ,{ "constname": "k_unMaxPropertyStringSize","consttype": "const uint32_t", "constval": "32768"} ,{ @@ -744,7 +802,7 @@ ,{ "constname": "IVRChaperoneSetup_Version","consttype": "const char *const", "constval": "IVRChaperoneSetup_005"} ,{ - "constname": "IVRCompositor_Version","consttype": "const char *const", "constval": "IVRCompositor_019"} + "constname": "IVRCompositor_Version","consttype": "const char *const", "constval": "IVRCompositor_020"} ,{ "constname": "k_unVROverlayMaxKeyLength","consttype": "const uint32_t", "constval": "128"} ,{ @@ -754,7 +812,7 @@ ,{ "constname": "k_unMaxOverlayIntersectionMaskPrimitivesCount","consttype": "const uint32_t", "constval": "32"} ,{ - "constname": "IVROverlay_Version","consttype": "const char *const", "constval": "IVROverlay_014"} + "constname": "IVROverlay_Version","consttype": "const char *const", "constval": "IVROverlay_016"} ,{ "constname": "k_pch_Controller_Component_GDC2015","consttype": "const char *const", "constval": "gdc2015"} ,{ @@ -787,8 +845,6 @@ "constname": "k_pch_SteamVR_DisplayDebug_Bool","consttype": "const char *const", "constval": "displayDebug"} ,{ "constname": "k_pch_SteamVR_DebugProcessPipe_String","consttype": "const char *const", "constval": "debugProcessPipe"} -,{ - "constname": "k_pch_SteamVR_EnableDistortion_Bool","consttype": "const char *const", "constval": "enableDistortion"} ,{ "constname": "k_pch_SteamVR_DisplayDebugX_Int32","consttype": "const char *const", "constval": "displayDebugX"} ,{ @@ -877,8 +933,6 @@ "constname": "k_pch_Lighthouse_DBHistory_Bool","consttype": "const char *const", "constval": "dbhistory"} ,{ "constname": "k_pch_Null_Section","consttype": "const char *const", "constval": "driver_null"} -,{ - "constname": "k_pch_Null_EnableNullDriver_Bool","consttype": "const char *const", "constval": "enable"} ,{ "constname": "k_pch_Null_SerialNumber_String","consttype": "const char *const", "constval": "serialNumber"} ,{ @@ -1017,6 +1071,8 @@ "constname": "k_pch_Dashboard_ArcadeMode_Bool","consttype": "const char *const", "constval": "arcadeMode"} ,{ "constname": "k_pch_modelskin_Section","consttype": "const char *const", "constval": "modelskins"} +,{ + "constname": "k_pch_Driver_Enable_Bool","consttype": "const char *const", "constval": "enable"} ,{ "constname": "IVRScreenshots_Version","consttype": "const char *const", "constval": "IVRScreenshots_001"} ,{ @@ -1080,6 +1136,10 @@ { "fieldname": "m_nHeight", "fieldtype": "uint32_t"}, { "fieldname": "m_nFormat", "fieldtype": "uint32_t"}, { "fieldname": "m_nSampleCount", "fieldtype": "uint32_t"}]} +,{"struct": "vr::D3D12TextureData_t","fields": [ +{ "fieldname": "m_pResource", "fieldtype": "struct ID3D12Resource *"}, +{ "fieldname": "m_pCommandQueue", "fieldtype": "struct ID3D12CommandQueue *"}, +{ "fieldname": "m_nNodeMask", "fieldtype": "uint32_t"}]} ,{"struct": "vr::VREvent_Controller_t","fields": [ { "fieldname": "button", "fieldtype": "uint32_t"}]} ,{"struct": "vr::VREvent_Mouse_t","fields": [ @@ -1136,6 +1196,9 @@ { "fieldname": "nVisualMode", "fieldtype": "uint32_t"}]} ,{"struct": "vr::VREvent_MessageOverlay_t","fields": [ { "fieldname": "unVRMessageOverlayResponse", "fieldtype": "uint32_t"}]} +,{"struct": "vr::VREvent_Property_t","fields": [ +{ "fieldname": "container", "fieldtype": "PropertyContainerHandle_t"}, +{ "fieldname": "prop", "fieldtype": "enum vr::ETrackedDeviceProperty"}]} ,{"struct": "vr::(anonymous)","fields": [ { "fieldname": "reserved", "fieldtype": "struct vr::VREvent_Reserved_t"}, { "fieldname": "controller", "fieldtype": "struct vr::VREvent_Controller_t"}, @@ -1155,7 +1218,8 @@ { "fieldname": "screenshotProgress", "fieldtype": "struct vr::VREvent_ScreenshotProgress_t"}, { "fieldname": "applicationLaunch", "fieldtype": "struct vr::VREvent_ApplicationLaunch_t"}, { "fieldname": "cameraSurface", "fieldtype": "struct vr::VREvent_EditingCameraSurface_t"}, -{ "fieldname": "messageOverlay", "fieldtype": "struct vr::VREvent_MessageOverlay_t"}]} +{ "fieldname": "messageOverlay", "fieldtype": "struct vr::VREvent_MessageOverlay_t"}, +{ "fieldname": "property", "fieldtype": "struct vr::VREvent_Property_t"}]} ,{"struct": "vr::VREvent_t","fields": [ { "fieldname": "eventType", "fieldtype": "uint32_t"}, { "fieldname": "trackedDeviceIndex", "fieldtype": "TrackedDeviceIndex_t"}, @@ -2094,6 +2158,11 @@ { "paramname": "pchWorkingDirectory" ,"paramtype": "const char *"} ] } +,{ + "classname": "vr::IVRApplications", + "methodname": "GetCurrentSceneProcessId", + "returntype": "uint32_t" +} ,{ "classname": "vr::IVRChaperone", "methodname": "GetCalibrationState", @@ -2559,6 +2628,14 @@ { "paramname": "ppD3D11ShaderResourceView" ,"paramtype": "void **"} ] } +,{ + "classname": "vr::IVRCompositor", + "methodname": "ReleaseMirrorTextureD3D11", + "returntype": "void", + "params": [ +{ "paramname": "pD3D11ShaderResourceView" ,"paramtype": "void *"} + ] +} ,{ "classname": "vr::IVRCompositor", "methodname": "GetMirrorTextureGL", @@ -2628,7 +2705,7 @@ "returntype": "vr::EVROverlayError", "params": [ { "paramname": "pchOverlayKey" ,"paramtype": "const char *"}, -{ "paramname": "pchOverlayFriendlyName" ,"paramtype": "const char *"}, +{ "paramname": "pchOverlayName" ,"paramtype": "const char *"}, { "paramname": "pOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t *"} ] } @@ -2675,6 +2752,15 @@ { "paramname": "pError" ,"paramtype": "vr::EVROverlayError *"} ] } +,{ + "classname": "vr::IVROverlay", + "methodname": "SetOverlayName", + "returntype": "vr::EVROverlayError", + "params": [ +{ "paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}, +{ "paramname": "pchName" ,"paramtype": "const char *"} + ] +} ,{ "classname": "vr::IVROverlay", "methodname": "GetOverlayImageData", @@ -2882,6 +2968,28 @@ { "paramname": "pOverlayTextureBounds" ,"paramtype": "struct vr::VRTextureBounds_t *"} ] } +,{ + "classname": "vr::IVROverlay", + "methodname": "GetOverlayRenderModel", + "returntype": "uint32_t", + "params": [ +{ "paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}, +{ "paramname": "pchValue" ,"paramtype": "char *"}, +{ "paramname": "unBufferSize" ,"paramtype": "uint32_t"}, +{ "paramname": "pColor" ,"paramtype": "struct vr::HmdColor_t *"}, +{ "paramname": "pError" ,"paramtype": "vr::EVROverlayError *"} + ] +} +,{ + "classname": "vr::IVROverlay", + "methodname": "SetOverlayRenderModel", + "returntype": "vr::EVROverlayError", + "params": [ +{ "paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}, +{ "paramname": "pchRenderModel" ,"paramtype": "const char *"}, +{ "paramname": "pColor" ,"paramtype": "const struct vr::HmdColor_t *"} + ] +} ,{ "classname": "vr::IVROverlay", "methodname": "GetOverlayTransformType", @@ -2952,6 +3060,26 @@ { "paramname": "unComponentNameSize" ,"paramtype": "uint32_t"} ] } +,{ + "classname": "vr::IVROverlay", + "methodname": "GetOverlayTransformOverlayRelative", + "returntype": "vr::EVROverlayError", + "params": [ +{ "paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}, +{ "paramname": "ulOverlayHandleParent" ,"paramtype": "vr::VROverlayHandle_t *"}, +{ "paramname": "pmatParentOverlayToOverlayTransform" ,"paramtype": "struct vr::HmdMatrix34_t *"} + ] +} +,{ + "classname": "vr::IVROverlay", + "methodname": "SetOverlayTransformOverlayRelative", + "returntype": "vr::EVROverlayError", + "params": [ +{ "paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}, +{ "paramname": "ulOverlayHandleParent" ,"paramtype": "vr::VROverlayHandle_t"}, +{ "paramname": "pmatParentOverlayToOverlayTransform" ,"paramtype": "const struct vr::HmdMatrix34_t *"} + ] +} ,{ "classname": "vr::IVROverlay", "methodname": "ShowOverlay", diff --git a/examples/ThirdPartyLibs/openvr/headers/openvr_capi.h b/examples/ThirdPartyLibs/openvr/headers/openvr_capi.h index daffdfb22..f89566817 100644 --- a/examples/ThirdPartyLibs/openvr/headers/openvr_capi.h +++ b/examples/ThirdPartyLibs/openvr/headers/openvr_capi.h @@ -17,7 +17,11 @@ #define EXTERN_C #endif +#if defined( _WIN32 ) #define OPENVR_FNTABLE_CALLTYPE __stdcall +#else +#define OPENVR_FNTABLE_CALLTYPE +#endif // OPENVR API export macro #if defined( _WIN32 ) && !defined( _X360 ) @@ -50,6 +54,9 @@ typedef char bool; #include #endif +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + // OpenVR Constants @@ -58,6 +65,20 @@ static const unsigned int k_unTrackedDeviceIndex_Hmd = 0; static const unsigned int k_unMaxTrackedDeviceCount = 16; static const unsigned int k_unTrackedDeviceIndexOther = 4294967294; static const unsigned int k_unTrackedDeviceIndexInvalid = 4294967295; +static const unsigned long k_ulInvalidPropertyContainer = 0; +static const unsigned int k_unInvalidPropertyTag = 0; +static const unsigned int k_unFloatPropertyTag = 1; +static const unsigned int k_unInt32PropertyTag = 2; +static const unsigned int k_unUint64PropertyTag = 3; +static const unsigned int k_unBoolPropertyTag = 4; +static const unsigned int k_unStringPropertyTag = 5; +static const unsigned int k_unHmdMatrix34PropertyTag = 20; +static const unsigned int k_unHmdMatrix44PropertyTag = 21; +static const unsigned int k_unHmdVector3PropertyTag = 22; +static const unsigned int k_unHmdVector4PropertyTag = 23; +static const unsigned int k_unHiddenAreaPropertyTag = 30; +static const unsigned int k_unOpenVRInternalReserved_Start = 1000; +static const unsigned int k_unOpenVRInternalReserved_End = 10000; static const unsigned int k_unMaxPropertyStringSize = 32768; static const unsigned int k_unControllerStateAxisCount = 5; static const unsigned long k_ulOverlayHandleInvalid = 0; @@ -71,12 +92,12 @@ static const char * k_pch_MimeType_GameTheater = "vr/game_theater"; static const char * IVRApplications_Version = "IVRApplications_006"; static const char * IVRChaperone_Version = "IVRChaperone_003"; static const char * IVRChaperoneSetup_Version = "IVRChaperoneSetup_005"; -static const char * IVRCompositor_Version = "IVRCompositor_019"; +static const char * IVRCompositor_Version = "IVRCompositor_020"; static const unsigned int k_unVROverlayMaxKeyLength = 128; static const unsigned int k_unVROverlayMaxNameLength = 128; static const unsigned int k_unMaxOverlayCount = 64; static const unsigned int k_unMaxOverlayIntersectionMaskPrimitivesCount = 32; -static const char * IVROverlay_Version = "IVROverlay_014"; +static const char * IVROverlay_Version = "IVROverlay_016"; static const char * k_pch_Controller_Component_GDC2015 = "gdc2015"; static const char * k_pch_Controller_Component_Base = "base"; static const char * k_pch_Controller_Component_Tip = "tip"; @@ -93,7 +114,6 @@ static const char * k_pch_SteamVR_ForcedDriverKey_String = "forcedDriver"; static const char * k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd"; static const char * k_pch_SteamVR_DisplayDebug_Bool = "displayDebug"; static const char * k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe"; -static const char * k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion"; static const char * k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX"; static const char * k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY"; static const char * k_pch_SteamVR_SendSystemButtonToAllApps_Bool = "sendSystemButtonToAllApps"; @@ -138,7 +158,6 @@ static const char * k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguation static const char * k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation"; static const char * k_pch_Lighthouse_DBHistory_Bool = "dbhistory"; static const char * k_pch_Null_Section = "driver_null"; -static const char * k_pch_Null_EnableNullDriver_Bool = "enable"; static const char * k_pch_Null_SerialNumber_String = "serialNumber"; static const char * k_pch_Null_ModelNumber_String = "modelNumber"; static const char * k_pch_Null_WindowX_Int32 = "windowX"; @@ -208,6 +227,7 @@ static const char * k_pch_Dashboard_Section = "dashboard"; static const char * k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard"; static const char * k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode"; static const char * k_pch_modelskin_Section = "modelskins"; +static const char * k_pch_Driver_Enable_Bool = "enable"; static const char * IVRScreenshots_Version = "IVRScreenshots_001"; static const char * IVRResources_Version = "IVRResources_001"; @@ -224,6 +244,8 @@ typedef enum ETextureType ETextureType_TextureType_DirectX = 0, ETextureType_TextureType_OpenGL = 1, ETextureType_TextureType_Vulkan = 2, + ETextureType_TextureType_IOSurface = 3, + ETextureType_TextureType_DirectX12 = 4, } ETextureType; typedef enum EColorSpace @@ -249,6 +271,7 @@ typedef enum ETrackedDeviceClass ETrackedDeviceClass_TrackedDeviceClass_Controller = 2, ETrackedDeviceClass_TrackedDeviceClass_GenericTracker = 3, ETrackedDeviceClass_TrackedDeviceClass_TrackingReference = 4, + ETrackedDeviceClass_TrackedDeviceClass_DisplayRedirect = 5, } ETrackedDeviceClass; typedef enum ETrackedControllerRole @@ -302,6 +325,8 @@ typedef enum ETrackedDeviceProperty ETrackedDeviceProperty_Prop_DriverVersion_String = 1031, ETrackedDeviceProperty_Prop_Firmware_ForceUpdateRequired_Bool = 1032, ETrackedDeviceProperty_Prop_ViveSystemButtonFixRequired_Bool = 1033, + ETrackedDeviceProperty_Prop_ParentDriver_Uint64 = 1034, + ETrackedDeviceProperty_Prop_ResourceRoot_String = 1035, ETrackedDeviceProperty_Prop_ReportsTimeSinceVSync_Bool = 2000, ETrackedDeviceProperty_Prop_SecondsFromVsyncToPhotons_Float = 2001, ETrackedDeviceProperty_Prop_DisplayFrequency_Float = 2002, @@ -340,6 +365,11 @@ typedef enum ETrackedDeviceProperty ETrackedDeviceProperty_Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, ETrackedDeviceProperty_Prop_DisplaySuppressed_Bool = 2036, ETrackedDeviceProperty_Prop_DisplayAllowNightMode_Bool = 2037, + ETrackedDeviceProperty_Prop_DisplayMCImageWidth_Int32 = 2038, + ETrackedDeviceProperty_Prop_DisplayMCImageHeight_Int32 = 2039, + ETrackedDeviceProperty_Prop_DisplayMCImageNumChannels_Int32 = 2040, + ETrackedDeviceProperty_Prop_DisplayMCImageData_Binary = 2041, + ETrackedDeviceProperty_Prop_SecondsFromPhotonsToVblank_Float = 2042, ETrackedDeviceProperty_Prop_AttachedDeviceId_String = 3000, ETrackedDeviceProperty_Prop_SupportedButtons_Uint64 = 3001, ETrackedDeviceProperty_Prop_Axis0Type_Int32 = 3002, @@ -364,6 +394,15 @@ typedef enum ETrackedDeviceProperty ETrackedDeviceProperty_Prop_NamedIconPathDeviceNotReady_String = 5006, ETrackedDeviceProperty_Prop_NamedIconPathDeviceStandby_String = 5007, ETrackedDeviceProperty_Prop_NamedIconPathDeviceAlertLow_String = 5008, + ETrackedDeviceProperty_Prop_DisplayHiddenArea_Binary_Start = 5100, + ETrackedDeviceProperty_Prop_DisplayHiddenArea_Binary_End = 5150, + ETrackedDeviceProperty_Prop_UserConfigPath_String = 6000, + ETrackedDeviceProperty_Prop_InstallPath_String = 6001, + ETrackedDeviceProperty_Prop_HasDisplayComponent_Bool = 6002, + ETrackedDeviceProperty_Prop_HasControllerComponent_Bool = 6003, + ETrackedDeviceProperty_Prop_HasCameraComponent_Bool = 6004, + ETrackedDeviceProperty_Prop_HasDriverDirectModeComponent_Bool = 6005, + ETrackedDeviceProperty_Prop_HasVirtualDisplayComponent_Bool = 6006, ETrackedDeviceProperty_Prop_VendorSpecific_Reserved_Start = 10000, ETrackedDeviceProperty_Prop_VendorSpecific_Reserved_End = 10999, } ETrackedDeviceProperty; @@ -381,6 +420,7 @@ typedef enum ETrackedPropertyError ETrackedPropertyError_TrackedProp_StringExceedsMaximumLength = 8, ETrackedPropertyError_TrackedProp_NotYetAvailable = 9, ETrackedPropertyError_TrackedProp_PermissionDenied = 10, + ETrackedPropertyError_TrackedProp_InvalidOperation = 11, } ETrackedPropertyError; typedef enum EVRSubmitFlags @@ -418,6 +458,7 @@ typedef enum EVREventType EVREventType_VREvent_TrackedDeviceRoleChanged = 108, EVREventType_VREvent_WatchdogWakeUpRequested = 109, EVREventType_VREvent_LensDistortionChanged = 110, + EVREventType_VREvent_PropertyChanged = 111, EVREventType_VREvent_ButtonPress = 200, EVREventType_VREvent_ButtonUnpress = 201, EVREventType_VREvent_ButtonTouch = 202, @@ -464,6 +505,7 @@ typedef enum EVREventType EVREventType_VREvent_ScreenshotFailed = 522, EVREventType_VREvent_SubmitScreenshotToDashboard = 523, EVREventType_VREvent_ScreenshotProgressToDashboard = 524, + EVREventType_VREvent_PrimaryDashboardDeviceChanged = 525, EVREventType_VREvent_Notification_Shown = 600, EVREventType_VREvent_Notification_Hidden = 601, EVREventType_VREvent_Notification_BeginInteraction = 602, @@ -497,6 +539,9 @@ typedef enum EVREventType EVREventType_VREvent_ApplicationTransitionNewAppStarted = 1302, EVREventType_VREvent_ApplicationListUpdated = 1303, EVREventType_VREvent_ApplicationMimeTypeLoad = 1304, + EVREventType_VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, + EVREventType_VREvent_ProcessConnected = 1306, + EVREventType_VREvent_ProcessDisconnected = 1307, EVREventType_VREvent_Compositor_MirrorWindowShown = 1400, EVREventType_VREvent_Compositor_MirrorWindowHidden = 1401, EVREventType_VREvent_Compositor_ChaperoneBoundsShown = 1410, @@ -557,6 +602,7 @@ typedef enum EHiddenAreaMeshType EHiddenAreaMeshType_k_eHiddenAreaMesh_Standard = 0, EHiddenAreaMeshType_k_eHiddenAreaMesh_Inverse = 1, EHiddenAreaMeshType_k_eHiddenAreaMesh_LineLoop = 2, + EHiddenAreaMeshType_k_eHiddenAreaMesh_Max = 3, } EHiddenAreaMeshType; typedef enum EVRControllerAxisType @@ -617,7 +663,8 @@ typedef enum EVRApplicationType EVRApplicationType_VRApplication_Utility = 4, EVRApplicationType_VRApplication_VRMonitor = 5, EVRApplicationType_VRApplication_SteamWatchdog = 6, - EVRApplicationType_VRApplication_Max = 7, + EVRApplicationType_VRApplication_Bootstrapper = 7, + EVRApplicationType_VRApplication_Max = 8, } EVRApplicationType; typedef enum EVRFirmwareError @@ -802,6 +849,7 @@ typedef enum EVRApplicationProperty EVRApplicationProperty_VRApplicationProperty_IsDashboardOverlay_Bool = 60, EVRApplicationProperty_VRApplicationProperty_IsTemplate_Bool = 61, EVRApplicationProperty_VRApplicationProperty_IsInstanced_Bool = 62, + EVRApplicationProperty_VRApplicationProperty_IsInternal_Bool = 63, EVRApplicationProperty_VRApplicationProperty_LastLaunchTime_Uint64 = 70, } EVRApplicationProperty; @@ -994,11 +1042,14 @@ typedef enum EVRScreenshotError typedef uint32_t TrackedDeviceIndex_t; typedef uint32_t VRNotificationId; typedef uint64_t VROverlayHandle_t; + typedef void * glSharedTextureHandle_t; typedef int32_t glInt_t; typedef uint32_t glUInt_t; typedef uint64_t SharedTextureHandle_t; typedef uint32_t TrackedDeviceIndex_t; +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; typedef uint64_t VROverlayHandle_t; typedef uint64_t TrackedCameraHandle_t; typedef uint32_t ScreenshotHandle_t; @@ -1126,6 +1177,13 @@ typedef struct VRVulkanTextureData_t uint32_t m_nSampleCount; } VRVulkanTextureData_t; +typedef struct D3D12TextureData_t +{ + struct ID3D12Resource * m_pResource; // struct ID3D12Resource * + struct ID3D12CommandQueue * m_pCommandQueue; // struct ID3D12CommandQueue * + uint32_t m_nNodeMask; +} D3D12TextureData_t; + typedef struct VREvent_Controller_t { uint32_t button; @@ -1239,6 +1297,12 @@ typedef struct VREvent_MessageOverlay_t uint32_t unVRMessageOverlayResponse; } VREvent_MessageOverlay_t; +typedef struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + enum ETrackedDeviceProperty prop; +} VREvent_Property_t; + typedef struct HiddenAreaMesh_t { struct HmdVector2_t * pVertexData; // const struct vr::HmdVector2_t * @@ -1384,6 +1448,9 @@ typedef struct RenderModel_Vertex_t float rfTextureCoord[2]; //float[2] } RenderModel_Vertex_t; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( push, 4 ) +#endif typedef struct RenderModel_TextureMap_t { uint16_t unWidth; @@ -1391,6 +1458,12 @@ typedef struct RenderModel_TextureMap_t uint8_t * rubTextureMapData; // const uint8_t * } RenderModel_TextureMap_t; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( push, 4 ) +#endif typedef struct RenderModel_t { struct RenderModel_Vertex_t * rVertexData; // const struct vr::RenderModel_Vertex_t * @@ -1400,6 +1473,9 @@ typedef struct RenderModel_t TextureID_t diffuseTextureId; } RenderModel_t; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif typedef struct RenderModel_ControllerMode_State_t { bool bScrollWheelVisible; @@ -1577,6 +1653,7 @@ struct VR_IVRApplications_FnTable char * (OPENVR_FNTABLE_CALLTYPE *GetApplicationsTransitionStateNameFromEnum)(EVRApplicationTransitionState state); bool (OPENVR_FNTABLE_CALLTYPE *IsQuitUserPromptRequested)(); EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchInternalProcess)(char * pchBinaryPath, char * pchArguments, char * pchWorkingDirectory); + uint32_t (OPENVR_FNTABLE_CALLTYPE *GetCurrentSceneProcessId)(); }; struct VR_IVRChaperone_FnTable @@ -1651,6 +1728,7 @@ struct VR_IVRCompositor_FnTable void (OPENVR_FNTABLE_CALLTYPE *ForceReconnectProcess)(); void (OPENVR_FNTABLE_CALLTYPE *SuspendRendering)(bool bSuspend); EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetMirrorTextureD3D11)(EVREye eEye, void * pD3D11DeviceOrResource, void ** ppD3D11ShaderResourceView); + void (OPENVR_FNTABLE_CALLTYPE *ReleaseMirrorTextureD3D11)(void * pD3D11ShaderResourceView); EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetMirrorTextureGL)(EVREye eEye, glUInt_t * pglTextureId, glSharedTextureHandle_t * pglSharedTextureHandle); bool (OPENVR_FNTABLE_CALLTYPE *ReleaseSharedGLTexture)(glUInt_t glTextureId, glSharedTextureHandle_t glSharedTextureHandle); void (OPENVR_FNTABLE_CALLTYPE *LockGLSharedTextureForAccess)(glSharedTextureHandle_t glSharedTextureHandle); @@ -1662,12 +1740,13 @@ struct VR_IVRCompositor_FnTable struct VR_IVROverlay_FnTable { EVROverlayError (OPENVR_FNTABLE_CALLTYPE *FindOverlay)(char * pchOverlayKey, VROverlayHandle_t * pOverlayHandle); - EVROverlayError (OPENVR_FNTABLE_CALLTYPE *CreateOverlay)(char * pchOverlayKey, char * pchOverlayFriendlyName, VROverlayHandle_t * pOverlayHandle); + EVROverlayError (OPENVR_FNTABLE_CALLTYPE *CreateOverlay)(char * pchOverlayKey, char * pchOverlayName, VROverlayHandle_t * pOverlayHandle); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *DestroyOverlay)(VROverlayHandle_t ulOverlayHandle); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetHighQualityOverlay)(VROverlayHandle_t ulOverlayHandle); VROverlayHandle_t (OPENVR_FNTABLE_CALLTYPE *GetHighQualityOverlay)(); uint32_t (OPENVR_FNTABLE_CALLTYPE *GetOverlayKey)(VROverlayHandle_t ulOverlayHandle, char * pchValue, uint32_t unBufferSize, EVROverlayError * pError); uint32_t (OPENVR_FNTABLE_CALLTYPE *GetOverlayName)(VROverlayHandle_t ulOverlayHandle, char * pchValue, uint32_t unBufferSize, EVROverlayError * pError); + EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayName)(VROverlayHandle_t ulOverlayHandle, char * pchName); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayImageData)(VROverlayHandle_t ulOverlayHandle, void * pvBuffer, uint32_t unBufferSize, uint32_t * punWidth, uint32_t * punHeight); char * (OPENVR_FNTABLE_CALLTYPE *GetOverlayErrorNameFromEnum)(EVROverlayError error); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayRenderingPid)(VROverlayHandle_t ulOverlayHandle, uint32_t unPID); @@ -1690,6 +1769,8 @@ struct VR_IVROverlay_FnTable EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTextureColorSpace)(VROverlayHandle_t ulOverlayHandle, EColorSpace * peTextureColorSpace); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTextureBounds)(VROverlayHandle_t ulOverlayHandle, struct VRTextureBounds_t * pOverlayTextureBounds); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTextureBounds)(VROverlayHandle_t ulOverlayHandle, struct VRTextureBounds_t * pOverlayTextureBounds); + uint32_t (OPENVR_FNTABLE_CALLTYPE *GetOverlayRenderModel)(VROverlayHandle_t ulOverlayHandle, char * pchValue, uint32_t unBufferSize, struct HmdColor_t * pColor, EVROverlayError * pError); + EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayRenderModel)(VROverlayHandle_t ulOverlayHandle, char * pchRenderModel, struct HmdColor_t * pColor); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformType)(VROverlayHandle_t ulOverlayHandle, VROverlayTransformType * peTransformType); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTransformAbsolute)(VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, struct HmdMatrix34_t * pmatTrackingOriginToOverlayTransform); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformAbsolute)(VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin * peTrackingOrigin, struct HmdMatrix34_t * pmatTrackingOriginToOverlayTransform); @@ -1697,6 +1778,8 @@ struct VR_IVROverlay_FnTable EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformTrackedDeviceRelative)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t * punTrackedDevice, struct HmdMatrix34_t * pmatTrackedDeviceToOverlayTransform); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTransformTrackedDeviceComponent)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unDeviceIndex, char * pchComponentName); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformTrackedDeviceComponent)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t * punDeviceIndex, char * pchComponentName, uint32_t unComponentNameSize); + EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformOverlayRelative)(VROverlayHandle_t ulOverlayHandle, VROverlayHandle_t * ulOverlayHandleParent, struct HmdMatrix34_t * pmatParentOverlayToOverlayTransform); + EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTransformOverlayRelative)(VROverlayHandle_t ulOverlayHandle, VROverlayHandle_t ulOverlayHandleParent, struct HmdMatrix34_t * pmatParentOverlayToOverlayTransform); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *ShowOverlay)(VROverlayHandle_t ulOverlayHandle); EVROverlayError (OPENVR_FNTABLE_CALLTYPE *HideOverlay)(VROverlayHandle_t ulOverlayHandle); bool (OPENVR_FNTABLE_CALLTYPE *IsOverlayVisible)(VROverlayHandle_t ulOverlayHandle); diff --git a/examples/ThirdPartyLibs/openvr/headers/openvr_driver.h b/examples/ThirdPartyLibs/openvr/headers/openvr_driver.h index c2d550eba..e0732a0f5 100644 --- a/examples/ThirdPartyLibs/openvr/headers/openvr_driver.h +++ b/examples/ThirdPartyLibs/openvr/headers/openvr_driver.h @@ -21,19 +21,13 @@ struct VkPhysicalDevice_T; struct VkInstance_T; struct VkQueue_T; +// Forward declarations to avoid requiring d3d12.h +struct ID3D12Resource; +struct ID3D12CommandQueue; + namespace vr { - -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. - #pragma pack( push, 4 ) -#else - #pragma pack( push, 8 ) -#endif +#pragma pack( push, 8 ) typedef void* glSharedTextureHandle_t; typedef int32_t glInt_t; @@ -116,6 +110,8 @@ enum ETextureType TextureType_DirectX = 0, // Handle is an ID3D11Texture TextureType_OpenGL = 1, // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure + TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurfaceRef + TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure }; enum EColorSpace @@ -164,6 +160,7 @@ enum ETrackedDeviceClass TrackedDeviceClass_Controller = 2, // Tracked controllers TrackedDeviceClass_GenericTracker = 3, // Generic trackers, similar to controllers TrackedDeviceClass_TrackingReference = 4, // Camera and base stations that serve as tracking reference points + TrackedDeviceClass_DisplayRedirect = 5, // Accessories that aren't necessarily tracked themselves, but may redirect video output from other tracked devices }; @@ -199,6 +196,30 @@ enum ETrackingUniverseOrigin TrackingUniverseRawAndUncalibrated = 2, // Poses are provided in the coordinate system defined by the driver. It has Y up and is unified for devices of the same driver. You usually don't want this one. }; +// Refers to a single container of properties +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; + +static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0; +static const PropertyTypeTag_t k_unInvalidPropertyTag = 0; + +// Use these tags to set/get common types as struct properties +static const PropertyTypeTag_t k_unFloatPropertyTag = 1; +static const PropertyTypeTag_t k_unInt32PropertyTag = 2; +static const PropertyTypeTag_t k_unUint64PropertyTag = 3; +static const PropertyTypeTag_t k_unBoolPropertyTag = 4; +static const PropertyTypeTag_t k_unStringPropertyTag = 5; + +static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20; +static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21; +static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22; +static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23; + +static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30; + +static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000; +static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000; + /** Each entry in this enum represents a property that can be retrieved about a * tracked device. Many fields are only valid for one ETrackedDeviceClass. */ @@ -241,6 +262,8 @@ enum ETrackedDeviceProperty Prop_DriverVersion_String = 1031, Prop_Firmware_ForceUpdateRequired_Bool = 1032, Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + Prop_ResourceRoot_String = 1035, // Properties that are unique to TrackedDeviceClass_HMD Prop_ReportsTimeSinceVSync_Bool = 2000, @@ -281,6 +304,11 @@ enum ETrackedDeviceProperty Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, Prop_DisplaySuppressed_Bool = 2036, Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_SecondsFromPhotonsToVblank_Float = 2042, // Properties that are unique to TrackedDeviceClass_Controller Prop_AttachedDeviceId_String = 3000, @@ -312,6 +340,19 @@ enum ETrackedDeviceProperty Prop_NamedIconPathDeviceStandby_String = 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others Prop_NamedIconPathDeviceAlertLow_String = 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others + // Properties that are used by helpers, but are opaque to applications + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + + // Properties that are unique to drivers + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + Prop_HasDisplayComponent_Bool = 6002, + Prop_HasControllerComponent_Bool = 6003, + Prop_HasCameraComponent_Bool = 6004, + Prop_HasDriverDirectModeComponent_Bool = 6005, + Prop_HasVirtualDisplayComponent_Bool = 6006, + // Vendors are free to expose private debug data in this reserved region Prop_VendorSpecific_Reserved_Start = 10000, Prop_VendorSpecific_Reserved_End = 10999, @@ -327,13 +368,14 @@ enum ETrackedPropertyError TrackedProp_WrongDataType = 1, TrackedProp_WrongDeviceClass = 2, TrackedProp_BufferTooSmall = 3, - TrackedProp_UnknownProperty = 4, + TrackedProp_UnknownProperty = 4, // Driver has not set the property (and may not ever). TrackedProp_InvalidDevice = 5, TrackedProp_CouldNotContactServer = 6, TrackedProp_ValueNotProvidedByDevice = 7, TrackedProp_StringExceedsMaximumLength = 8, TrackedProp_NotYetAvailable = 9, // The property value isn't known yet, but is expected soon. Call again later. TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, }; /** Allows the application to control what part of the provided texture will be used in the @@ -376,6 +418,14 @@ struct VRVulkanTextureData_t uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount; }; +/** Data required for passing D3D12 textures to IVRCompositor::Submit. +* Be sure to call OpenVR_Shutdown before destroying these resources. */ +struct D3D12TextureData_t +{ + ID3D12Resource *m_pResource; + ID3D12CommandQueue *m_pCommandQueue; + uint32_t m_nNodeMask; +}; /** Status of the overall system or tracked objects */ enum EVRState @@ -399,7 +449,7 @@ enum EVREventType VREvent_TrackedDeviceActivated = 100, VREvent_TrackedDeviceDeactivated = 101, VREvent_TrackedDeviceUpdated = 102, - VREvent_TrackedDeviceUserInteractionStarted = 103, + VREvent_TrackedDeviceUserInteractionStarted = 103, VREvent_TrackedDeviceUserInteractionEnded = 104, VREvent_IpdChanged = 105, VREvent_EnterStandbyMode = 106, @@ -407,6 +457,7 @@ enum EVREventType VREvent_TrackedDeviceRoleChanged = 108, VREvent_WatchdogWakeUpRequested = 109, VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, VREvent_ButtonPress = 200, // data is controller VREvent_ButtonUnpress = 201, // data is controller @@ -436,78 +487,83 @@ enum EVREventType VREvent_OverlayShown = 500, VREvent_OverlayHidden = 501, - VREvent_DashboardActivated = 502, - VREvent_DashboardDeactivated = 503, - VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay - VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay - VREvent_ResetDashboard = 506, // Send to the overlay manager - VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID - VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading - VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it - VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it - VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it - VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else + VREvent_DashboardActivated = 502, + VREvent_DashboardDeactivated = 503, + VREvent_DashboardThumbSelected = 504, // Sent to the overlay manager - data is overlay + VREvent_DashboardRequested = 505, // Sent to the overlay manager - data is overlay + VREvent_ResetDashboard = 506, // Send to the overlay manager + VREvent_RenderToast = 507, // Send to the dashboard to render a toast - data is the notification ID + VREvent_ImageLoaded = 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading + VREvent_ShowKeyboard = 509, // Sent to keyboard renderer in the dashboard to invoke it + VREvent_HideKeyboard = 510, // Sent to keyboard renderer in the dashboard to hide it + VREvent_OverlayGamepadFocusGained = 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it + VREvent_OverlayGamepadFocusLost = 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else VREvent_OverlaySharedTextureChanged = 513, - VREvent_DashboardGuideButtonDown = 514, - VREvent_DashboardGuideButtonUp = 515, - VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot - VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load - VREvent_DashboardOverlayCreated = 518, + VREvent_DashboardGuideButtonDown = 514, + VREvent_DashboardGuideButtonUp = 515, + VREvent_ScreenshotTriggered = 516, // Screenshot button combo was pressed, Dashboard should request a screenshot + VREvent_ImageFailed = 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load + VREvent_DashboardOverlayCreated = 518, // Screenshot API - VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot - VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken - VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken - VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted - VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_RequestScreenshot = 520, // Sent by vrclient application to compositor to take a screenshot + VREvent_ScreenshotTaken = 521, // Sent by compositor to the application that the screenshot has been taken + VREvent_ScreenshotFailed = 522, // Sent by compositor to the application that the screenshot failed to be taken + VREvent_SubmitScreenshotToDashboard = 523, // Sent by compositor to the dashboard that a completed screenshot was submitted + VREvent_ScreenshotProgressToDashboard = 524, // Sent by compositor to the dashboard that a completed screenshot was submitted + + VREvent_PrimaryDashboardDeviceChanged = 525, VREvent_Notification_Shown = 600, VREvent_Notification_Hidden = 601, VREvent_Notification_BeginInteraction = 602, VREvent_Notification_Destroyed = 603, - VREvent_Quit = 700, // data is process - VREvent_ProcessQuit = 701, // data is process - VREvent_QuitAborted_UserPrompt = 702, // data is process - VREvent_QuitAcknowledged = 703, // data is process - VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down + VREvent_Quit = 700, // data is process + VREvent_ProcessQuit = 701, // data is process + VREvent_QuitAborted_UserPrompt = 702, // data is process + VREvent_QuitAcknowledged = 703, // data is process + VREvent_DriverRequestedQuit = 704, // The driver has requested that SteamVR shut down - VREvent_ChaperoneDataHasChanged = 800, - VREvent_ChaperoneUniverseHasChanged = 801, - VREvent_ChaperoneTempDataHasChanged = 802, - VREvent_ChaperoneSettingsHaveChanged = 803, - VREvent_SeatedZeroPoseReset = 804, + VREvent_ChaperoneDataHasChanged = 800, + VREvent_ChaperoneUniverseHasChanged = 801, + VREvent_ChaperoneTempDataHasChanged = 802, + VREvent_ChaperoneSettingsHaveChanged = 803, + VREvent_SeatedZeroPoseReset = 804, - VREvent_AudioSettingsHaveChanged = 820, + VREvent_AudioSettingsHaveChanged = 820, - VREvent_BackgroundSettingHasChanged = 850, - VREvent_CameraSettingsHaveChanged = 851, - VREvent_ReprojectionSettingHasChanged = 852, - VREvent_ModelSkinSettingsHaveChanged = 853, - VREvent_EnvironmentSettingsHaveChanged = 854, - VREvent_PowerSettingsHaveChanged = 855, + VREvent_BackgroundSettingHasChanged = 850, + VREvent_CameraSettingsHaveChanged = 851, + VREvent_ReprojectionSettingHasChanged = 852, + VREvent_ModelSkinSettingsHaveChanged = 853, + VREvent_EnvironmentSettingsHaveChanged = 854, + VREvent_PowerSettingsHaveChanged = 855, - VREvent_StatusUpdate = 900, + VREvent_StatusUpdate = 900, - VREvent_MCImageUpdated = 1000, + VREvent_MCImageUpdated = 1000, - VREvent_FirmwareUpdateStarted = 1100, - VREvent_FirmwareUpdateFinished = 1101, + VREvent_FirmwareUpdateStarted = 1100, + VREvent_FirmwareUpdateFinished = 1101, - VREvent_KeyboardClosed = 1200, - VREvent_KeyboardCharInput = 1201, - VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard + VREvent_KeyboardClosed = 1200, + VREvent_KeyboardCharInput = 1201, + VREvent_KeyboardDone = 1202, // Sent when DONE button clicked on keyboard - VREvent_ApplicationTransitionStarted = 1300, - VREvent_ApplicationTransitionAborted = 1301, - VREvent_ApplicationTransitionNewAppStarted = 1302, - VREvent_ApplicationListUpdated = 1303, - VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionStarted = 1300, + VREvent_ApplicationTransitionAborted = 1301, + VREvent_ApplicationTransitionNewAppStarted = 1302, + VREvent_ApplicationListUpdated = 1303, + VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ApplicationTransitionNewAppLaunchComplete = 1305, + VREvent_ProcessConnected = 1306, + VREvent_ProcessDisconnected = 1307, - VREvent_Compositor_MirrorWindowShown = 1400, - VREvent_Compositor_MirrorWindowHidden = 1401, - VREvent_Compositor_ChaperoneBoundsShown = 1410, - VREvent_Compositor_ChaperoneBoundsHidden = 1411, + VREvent_Compositor_MirrorWindowShown = 1400, + VREvent_Compositor_MirrorWindowHidden = 1401, + VREvent_Compositor_ChaperoneBoundsShown = 1410, + VREvent_Compositor_ChaperoneBoundsHidden = 1411, VREvent_TrackedCamera_StartVideoStream = 1500, VREvent_TrackedCamera_StopVideoStream = 1501, @@ -515,26 +571,30 @@ enum EVREventType VREvent_TrackedCamera_ResumeVideoStream = 1503, VREvent_TrackedCamera_EditingSurface = 1550, - VREvent_PerformanceTest_EnableCapture = 1600, - VREvent_PerformanceTest_DisableCapture = 1601, - VREvent_PerformanceTest_FidelityLevel = 1602, + VREvent_PerformanceTest_EnableCapture = 1600, + VREvent_PerformanceTest_DisableCapture = 1601, + VREvent_PerformanceTest_FidelityLevel = 1602, - VREvent_MessageOverlay_Closed = 1650, + VREvent_MessageOverlay_Closed = 1650, // Vendors are free to expose private events in this reserved region - VREvent_VendorSpecific_Reserved_Start = 10000, - VREvent_VendorSpecific_Reserved_End = 19999, + VREvent_VendorSpecific_Reserved_Start = 10000, + VREvent_VendorSpecific_Reserved_End = 19999, }; /** Level of Hmd activity */ +// UserInteraction_Timeout means the device is in the process of timing out. +// InUse = ( k_EDeviceActivityLevel_UserInteraction || k_EDeviceActivityLevel_UserInteraction_Timeout ) +// VREvent_TrackedDeviceUserInteractionStarted fires when the devices transitions from Standby -> UserInteraction or Idle -> UserInteraction. +// VREvent_TrackedDeviceUserInteractionEnded fires when the devices transitions from UserInteraction_Timeout -> Idle enum EDeviceActivityLevel -{ - k_EDeviceActivityLevel_Unknown = -1, - k_EDeviceActivityLevel_Idle = 0, - k_EDeviceActivityLevel_UserInteraction = 1, - k_EDeviceActivityLevel_UserInteraction_Timeout = 2, - k_EDeviceActivityLevel_Standby = 3, +{ + k_EDeviceActivityLevel_Unknown = -1, + k_EDeviceActivityLevel_Idle = 0, // No activity for the last 10 seconds + k_EDeviceActivityLevel_UserInteraction = 1, // Activity (movement or prox sensor) is happening now + k_EDeviceActivityLevel_UserInteraction_Timeout = 2, // No activity for the last 0.5 seconds + k_EDeviceActivityLevel_Standby = 3, // Idle for at least 5 seconds (configurable in Settings -> Power Management) }; @@ -711,6 +771,12 @@ struct VREvent_MessageOverlay_t uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum }; +struct VREvent_Property_t +{ + PropertyContainerHandle_t container; + ETrackedDeviceProperty prop; +}; + /** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */ typedef union { @@ -733,8 +799,16 @@ typedef union VREvent_ApplicationLaunch_t applicationLaunch; VREvent_EditingCameraSurface_t cameraSurface; VREvent_MessageOverlay_t messageOverlay; + VREvent_Property_t property; } VREvent_Data_t; + +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + /** An event posted by the server to all running applications */ struct VREvent_t { @@ -745,6 +819,9 @@ struct VREvent_t VREvent_Data_t data; }; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif /** The mesh to draw into the stencil (or depth) buffer to perform * early stencil (or depth) kills of pixels that will never appear on the HMD. @@ -764,6 +841,8 @@ enum EHiddenAreaMeshType k_eHiddenAreaMesh_Standard = 0, k_eHiddenAreaMesh_Inverse = 1, k_eHiddenAreaMesh_LineLoop = 2, + + k_eHiddenAreaMesh_Max = 3, }; @@ -791,6 +870,12 @@ struct VRControllerAxis_t static const uint32_t k_unControllerStateAxisCount = 5; +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + /** Holds all the state of a controller at one moment in time. */ struct VRControllerState001_t { @@ -805,6 +890,9 @@ struct VRControllerState001_t // Axis data for the controller's analog inputs VRControllerAxis_t rAxis[ k_unControllerStateAxisCount ]; }; +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif typedef VRControllerState001_t VRControllerState_t; @@ -887,6 +975,7 @@ enum EVRApplicationType // interfaces (like IVRSettings and IVRApplications) but not hardware. VRApplication_VRMonitor = 5, // Reserved for vrmonitor VRApplication_SteamWatchdog = 6,// Reserved for Steam + VRApplication_Bootstrapper = 7, // Start up SteamVR VRApplication_Max }; @@ -1132,16 +1221,7 @@ static const uint32_t k_unScreenshotHandleInvalid = 0; namespace vr { -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. - #pragma pack( push, 4 ) -#else - #pragma pack( push, 8 ) -#endif +#pragma pack( push, 8 ) enum ECameraVideoStreamFormat { @@ -1274,7 +1354,6 @@ namespace vr static const char * const k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd"; static const char * const k_pch_SteamVR_DisplayDebug_Bool = "displayDebug"; static const char * const k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe"; - static const char * const k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion"; static const char * const k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX"; static const char * const k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY"; static const char * const k_pch_SteamVR_SendSystemButtonToAllApps_Bool= "sendSystemButtonToAllApps"; @@ -1325,7 +1404,6 @@ namespace vr //----------------------------------------------------------------------------- // null keys static const char * const k_pch_Null_Section = "driver_null"; - static const char * const k_pch_Null_EnableNullDriver_Bool = "enable"; static const char * const k_pch_Null_SerialNumber_String = "serialNumber"; static const char * const k_pch_Null_ModelNumber_String = "modelNumber"; static const char * const k_pch_Null_WindowX_Int32 = "windowX"; @@ -1426,6 +1504,10 @@ namespace vr // model skin keys static const char * const k_pch_modelskin_Section = "modelskins"; + //----------------------------------------------------------------------------- + // driver keys - These could be checked in any driver_ section + static const char * const k_pch_Driver_Enable_Bool = "enable"; + } // namespace vr // iservertrackeddevicedriver.h @@ -1543,37 +1625,11 @@ public: // Tracking Methods // ------------------------------------ virtual DriverPose_t GetPose() = 0; - - // ------------------------------------ - // Property Methods - // ------------------------------------ - - /** Returns a bool property. If the property is not available this function will return false. */ - virtual bool GetBoolTrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a float property. If the property is not available this function will return 0. */ - virtual float GetFloatTrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns an int property. If the property is not available this function will return 0. */ - virtual int32_t GetInt32TrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a uint64 property. If the property is not available this function will return 0. */ - virtual uint64_t GetUint64TrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a matrix property. If the device index is not valid or the property is not a matrix type, this function will return identity. */ - virtual HmdMatrix34_t GetMatrix34TrackedDeviceProperty( ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) = 0; - - /** Returns a string property. If the property is not available this function will return 0 and pError will be - * set to an error. Otherwise it returns the length of the number of bytes necessary to hold this string including - * the trailing null. If the buffer is too small the error will be TrackedProp_BufferTooSmall. Drivers may not - * return strings longer than k_unMaxPropertyStringSize. */ - virtual uint32_t GetStringTrackedDeviceProperty( ETrackedDeviceProperty prop, char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError ) = 0; - }; -static const char *ITrackedDeviceServerDriver_Version = "ITrackedDeviceServerDriver_004"; +static const char *ITrackedDeviceServerDriver_Version = "ITrackedDeviceServerDriver_005"; } // ivrdisplaycomponent.h @@ -1745,73 +1801,21 @@ namespace vr class ITrackedDeviceServerDriver; struct TrackedDeviceDriverInfo_t; struct DriverPose_t; - -class IDriverLog -{ -public: - /** Writes a log message to the log file prefixed with the driver name */ - virtual void Log( const char *pchLogMessage ) = 0; -}; +typedef PropertyContainerHandle_t DriverHandle_t; /** This interface is provided by vrserver to allow the driver to notify * the system when something changes about a device. These changes must * not change the serial number or class of the device because those values * are permanently associated with the device's index. */ -class IServerDriverHost +class IVRDriverContext { public: - /** Notifies the server that a tracked device has been added. If this function returns true - * the server will call Activate on the device. If it returns false some kind of error - * has occurred and the device will not be activated. */ - virtual bool TrackedDeviceAdded( const char *pchDeviceSerialNumber ) = 0; + /** Returns the requested interface. If the interface was not available it will return NULL and fill + * out the error. */ + virtual void *GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError = nullptr ) = 0; - /** Notifies the server that a tracked device's pose has been updated */ - virtual void TrackedDevicePoseUpdated( uint32_t unWhichDevice, const DriverPose_t & newPose ) = 0; - - /** Notifies the server that the property cache for the specified device should be invalidated */ - virtual void TrackedDevicePropertiesChanged( uint32_t unWhichDevice ) = 0; - - /** Notifies the server that vsync has occurred on the the display attached to the device. This is - * only permitted on devices of the HMD class. */ - virtual void VsyncEvent( double vsyncTimeOffsetSeconds ) = 0; - - /** notifies the server that the button was pressed */ - virtual void TrackedDeviceButtonPressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server that the button was unpressed */ - virtual void TrackedDeviceButtonUnpressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server that the button was pressed */ - virtual void TrackedDeviceButtonTouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server that the button was unpressed */ - virtual void TrackedDeviceButtonUntouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; - - /** notifies the server than a controller axis changed */ - virtual void TrackedDeviceAxisUpdated( uint32_t unWhichDevice, uint32_t unWhichAxis, const VRControllerAxis_t & axisState ) = 0; - - /** Notifies the server that the MC image has been updated for the display attached to the device. This is - * only permitted on devices of the HMD class. */ - virtual void MCImageUpdated() = 0; - - /** always returns a pointer to a valid interface pointer of IVRSettings */ - virtual IVRSettings *GetSettings( const char *pchInterfaceVersion ) = 0; - - /** Notifies the server that the physical IPD adjustment has been moved on the HMD */ - virtual void PhysicalIpdSet( uint32_t unWhichDevice, float fPhysicalIpdMeters ) = 0; - - /** Notifies the server that the proximity sensor on the specified device */ - virtual void ProximitySensorState( uint32_t unWhichDevice, bool bProximitySensorTriggered ) = 0; - - /** Sends a vendor specific event (VREvent_VendorSpecific_Reserved_Start..VREvent_VendorSpecific_Reserved_End */ - virtual void VendorSpecificEvent( uint32_t unWhichDevice, vr::EVREventType eventType, const VREvent_Data_t & eventData, double eventTimeOffset ) = 0; - - /** Returns true if SteamVR is exiting */ - virtual bool IsExiting() = 0; - - /** Returns true and fills the event with the next event on the queue if there is one. If there are no events - * this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */ - virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0; + /** Returns the property container handle for this driver */ + virtual DriverHandle_t GetDriverHandle() = 0; }; @@ -1828,7 +1832,7 @@ public: * config files. * pchDriverInstallDir - The absolute path of the root directory for the driver. */ - virtual EVRInitError Init( IDriverLog *pDriverLog, vr::IServerDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) = 0; + virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0; /** cleans up the driver right before it is unloaded */ virtual void Cleanup() = 0; @@ -1836,15 +1840,6 @@ public: /** Returns the version of the ITrackedDeviceServerDriver interface used by this driver */ virtual const char * const *GetInterfaceVersions() = 0; - /** returns the number of HMDs that this driver manages that are physically connected. */ - virtual uint32_t GetTrackedDeviceCount() = 0; - - /** returns a single HMD */ - virtual ITrackedDeviceServerDriver *GetTrackedDeviceDriver( uint32_t unWhich ) = 0; - - /** returns a single HMD by ID */ - virtual ITrackedDeviceServerDriver* FindTrackedDeviceDriver( const char *pchId ) = 0; - /** Allows the driver do to some work in the main loop of the server. */ virtual void RunFrame() = 0; @@ -1865,108 +1860,535 @@ public: }; -static const char *IServerTrackedDeviceProvider_Version = "IServerTrackedDeviceProvider_003"; +static const char *IServerTrackedDeviceProvider_Version = "IServerTrackedDeviceProvider_004"; -/** This interface is provided by vrclient to allow the driver call back and query various information */ -class IClientDriverHost + + +/** This interface must be implemented in each driver. It will be loaded in vrclient.dll */ +class IVRWatchdogProvider { public: - /** Returns the device class of a tracked device. If there has not been a device connected in this slot - * since the application started this function will return TrackedDevice_Invalid. For previous detected - * devices the function will return the previously observed device class. - * - * To determine which devices exist on the system, just loop from 0 to k_unMaxTrackedDeviceCount and check - * the device class. Every device with something other than TrackedDevice_Invalid is associated with an - * actual tracked device. */ - virtual ETrackedDeviceClass GetTrackedDeviceClass( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + /** initializes the driver in watchdog mode. */ + virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0; - /** Returns true if there is a device connected in this slot. */ - virtual bool IsTrackedDeviceConnected( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0; + /** cleans up the driver right before it is unloaded */ + virtual void Cleanup() = 0; +}; - /** Returns a bool property. If the device index is not valid or the property is not a bool type this function will return false. */ - virtual bool GetBoolTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; +static const char *IVRWatchdogProvider_Version = "IVRWatchdogProvider_001"; - /** Returns a float property. If the device index is not valid or the property is not a float type this function will return 0. */ - virtual float GetFloatTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; +} +// ivrproperties.h +#include - /** Returns an int property. If the device index is not valid or the property is not a int type this function will return 0. */ - virtual int32_t GetInt32TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; +namespace vr +{ - /** Returns a uint64 property. If the device index is not valid or the property is not a uint64 type this function will return 0. */ - virtual uint64_t GetUint64TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0; + enum EPropertyWriteType + { + PropertyWrite_Set = 0, + PropertyWrite_Erase = 1, + PropertyWrite_SetError = 2 + }; - /** Returns a string property. If the device index is not valid or the property is not a float type this function will + struct PropertyWrite_t + { + ETrackedDeviceProperty prop; + EPropertyWriteType writeType; + ETrackedPropertyError eSetError; + void *pvBuffer; + uint32_t unBufferSize; + PropertyTypeTag_t unTag; + ETrackedPropertyError eError; + }; + + struct PropertyRead_t + { + ETrackedDeviceProperty prop; + void *pvBuffer; + uint32_t unBufferSize; + PropertyTypeTag_t unTag; + uint32_t unRequiredBufferSize; + ETrackedPropertyError eError; + }; + + +class IVRProperties +{ +public: + + /** Reads a set of properties atomically. See the PropertyReadBatch_t struct for more information. */ + virtual ETrackedPropertyError ReadPropertyBatch( PropertyContainerHandle_t ulContainerHandle, PropertyRead_t *pBatch, uint32_t unBatchEntryCount ) = 0; + + /** Writes a set of properties atomically. See the PropertyWriteBatch_t struct for more information. */ + virtual ETrackedPropertyError WritePropertyBatch( PropertyContainerHandle_t ulContainerHandle, PropertyWrite_t *pBatch, uint32_t unBatchEntryCount ) = 0; + + /** returns a string that corresponds with the specified property error. The string will be the name + * of the error enum value for all valid error codes */ + virtual const char *GetPropErrorNameFromEnum( ETrackedPropertyError error ) = 0; + + /** Returns a container handle given a tracked device index */ + virtual PropertyContainerHandle_t TrackedDeviceToPropertyContainer( TrackedDeviceIndex_t nDevice ) = 0; + +}; + +static const char * const IVRProperties_Version = "IVRProperties_001"; + +class CVRPropertyHelpers +{ +public: + CVRPropertyHelpers( IVRProperties * pProperties ) : m_pProperties( pProperties ) {} + + /** Returns a scaler property. If the device index is not valid or the property value type does not match, + * this function will return false. */ + bool GetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + float GetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + int32_t GetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + uint64_t GetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ); + + /** Returns a single typed property. If the device index is not valid or the property is not a string type this function will * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing - * null. Strings will generally fit in buffers of k_unTrackingStringSize characters. */ - virtual uint32_t GetStringTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0; + * null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ + uint32_t GetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() void *pvBuffer, uint32_t unBufferSize, PropertyTypeTag_t *punTag, ETrackedPropertyError *pError = 0L ); - /** always returns a pointer to a valid interface pointer of IVRSettings */ - virtual void *GetGenericInterface( const char *pchInterfaceVersion ) = 0; + /** Returns a string property. If the device index is not valid or the property is not a string type this function will + * return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing + * null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ + uint32_t GetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ); + + /** Returns a string property as a std::string. If the device index is not valid or the property is not a string type this function will + * return an empty string. */ + std::string GetStringProperty( vr::PropertyContainerHandle_t ulContainer, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError = nullptr ); + + /** Sets a scaler property. The new value will be returned on any subsequent call to get this property in any process. */ + ETrackedPropertyError SetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, bool bNewValue ); + ETrackedPropertyError SetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, float fNewValue ); + ETrackedPropertyError SetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, int32_t nNewValue ); + ETrackedPropertyError SetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, uint64_t ulNewValue ); + + /** Sets a string property. The new value will be returned on any subsequent call to get this property in any process. */ + ETrackedPropertyError SetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, const char *pchNewValue ); + + /** Sets a single typed property. The new value will be returned on any subsequent call to get this property in any process. */ + ETrackedPropertyError SetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, void *pvNewValue, uint32_t unNewValueSize, PropertyTypeTag_t unTag ); + + /** Sets the error return value for a property. This value will be returned on all subsequent requests to get the property */ + ETrackedPropertyError SetPropertyError( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError eError ); + + /** Clears any value or error set for the property. */ + ETrackedPropertyError EraseProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop ); + + /* Turns a device index into a property container handle. */ + PropertyContainerHandle_t TrackedDeviceToPropertyContainer( TrackedDeviceIndex_t nDevice ) { return m_pProperties->TrackedDeviceToPropertyContainer( nDevice ); } + +private: + template + T GetPropertyHelper( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError, T bDefault, PropertyTypeTag_t unTypeTag ); + + IVRProperties *m_pProperties; +}; + + +inline uint32_t CVRPropertyHelpers::GetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() void *pvBuffer, uint32_t unBufferSize, PropertyTypeTag_t *punTag, ETrackedPropertyError *pError ) +{ + PropertyRead_t batch; + batch.prop = prop; + batch.pvBuffer = pvBuffer; + batch.unBufferSize = unBufferSize; + + m_pProperties->ReadPropertyBatch( ulContainerHandle, &batch, 1 ); + + if ( pError ) + { + *pError = batch.eError; + } + + if ( punTag ) + { + *punTag = batch.unTag; + } + + return batch.unRequiredBufferSize; +} + + +/** Sets a single typed property. The new value will be returned on any subsequent call to get this property in any process. */ +inline ETrackedPropertyError CVRPropertyHelpers::SetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, void *pvNewValue, uint32_t unNewValueSize, PropertyTypeTag_t unTag ) +{ + PropertyWrite_t batch; + batch.writeType = PropertyWrite_Set; + batch.prop = prop; + batch.pvBuffer = pvNewValue; + batch.unBufferSize = unNewValueSize; + batch.unTag = unTag; + + m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 ); + + return batch.eError; +} + + +/** Returns a string property. If the device index is not valid or the property is not a string type this function will +* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing +* null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */ +inline uint32_t CVRPropertyHelpers::GetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError ) +{ + PropertyTypeTag_t unTag; + ETrackedPropertyError error; + uint32_t unRequiredSize = GetProperty( ulContainerHandle, prop, pchValue, unBufferSize, &unTag, &error ); + if ( unTag != k_unStringPropertyTag && error == TrackedProp_Success ) + { + error = TrackedProp_WrongDataType; + } + + if ( pError ) + { + *pError = error; + } + + if ( error != TrackedProp_Success ) + { + if ( pchValue && unBufferSize ) + { + *pchValue = '\0'; + } + } + + return unRequiredSize; +} + + +/** Returns a string property as a std::string. If the device index is not valid or the property is not a string type this function will +* return an empty string. */ +inline std::string CVRPropertyHelpers::GetStringProperty( vr::PropertyContainerHandle_t ulContainer, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError ) +{ + char buf[1024]; + vr::ETrackedPropertyError err; + uint32_t unRequiredBufferLen = GetStringProperty( ulContainer, prop, buf, sizeof(buf), &err ); + + std::string sResult; + + if ( err == TrackedProp_Success ) + { + sResult = buf; + } + else if ( err == TrackedProp_BufferTooSmall ) + { + char *pchBuffer = new char[unRequiredBufferLen]; + unRequiredBufferLen = GetStringProperty( ulContainer, prop, pchBuffer, unRequiredBufferLen, &err ); + sResult = pchBuffer; + delete[] pchBuffer; + } + + if ( peError ) + { + *peError = err; + } + + return sResult; +} + + +/** Sets a string property. The new value will be returned on any subsequent call to get this property in any process. */ +inline ETrackedPropertyError CVRPropertyHelpers::SetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, const char *pchNewValue ) +{ + if ( !pchNewValue ) + return TrackedProp_InvalidOperation; + + // this is strlen without the dependency on string.h + const char *pchCurr = pchNewValue; + while ( *pchCurr ) + { + pchCurr++; + } + + return SetProperty( ulContainerHandle, prop, (void *)pchNewValue, (uint32_t)(pchCurr - pchNewValue) + 1, k_unStringPropertyTag ); +} + + +template +inline T CVRPropertyHelpers::GetPropertyHelper( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError, T bDefault, PropertyTypeTag_t unTypeTag ) +{ + T bValue; + ETrackedPropertyError eError; + PropertyTypeTag_t unReadTag; + GetProperty( ulContainerHandle, prop, &bValue, sizeof( bValue ), &unReadTag, &eError ); + if ( unReadTag != unTypeTag && eError == TrackedProp_Success ) + { + eError = TrackedProp_WrongDataType; + }; + + if ( pError ) + *pError = eError; + if ( eError != TrackedProp_Success ) + { + return bDefault; + } + else + { + return bValue; + } +} + + +inline bool CVRPropertyHelpers::GetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, false, k_unBoolPropertyTag ); +} + + +inline float CVRPropertyHelpers::GetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, 0.f, k_unFloatPropertyTag ); +} + +inline int32_t CVRPropertyHelpers::GetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, 0, k_unInt32PropertyTag ); +} + +inline uint64_t CVRPropertyHelpers::GetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError ) +{ + return GetPropertyHelper( ulContainerHandle, prop, pError, 0, k_unUint64PropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, bool bNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &bNewValue, sizeof( bNewValue ), k_unBoolPropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, float fNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &fNewValue, sizeof( fNewValue ), k_unFloatPropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, int32_t nNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &nNewValue, sizeof( nNewValue ), k_unInt32PropertyTag ); +} + +inline ETrackedPropertyError CVRPropertyHelpers::SetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, uint64_t ulNewValue ) +{ + return SetProperty( ulContainerHandle, prop, &ulNewValue, sizeof( ulNewValue ), k_unUint64PropertyTag ); +} + +/** Sets the error return value for a property. This value will be returned on all subsequent requests to get the property */ +inline ETrackedPropertyError CVRPropertyHelpers::SetPropertyError( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError eError ) +{ + PropertyWrite_t batch; + batch.writeType = PropertyWrite_SetError; + batch.prop = prop; + batch.eSetError = eError; + + m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 ); + + return batch.eError; +} + +/** Clears any value or error set for the property. */ +inline ETrackedPropertyError CVRPropertyHelpers::EraseProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop ) +{ + PropertyWrite_t batch; + batch.writeType = PropertyWrite_Erase; + batch.prop = prop; + + m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 ); + + return batch.eError; + +} + +} + + +// ivrdriverlog.h +namespace vr +{ + +class IVRDriverLog +{ +public: + /** Writes a log message to the log file prefixed with the driver name */ + virtual void Log( const char *pchLogMessage ) = 0; +}; + + +static const char *IVRDriverLog_Version = "IVRDriverLog_001"; + +} +// ivrserverdriverhost.h +namespace vr +{ + +class ITrackedDeviceServerDriver; +struct TrackedDeviceDriverInfo_t; +struct DriverPose_t; + +/** This interface is provided by vrserver to allow the driver to notify +* the system when something changes about a device. These changes must +* not change the serial number or class of the device because those values +* are permanently associated with the device's index. */ +class IVRServerDriverHost +{ +public: + /** Notifies the server that a tracked device has been added. If this function returns true + * the server will call Activate on the device. If it returns false some kind of error + * has occurred and the device will not be activated. */ + virtual bool TrackedDeviceAdded( const char *pchDeviceSerialNumber, ETrackedDeviceClass eDeviceClass, ITrackedDeviceServerDriver *pDriver ) = 0; + + /** Notifies the server that a tracked device's pose has been updated */ + virtual void TrackedDevicePoseUpdated( uint32_t unWhichDevice, const DriverPose_t & newPose, uint32_t unPoseStructSize ) = 0; + + /** Notifies the server that vsync has occurred on the the display attached to the device. This is + * only permitted on devices of the HMD class. */ + virtual void VsyncEvent( double vsyncTimeOffsetSeconds ) = 0; + + /** notifies the server that the button was pressed */ + virtual void TrackedDeviceButtonPressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server that the button was unpressed */ + virtual void TrackedDeviceButtonUnpressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server that the button was pressed */ + virtual void TrackedDeviceButtonTouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server that the button was unpressed */ + virtual void TrackedDeviceButtonUntouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0; + + /** notifies the server than a controller axis changed */ + virtual void TrackedDeviceAxisUpdated( uint32_t unWhichDevice, uint32_t unWhichAxis, const VRControllerAxis_t & axisState ) = 0; + + /** Notifies the server that the proximity sensor on the specified device */ + virtual void ProximitySensorState( uint32_t unWhichDevice, bool bProximitySensorTriggered ) = 0; + + /** Sends a vendor specific event (VREvent_VendorSpecific_Reserved_Start..VREvent_VendorSpecific_Reserved_End */ + virtual void VendorSpecificEvent( uint32_t unWhichDevice, vr::EVREventType eventType, const VREvent_Data_t & eventData, double eventTimeOffset ) = 0; + + /** Returns true if SteamVR is exiting */ + virtual bool IsExiting() = 0; + + /** Returns true and fills the event with the next event on the queue if there is one. If there are no events + * this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */ + virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0; + + /** Provides access to device poses for drivers. Poses are in their "raw" tracking space which is uniquely + * defined by each driver providing poses for its devices. It is up to clients of this function to correlate + * poses across different drivers. Poses are indexed by their device id, and their associated driver and + * other properties can be looked up via IVRProperties. */ + virtual void GetRawTrackedDevicePoses( float fPredictedSecondsFromNow, TrackedDevicePose_t *pTrackedDevicePoseArray, uint32_t unTrackedDevicePoseArrayCount ) = 0; +}; + +static const char *IVRServerDriverHost_Version = "IVRServerDriverHost_004"; + +} + +// ivrhiddenarea.h +namespace vr +{ + +class CVRHiddenAreaHelpers +{ +public: + CVRHiddenAreaHelpers( IVRProperties *pProperties ) : m_pProperties( pProperties ) {} + + /** Stores a hidden area mesh in a property */ + ETrackedPropertyError SetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount ); + + /** retrieves a hidden area mesh from a property. Returns the vert count read out of the property. */ + uint32_t GetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount, ETrackedPropertyError *peError ); + +private: + ETrackedDeviceProperty GetPropertyEnum( EVREye eEye, EHiddenAreaMeshType type ) + { + return (ETrackedDeviceProperty)(Prop_DisplayHiddenArea_Binary_Start + ((int)type * 2) + (int)eEye); + } + + IVRProperties *m_pProperties; +}; + + +inline ETrackedPropertyError CVRHiddenAreaHelpers::SetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount ) +{ + ETrackedDeviceProperty prop = GetPropertyEnum( eEye, type ); + CVRPropertyHelpers propHelpers( m_pProperties ); + return propHelpers.SetProperty( propHelpers.TrackedDeviceToPropertyContainer( k_unTrackedDeviceIndex_Hmd ), prop, pVerts, sizeof( HmdVector2_t ) * unVertCount, k_unHiddenAreaPropertyTag ); +} + + +inline uint32_t CVRHiddenAreaHelpers::GetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount, ETrackedPropertyError *peError ) +{ + ETrackedDeviceProperty prop = GetPropertyEnum( eEye, type ); + CVRPropertyHelpers propHelpers( m_pProperties ); + ETrackedPropertyError propError; + PropertyTypeTag_t unTag; + uint32_t unBytesNeeded = propHelpers.GetProperty( propHelpers.TrackedDeviceToPropertyContainer( k_unTrackedDeviceIndex_Hmd ), prop, pVerts, sizeof( HmdVector2_t )*unVertCount, &unTag, &propError ); + if ( propError == TrackedProp_Success && unTag != k_unHiddenAreaPropertyTag ) + { + propError = TrackedProp_WrongDataType; + unBytesNeeded = 0; + } + + if ( peError ) + { + *peError = propError; + } + + return unBytesNeeded / sizeof( HmdVector2_t ); +} + +} +// ivrwatchdoghost.h +namespace vr +{ + +/** This interface is provided by vrclient to allow the driver to make everything wake up */ +class IVRWatchdogHost +{ +public: /** Client drivers in watchdog mode should call this when they have received a signal from hardware that should * cause SteamVR to start */ virtual void WatchdogWakeUp() = 0; }; +static const char *IVRWatchdogHost_Version = "IVRWatchdogHost_001"; -/** Defines the mode that the client driver should start in. */ -enum EClientDriverMode -{ - ClientDriverMode_Normal = 0, - ClientDriverMode_Watchdog = 1, // client should return VRInitError_Init_LowPowerWatchdogNotSupported if it can't support this mode }; -/** This interface must be implemented in each driver. It will be loaded in vrclient.dll */ -class IClientTrackedDeviceProvider + +// ivrvirtualdisplay.h +namespace vr { -public: - /** initializes the driver. This will be called before any other methods are called, - * except BIsHmdPresent(). BIsHmdPresent is called outside of the Init/Cleanup pair. - * If Init returns anything other than VRInitError_None the driver DLL will be unloaded. - * - * pDriverHost will never be NULL, and will always be a pointer to a IClientDriverHost interface - * - * pchUserDriverConfigDir - The absolute path of the directory where the driver should store user - * config files. - * pchDriverInstallDir - The absolute path of the root directory for the driver. - */ - virtual EVRInitError Init( EClientDriverMode eDriverMode, IDriverLog *pDriverLog, vr::IClientDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ) = 0; + // ---------------------------------------------------------------------------------------------- + // Purpose: This component is used for drivers that implement a virtual display (e.g. wireless). + // ---------------------------------------------------------------------------------------------- + class IVRVirtualDisplay + { + public: - /** cleans up the driver right before it is unloaded */ - virtual void Cleanup() = 0; + /** Submits final backbuffer for display. */ + virtual void Present( vr::SharedTextureHandle_t backbufferTextureHandle ) = 0; - /** Called when the client needs to inform an application if an HMD is attached that uses - * this driver. This method should be as lightweight as possible and should have no side effects - * such as hooking process functions or leaving resources loaded. Init will not be called before - * this method and Cleanup will not be called after it. - */ - virtual bool BIsHmdPresent( const char *pchUserConfigDir ) = 0; + /** Block until the last presented buffer start scanning out. */ + virtual void WaitForPresent() = 0; - /** called when the client inits an HMD to let the client driver know which one is in use */ - virtual EVRInitError SetDisplayId( const char *pchDisplayId ) = 0; + /** Provides timing data for synchronizing with display. */ + virtual bool GetTimeSinceLastVsync( float *pfSecondsSinceLastVsync, uint64_t *pulFrameCounter ) = 0; + }; - /** Returns the stencil mesh information for the current HMD. If this HMD does not have a stencil mesh the vertex data and count will be - * NULL and 0 respectively. This mesh is meant to be rendered into the stencil buffer (or into the depth buffer setting nearz) before rendering - * each eye's view. The pixels covered by this mesh will never be seen by the user after the lens distortion is applied and based on visibility to the panels. - * This will improve perf by letting the GPU early-reject pixels the user will never see before running the pixel shader. - * NOTE: Render this mesh with backface culling disabled since the winding order of the vertices can be different per-HMD or per-eye. - */ - virtual HiddenAreaMesh_t GetHiddenAreaMesh( EVREye eEye, EHiddenAreaMeshType type ) = 0; - - /** Get the MC image for the current HMD. - * Returns the size in bytes of the buffer required to hold the specified resource. */ - virtual uint32_t GetMCImage( uint32_t *pImgWidth, uint32_t *pImgHeight, uint32_t *pChannels, void *pDataBuffer, uint32_t unBufferLen ) = 0; -}; - -static const char *IClientTrackedDeviceProvider_Version = "IClientTrackedDeviceProvider_005"; + static const char *IVRVirtualDisplay_Version = "IVRVirtualDisplay_001"; + /** Returns the current IVRVirtualDisplay pointer or NULL the interface could not be found. */ + VR_INTERFACE vr::IVRVirtualDisplay *VR_CALLTYPE VRVirtualDisplay(); } + + namespace vr { static const char * const k_InterfaceVersions[] = @@ -1978,9 +2400,186 @@ namespace vr IVRControllerComponent_Version, IVRCameraComponent_Version, IServerTrackedDeviceProvider_Version, - IClientTrackedDeviceProvider_Version, + IVRWatchdogProvider_Version, + IVRVirtualDisplay_Version, nullptr }; + + inline IVRDriverContext *&VRDriverContext() + { + static IVRDriverContext *pHost; + return pHost; + } + + class COpenVRDriverContext + { + public: + COpenVRDriverContext() : m_propertyHelpers(nullptr), m_hiddenAreaHelpers(nullptr) { Clear(); } + void Clear(); + + EVRInitError InitServer(); + EVRInitError InitWatchdog(); + + IVRSettings *VRSettings() + { + if ( m_pVRSettings == nullptr ) + { + EVRInitError eError; + m_pVRSettings = (IVRSettings *)VRDriverContext()->GetGenericInterface( IVRSettings_Version, &eError ); + } + return m_pVRSettings; + } + + IVRProperties *VRPropertiesRaw() + { + if ( m_pVRProperties == nullptr ) + { + EVRInitError eError; + m_pVRProperties = (IVRProperties *)VRDriverContext()->GetGenericInterface( IVRProperties_Version, &eError ); + m_propertyHelpers = CVRPropertyHelpers( m_pVRProperties ); + m_hiddenAreaHelpers = CVRHiddenAreaHelpers( m_pVRProperties ); + } + return m_pVRProperties; + } + + CVRPropertyHelpers *VRProperties() + { + VRPropertiesRaw(); + return &m_propertyHelpers; + } + + CVRHiddenAreaHelpers *VRHiddenArea() + { + VRPropertiesRaw(); + return &m_hiddenAreaHelpers; + } + + IVRServerDriverHost *VRServerDriverHost() + { + if ( m_pVRServerDriverHost == nullptr ) + { + EVRInitError eError; + m_pVRServerDriverHost = (IVRServerDriverHost *)VRDriverContext()->GetGenericInterface( IVRServerDriverHost_Version, &eError ); + } + return m_pVRServerDriverHost; + } + + IVRWatchdogHost *VRWatchdogHost() + { + if ( m_pVRWatchdogHost == nullptr ) + { + EVRInitError eError; + m_pVRWatchdogHost = (IVRWatchdogHost *)VRDriverContext()->GetGenericInterface( IVRWatchdogHost_Version, &eError ); + } + return m_pVRWatchdogHost; + } + + IVRDriverLog *VRDriverLog() + { + if ( m_pVRDriverLog == nullptr ) + { + EVRInitError eError; + m_pVRDriverLog = (IVRDriverLog *)VRDriverContext()->GetGenericInterface( IVRDriverLog_Version, &eError ); + } + return m_pVRDriverLog; + } + + DriverHandle_t VR_CALLTYPE VRDriverHandle() + { + return VRDriverContext()->GetDriverHandle(); + } + + private: + IVRSettings *m_pVRSettings; + IVRProperties *m_pVRProperties; + CVRPropertyHelpers m_propertyHelpers; + CVRHiddenAreaHelpers m_hiddenAreaHelpers; + IVRServerDriverHost *m_pVRServerDriverHost; + IVRWatchdogHost *m_pVRWatchdogHost; + IVRDriverLog *m_pVRDriverLog; + }; + + inline COpenVRDriverContext &OpenVRInternal_ModuleServerDriverContext() + { + static void *ctx[sizeof( COpenVRDriverContext ) / sizeof( void * )]; + return *(COpenVRDriverContext *)ctx; // bypass zero-init constructor + } + + inline IVRSettings *VR_CALLTYPE VRSettings() { return OpenVRInternal_ModuleServerDriverContext().VRSettings(); } + inline IVRProperties *VR_CALLTYPE VRPropertiesRaw() { return OpenVRInternal_ModuleServerDriverContext().VRPropertiesRaw(); } + inline CVRPropertyHelpers *VR_CALLTYPE VRProperties() { return OpenVRInternal_ModuleServerDriverContext().VRProperties(); } + inline CVRHiddenAreaHelpers *VR_CALLTYPE VRHiddenArea() { return OpenVRInternal_ModuleServerDriverContext().VRHiddenArea(); } + inline IVRDriverLog *VR_CALLTYPE VRDriverLog() { return OpenVRInternal_ModuleServerDriverContext().VRDriverLog(); } + inline IVRServerDriverHost *VR_CALLTYPE VRServerDriverHost() { return OpenVRInternal_ModuleServerDriverContext().VRServerDriverHost(); } + inline IVRWatchdogHost *VR_CALLTYPE VRWatchdogHost() { return OpenVRInternal_ModuleServerDriverContext().VRWatchdogHost(); } + inline DriverHandle_t VR_CALLTYPE VRDriverHandle() { return OpenVRInternal_ModuleServerDriverContext().VRDriverHandle(); } + inline void COpenVRDriverContext::Clear() + { + m_pVRSettings = nullptr; + m_pVRProperties = nullptr; + m_pVRServerDriverHost = nullptr; + m_pVRDriverLog = nullptr; + m_pVRWatchdogHost = nullptr; + } + + inline EVRInitError COpenVRDriverContext::InitServer() + { + Clear(); + if ( !VRServerDriverHost() + || !VRSettings() + || !VRProperties() + || !VRDriverLog() ) + return VRInitError_Init_InterfaceNotFound; + return VRInitError_None; + } + + inline EVRInitError COpenVRDriverContext::InitWatchdog() + { + Clear(); + if ( !VRWatchdogHost() + || !VRSettings() + || !VRDriverLog() ) + return VRInitError_Init_InterfaceNotFound; + return VRInitError_None; + } + + inline EVRInitError InitServerDriverContext( IVRDriverContext *pContext ) + { + VRDriverContext() = pContext; + return OpenVRInternal_ModuleServerDriverContext().InitServer(); + } + + inline EVRInitError InitWatchdogDriverContext( IVRDriverContext *pContext ) + { + VRDriverContext() = pContext; + return OpenVRInternal_ModuleServerDriverContext().InitWatchdog(); + } + + inline void CleanupDriverContext() + { + VRDriverContext() = nullptr; + OpenVRInternal_ModuleServerDriverContext().Clear(); + } + + #define VR_INIT_SERVER_DRIVER_CONTEXT( pContext ) \ + { \ + vr::EVRInitError eError = vr::InitServerDriverContext( pContext ); \ + if( eError != vr::VRInitError_None ) \ + return eError; \ + } + + #define VR_CLEANUP_SERVER_DRIVER_CONTEXT() \ + vr::CleanupDriverContext(); + + #define VR_INIT_WATCHDOG_DRIVER_CONTEXT( pContext ) \ + { \ + vr::EVRInitError eError = vr::InitWatchdogDriverContext( pContext ); \ + if( eError != vr::VRInitError_None ) \ + return eError; \ + } + + #define VR_CLEANUP_WATCHDOG_DRIVER_CONTEXT() \ + vr::CleanupDriverContext(); } // End diff --git a/examples/ThirdPartyLibs/openvr/lib/linux32/libopenvr_api.so b/examples/ThirdPartyLibs/openvr/lib/linux32/libopenvr_api.so new file mode 100644 index 000000000..ccfeabae6 Binary files /dev/null and b/examples/ThirdPartyLibs/openvr/lib/linux32/libopenvr_api.so differ diff --git a/examples/ThirdPartyLibs/openvr/lib/linux64/libopenvr_api.so b/examples/ThirdPartyLibs/openvr/lib/linux64/libopenvr_api.so index 46470254e..d83a610fc 100644 Binary files a/examples/ThirdPartyLibs/openvr/lib/linux64/libopenvr_api.so and b/examples/ThirdPartyLibs/openvr/lib/linux64/libopenvr_api.so differ diff --git a/examples/ThirdPartyLibs/openvr/lib/win32/openvr_api.lib b/examples/ThirdPartyLibs/openvr/lib/win32/openvr_api.lib index 1521479a9..130bad031 100644 Binary files a/examples/ThirdPartyLibs/openvr/lib/win32/openvr_api.lib and b/examples/ThirdPartyLibs/openvr/lib/win32/openvr_api.lib differ diff --git a/examples/ThirdPartyLibs/openvr/lib/win64/openvr_api.lib b/examples/ThirdPartyLibs/openvr/lib/win64/openvr_api.lib index 9fdab5635..e8d9abf0e 100644 Binary files a/examples/ThirdPartyLibs/openvr/lib/win64/openvr_api.lib and b/examples/ThirdPartyLibs/openvr/lib/win64/openvr_api.lib differ diff --git a/examples/ThirdPartyLibs/openvr/samples/shared/compat.h b/examples/ThirdPartyLibs/openvr/samples/shared/compat.h index 0163b08f2..154f8b072 100644 --- a/examples/ThirdPartyLibs/openvr/samples/shared/compat.h +++ b/examples/ThirdPartyLibs/openvr/samples/shared/compat.h @@ -15,6 +15,7 @@ #define vsprintf_s sprintf #define _stricmp strcmp #define stricmp strcmp +#define strnicmp strncasecmp #define strcpy_s(dst, n, src) int(strncpy(dst, src, n) != nullptr) #define fopen_s(fd, path, mode) int((*fd = fopen(path, mode)) != nullptr) #define _vsnprintf_s(buffer, size, fmt, ap) vsnprintf(buffer, size, fmt, ap) @@ -24,4 +25,4 @@ typedef int errno_t; #endif // _WIN32 -#endif // OPENVR_SAMPLES_SHARED_COMPAT_H_ \ No newline at end of file +#endif // OPENVR_SAMPLES_SHARED_COMPAT_H_ diff --git a/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.cpp b/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.cpp index d148a5d84..2ea352406 100644 --- a/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.cpp +++ b/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.cpp @@ -1,22 +1,27 @@ //========= Copyright Valve Corporation ============// +#include "compat.h" +#include "strtools.h" #include "pathtools.h" -//#include "hmdplatform_private.h" -//#include "vrcommon/strtools.h" #if defined( _WIN32) #include #include #include #include -#elif defined OSX -#include -#include -#include "osxfilebridge.h" -#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet -#define _MAX_PATH MAX_PATH // yet another form of _PATH define we use -#elif defined(LINUX) +#include + +#undef GetEnvironmentVariable +#else #include #include +#include +#include +#endif +#if defined OSX +#include +#include +#include +#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet #endif #include @@ -26,44 +31,54 @@ /** Returns the path (including filename) to the current executable */ std::string Path_GetExecutablePath() { - bool bSuccess = false; - char rchPath[ 1024 ]; - size_t nBuff = sizeof(rchPath); #if defined( _WIN32 ) - bSuccess = ::GetModuleFileNameA(NULL, rchPath, (DWORD)nBuff) > 0; -#elif defined OSX - uint32_t _nBuff = nBuff; - bSuccess = _NSGetExecutablePath(rchPath, &_nBuff) == 0; - rchPath[nBuff-1] = '\0'; -#elif defined LINUX - ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 ); - if ( nRead != -1 ) - { - rchPath[ nRead ] = 0; - bSuccess = true; - } - else - { - rchPath[ 0 ] = '\0'; - } -#else - AssertMsg( false, "Implement Plat_GetExecutablePath" ); -#endif + wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH]; + char *pchPath = new char[MAX_UNICODE_PATH_IN_UTF8]; + ::GetModuleFileNameW( NULL, pwchPath, MAX_UNICODE_PATH ); + WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL ); + delete[] pwchPath; + std::string sPath = pchPath; + delete[] pchPath; + return sPath; +#elif defined( OSX ) + char rchPath[1024]; + uint32_t nBuff = sizeof( rchPath ); + bool bSuccess = _NSGetExecutablePath(rchPath, &nBuff) == 0; + rchPath[nBuff-1] = '\0'; if( bSuccess ) return rchPath; else return ""; +#elif defined LINUX + char rchPath[1024]; + size_t nBuff = sizeof( rchPath ); + ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 ); + if ( nRead != -1 ) + { + rchPath[ nRead ] = 0; + return rchPath; + } + else + { + return ""; + } +#else + AssertMsg( false, "Implement Plat_GetExecutablePath" ); + return ""; +#endif + } /** Returns the path of the current working directory */ std::string Path_GetWorkingDirectory() { std::string sPath; - char buf[ 1024 ]; #if defined( _WIN32 ) - sPath = _getcwd( buf, sizeof( buf ) ); + wchar_t buf[MAX_UNICODE_PATH]; + sPath = UTF16to8( _wgetcwd( buf, MAX_UNICODE_PATH ) ); #else + char buf[ 1024 ]; sPath = getcwd( buf, sizeof( buf ) ); #endif return sPath; @@ -74,37 +89,14 @@ bool Path_SetWorkingDirectory( const std::string & sPath ) { bool bSuccess; #if defined( _WIN32 ) - bSuccess = 0 == _chdir( sPath.c_str() ); + std::wstring wsPath = UTF8to16( sPath.c_str() ); + bSuccess = 0 == _wchdir( wsPath.c_str() ); #else bSuccess = 0 == chdir( sPath.c_str() ); #endif return bSuccess; } -std::string Path_GetModulePath() -{ -#if defined( _WIN32 ) - char path[32768]; - HMODULE hm = NULL; - - if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCSTR) &Path_GetModulePath, - &hm)) - { - int ret = GetLastError(); - fprintf(stderr, "GetModuleHandle returned %d\n", ret); - return ""; - } - GetModuleFileNameA(hm, path, sizeof(path)); - FreeLibrary( hm ); - return path; -#else - Dl_info dl_info; - dladdr((void *)Path_GetModulePath, &dl_info); - return dl_info.dli_fname; -#endif -} - /** Returns the specified path without its filename */ std::string Path_StripFilename( const std::string & sPath, char slash ) { @@ -151,17 +143,45 @@ std::string Path_StripExtension( const std::string & sPath ) return sPath; } +/** returns just extension of the provided filename (if any). */ +std::string Path_GetExtension( const std::string & sPath ) +{ + for ( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ ) + { + if ( *i == '.' ) + { + return std::string( i.base(), sPath.end() ); + } + + // if we find a slash there is no extension + if ( *i == '\\' || *i == '/' ) + break; + } + + // we didn't find an extension + return ""; +} bool Path_IsAbsolute( const std::string & sPath ) { if( sPath.empty() ) return false; - if( sPath.find( ':' ) != std::string::npos ) - return true; +#if defined( WIN32 ) + if ( sPath.size() < 3 ) // must be c:\x or \\x at least + return false; - if( sPath[0] == '\\' || sPath[0] == '/' ) + if ( sPath[1] == ':' ) // drive letter plus slash, but must test both slash cases + { + if ( sPath[2] == '\\' || sPath[2] == '/' ) + return true; + } + else if ( sPath[0] == '\\' && sPath[1] == '\\' ) // UNC path return true; +#else + if( sPath[0] == '\\' || sPath[0] == '/' ) // any leading slash + return true; +#endif return false; } @@ -223,6 +243,8 @@ std::string Path_Join( const std::string & first, const std::string & second, ch // only insert a slash if we don't already have one std::string::size_type nLen = first.length(); + if( !nLen ) + return second; #if defined(_WIN32) if( first.back() == '\\' || first.back() == '/' ) nLen--; @@ -257,6 +279,41 @@ std::string Path_Join( return Path_Join( Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash ), fifth, slash ); } + +std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash ) +{ + if ( slash == 0 ) + slash = Path_GetSlash(); + + std::string sPath = sRawPath; + std::string::size_type nCurrent = sRawPath.length(); + if ( nCurrent == 0 ) + return sPath; + + int nLastFound = -1; + nCurrent--; + while( nCurrent != 0 ) + { + if ( sRawPath[ nCurrent ] == slash ) + { + nLastFound = (int)nCurrent; + nCurrent--; + } + else + { + break; + } + } + + if ( nLastFound >= 0 ) + { + sPath.erase( nLastFound, std::string::npos ); + } + + return sPath; +} + + /** Removes redundant /.. elements in the path. Returns an empty path if the * specified path has a broken number of directories for its number of ..s */ std::string Path_Compact( const std::string & sRawPath, char slash ) @@ -336,17 +393,15 @@ std::string Path_Compact( const std::string & sRawPath, char slash ) return sPath; } -#define MAX_UNICODE_PATH 32768 -#define MAX_UNICODE_PATH_IN_UTF8 ( MAX_UNICODE_PATH * 4 ) /** Returns the path to the current DLL or exe */ -std::string GetThisModulePath() +std::string Path_GetThisModulePath() { // gets the path of vrclient.dll itself #ifdef WIN32 HMODULE hmodule = NULL; - ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(GetThisModulePath), &hmodule); + ::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast(Path_GetThisModulePath), &hmodule ); wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH]; char *pchPath = new char[ MAX_UNICODE_PATH_IN_UTF8 ]; @@ -361,7 +416,7 @@ std::string GetThisModulePath() #elif defined( OSX ) || defined( LINUX ) // get the addr of a function in vrclient.so and then ask the dlopen system about it Dl_info info; - dladdr( (void *)GetThisModulePath, &info ); + dladdr( (void *)Path_GetThisModulePath, &info ); return info.dli_fname; #endif @@ -379,19 +434,44 @@ bool Path_IsDirectory( const std::string & sPath ) sFixedPath.erase( sFixedPath.end() - 1, sFixedPath.end() ); // see if the specified path actually exists. + +#if defined(POSIX) struct stat buf; - if ( stat ( sFixedPath.c_str(), &buf ) == -1) + if ( stat( sFixedPath.c_str(), &buf ) == -1 ) { return false; } -#if defined(LINUX) +#if defined( LINUX ) || defined( OSX ) return S_ISDIR( buf.st_mode ); #else - return ( buf.st_mode & _S_IFDIR ) != 0; + return (buf.st_mode & _S_IFDIR) != 0; +#endif + +#else + struct _stat buf; + std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() ); + if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 ) + { + return false; + } + + return (buf.st_mode & _S_IFDIR) != 0; #endif } +/** returns true if the specified path represents an app bundle */ +bool Path_IsAppBundle( const std::string & sPath ) +{ +#if defined(OSX) + NSBundle *bundle = [ NSBundle bundleWithPath: [ NSString stringWithUTF8String:sPath.c_str() ] ]; + bool bisAppBundle = ( nullptr != bundle ); + [ bundle release ]; + return bisAppBundle; +#else + return false; +#endif +} //----------------------------------------------------------------------------- // Purpose: returns true if the the path exists @@ -402,11 +482,20 @@ bool Path_Exists( const std::string & sPath ) if( sFixedPath.empty() ) return false; +#if defined( WIN32 ) + struct _stat buf; + std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() ); + if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 ) + { + return false; + } +#else struct stat buf; if ( stat ( sFixedPath.c_str(), &buf ) == -1) { return false; } +#endif return true; } @@ -475,11 +564,9 @@ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize #if defined( POSIX ) f = fopen( strFilename.c_str(), "rb" ); #else - errno_t err = fopen_s(&f, strFilename.c_str(), "rb"); - if ( err != 0 ) - { - f = NULL; - } + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + // the open operation needs to be sharable, therefore use of _wfsopen instead of _wfopen_s + f = _wfsopen( wstrFilename.c_str(), L"rb", _SH_DENYNO ); #endif unsigned char* buf = NULL; @@ -508,6 +595,68 @@ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize return buf; } +uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize ) +{ + FILE *f; +#if defined( POSIX ) + f = fopen( strFilename.c_str(), "rb" ); +#else + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"rb" ); + if ( err != 0 ) + { + f = NULL; + } +#endif + + uint32_t unSizeToReturn = 0; + + if ( f != NULL ) + { + fseek( f, 0, SEEK_END ); + uint32_t size = (uint32_t)ftell( f ); + fseek( f, 0, SEEK_SET ); + + if ( size > unSize || !pBuffer ) + { + unSizeToReturn = (uint32_t)size; + } + else + { + if ( fread( pBuffer, size, 1, f ) == 1 ) + { + unSizeToReturn = (uint32_t)size; + } + } + + fclose( f ); + } + + return unSizeToReturn; +} + +bool Path_WriteBinaryFile(const std::string &strFilename, unsigned char *pData, unsigned nSize) +{ + FILE *f; +#if defined( POSIX ) + f = fopen(strFilename.c_str(), "wb"); +#else + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"wb" ); + if (err != 0) + { + f = NULL; + } +#endif + + size_t written = 0; + if (f != NULL) { + written = fwrite(pData, sizeof(unsigned char), nSize, f); + fclose(f); + } + + return written = nSize ? true : false; +} std::string Path_ReadTextFile( const std::string &strFilename ) { @@ -520,7 +669,7 @@ std::string Path_ReadTextFile( const std::string &strFilename ) return ""; // convert CRLF -> LF - int outsize = 1; + size_t outsize = 1; for (int i=1; i < size; i++) { if (buf[i] == '\n' && buf[i-1] == '\r') // CRLF @@ -529,7 +678,7 @@ std::string Path_ReadTextFile( const std::string &strFilename ) buf[outsize++] = buf[i]; // just copy } - std::string ret((char *)buf, (char *)(buf + outsize)); + std::string ret((char *)buf, outsize); delete[] buf; return ret; } @@ -541,7 +690,8 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch #if defined( POSIX ) f = fopen( strFilename.c_str(), "w" ); #else - errno_t err = fopen_s(&f, strFilename.c_str(), "w"); + std::wstring wstrFilename = UTF8to16( strFilename.c_str() ); + errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"w" ); if ( err != 0 ) { f = NULL; @@ -557,4 +707,113 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch } return ok; -} \ No newline at end of file +} + +bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData ) +{ + std::string strTmpFilename = strFilename + ".tmp"; + + if ( !Path_WriteStringToTextFile( strTmpFilename, pchData ) ) + return false; + + // Platform specific atomic file replacement +#if defined( _WIN32 ) + std::wstring wsFilename = UTF8to16( strFilename.c_str() ); + std::wstring wsTmpFilename = UTF8to16( strTmpFilename.c_str() ); + if ( !::ReplaceFileW( wsFilename.c_str(), wsTmpFilename.c_str(), nullptr, 0, 0, 0 ) ) + { + // if we couldn't ReplaceFile, try a non-atomic write as a fallback + if ( !Path_WriteStringToTextFile( strFilename, pchData ) ) + return false; + } +#elif defined( POSIX ) + if ( rename( strTmpFilename.c_str(), strFilename.c_str() ) == -1 ) + return false; +#else +#error Do not know how to write atomic file +#endif + + return true; +} + + +#if defined(WIN32) +#define FILE_URL_PREFIX "file:///" +#else +#define FILE_URL_PREFIX "file://" +#endif + +// ---------------------------------------------------------------------------------------------------------------------------- +// Purpose: Turns a path to a file on disk into a URL (or just returns the value if it's already a URL) +// ---------------------------------------------------------------------------------------------------------------------------- +std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath ) +{ + if ( !strnicmp( sRelativePath.c_str(), "http://", 7 ) + || !strnicmp( sRelativePath.c_str(), "https://", 8 ) + || !strnicmp( sRelativePath.c_str(), "file://", 7 ) ) + { + return sRelativePath; + } + else + { + std::string sAbsolute = Path_MakeAbsolute( sRelativePath, sBasePath ); + if ( sAbsolute.empty() ) + return sAbsolute; + return std::string( FILE_URL_PREFIX ) + sAbsolute; + } +} + +// ----------------------------------------------------------------------------------------------------- +// Purpose: Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned +// ----------------------------------------------------------------------------------------------------- +std::string Path_UrlToFilePath( const std::string & sFileUrl ) +{ + if ( !strnicmp( sFileUrl.c_str(), FILE_URL_PREFIX, strlen( FILE_URL_PREFIX ) ) ) + { + return sFileUrl.c_str() + strlen( FILE_URL_PREFIX ); + } + else + { + return ""; + } +} + + +// ----------------------------------------------------------------------------------------------------- +// Purpose: Returns the root of the directory the system wants us to store user documents in +// ----------------------------------------------------------------------------------------------------- +std::string GetUserDocumentsPath() +{ +#if defined( WIN32 ) + WCHAR rwchPath[MAX_PATH]; + + if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) ) + { + return ""; + } + + // Convert the path to UTF-8 and store in the output + std::string sUserPath = UTF16to8( rwchPath ); + + return sUserPath; +#elif defined( OSX ) + @autoreleasepool { + NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES ); + if ( [paths count] == 0 ) + { + return ""; + } + + return [[paths objectAtIndex:0] UTF8String]; + } +#elif defined( LINUX ) + // @todo: not solved/changed as part of OSX - still not real - just removed old class based steam cut and paste + const char *pchHome = getenv( "HOME" ); + if ( pchHome == NULL ) + { + return ""; + } + return pchHome; +#endif +} + diff --git a/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.h b/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.h index c38ec5612..7c34a7175 100644 --- a/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.h +++ b/examples/ThirdPartyLibs/openvr/samples/shared/pathtools.h @@ -2,6 +2,7 @@ #pragma once #include +#include /** Returns the path (including filename) to the current executable */ std::string Path_GetExecutablePath(); @@ -13,7 +14,7 @@ std::string Path_GetWorkingDirectory(); bool Path_SetWorkingDirectory( const std::string & sPath ); /** returns the path (including filename) of the current shared lib or DLL */ -std::string Path_GetModulePath(); +std::string Path_GetThisModulePath(); /** Returns the specified path without its filename. * If slash is unspecified the native path separator of the current platform @@ -27,6 +28,9 @@ std::string Path_StripDirectory( const std::string & sPath, char slash = 0 ); * If there is a path the path is left intact. */ std::string Path_StripExtension( const std::string & sPath ); +/** returns just extension of the provided filename (if any). */ +std::string Path_GetExtension( const std::string & sPath ); + /** Returns true if the path is absolute */ bool Path_IsAbsolute( const std::string & sPath ); @@ -60,11 +64,14 @@ std::string Path_Join( * will be used. */ std::string Path_Compact( const std::string & sRawPath, char slash = 0 ); +//** Removed trailing slashes */ +std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 ); + /** returns true if the specified path exists and is a directory */ bool Path_IsDirectory( const std::string & sPath ); -/** Returns the path to the current DLL or exe */ -std::string GetThisModulePath(); +/** returns true if the specified path represents an app bundle */ +bool Path_IsAppBundle( const std::string & sPath ); /** returns true if the the path exists */ bool Path_Exists( const std::string & sPath ); @@ -75,11 +82,31 @@ std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartD /** Path operations to read or write text/binary files */ unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize ); +uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize ); +bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize ); std::string Path_ReadTextFile( const std::string &strFilename ); bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData ); +bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData ); + +/** Returns a file:// url for paths, or an http or https url if that's what was provided */ +std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath ); + +/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */ +std::string Path_UrlToFilePath( const std::string & sFileUrl ); + +/** Returns the root of the directory the system wants us to store user documents in */ +std::string GetUserDocumentsPath(); + +#ifndef MAX_UNICODE_PATH + #define MAX_UNICODE_PATH 32767 +#endif + +#ifndef MAX_UNICODE_PATH_IN_UTF8 + #define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4) +#endif //----------------------------------------------------------------------------- -#if defined(_WIN32) +#if defined(WIN32) #define DYNAMIC_LIB_EXT ".dll" #ifdef _WIN64 #define PLATSUBDIR "win64" @@ -91,8 +118,12 @@ bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pch #define PLATSUBDIR "osx32" #elif defined(LINUX) #define DYNAMIC_LIB_EXT ".so" +#if defined( LINUX32 ) #define PLATSUBDIR "linux32" #else +#define PLATSUBDIR "linux64" +#endif +#else #warning "Unknown platform for PLATSUBDIR" #define PLATSUBDIR "unknown_platform" #endif diff --git a/examples/ThirdPartyLibs/openvr/samples/shared/strtools.cpp b/examples/ThirdPartyLibs/openvr/samples/shared/strtools.cpp new file mode 100644 index 000000000..6166db483 --- /dev/null +++ b/examples/ThirdPartyLibs/openvr/samples/shared/strtools.cpp @@ -0,0 +1,437 @@ +//========= Copyright Valve Corporation ============// +#include "strtools.h" +#include +#include +#include + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool StringHasPrefix( const std::string & sString, const std::string & sPrefix ) +{ + return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() ); +} + +bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix ) +{ + return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() ); +} + + +bool StringHasSuffix( const std::string &sString, const std::string &sSuffix ) +{ + size_t cStrLen = sString.length(); + size_t cSuffixLen = sSuffix.length(); + + if ( cSuffixLen > cStrLen ) + return false; + + std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen ); + + return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() ); +} + +bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix ) +{ + size_t cStrLen = sString.length(); + size_t cSuffixLen = sSuffix.length(); + + if ( cSuffixLen > cStrLen ) + return false; + + std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen ); + + return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +std::string UTF16to8(const wchar_t * in) +{ + std::string out; + unsigned int codepoint = 0; + for ( ; in && *in != 0; ++in ) + { + if (*in >= 0xd800 && *in <= 0xdbff) + codepoint = ((*in - 0xd800) << 10) + 0x10000; + else + { + if (*in >= 0xdc00 && *in <= 0xdfff) + codepoint |= *in - 0xdc00; + else + codepoint = *in; + + if (codepoint <= 0x7f) + out.append(1, static_cast(codepoint)); + else if (codepoint <= 0x7ff) + { + out.append(1, static_cast(0xc0 | ((codepoint >> 6) & 0x1f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + else if (codepoint <= 0xffff) + { + out.append(1, static_cast(0xe0 | ((codepoint >> 12) & 0x0f))); + out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + else + { + out.append(1, static_cast(0xf0 | ((codepoint >> 18) & 0x07))); + out.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3f))); + out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + codepoint = 0; + } + } + return out; +} + +std::wstring UTF8to16(const char * in) +{ + std::wstring out; + unsigned int codepoint = 0; + int following = 0; + for ( ; in && *in != 0; ++in ) + { + unsigned char ch = *in; + if (ch <= 0x7f) + { + codepoint = ch; + following = 0; + } + else if (ch <= 0xbf) + { + if (following > 0) + { + codepoint = (codepoint << 6) | (ch & 0x3f); + --following; + } + } + else if (ch <= 0xdf) + { + codepoint = ch & 0x1f; + following = 1; + } + else if (ch <= 0xef) + { + codepoint = ch & 0x0f; + following = 2; + } + else + { + codepoint = ch & 0x07; + following = 3; + } + if (following == 0) + { + if (codepoint > 0xffff) + { + out.append(1, static_cast(0xd800 + (codepoint >> 10))); + out.append(1, static_cast(0xdc00 + (codepoint & 0x03ff))); + } + else + out.append(1, static_cast(codepoint)); + codepoint = 0; + } + } + return out; +} + + +void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource ) +{ + pchBuffer[ unBufferSizeBytes - 1 ] = '\0'; + strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 ); +} + + +// -------------------------------------------------------------------- +// Purpose: converts a string to upper case +// -------------------------------------------------------------------- +std::string StringToUpper( const std::string & sString ) +{ + std::string sOut; + sOut.reserve( sString.size() + 1 ); + for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ ) + { + sOut.push_back( (char)toupper( *i ) ); + } + + return sOut; +} + + +// -------------------------------------------------------------------- +// Purpose: converts a string to lower case +// -------------------------------------------------------------------- +std::string StringToLower( const std::string & sString ) +{ + std::string sOut; + sOut.reserve( sString.size() + 1 ); + for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ ) + { + sOut.push_back( (char)tolower( *i ) ); + } + + return sOut; +} + + +uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen ) +{ + uint32_t unLen = (uint32_t)sValue.length() + 1; + if( !pchBuffer || !unBufferLen ) + return unLen; + + if( unBufferLen < unLen ) + { + pchBuffer[0] = '\0'; + } + else + { + memcpy( pchBuffer, sValue.c_str(), unLen ); + } + + return unLen; +} + +void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen ) +{ + sDest.resize( unBufferLen + 1 ); + memcpy( const_cast< char* >( sDest.c_str() ), pchBuffer, unBufferLen ); + const_cast< char* >( sDest.c_str() )[ unBufferLen ] = '\0'; +} + +/** Returns a std::string from a uint64_t */ +std::string Uint64ToString( uint64_t ulValue ) +{ + char buf[ 22 ]; +#if defined( _WIN32 ) + sprintf_s( buf, "%llu", ulValue ); +#else + snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue ); +#endif + return buf; +} + + +/** returns a uint64_t from a string */ +uint64_t StringToUint64( const std::string & sValue ) +{ + return strtoull( sValue.c_str(), NULL, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15. +//----------------------------------------------------------------------------- +char cIntToHexDigit( int nValue ) +{ + //Assert( nValue >= 0 && nValue <= 15 ); + return "0123456789ABCDEF"[ nValue & 15 ]; +} + +//----------------------------------------------------------------------------- +// Purpose: Helper for converting a hex char value to numeric, return -1 if the char +// is not a valid hex digit. +//----------------------------------------------------------------------------- +int iHexCharToInt( char cValue ) +{ + int32_t iValue = cValue; + if ( (uint32_t)( iValue - '0' ) < 10 ) + return iValue - '0'; + + iValue |= 0x20; + if ( (uint32_t)( iValue - 'a' ) < 6 ) + return iValue - 'a' + 10; + + return -1; +} + +//----------------------------------------------------------------------------- +// Purpose: Internal implementation of encode, works in the strict RFC manner, or +// with spaces turned to + like HTML form encoding. +//----------------------------------------------------------------------------- +void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace ) +{ + //AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" ); + + int iDestPos = 0; + for ( int i=0; i < nSourceLen; ++i ) + { + // worst case we need 3 additional chars + if( (iDestPos+3) > nDestLen ) + { + pchDest[0] = '\0'; +// AssertMsg( false, "Target buffer too short\n" ); + return; + } + + // We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped. + // These are the characters allowed by both the original RFC 1738 and the latest RFC 3986. + // Current specs also allow '~', but that is forbidden under original RFC 1738. + if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' ) + && pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.' + ) + { + if ( bUsePlusForSpace && pchSource[i] == ' ' ) + { + pchDest[iDestPos++] = '+'; + } + else + { + pchDest[iDestPos++] = '%'; + uint8_t iValue = pchSource[i]; + if ( iValue == 0 ) + { + pchDest[iDestPos++] = '0'; + pchDest[iDestPos++] = '0'; + } + else + { + char cHexDigit1 = cIntToHexDigit( iValue % 16 ); + iValue /= 16; + char cHexDigit2 = cIntToHexDigit( iValue ); + pchDest[iDestPos++] = cHexDigit2; + pchDest[iDestPos++] = cHexDigit1; + } + } + } + else + { + pchDest[iDestPos++] = pchSource[i]; + } + } + + if( (iDestPos+1) > nDestLen ) + { + pchDest[0] = '\0'; + //AssertMsg( false, "Target buffer too short to terminate\n" ); + return; + } + + // Null terminate + pchDest[iDestPos++] = 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Internal implementation of decode, works in the strict RFC manner, or +// with spaces turned to + like HTML form encoding. +// +// Returns the amount of space used in the output buffer. +//----------------------------------------------------------------------------- +size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace ) +{ + if ( nDecodeDestLen < nEncodedSourceLen ) + { + //AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" ); + return 0; + } + + int iDestPos = 0; + for( int i=0; i < nEncodedSourceLen; ++i ) + { + if ( bUsePlusForSpace && pchEncodedSource[i] == '+' ) + { + pchDecodeDest[ iDestPos++ ] = ' '; + } + else if ( pchEncodedSource[i] == '%' ) + { + // Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that + + // First make sure we have 2 more chars + if ( i < nEncodedSourceLen - 2 ) + { + char cHexDigit1 = pchEncodedSource[i+1]; + char cHexDigit2 = pchEncodedSource[i+2]; + + // Turn the chars into a hex value, if they are not valid, then we'll + // just place the % and the following two chars direct into the string, + // even though this really shouldn't happen, who knows what bad clients + // may do with encoding. + bool bValid = false; + int iValue = iHexCharToInt( cHexDigit1 ); + if ( iValue != -1 ) + { + iValue *= 16; + int iValue2 = iHexCharToInt( cHexDigit2 ); + if ( iValue2 != -1 ) + { + iValue += iValue2; + pchDecodeDest[ iDestPos++ ] = (char)iValue; + bValid = true; + } + } + + if ( !bValid ) + { + pchDecodeDest[ iDestPos++ ] = '%'; + pchDecodeDest[ iDestPos++ ] = cHexDigit1; + pchDecodeDest[ iDestPos++ ] = cHexDigit2; + } + } + + // Skip ahead + i += 2; + } + else + { + pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i]; + } + } + + // We may not have extra room to NULL terminate, since this can be used on raw data, but if we do + // go ahead and do it as this can avoid bugs. + if ( iDestPos < nDecodeDestLen ) + { + pchDecodeDest[iDestPos] = 0; + } + + return (size_t)iDestPos; +} + +//----------------------------------------------------------------------------- +// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +//----------------------------------------------------------------------------- +void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ) +{ + return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed. +//----------------------------------------------------------------------------- +size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen ) +{ + return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true ); +} + +//----------------------------------------------------------------------------- +void V_StripExtension( std::string &in ) +{ + // Find the last dot. If it's followed by a dot or a slash, then it's part of a + // directory specifier like ../../somedir/./blah. + std::string::size_type test = in.rfind( '.' ); + if ( test != std::string::npos ) + { + // This handles things like ".\blah" or "c:\my@email.com\abc\def\geh" + // Which would otherwise wind up with "" and "c:\my@email", respectively. + if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test ) + { + in.resize( test ); + } + } +} + diff --git a/examples/ThirdPartyLibs/openvr/samples/shared/strtools.h b/examples/ThirdPartyLibs/openvr/samples/shared/strtools.h new file mode 100644 index 000000000..b69ef15dc --- /dev/null +++ b/examples/ThirdPartyLibs/openvr/samples/shared/strtools.h @@ -0,0 +1,130 @@ +//========= Copyright Valve Corporation ============// +#pragma once + +#include +#include +#include + +/** returns true if the string has the prefix */ +bool StringHasPrefix( const std::string & sString, const std::string & sPrefix ); +bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix ); + +/** returns if the string has the suffix */ +bool StringHasSuffix( const std::string &sString, const std::string &sSuffix ); +bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix ); + +/** converts a UTF-16 string to a UTF-8 string */ +std::string UTF16to8(const wchar_t * in); + +/** converts a UTF-8 string to a UTF-16 string */ +std::wstring UTF8to16(const char * in); +#define Utf16FromUtf8 UTF8to16 + +/** safely copy a string into a buffer */ +void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource ); +template< size_t bufferSize > +void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource ) +{ + strcpy_safe( buffer, bufferSize, pchSource ); +} + + +/** converts a string to upper case */ +std::string StringToUpper( const std::string & sString ); + +/** converts a string to lower case */ +std::string StringToLower( const std::string & sString ); + +// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it +#if defined( OSX ) || defined( LINUX ) +#include +inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); } +#ifndef _stricmp +#define _stricmp stricmp +#endif +inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); } +#define _strnicmp strnicmp + +#ifndef _vsnprintf_s +#define _vsnprintf_s vsnprintf +#endif + +#define _TRUNCATE ((size_t)-1) + +#endif + +#if defined( OSX ) +// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but +// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not. +inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count) +{ + return wcslcpy(strDest, strSource, numberOfElements); +} + +inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count) +{ + return strlcpy(strDest, strSource, numberOfElements); +} + +#endif + +#if defined( LINUX ) +// this implementation does not return whether or not the destination was +// truncated, but that is straightforward to fix if anybody actually needs the +// return code. +#include "string.h" +inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count) +{ + wcsncpy(strDest, strSource, numberOfElements); + strDest[numberOfElements-1] = '\0'; +} + +inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count) +{ + strncpy(strDest, strSource, numberOfElements); + strDest[numberOfElements-1] = '\0'; +} + +#endif + +#if defined( _WIN32 ) && _MSC_VER < 1800 +inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); } +#endif + +/* Handles copying a std::string into a buffer as would be provided in an API */ +uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen ); + +/* Handles copying a buffer into an std::string and auto adds null terminator */ +void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen ); + +/** Returns a std::string from a uint64_t */ +std::string Uint64ToString( uint64_t ulValue ); + +/** returns a uint64_t from a string */ +uint64_t StringToUint64( const std::string & sValue ); + +//----------------------------------------------------------------------------- +// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +//----------------------------------------------------------------------------- +void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen ); + +//----------------------------------------------------------------------------- +// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2. +// This version of the call isn't a strict RFC implementation, but uses + for space as is +// the standard in HTML form encoding, despite it not being part of the RFC. +// +// Dest buffer should be at least as large as source buffer to guarantee room for decode. +// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed. +//----------------------------------------------------------------------------- +size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen ); + +//----------------------------------------------------------------------------- +// Purpose: strip extension from a path +//----------------------------------------------------------------------------- +void V_StripExtension( std::string &in ); + + diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 3fb92f323..aaa173924 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -757,7 +757,7 @@ static PyObject* pybullet_loadURDF(PyObject* self, PyObject* args, PyObject* key double startOrnY = 0.0; double startOrnZ = 0.0; double startOrnW = 1.0; - int useMaximalCoordinates = 0; + int useMaximalCoordinates = -1; int useFixedBase = 0; int backwardsCompatibilityArgs = 0; @@ -845,9 +845,9 @@ static PyObject* pybullet_loadURDF(PyObject* self, PyObject* args, PyObject* key b3LoadUrdfCommandSetStartPosition(command, startPosX, startPosY, startPosZ); b3LoadUrdfCommandSetStartOrientation(command, startOrnX, startOrnY, startOrnZ, startOrnW); - if (useMaximalCoordinates) + if (useMaximalCoordinates>=0) { - b3LoadUrdfCommandSetUseMultiBody(command, 0); + b3LoadUrdfCommandSetUseMultiBody(command, useMaximalCoordinates); } if (useFixedBase) { @@ -1738,6 +1738,40 @@ static PyObject* pybullet_getBodyUniqueId(PyObject* self, PyObject* args, PyObje } } +static PyObject* pybullet_removeBody(PyObject* self, PyObject* args, PyObject* keywds) +{ + { + int bodyUniqueId = -1; + b3PhysicsClientHandle sm = 0; + + int physicsClientId = 0; + static char* kwlist[] = {"bodyUniqueId", "physicsClientId", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|i", kwlist, &bodyUniqueId, &physicsClientId)) + { + return NULL; + } + sm = getPhysicsClient(physicsClientId); + if (sm == 0) + { + PyErr_SetString(SpamError, "Not connected to physics server."); + return NULL; + } + if (bodyUniqueId>=0) + { + b3SharedMemoryStatusHandle statusHandle; + int statusType; + if (b3CanSubmitCommand(sm)) + { + statusHandle = b3SubmitClientCommandAndWaitStatus( sm, b3InitRemoveBodyCommand(sm,bodyUniqueId)); + statusType = b3GetStatusType(statusHandle); + } + } + } + + Py_INCREF(Py_None); + return Py_None; +} + static PyObject* pybullet_getBodyInfo(PyObject* self, PyObject* args, PyObject* keywds) { { @@ -5460,6 +5494,9 @@ static PyMethodDef SpamMethods[] = { {"getBodyInfo", (PyCFunction)pybullet_getBodyInfo, METH_VARARGS | METH_KEYWORDS, "Get the body info, given a body unique id."}, + {"removeBody", (PyCFunction)pybullet_removeBody, METH_VARARGS | METH_KEYWORDS, + "Remove a body by its body unique id."}, + {"getNumConstraints", (PyCFunction)pybullet_getNumConstraints, METH_VARARGS | METH_KEYWORDS, "Get the number of user-created constraints in the simulation."}, diff --git a/src/Bullet3Common/b3ResizablePool.h b/src/Bullet3Common/b3ResizablePool.h new file mode 100644 index 000000000..06ad8a778 --- /dev/null +++ b/src/Bullet3Common/b3ResizablePool.h @@ -0,0 +1,182 @@ + +#ifndef B3_RESIZABLE_POOL_H +#define B3_RESIZABLE_POOL_H + +#include "Bullet3Common/b3AlignedObjectArray.h" + +enum +{ + B3_POOL_HANDLE_TERMINAL_FREE=-1, + B3_POOL_HANDLE_TERMINAL_USED =-2 +}; + +template +struct b3PoolBodyHandle : public U +{ + B3_DECLARE_ALIGNED_ALLOCATOR(); + + int m_nextFreeHandle; + void setNextFree(int next) + { + m_nextFreeHandle = next; + } + int getNextFree() const + { + return m_nextFreeHandle; + } +}; + +template +class b3ResizablePool +{ + +protected: + b3AlignedObjectArray m_bodyHandles; + int m_numUsedHandles; // number of active handles + int m_firstFreeHandle; // free handles list + + T* getHandleInternal(int handle) + { + return &m_bodyHandles[handle]; + + } + const T* getHandleInternal(int handle) const + { + return &m_bodyHandles[handle]; + } + +public: + + b3ResizablePool() + { + initHandles(); + } + + virtual ~b3ResizablePool() + { + exitHandles(); + } +///handle management + + int getNumHandles() const + { + return m_bodyHandles.size(); + } + + void getUsedHandles(b3AlignedObjectArray& usedHandles) const + { + + for (int i=0;i=0); + b3Assert(handle=m_bodyHandles.size())) + { + return 0; + } + + if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED) + { + return &m_bodyHandles[handle]; + } + return 0; + + } + const T* getHandle(int handle) const + { + b3Assert(handle>=0); + b3Assert(handle=m_bodyHandles.size())) + { + return 0; + } + + if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED) + { + return &m_bodyHandles[handle]; + } + return 0; + } + + void increaseHandleCapacity(int extraCapacity) + { + int curCapacity = m_bodyHandles.size(); + //b3Assert(curCapacity == m_numUsedHandles); + int newCapacity = curCapacity + extraCapacity; + m_bodyHandles.resize(newCapacity); + + { + for (int i = curCapacity; i < newCapacity; i++) + m_bodyHandles[i].setNextFree(i + 1); + + + m_bodyHandles[newCapacity - 1].setNextFree(-1); + } + m_firstFreeHandle = curCapacity; + } + void initHandles() + { + m_numUsedHandles = 0; + m_firstFreeHandle = -1; + + increaseHandleCapacity(1); + } + + void exitHandles() + { + m_bodyHandles.resize(0); + m_firstFreeHandle = -1; + m_numUsedHandles = 0; + } + + int allocHandle() + { + b3Assert(m_firstFreeHandle>=0); + + int handle = m_firstFreeHandle; + m_firstFreeHandle = getHandleInternal(handle)->getNextFree(); + m_numUsedHandles++; + + if (m_firstFreeHandle<0) + { + //int curCapacity = m_bodyHandles.size(); + int additionalCapacity= m_bodyHandles.size(); + increaseHandleCapacity(additionalCapacity); + + + getHandleInternal(handle)->setNextFree(m_firstFreeHandle); + } + getHandleInternal(handle)->setNextFree(B3_POOL_HANDLE_TERMINAL_USED); + getHandleInternal(handle)->clear(); + return handle; + } + + + void freeHandle(int handle) + { + b3Assert(handle >= 0); + + if (m_bodyHandles[handle].getNextFree()==B3_POOL_HANDLE_TERMINAL_USED) + { + getHandleInternal(handle)->clear(); + getHandleInternal(handle)->setNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + m_numUsedHandles--; + } + } +}; + ///end handle management + + #endif //B3_RESIZABLE_POOL_H + \ No newline at end of file