PyBullet: add planar reflection example,

See examples/pybullet/examples/addPlanarReflection.py
This commit is contained in:
erwincoumans
2018-04-11 01:03:36 -07:00
parent 39edcf699c
commit ffc808784b
11 changed files with 155 additions and 15 deletions

View File

@@ -9,6 +9,6 @@ newmtl Material
Kd 0.5880 0.5880 0.5880 Kd 0.5880 0.5880 0.5880
Ks 0.0000 0.0000 0.0000 Ks 0.0000 0.0000 0.0000
Ke 0.0000 0.0000 0.0000 Ke 0.0000 0.0000 0.0000
map_Kd tex4x4.png map_Kd checker_blue.png

View File

@@ -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
v -15.000000 -15.000000 0.000000 v -15.000000 -15.000000 0.000000
vt 1.000000 0.000000 vt 15.000000 0.000000
vt 1.000000 1.000000 vt 15.000000 15.000000
vt 0.000000 1.000000 vt 0.000000 15.000000
vt 0.000000 0.000000 vt 0.000000 0.000000
usemtl Material usemtl Material

View File

@@ -12,7 +12,7 @@
<visual> <visual>
<origin rpy="0 0 0" xyz="0 0 0"/> <origin rpy="0 0 0" xyz="0 0 0"/>
<geometry> <geometry>
<mesh filename="plane.obj" scale="1 1 1"/> <mesh filename="plane_transparent.obj" scale="1 1 1"/>
</geometry> </geometry>
<material name="white"> <material name="white">
<color rgba="1 1 1 .7"/> <color rgba="1 1 1 .7"/>

View File

@@ -16,6 +16,7 @@ enum
B3_CREATE_SHADOWMAP_RENDERMODE, B3_CREATE_SHADOWMAP_RENDERMODE,
B3_USE_SHADOWMAP_RENDERMODE, B3_USE_SHADOWMAP_RENDERMODE,
B3_USE_SHADOWMAP_RENDERMODE_REFLECTION, B3_USE_SHADOWMAP_RENDERMODE_REFLECTION,
B3_USE_SHADOWMAP_RENDERMODE_REFLECTION_PLANE,
B3_USE_PROJECTIVE_TEXTURE_RENDERMODE, B3_USE_PROJECTIVE_TEXTURE_RENDERMODE,
}; };
@@ -77,6 +78,8 @@ struct CommonRenderInterface
virtual void replaceTexture(int shapeIndex, int textureIndex){}; virtual void replaceTexture(int shapeIndex, int textureIndex){};
virtual void removeTexture(int textureIndex) = 0; virtual void removeTexture(int textureIndex) = 0;
virtual void setPlaneReflectionShapeIndex(int index) {}
virtual int getShapeIndexFromInstance(int srcIndex) {return -1;} virtual int getShapeIndexFromInstance(int srcIndex) {return -1;}
virtual bool readSingleInstanceTransformToCPU(float* position, float* orientation, int srcIndex)=0; virtual bool readSingleInstanceTransformToCPU(float* position, float* orientation, int srcIndex)=0;

View File

@@ -1026,6 +1026,10 @@ void OpenGLGuiHelper::setVisualizerFlagCallback(VisualizerFlagCallback callback)
void OpenGLGuiHelper::setVisualizerFlag(int flag, int enable) void OpenGLGuiHelper::setVisualizerFlag(int flag, int enable)
{ {
if (getRenderInterface() && flag==16)//COV_ENABLE_PLANAR_REFLECTION
{
getRenderInterface()->setPlaneReflectionShapeIndex(enable);
}
if (m_data->m_visualizerFlagCallback) if (m_data->m_visualizerFlagCallback)
(m_data->m_visualizerFlagCallback)(flag,enable); (m_data->m_visualizerFlagCallback)(flag,enable);
} }

View File

