Ghost Context Refactor
[blender-staging.git] / source / gameengine / VideoTexture / ImageRender.cpp
index 4d5b3a0130f65f6a0dbeb90165e15c2dee5817b2..617e7fd1d8e5bb51a8d04c40249cf2bebf036d29 100644 (file)
@@ -1,42 +1,48 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software  Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (c) 2007 The Zdeno Ash Miklas
+ *
+ * This source file is part of VideoTexture library
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
 /** \file gameengine/VideoTexture/ImageRender.cpp
  *  \ingroup bgevideotex
  */
-/* $Id$
------------------------------------------------------------------------------
-This source file is part of VideoTexture library
-
-Copyright (c) 2007 The Zdeno Ash Miklas
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU Lesser General Public License as published by the Free Software
-Foundation; either version 2 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place - Suite 330, Boston, MA 02111-1307, USA, or go to
-http://www.gnu.org/copyleft/lesser.txt.
------------------------------------------------------------------------------
-*/
 
 // implementation
 
-#include <PyObjectPlus.h>
+#include "PyObjectPlus.h"
 #include <structmember.h>
 #include <float.h>
 #include <math.h>
 
 
-#include "GL/glew.h"
+#include "glew-mx.h"
 
 #include "KX_PythonInit.h"
 #include "DNA_scene_types.h"
 #include "RAS_CameraData.h"
 #include "RAS_MeshObject.h"
+#include "RAS_Polygon.h"
 #include "BLI_math.h"
 
 #include "ImageRender.h"
@@ -47,17 +53,17 @@ http://www.gnu.org/copyleft/lesser.txt.
 
 ExceptionID SceneInvalid, CameraInvalid, ObserverInvalid;
 ExceptionID MirrorInvalid, MirrorSizeInvalid, MirrorNormalInvalid, MirrorHorizontal, MirrorTooSmall;
-ExpDesc SceneInvalidDesc (SceneInvalid, "Scene object is invalid");
-ExpDesc CameraInvalidDesc (CameraInvalid, "Camera object is invalid");
-ExpDesc ObserverInvalidDesc (ObserverInvalid, "Observer object is invalid");
-ExpDesc MirrorInvalidDesc (MirrorInvalid, "Mirror object is invalid");
-ExpDesc MirrorSizeInvalidDesc (MirrorSizeInvalid, "Mirror has no vertex or no size");
-ExpDesc MirrorNormalInvalidDesc (MirrorNormalInvalid, "Cannot determine mirror plane");
-ExpDesc MirrorHorizontalDesc (MirrorHorizontal, "Mirror is horizontal in local space");
-ExpDesc MirrorTooSmallDesc (MirrorTooSmall, "Mirror is too small");
+ExpDesc SceneInvalidDesc(SceneInvalid, "Scene object is invalid");
+ExpDesc CameraInvalidDesc(CameraInvalid, "Camera object is invalid");
+ExpDesc ObserverInvalidDesc(ObserverInvalid, "Observer object is invalid");
+ExpDesc MirrorInvalidDesc(MirrorInvalid, "Mirror object is invalid");
+ExpDesc MirrorSizeInvalidDesc(MirrorSizeInvalid, "Mirror has no vertex or no size");
+ExpDesc MirrorNormalInvalidDesc(MirrorNormalInvalid, "Cannot determine mirror plane");
+ExpDesc MirrorHorizontalDesc(MirrorHorizontal, "Mirror is horizontal in local space");
+ExpDesc MirrorTooSmallDesc(MirrorTooSmall, "Mirror is too small");
 
 // constructor
-ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : 
+ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera) :
     ImageViewport(),
     m_render(true),
     m_scene(scene),
@@ -65,7 +71,9 @@ ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) :
     m_owncamera(false),
     m_observer(NULL),
     m_mirror(NULL),
-    m_clip(100.f)
+    m_clip(100.f),
+    m_mirrorHalfWidth(0.f),
+    m_mirrorHalfHeight(0.f)
 {
        // initialize background color
        setBackground(0, 0, 255, 255);
@@ -73,7 +81,6 @@ ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) :
        m_engine = KX_GetActiveEngine();
        m_rasterizer = m_engine->GetRasterizer();
        m_canvas = m_engine->GetCanvas();
