diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2012-10-21 02:28:44 +0400 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2012-10-21 02:28:44 +0400 |
commit | 4213eca5fc3b5f2c2b23945e9462b38e13f843c4 (patch) | |
tree | 8f296c8e6847423ec0ded76e04a38efb44543d5c | |
parent | 7deb8d8a26a63a338b845eae3617111316e015f9 (diff) |
BGE VideoTexture: add depth buffer access to ImageViewport and ImageRender.
2 new attributes to ImageViewport and ImageRender object:
depth: set to True to retrieve the depth buffer as an array of float
(not suitable for texture source).
zbuff: set to True to retrieve the depth buffer as a grey scale pixel array
(suitable for texture source).
A new mode 'F' is added to VideoTexture.imageToArray() to allow returning the image
buffer as a one dimensional array of float. This mode should only be used to retrieve
the depth buffer of ImageViewport and ImageRender objects.
Example:
viewport = VideoTexture.ImageViewport()
viewport.depth = True
depth = VideoTexture.imageToArray(viewport,'F')
# show depth of bottom left pixel
# 1.0 = infinite, 0.0 = on near clip plane.
print(depth[0])
-rw-r--r-- | doc/python_api/rst/bge.texture.rst | 23 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/FilterBase.h | 4 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/FilterSource.h | 60 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageBase.cpp | 60 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageBase.h | 22 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageRender.cpp | 4 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/ImageViewport.cpp | 36 |
7 files changed, 204 insertions, 5 deletions
diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst index 07d83f66bd4..0c9e9da0661 100644 --- a/doc/python_api/rst/bge.texture.rst +++ b/doc/python_api/rst/bge.texture.rst @@ -351,6 +351,15 @@ When the texture object is deleted, the new texture is deleted and the old textu use whole viewport to render + .. attribute:: depth + + use depth component of render as array of float - not suitable for texture source, + should only be used with bge.texture.imageToArray(mode='F') + + .. attribute:: zbuff + + use depth component of render as grey scale color - suitable for texture source + .. class:: ImageViewport() Image source from viewport @@ -399,6 +408,15 @@ When the texture object is deleted, the new texture is deleted and the old textu use whole viewport to capture + .. attribute:: depth + + use depth component of viewport as array of float - not suitable for texture source, + should only be used with bge.texture.imageToArray(mode='F') + + .. attribute:: zbuff + + use depth component of viewport as grey scale color - suitable for texture source + .. class:: Texture(gameObj) Texture objects @@ -518,13 +536,16 @@ When the texture object is deleted, the new texture is deleted and the old textu 0 to force a fixed 0 color channel and 1 to force a fixed 255 color channel. Example: "BGR" will return 3 bytes per pixel with the Blue, Green and Red channels in that order. "RGB1" will return 4 bytes per pixel with the Red, Green, Blue channels in that order and the alpha channel forced to 255. + A special mode "F" allows to return the image as an array of float. This mode should only be used to retrieve + the depth buffer of the ImageViewport and ImageRender object. The default mode is "RGBA". + :type mode: string :rtype: :class:`~bgl.buffer` :return: A object representing the image as one dimensional array of bytes of size (pixel_size*width*height), line by line starting from the bottom of the image. The pixel size and format is determined by the mode - parameter. + parameter. For mode 'F', the array is a one dimensional array of float of size (width*height). .. function:: materialID(object,name) diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h index 422cf86f23e..98bc495375a 100644 --- a/source/gameengine/VideoTexture/FilterBase.h +++ b/source/gameengine/VideoTexture/FilterBase.h @@ -95,6 +95,10 @@ protected: virtual unsigned int filter (unsigned int * src, short x, short y, short * size, unsigned int pixSize, unsigned int val = 0) { return val; } + /// filter pixel, source float buffer + virtual unsigned int filter (float * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val = 0) + { return val; } /// get source pixel size virtual unsigned int getPixelSize (void) { return 1; } diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index a4900e8c148..0e0a3e8d1b9 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -31,7 +31,6 @@ http://www.gnu.org/copyleft/lesser.txt. #include "FilterBase.h" - /// class for RGB24 conversion class FilterRGB24 : public FilterBase { @@ -97,6 +96,65 @@ protected: { VT_RGBA(val,src[2],src[1],src[0],0xFF); return val; } }; +/// class for Z_buffer conversion +class FilterZZZA : public FilterBase +{ +public: + /// constructor + FilterZZZA (void) {} + /// destructor + virtual ~FilterZZZA (void) {} + + /// get source pixel size + virtual unsigned int getPixelSize (void) { return 1; } + +protected: + /// filter pixel, source float buffer + virtual unsigned int filter (float * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val) + { + // calculate gray value + // convert float to unsigned char + unsigned int depth = int(src[0] * 255); + // return depth scale value + VT_R(val) = depth; + VT_G(val) = depth; + VT_B(val) = depth; + VT_A(val) = 0xFF; + + return val; + } +}; + + +/// class for Z_buffer conversion +class FilterDEPTH : public FilterBase +{ +public: + /// constructor + FilterDEPTH (void) {} + /// destructor + virtual ~FilterDEPTH (void) {} + + /// get source pixel size + virtual unsigned int getPixelSize (void) { return 1; } + +protected: + /// filter pixel, source float buffer + virtual unsigned int filter (float * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val) + { + // Copy the float value straight away + // The user can retrieve the original float value by using + // 'F' mode in BGL buffer + memcpy(&val, src, sizeof (unsigned int)); + return val; + } +}; + + + + /// class for YV12 conversion class FilterYV12 : public FilterBase { diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index 2de49795681..de54d8e8940 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -49,6 +49,8 @@ extern "C" { // constructor ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0), m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false), +m_zbuff(false), +m_depth(false), m_staticSources(staticSrc), m_pyfilter(NULL) { m_size[0] = m_size[1] = 0; @@ -402,6 +404,18 @@ PyObject *Image_getImage (PyImage *self, char * mode) { buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, image); } + else if (!strcasecmp(mode, "F")) + { + // this mode returns the image as an array of float. + // This makes sense ONLY for the depth buffer: + // source = VideoTexture.ImageViewport() + // source.depth = True + // depth = VideoTexture.imageToArray(source, 'F') + + // adapt dimension from byte to float + dimensions /= sizeof(float); + buffer = BGL_MakeBuffer( GL_FLOAT, 1, &dimensions, image); + } else { int i, c, ncolor, pixels; @@ -532,6 +546,52 @@ int Image_setFlip (PyImage *self, PyObject *value, void *closure) return 0; } +// get zbuff +PyObject * Image_getZbuff (PyImage * self, void * closure) +{ + if (self->m_image != NULL && self->m_image->getZbuff()) Py_RETURN_TRUE; + else Py_RETURN_FALSE; +} + +// set zbuff +int Image_setZbuff (PyImage * self, PyObject * value, void * closure) +{ + // check parameter, report failure + if (value == NULL || !PyBool_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "The value must be a bool"); + return -1; + } + // set scale + if (self->m_image != NULL) self->m_image->setZbuff(value == Py_True); + // success + return 0; +} + +// get depth +PyObject * Image_getDepth (PyImage * self, void * closure) +{ + if (self->m_image != NULL && self->m_image->getDepth()) Py_RETURN_TRUE; + else Py_RETURN_FALSE; +} + +// set depth +int Image_setDepth (PyImage * self, PyObject * value, void * closure) +{ + // check parameter, report failure + if (value == NULL || !PyBool_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "The value must be a bool"); + return -1; + } + // set scale + if (self->m_image != NULL) self->m_image->setDepth(value == Py_True); + // success + return 0; +} + + + // get filter source object PyObject *Image_getSource (PyImage *self, PyObject *args) diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h index bb3f0c19e4b..a9f25f61406 100644 --- a/source/gameengine/VideoTexture/ImageBase.h +++ b/source/gameengine/VideoTexture/ImageBase.h @@ -78,6 +78,14 @@ public: bool getFlip (void) { return m_flip; } /// set vertical flip void setFlip (bool flip) { m_flip = flip; } + /// get Z buffer + bool getZbuff (void) { return m_zbuff; } + /// set Z buffer + void setZbuff (bool zbuff) { m_zbuff = zbuff; } + /// get depth + bool getDepth (void) { return m_depth; } + /// set depth + void setDepth (bool depth) { m_depth = depth; } /// get source object PyImage * getSource (const char * id); @@ -111,6 +119,10 @@ protected: bool m_scaleChange; /// flip image vertically bool m_flip; + /// use the Z buffer as a texture + bool m_zbuff; + /// extract the Z buffer with unisgned int precision + bool m_depth; /// source image list ImageSourceList m_sources; @@ -347,7 +359,15 @@ int Image_setFlip (PyImage *self, PyObject *value, void *closure); PyObject *Image_getSource (PyImage *self, PyObject *args); // set filter source object PyObject *Image_setSource (PyImage *self, PyObject *args); - +// get Z buffer +PyObject * Image_getZbuff (PyImage * self, void * closure); +// set Z buffer +int Image_setZbuff (PyImage * self, PyObject * value, void * closure); +// get depth +PyObject * Image_getDepth (PyImage * self, void * closure); +// set depth +int Image_setDepth (PyImage * self, PyObject * value, void * closure); + // get pixel filter object PyObject *Image_getFilter (PyImage *self, void *closure); // set pixel filter object diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 2135d0a07eb..85857165403 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -385,6 +385,8 @@ static PyGetSetDef imageRenderGetSets[] = {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL}, {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL}, + {(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer using unsigned int precision", NULL}, {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; @@ -547,6 +549,8 @@ static PyGetSetDef imageMirrorGetSets[] = {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL}, {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL}, + {(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer using unsigned int precision", NULL}, {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index 9b503efcf39..0836422576f 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -50,6 +50,8 @@ ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false) //glGetIntegerv(GL_VIEWPORT, m_viewport); // create buffer for viewport image + // Warning: this buffer is also used to get the depth buffer as an array of + // float (1 float = 4 bytes per pixel) m_viewportImage = new BYTE [4 * getViewportSize()[0] * getViewportSize()[1]]; // set attributes setWhole(false); @@ -57,7 +59,9 @@ ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false) // destructor ImageViewport::~ImageViewport (void) -{ delete [] m_viewportImage; } +{ + delete [] m_viewportImage; +} // use whole viewport to capture image @@ -131,7 +135,7 @@ void ImageViewport::calcImage (unsigned int texId, double ts) } // if texture can be directly created if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0]) - && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) + && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip && !m_zbuff && !m_depth) { // just copy current viewport to texture glBindTexture(GL_TEXTURE_2D, texId); @@ -142,6 +146,32 @@ void ImageViewport::calcImage (unsigned int texId, double ts) // otherwise copy viewport to buffer, if image is not available else if (!m_avail) { + if (m_zbuff) + { + // Use read pixels with the depth buffer + // *** misusing m_viewportImage here, but since it has the correct size + // (4 bytes per pixel = size of float) and we just need it to apply + // the filter, it's ok + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], + GL_DEPTH_COMPONENT, GL_FLOAT, m_viewportImage); + // filter loaded data + FilterZZZA filt; + filterImage(filt, (float *)m_viewportImage, m_capSize); + } + else + + if (m_depth) + { + // Use read pixels with the depth buffer + // See warning above about m_viewportImage. + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], + GL_DEPTH_COMPONENT, GL_FLOAT, m_viewportImage); + // filter loaded data + FilterDEPTH filt; + filterImage(filt, (float *)m_viewportImage, m_capSize); + } + else + // get frame buffer data if (m_alpha) { @@ -310,6 +340,8 @@ static PyGetSetDef imageViewportGetSets[] = {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL}, {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL}, + {(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer as array of float", NULL}, {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; |