@@ -361,7 +361,8 @@ GLInstancingRenderer::GLInstancingRenderer(int maxNumObjectCapacity, int maxShap
m_textureinitialized(false), m_textureinitialized(false),
m_screenWidth(0), m_screenWidth(0),
m_screenHeight(0), m_screenHeight(0),
m_upAxis(1) m_upAxis(1),
m_planeReflectionShapeIndex(-1)
{ {
m_data = new InternalDataRenderer; m_data = new InternalDataRenderer;
@@ -1597,13 +1598,44 @@ void GLInstancingRenderer::renderScene()
{ {
renderSceneInternal(B3_CREATE_SHADOWMAP_RENDERMODE); renderSceneInternal(B3_CREATE_SHADOWMAP_RENDERMODE);
//glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
//renderSceneInternal(B3_USE_SHADOWMAP_RENDERMODE_REFLECTION);
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); renderSceneInternal(B3_USE_SHADOWMAP_RENDERMODE);
} }
else if (m_data->m_useProjectiveTexture) else if (m_data->m_useProjectiveTexture)
{ {
renderSceneInternal(B3_USE_PROJECTIVE_TEXTURE_RENDERMODE); renderSceneInternal(B3_USE_PROJECTIVE_TEXTURE_RENDERMODE);
} }
else else
@@ -2040,6 +2072,13 @@ void GLInstancingRenderer::renderSceneInternal(int orgRenderMode)
{ {
int renderMode=orgRenderMode; int renderMode=orgRenderMode;
bool reflectionPass = false; 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) if (orgRenderMode==B3_USE_SHADOWMAP_RENDERMODE_REFLECTION)
{ {
reflectionPass = true; reflectionPass = true;
@@ -2085,8 +2124,8 @@ void GLInstancingRenderer::renderSceneInternal(int orgRenderMode)
//GLfloat depthModelViewMatrix2[4][4]; //GLfloat depthModelViewMatrix2[4][4];
// For projective texture mapping // For projective texture mapping
float textureProjectionMatrix[4][4]; //float textureProjectionMatrix[4][4];
GLfloat textureModelViewMatrix[4][4]; //GLfloat textureModelViewMatrix[4][4];
// Compute the MVP matrix from the light's point of view // Compute the MVP matrix from the light's point of view
if (renderMode==B3_CREATE_SHADOWMAP_RENDERMODE) if (renderMode==B3_CREATE_SHADOWMAP_RENDERMODE)
@@ -2254,6 +2293,7 @@ b3Assert(glGetError() ==GL_NO_ERROR);
for (int obj=0;obj<m_graphicsInstances.size();obj++) for (int obj=0;obj<m_graphicsInstances.size();obj++)
{ {
b3GraphicsInstance* gfxObj = m_graphicsInstances[obj]; b3GraphicsInstance* gfxObj = m_graphicsInstances[obj];
if (gfxObj->m_numGraphicsInstances) if (gfxObj->m_numGraphicsInstances)
{ {
SortableTransparentInstance inst; SortableTransparentInstance inst;
@@ -2303,6 +2343,10 @@ b3Assert(glGetError() ==GL_NO_ERROR);
int shapeIndex = transparentInstances[i].m_shapeIndex; int shapeIndex = transparentInstances[i].m_shapeIndex;
//during a reflectionPlanePass, only draw the plane, nothing else
if ((shapeIndex!=m_planeReflectionShapeIndex) && reflectionPlanePass)
continue;
b3GraphicsInstance* gfxObj = m_graphicsInstances[shapeIndex]; b3GraphicsInstance* gfxObj = m_graphicsInstances[shapeIndex];
//only draw stuff (opaque/transparent) if it is the right pass //only draw stuff (opaque/transparent) if it is the right pass
@@ -2503,6 +2547,8 @@ b3Assert(glGetError() ==GL_NO_ERROR);
float MVP[16]; float MVP[16];
if (reflectionPass) 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 tmp[16];
float reflectionMatrix[16] = {1,0,0,0, float reflectionMatrix[16] = {1,0,0,0,
0,1,0,0, 0,1,0,0,
@@ -2669,6 +2715,11 @@ void GLInstancingRenderer::CleanupShaders()
{ {
} }
void GLInstancingRenderer::setPlaneReflectionShapeIndex(int index)
{
m_planeReflectionShapeIndex = index;
}
void GLInstancingRenderer::enableShadowMap() void GLInstancingRenderer::enableShadowMap()
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);

View File

@@ -40,6 +40,8 @@ class GLInstancingRenderer : public CommonRenderInterface
int m_upAxis; int m_upAxis;
int m_planeReflectionShapeIndex;
int registerGraphicsInstanceInternal(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); int registerGraphicsInstanceInternal(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling);
void rebuildGraphicsInstances(); void rebuildGraphicsInstances();
@@ -152,6 +154,8 @@ public:
virtual void enableShadowMap(); virtual void enableShadowMap();
virtual void setPlaneReflectionShapeIndex(int index);
virtual void clearZBuffer(); virtual void clearZBuffer();
virtual void setRenderFrameBuffer(unsigned int renderFrameBuffer); virtual void setRenderFrameBuffer(unsigned int renderFrameBuffer);

View File

@@ -648,6 +648,7 @@ enum b3ConfigureDebugVisualizerEnum
COV_ENABLE_RGB_BUFFER_PREVIEW, COV_ENABLE_RGB_BUFFER_PREVIEW,
COV_ENABLE_DEPTH_BUFFER_PREVIEW, COV_ENABLE_DEPTH_BUFFER_PREVIEW,
COV_ENABLE_SEGMENTATION_MARK_PREVIEW, COV_ENABLE_SEGMENTATION_MARK_PREVIEW,
COV_ENABLE_PLANAR_REFLECTION,
}; };

View File

@@ -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

View File

@@ -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) 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) collisionShapeId = p.createCollisionShape(shapeType=p.GEOM_MESH, fileName="duck_vhacd.obj", collisionFramePosition=shift,meshScale=meshScale)
rangex = 32 rangex = 5
rangey = 32 rangey = 5
for i in range (rangex): for i in range (rangex):
for j in range (rangey ): 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.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)): for l in range(len(rayInfo)):
hit = rayInfo[l] hit = rayInfo[l]
objectUid = hit[0] objectUid = hit[0]
if (objectUid>=0): if (objectUid>=1):
#p.removeBody(objectUid) #p.removeBody(objectUid)
p.changeVisualShape(objectUid,-1,rgbaColor=colors[currentColor]) p.changeVisualShape(objectUid,-1,rgbaColor=colors[currentColor])
currentColor+=1 currentColor+=1

View File

@@ -9152,6 +9152,8 @@ initpybullet(void)
PyModule_AddIntConstant(m, "COV_ENABLE_RGB_BUFFER_PREVIEW", COV_ENABLE_RGB_BUFFER_PREVIEW); 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_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_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_TINY_RENDERER", ER_TINY_RENDERER);
PyModule_AddIntConstant(m, "ER_BULLET_HARDWARE_OPENGL", ER_BULLET_HARDWARE_OPENGL); PyModule_AddIntConstant(m, "ER_BULLET_HARDWARE_OPENGL", ER_BULLET_HARDWARE_OPENGL);