-       m_rendertools = m_engine->GetRenderTools();
 }
 
 // destructor
@@ -137,7 +144,7 @@ void ImageRender::Render()
                // compute distance of observer to mirror = D - observerPos . normal
                MT_Scalar observerDistance = mirrorPlaneDTerm - observerWorldPos.dot(mirrorWorldZ);
                // if distance < 0.01 => observer is on wrong side of mirror, don't render
-               if (observerDistance < 0.01f)
+               if (observerDistance < 0.01)
                        return;
                // set camera world position = observerPos + normal * 2 * distance
                MT_Point3 cameraWorldPos = observerWorldPos + (MT_Scalar(2.0)*observerDistance)*mirrorWorldZ;
@@ -192,10 +199,9 @@ void ImageRender::Render()
        m_canvas->SetViewPort(m_position[0], m_position[1], m_position[0]+m_capSize[0]-1, m_position[1]+m_capSize[1]-1);
        m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]);
        m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
-       m_rasterizer->BeginFrame(RAS_IRasterizer::KX_TEXTURED,m_engine->GetClockTime());
-       m_rendertools->BeginFrame(m_rasterizer);
+       m_rasterizer->BeginFrame(m_engine->GetClockTime());
        m_engine->SetWorldSettings(m_scene->GetWorldInfo());
-       m_rendertools->SetAuxilaryClientInfo(m_scene);
+       m_rasterizer->SetAuxilaryClientInfo(m_scene);
        m_rasterizer->DisplayFog();
        // matrix calculation, don't apply any of the stereo mode
        m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO);
@@ -207,13 +213,14 @@ void ImageRender::Render()
                            frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar);
 
                m_camera->SetProjectionMatrix(projmat);
-       } else if (m_camera->hasValidProjectionMatrix())
-       {
+       }
+       else if (m_camera->hasValidProjectionMatrix()) {
                m_rasterizer->SetProjectionMatrix(m_camera->GetProjectionMatrix());
-       } else
-       {
+       }
+       else {
                float lens = m_camera->GetLens();
                float sensor_x = m_camera->GetSensorWidth();
+               float sensor_y = m_camera->GetSensorHeight();
                bool orthographic = !m_camera->GetCameraData()->m_perspective;
                float nearfrust = m_camera->GetCameraNear();
                float farfrust = m_camera->GetCameraFar();
@@ -233,18 +240,21 @@ void ImageRender::Render()
                                    farfrust,
                                    m_camera->GetScale(),
                                    aspect_ratio,
+                                               m_camera->GetSensorFit(),
                                    frustrum
                                    );
 
                        projmat = m_rasterizer->GetOrthoMatrix(
                                    frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar);
-               } else
-               {
+               }
+               else {
                        RAS_FramingManager::ComputeDefaultFrustum(
                                    nearfrust,
                                    farfrust,
                                    lens,
                                    sensor_x,
+                                   sensor_y,
+                                   RAS_SENSORFIT_AUTO,
                                    aspect_ratio,
                                    frustrum);
                        
@@ -264,7 +274,11 @@ void ImageRender::Render()
 
        m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera);
 
-       m_scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
+       m_scene->UpdateAnimations(m_engine->GetFrameTime());
+
+       m_scene->RenderBuckets(camtrans, m_rasterizer);
+
+       m_scene->RenderFonts();
 
        // restore the canvas area now that the render is completed
        m_canvas->GetWindowArea() = area;
@@ -272,25 +286,25 @@ void ImageRender::Render()
 
 
 // cast Image pointer to ImageRender
-inline ImageRender * getImageRender (PyImage * self)
+inline ImageRender * getImageRender (PyImage *self)
 { return static_cast<ImageRender*>(self->m_image); }
 
 
 // python methods
 
 // Blender Scene type
-BlendType<KX_Scene> sceneType ("KX_Scene");
+static BlendType<KX_Scene> sceneType ("KX_Scene");
 // Blender Camera type
