From ffc808784b6e140cff62ea22a6bde2c845fe6f19 Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Wed, 11 Apr 2018 01:03:36 -0700 Subject: [PATCH] PyBullet: add planar reflection example, See examples/pybullet/examples/addPlanarReflection.py --- data/plane_transparent.mtl | 2 +- data/plane_transparent.obj | 6 +- data/plane_transparent.urdf | 2 +- .../CommonInterfaces/CommonRenderInterface.h | 3 + examples/ExampleBrowser/OpenGLGuiHelper.cpp | 4 + .../OpenGLWindow/GLInstancingRenderer.cpp | 65 ++++++++++++++-- examples/OpenGLWindow/GLInstancingRenderer.h | 4 + examples/SharedMemory/SharedMemoryPublic.h | 1 + .../pybullet/examples/addPlanarReflection.py | 75 +++++++++++++++++++ .../pybullet/examples/createVisualShape.py | 6 +- examples/pybullet/pybullet.c | 2 + 11 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 examples/pybullet/examples/addPlanarReflection.py diff --git a/data/plane_transparent.mtl b/data/plane_transparent.mtl index 6b700a066..8ce3f6b30 100644 --- a/data/plane_transparent.mtl +++ b/data/plane_transparent.mtl @@ -9,6 +9,6 @@ newmtl Material Kd 0.5880 0.5880 0.5880 Ks 0.0000 0.0000 0.0000 Ke 0.0000 0.0000 0.0000 - map_Kd tex4x4.png + map_Kd checker_blue.png diff --git a/data/plane_transparent.obj b/data/plane_transparent.obj index b1317066e..02e572bcc 100644 --- a/data/plane_transparent.obj +++ b/data/plane_transparent.obj @@ -7,9 +7,9 @@ v 15.000000 15.000000 0.000000 v -15.000000 15.000000 0.000000 v -15.000000 -15.000000 0.000000 -vt 1.000000 0.000000 -vt 1.000000 1.000000 -vt 0.000000 1.000000 +vt 15.000000 0.000000 +vt 15.000000 15.000000 +vt 0.000000 15.000000 vt 0.000000 0.000000 usemtl Material diff --git a/data/plane_transparent.urdf b/data/plane_transparent.urdf index 1634fd4b7..15deeac4a 100644 --- a/data/plane_transparent.urdf +++ b/data/plane_transparent.urdf @@ -12,7 +12,7 @@ - + diff --git a/examples/CommonInterfaces/CommonRenderInterface.h b/examples/CommonInterfaces/CommonRenderInterface.h index a64fe7dde..4401f96e7 100644 --- a/examples/CommonInterfaces/CommonRenderInterface.h +++ b/examples/CommonInterfaces/CommonRenderInterface.h @@ -16,6 +16,7 @@ enum B3_CREATE_SHADOWMAP_RENDERMODE, B3_USE_SHADOWMAP_RENDERMODE, B3_USE_SHADOWMAP_RENDERMODE_REFLECTION, + B3_USE_SHADOWMAP_RENDERMODE_REFLECTION_PLANE, B3_USE_PROJECTIVE_TEXTURE_RENDERMODE, }; @@ -77,6 +78,8 @@ struct CommonRenderInterface virtual void replaceTexture(int shapeIndex, int textureIndex){}; virtual void removeTexture(int textureIndex) = 0; + virtual void setPlaneReflectionShapeIndex(int index) {} + virtual int getShapeIndexFromInstance(int srcIndex) {return -1;} virtual bool readSingleInstanceTransformToCPU(float* position, float* orientation, int srcIndex)=0; diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp index 71970893a..b21aae329 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp +++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp @@ -1026,6 +1026,10 @@ void OpenGLGuiHelper::setVisualizerFlagCallback(VisualizerFlagCallback callback) void OpenGLGuiHelper::setVisualizerFlag(int flag, int enable) { + if (getRenderInterface() && flag==16)//COV_ENABLE_PLANAR_REFLECTION + { + getRenderInterface()->setPlaneReflectionShapeIndex(enable); + } if (m_data->m_visualizerFlagCallback) (m_data->m_visualizerFlagCallback)(flag,enable); } diff --git a/examples/OpenGLWindow/GLInstancingRenderer.cpp b/examples/OpenGLWindow/GLInstancingRenderer.cpp index 5d91a3bb6..7ac53b636 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.cpp +++ b/examples/OpenGLWindow/GLInstancingRenderer.cpp @@ -361,7 +361,8 @@ GLInstancingRenderer::GLInstancingRenderer(int maxNumObjectCapacity, int maxShap m_textureinitialized(false), m_screenWidth(0), m_screenHeight(0), - m_upAxis(1) + m_upAxis(1), + m_planeReflectionShapeIndex(-1) { m_data = new InternalDataRenderer; @@ -1597,13 +1598,44 @@ void GLInstancingRenderer::renderScene() { renderSceneInternal(B3_CREATE_SHADOWMAP_RENDERMODE); - //glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - //renderSceneInternal(B3_USE_SHADOWMAP_RENDERMODE_REFLECTION); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + if (m_planeReflectionShapeIndex>=0) + { + /* Don't update color or depth. */ + glDisable(GL_DEPTH_TEST); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* Draw 1 into the stencil buffer. */ + glEnable(GL_STENCIL_TEST); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xffffffff); + + /* Now render floor; floor pixels just get their stencil set to 1. */ + renderSceneInternal(B3_USE_SHADOWMAP_RENDERMODE_REFLECTION_PLANE); + + /* Re-enable update of color and depth. */ + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glEnable(GL_DEPTH_TEST); + + /* Now, only render where stencil is set to 1. */ + glStencilFunc(GL_EQUAL, 1, 0xffffffff); /* draw if ==1 */ + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + //draw the reflection objects + renderSceneInternal(B3_USE_SHADOWMAP_RENDERMODE_REFLECTION); + + glDisable(GL_STENCIL_TEST); + } + renderSceneInternal(B3_USE_SHADOWMAP_RENDERMODE); + + } else if (m_data->m_useProjectiveTexture) { + renderSceneInternal(B3_USE_PROJECTIVE_TEXTURE_RENDERMODE); } else @@ -2040,6 +2072,13 @@ void GLInstancingRenderer::renderSceneInternal(int orgRenderMode) { int renderMode=orgRenderMode; bool reflectionPass = false; + bool reflectionPlanePass = false; + + if (orgRenderMode==B3_USE_SHADOWMAP_RENDERMODE_REFLECTION_PLANE) + { + reflectionPlanePass = true; + renderMode = B3_USE_SHADOWMAP_RENDERMODE; + } if (orgRenderMode==B3_USE_SHADOWMAP_RENDERMODE_REFLECTION) { reflectionPass = true; @@ -2085,8 +2124,8 @@ void GLInstancingRenderer::renderSceneInternal(int orgRenderMode) //GLfloat depthModelViewMatrix2[4][4]; // For projective texture mapping - float textureProjectionMatrix[4][4]; - GLfloat textureModelViewMatrix[4][4]; + //float textureProjectionMatrix[4][4]; + //GLfloat textureModelViewMatrix[4][4]; // Compute the MVP matrix from the light's point of view if (renderMode==B3_CREATE_SHADOWMAP_RENDERMODE) @@ -2254,6 +2293,7 @@ b3Assert(glGetError() ==GL_NO_ERROR); for (int obj=0;objm_numGraphicsInstances) { SortableTransparentInstance inst; @@ -2300,9 +2340,13 @@ b3Assert(glGetError() ==GL_NO_ERROR); { for (int i=0;im_defaultTexturehandle; } - //disable lazy evaluation, it just leads to bugs + //disable lazy evaluation, it just leads to bugs //if (lastBindTexture != curBindTexture) { glBindTexture(GL_TEXTURE_2D,curBindTexture); @@ -2503,6 +2547,8 @@ b3Assert(glGetError() ==GL_NO_ERROR); float MVP[16]; if (reflectionPass) { + //todo: create an API to select this reflection matrix, to allow + //reflection planes different from Z-axis up through (0,0,0) float tmp[16]; float reflectionMatrix[16] = {1,0,0,0, 0,1,0,0, @@ -2669,6 +2715,11 @@ void GLInstancingRenderer::CleanupShaders() { } +void GLInstancingRenderer::setPlaneReflectionShapeIndex(int index) +{ + m_planeReflectionShapeIndex = index; +} + void GLInstancingRenderer::enableShadowMap() { glActiveTexture(GL_TEXTURE0); diff --git a/examples/OpenGLWindow/GLInstancingRenderer.h b/examples/OpenGLWindow/GLInstancingRenderer.h index 310d4f03f..b376cdd8d 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.h +++ b/examples/OpenGLWindow/GLInstancingRenderer.h @@ -39,6 +39,8 @@ class GLInstancingRenderer : public CommonRenderInterface int m_screenHeight; int m_upAxis; + + int m_planeReflectionShapeIndex; int registerGraphicsInstanceInternal(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); @@ -151,6 +153,8 @@ public: virtual int getTotalNumInstances() const; virtual void enableShadowMap(); + + virtual void setPlaneReflectionShapeIndex(int index); virtual void clearZBuffer(); diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h index c1b3b96c3..22623a93f 100644 --- a/examples/SharedMemory/SharedMemoryPublic.h +++ b/examples/SharedMemory/SharedMemoryPublic.h @@ -648,6 +648,7 @@ enum b3ConfigureDebugVisualizerEnum COV_ENABLE_RGB_BUFFER_PREVIEW, COV_ENABLE_DEPTH_BUFFER_PREVIEW, COV_ENABLE_SEGMENTATION_MARK_PREVIEW, + COV_ENABLE_PLANAR_REFLECTION, }; diff --git a/examples/pybullet/examples/addPlanarReflection.py b/examples/pybullet/examples/addPlanarReflection.py new file mode 100644 index 000000000..419789e90 --- /dev/null +++ b/examples/pybullet/examples/addPlanarReflection.py @@ -0,0 +1,75 @@ +import pybullet as p +import time +import math + +def getRayFromTo(mouseX,mouseY): + width, height, viewMat, projMat, cameraUp, camForward, horizon,vertical, _,_,dist, camTarget = p.getDebugVisualizerCamera() + camPos = [camTarget[0] - dist*camForward[0],camTarget[1] - dist*camForward[1],camTarget[2] - dist*camForward[2]] + farPlane = 10000 + rayForward = [(camTarget[0]-camPos[0]),(camTarget[1]-camPos[1]),(camTarget[2]-camPos[2])] + invLen = farPlane*1./(math.sqrt(rayForward[0]*rayForward[0]+rayForward[1]*rayForward[1]+rayForward[2]*rayForward[2])) + rayForward = [invLen*rayForward[0],invLen*rayForward[1],invLen*rayForward[2]] + rayFrom = camPos + oneOverWidth = float(1)/float(width) + oneOverHeight = float(1)/float(height) + dHor = [horizon[0] * oneOverWidth,horizon[1] * oneOverWidth,horizon[2] * oneOverWidth] + dVer = [vertical[0] * oneOverHeight,vertical[1] * oneOverHeight,vertical[2] * oneOverHeight] + rayToCenter=[rayFrom[0]+rayForward[0],rayFrom[1]+rayForward[1],rayFrom[2]+rayForward[2]] + rayTo = [rayFrom[0]+rayForward[0] - 0.5 * horizon[0] + 0.5 * vertical[0]+float(mouseX)*dHor[0]-float(mouseY)*dVer[0], + rayFrom[1]+rayForward[1] - 0.5 * horizon[1] + 0.5 * vertical[1]+float(mouseX)*dHor[1]-float(mouseY)*dVer[1], + rayFrom[2]+rayForward[2] - 0.5 * horizon[2] + 0.5 * vertical[2]+float(mouseX)*dHor[2]-float(mouseY)*dVer[2]] + return rayFrom,rayTo + +cid = p.connect(p.SHARED_MEMORY) +if (cid<0): + p.connect(p.GUI) +p.setPhysicsEngineParameter(numSolverIterations=10) +p.setTimeStep(1./120.) +logId = p.startStateLogging(p.STATE_LOGGING_PROFILE_TIMINGS, "visualShapeBench.json") +#useMaximalCoordinates is much faster then the default reduced coordinates (Featherstone) +p.loadURDF("plane_transparent.urdf", useMaximalCoordinates=True) +#disable rendering during creation. +p.configureDebugVisualizer(p.COV_ENABLE_RENDERING,0) +p.configureDebugVisualizer(p.COV_ENABLE_PLANAR_REFLECTION,1) + +p.configureDebugVisualizer(p.COV_ENABLE_GUI,0) +#disable tinyrenderer, software (CPU) renderer, we don't use it here +p.configureDebugVisualizer(p.COV_ENABLE_TINY_RENDERER,0) + +shift = [0,-0.02,0] +meshScale=[0.1,0.1,0.1] +#the visual shape and collision shape can be re-used by all createMultiBody instances (instancing) +visualShapeId = p.createVisualShape(shapeType=p.GEOM_MESH,fileName="duck.obj", rgbaColor=[1,1,1,1], specularColor=[0.4,.4,0], visualFramePosition=shift, meshScale=meshScale) +collisionShapeId = p.createCollisionShape(shapeType=p.GEOM_MESH, fileName="duck_vhacd.obj", collisionFramePosition=shift,meshScale=meshScale) + +rangex = 3 +rangey = 3 +for i in range (rangex): + for j in range (rangey ): + p.createMultiBody(baseMass=1,baseInertialFramePosition=[0,0,0],baseCollisionShapeIndex=collisionShapeId, baseVisualShapeIndex = visualShapeId, basePosition = [((-rangex/2)+i)*meshScale[0]*2,(-rangey/2+j)*meshScale[1]*2,1], useMaximalCoordinates=True) +p.configureDebugVisualizer(p.COV_ENABLE_RENDERING,1) +p.stopStateLogging(logId) +p.setGravity(0,0,-10) +p.setRealTimeSimulation(1) + +colors = [[1,0,0,1],[0,1,0,1],[0,0,1,1],[1,1,1,1]] +currentColor = 0 + +while (1): + mouseEvents = p.getMouseEvents() + for e in mouseEvents: + if ((e[0] == 2) and (e[3]==0) and (e[4]& p.KEY_WAS_TRIGGERED)): + mouseX = e[1] + mouseY = e[2] + rayFrom,rayTo=getRayFromTo(mouseX,mouseY) + rayInfo = p.rayTest(rayFrom,rayTo) + #p.addUserDebugLine(rayFrom,rayTo,[1,0,0],3) + for l in range(len(rayInfo)): + hit = rayInfo[l] + objectUid = hit[0] + if (objectUid>=1): + #p.removeBody(objectUid) + p.changeVisualShape(objectUid,-1,rgbaColor=colors[currentColor]) + currentColor+=1 + if (currentColor>=len(colors)): + currentColor=0 diff --git a/examples/pybullet/examples/createVisualShape.py b/examples/pybullet/examples/createVisualShape.py index 6e13b6c28..2d08ccdef 100644 --- a/examples/pybullet/examples/createVisualShape.py +++ b/examples/pybullet/examples/createVisualShape.py @@ -40,8 +40,8 @@ meshScale=[0.1,0.1,0.1] visualShapeId = p.createVisualShape(shapeType=p.GEOM_MESH,fileName="duck.obj", rgbaColor=[1,1,1,1], specularColor=[0.4,.4,0], visualFramePosition=shift, meshScale=meshScale) collisionShapeId = p.createCollisionShape(shapeType=p.GEOM_MESH, fileName="duck_vhacd.obj", collisionFramePosition=shift,meshScale=meshScale) -rangex = 32 -rangey = 32 +rangex = 5 +rangey = 5 for i in range (rangex): for j in range (rangey ): p.createMultiBody(baseMass=1,baseInertialFramePosition=[0,0,0],baseCollisionShapeIndex=collisionShapeId, baseVisualShapeIndex = visualShapeId, basePosition = [((-rangex/2)+i)*meshScale[0]*2,(-rangey/2+j)*meshScale[1]*2,1], useMaximalCoordinates=True) @@ -65,7 +65,7 @@ while (1): for l in range(len(rayInfo)): hit = rayInfo[l] objectUid = hit[0] - if (objectUid>=0): + if (objectUid>=1): #p.removeBody(objectUid) p.changeVisualShape(objectUid,-1,rgbaColor=colors[currentColor]) currentColor+=1 diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 3907a3938..2c86daef8 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -9152,6 +9152,8 @@ initpybullet(void) PyModule_AddIntConstant(m, "COV_ENABLE_RGB_BUFFER_PREVIEW", COV_ENABLE_RGB_BUFFER_PREVIEW); PyModule_AddIntConstant(m, "COV_ENABLE_DEPTH_BUFFER_PREVIEW", COV_ENABLE_DEPTH_BUFFER_PREVIEW); PyModule_AddIntConstant(m, "COV_ENABLE_SEGMENTATION_MARK_PREVIEW", COV_ENABLE_SEGMENTATION_MARK_PREVIEW); + PyModule_AddIntConstant(m, "COV_ENABLE_PLANAR_REFLECTION", COV_ENABLE_PLANAR_REFLECTION); + PyModule_AddIntConstant(m, "ER_TINY_RENDERER", ER_TINY_RENDERER); PyModule_AddIntConstant(m, "ER_BULLET_HARDWARE_OPENGL", ER_BULLET_HARDWARE_OPENGL);