-BlendType<KX_Camera> cameraType ("KX_Camera");
+static BlendType<KX_Camera> cameraType ("KX_Camera");
 
 
 // object initialization
-static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int ImageRender_init(PyObject *pySelf, PyObject *args, PyObject *kwds)
 {
        // parameters - scene object
-       PyObject * scene;
+       PyObject *scene;
        // camera object
-       PyObject * camera;
+       PyObject *camera;
        // parameter keywords
        static const char *kwlist[] = {"sceneObj", "cameraObj", NULL};
        // get parameters
@@ -312,7 +326,7 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds
                if (cameraPtr == NULL) THRWEXCP(CameraInvalid, S_OK);
 
                // get pointer to image structure
-               PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+               PyImage *self = reinterpret_cast<PyImage*>(pySelf);
                // create source object
                if (self->m_image != NULL) delete self->m_image;
                self->m_image = new ImageRender(scenePtr, cameraPtr);
@@ -328,7 +342,7 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds
 
 
 // get background color
-PyObject * getBackground (PyImage * self, void * closure)
+static PyObject *getBackground (PyImage *self, void *closure)
 {
        return Py_BuildValue("[BBBB]",
                             getImageRender(self)->getBackground(0),
@@ -338,7 +352,7 @@ PyObject * getBackground (PyImage * self, void * closure)
 }
 
 // set color
-static int setBackground (PyImage * self, PyObject * value, void * closure)
+static int setBackground(PyImage *self, PyObject *value, void *closure)
 {
        // check validity of parameter
        if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 4
@@ -351,10 +365,11 @@ static int setBackground (PyImage * self, PyObject * value, void * closure)
                return -1;
        }
        // set background color
-       getImageRender(self)->setBackground((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))),
-               (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))),
-               (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))),
-        (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 3))));
+       getImageRender(self)->setBackground(
+               (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+               (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
+               (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2))),
+               (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 3))));
        // success
        return 0;
 }
@@ -370,7 +385,7 @@ static PyMethodDef imageRenderMethods[] =
 static PyGetSetDef imageRenderGetSets[] =
 { 
        {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL},
-    // attribute from ImageViewport
+       // attribute from ImageViewport
        {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL},
        {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL},
        {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL},
@@ -378,16 +393,17 @@ static PyGetSetDef imageRenderGetSets[] =
        {(char*)"valid", (getter)Image_valid, NULL, (char*)"bool to tell if an image is available", NULL},
        {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL},
        {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
-       {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", 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}
 };
 
 
 // define python type
-PyTypeObject ImageRenderType =
-{ 
+PyTypeObject ImageRenderType = {
        PyVarObject_HEAD_INIT(NULL, 0)
        "VideoTexture.ImageRender",   /*tp_name*/
        sizeof(PyImage),          /*tp_basicsize*/
@@ -429,14 +445,14 @@ PyTypeObject ImageRenderType =
 };
 
 // object initialization
-static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+static int ImageMirror_init(PyObject *pySelf, PyObject *args, PyObject *kwds)
 {
        // parameters - scene object
-       PyObject * scene;
+       PyObject *scene;
        // reference object for mirror
-       PyObject * observer;
+       PyObject *observer;
        // object holding the mirror
-       PyObject * mirror;
+       PyObject *mirror;
        // material of the mirror
        short materialID = 0;
        // parameter keywords
@@ -454,7 +470,7 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
                else
                        THRWEXCP(SceneInvalid, S_OK);
                
-               if(scenePtr==NULL) /* incase the python proxy reference is invalid */
+               if (scenePtr==NULL) /* in case the python proxy reference is invalid */
                        THRWEXCP(SceneInvalid, S_OK);
                
                // get observer pointer
@@ -466,7 +482,7 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
                else
                        THRWEXCP(ObserverInvalid, S_OK);
                
-               if(observerPtr==NULL) /* incase the python proxy reference is invalid */
+               if (observerPtr==NULL) /* in case the python proxy reference is invalid */
                        THRWEXCP(ObserverInvalid, S_OK);
 
                // get mirror pointer
@@ -476,7 +492,7 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
                else
                        THRWEXCP(MirrorInvalid, S_OK);
                
-               if(mirrorPtr==NULL) /* incase the python proxy reference is invalid */
+               if (mirrorPtr==NULL) /* in case the python proxy reference is invalid */
                        THRWEXCP(MirrorInvalid, S_OK);
 
                // locate the material in the mirror
@@ -485,7 +501,7 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
                        THRWEXCP(MaterialNotAvail, S_OK);
 
                // get pointer to image structure
-               PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+               PyImage *self = reinterpret_cast<PyImage*>(pySelf);
 
                // create source object
                if (self->m_image != NULL)
@@ -505,13 +521,13 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds
 }
 
 // get background color
-PyObject * getClip (PyImage * self, void * closure)
+static PyObject *getClip (PyImage *self, void *closure)
 {
        return PyFloat_FromDouble(getImageRender(self)->getClip());
 }
 
 // set clip
-static int setClip (PyImage * self, PyObject * value, void * closure)
+static int setClip(PyImage *self, PyObject *value, void *closure)
 {
        // check validity of parameter
        double clip;
@@ -540,15 +556,17 @@ static PyGetSetDef imageMirrorGetSets[] =
        {(char*)"valid", (getter)Image_valid, NULL, (char*)"bool to tell if an image is available", NULL},
        {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL},
        {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
-       {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", 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}
 };
 
 
 // constructor
-ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObject * mirror, RAS_IPolyMaterial * mat) :
+ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObject *mirror, RAS_IPolyMaterial *mat) :
     ImageViewport(),
     m_render(false),
     m_scene(scene),
@@ -578,7 +596,6 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
        m_engine = KX_GetActiveEngine();
        m_rasterizer = m_engine->GetRasterizer();
        m_canvas = m_engine->GetCanvas();
-       m_rendertools = m_engine->GetRenderTools();
        // locate the vertex assigned to mat and do following calculation in mesh coordinates
        for (int meshIndex = 0; meshIndex < mirror->GetMeshCount(); meshIndex++)
        {
@@ -599,14 +616,13 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
                                mirrorVerts.push_back(v1);
                                mirrorVerts.push_back(v2);
                                mirrorVerts.push_back(v3);
-                               if (polygon->VertexCount() == 4)
-                               {
+                               if (polygon->VertexCount() == 4) {
                                        v4 = polygon->GetVertex(3);
                                        mirrorVerts.push_back(v4);
-                                       area = normal_quad_v3( normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ(), (float*)v4->getXYZ());
-                               } else
-                               {
-                                       area = normal_tri_v3( normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ());
+                                       area = normal_quad_v3(normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ(), (float*)v4->getXYZ());
+                               }
+                               else {
+                                       area = normal_tri_v3(normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ());
                                }
                                area = fabs(area);
                                mirrorArea += area;
@@ -632,8 +648,8 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
        // otherwise the Y axis is the up direction.
        // If the mirror is not perfectly vertical(horizontal), the Z(Y) axis projection on the mirror
        // plan by the normal will be the up direction.
-       if (fabs(mirrorNormal[2]) > fabs(mirrorNormal[1]) &&
-               fabs(mirrorNormal[2]) > fabs(mirrorNormal[0]))
+       if (fabsf(mirrorNormal[2]) > fabsf(mirrorNormal[1]) &&
+           fabsf(mirrorNormal[2]) > fabsf(mirrorNormal[0]))
        {
                // the mirror is more horizontal than vertical
                copy_v3_v3(axis, yaxis);
@@ -644,7 +660,7 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
                copy_v3_v3(axis, zaxis);
        }
        dist = dot_v3v3(mirrorNormal, axis);
-       if (fabs(dist) < FLT_EPSILON)
+       if (fabsf(dist) < FLT_EPSILON)
        {
                // the mirror is already fully aligned with up axis
                copy_v3_v3(mirrorUp, axis);
@@ -720,8 +736,7 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
 
 
 // define python type
-PyTypeObject ImageMirrorType =
-{ 
+PyTypeObject ImageMirrorType = {
        PyVarObject_HEAD_INIT(NULL, 0)
        "VideoTexture.ImageMirror",   /*tp_name*/
        sizeof(PyImage),          /*tp_basicsize*/