diff options
Diffstat (limited to 'source/gameengine/VideoTexture/ImageRender.cpp')
-rw-r--r-- | source/gameengine/VideoTexture/ImageRender.cpp | 594 |
1 files changed, 297 insertions, 297 deletions
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 6038416ba68..f7546d876b2 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -65,29 +65,29 @@ 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) { // initialize background color setBackground(0, 0, 255, 255); - // retrieve rendering objects - m_engine = KX_GetActiveEngine(); - m_rasterizer = m_engine->GetRasterizer(); - m_canvas = m_engine->GetCanvas(); - m_rendertools = m_engine->GetRenderTools(); + // retrieve rendering objects + m_engine = KX_GetActiveEngine(); + m_rasterizer = m_engine->GetRasterizer(); + m_canvas = m_engine->GetCanvas(); + m_rendertools = m_engine->GetRenderTools(); } // destructor ImageRender::~ImageRender (void) { - if (m_owncamera) - m_camera->Release(); + if (m_owncamera) + m_camera->Release(); } // set background color void ImageRender::setBackground (int red, int green, int blue, int alpha) { - m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f; + m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f; m_background[1] = (green < 0) ? 0.f : (green > 255) ? 1.f : float(green)/255.f; m_background[2] = (blue < 0) ? 0.f : (blue > 255) ? 1.f : float(blue)/255.f; m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f; @@ -97,157 +97,157 @@ void ImageRender::setBackground (int red, int green, int blue, int alpha) // capture image from viewport void ImageRender::calcImage (unsigned int texId, double ts) { - if (m_rasterizer->GetDrawingMode() != RAS_IRasterizer::KX_TEXTURED || // no need for texture - m_camera->GetViewport() || // camera must be inactive - m_camera == m_scene->GetActiveCamera()) - { - // no need to compute texture in non texture rendering - m_avail = false; - return; - } - // render the scene from the camera - Render(); + if (m_rasterizer->GetDrawingMode() != RAS_IRasterizer::KX_TEXTURED || // no need for texture + m_camera->GetViewport() || // camera must be inactive + m_camera == m_scene->GetActiveCamera()) + { + // no need to compute texture in non texture rendering + m_avail = false; + return; + } + // render the scene from the camera + Render(); // get image from viewport ImageViewport::calcImage(texId, ts); - // restore OpenGL state - m_canvas->EndFrame(); + // restore OpenGL state + m_canvas->EndFrame(); } void ImageRender::Render() { RAS_FrameFrustum frustrum; - if (!m_render) - return; - - if (m_mirror) - { - // mirror mode, compute camera frustrum, position and orientation - // convert mirror position and normal in world space - const MT_Matrix3x3 & mirrorObjWorldOri = m_mirror->GetSGNode()->GetWorldOrientation(); - const MT_Point3 & mirrorObjWorldPos = m_mirror->GetSGNode()->GetWorldPosition(); - const MT_Vector3 & mirrorObjWorldScale = m_mirror->GetSGNode()->GetWorldScaling(); - MT_Point3 mirrorWorldPos = - mirrorObjWorldPos + mirrorObjWorldScale * (mirrorObjWorldOri * m_mirrorPos); - MT_Vector3 mirrorWorldZ = mirrorObjWorldOri * m_mirrorZ; - // get observer world position - const MT_Point3 & observerWorldPos = m_observer->GetSGNode()->GetWorldPosition(); - // get plane D term = mirrorPos . normal - MT_Scalar mirrorPlaneDTerm = mirrorWorldPos.dot(mirrorWorldZ); - // 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) - return; - // set camera world position = observerPos + normal * 2 * distance - MT_Point3 cameraWorldPos = observerWorldPos + (MT_Scalar(2.0)*observerDistance)*mirrorWorldZ; - m_camera->GetSGNode()->SetLocalPosition(cameraWorldPos); - // set camera orientation: z=normal, y=mirror_up in world space, x= y x z - MT_Vector3 mirrorWorldY = mirrorObjWorldOri * m_mirrorY; - MT_Vector3 mirrorWorldX = mirrorObjWorldOri * m_mirrorX; - MT_Matrix3x3 cameraWorldOri( - mirrorWorldX[0], mirrorWorldY[0], mirrorWorldZ[0], - mirrorWorldX[1], mirrorWorldY[1], mirrorWorldZ[1], - mirrorWorldX[2], mirrorWorldY[2], mirrorWorldZ[2]); - m_camera->GetSGNode()->SetLocalOrientation(cameraWorldOri); - m_camera->GetSGNode()->UpdateWorldData(0.0); - // compute camera frustrum: - // get position of mirror relative to camera: offset = mirrorPos-cameraPos - MT_Vector3 mirrorOffset = mirrorWorldPos - cameraWorldPos; - // convert to camera orientation - mirrorOffset = mirrorOffset * cameraWorldOri; - // scale mirror size to world scale: - // get closest local axis for mirror Y and X axis and scale height and width by local axis scale - MT_Scalar x, y; - x = fabs(m_mirrorY[0]); - y = fabs(m_mirrorY[1]); - float height = (x > y) ? - ((x > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): - ((y > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); - x = fabs(m_mirrorX[0]); - y = fabs(m_mirrorX[1]); - float width = (x > y) ? - ((x > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): - ((y > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); - width *= m_mirrorHalfWidth; - height *= m_mirrorHalfHeight; - // left = offsetx-width - // right = offsetx+width - // top = offsety+height - // bottom = offsety-height - // near = -offsetz - // far = near+100 - frustrum.x1 = mirrorOffset[0]-width; - frustrum.x2 = mirrorOffset[0]+width; - frustrum.y1 = mirrorOffset[1]-height; - frustrum.y2 = mirrorOffset[1]+height; - frustrum.camnear = -mirrorOffset[2]; - frustrum.camfar = -mirrorOffset[2]+m_clip; - } + if (!m_render) + return; + + if (m_mirror) + { + // mirror mode, compute camera frustrum, position and orientation + // convert mirror position and normal in world space + const MT_Matrix3x3 & mirrorObjWorldOri = m_mirror->GetSGNode()->GetWorldOrientation(); + const MT_Point3 & mirrorObjWorldPos = m_mirror->GetSGNode()->GetWorldPosition(); + const MT_Vector3 & mirrorObjWorldScale = m_mirror->GetSGNode()->GetWorldScaling(); + MT_Point3 mirrorWorldPos = + mirrorObjWorldPos + mirrorObjWorldScale * (mirrorObjWorldOri * m_mirrorPos); + MT_Vector3 mirrorWorldZ = mirrorObjWorldOri * m_mirrorZ; + // get observer world position + const MT_Point3 & observerWorldPos = m_observer->GetSGNode()->GetWorldPosition(); + // get plane D term = mirrorPos . normal + MT_Scalar mirrorPlaneDTerm = mirrorWorldPos.dot(mirrorWorldZ); + // 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) + return; + // set camera world position = observerPos + normal * 2 * distance + MT_Point3 cameraWorldPos = observerWorldPos + (MT_Scalar(2.0)*observerDistance)*mirrorWorldZ; + m_camera->GetSGNode()->SetLocalPosition(cameraWorldPos); + // set camera orientation: z=normal, y=mirror_up in world space, x= y x z + MT_Vector3 mirrorWorldY = mirrorObjWorldOri * m_mirrorY; + MT_Vector3 mirrorWorldX = mirrorObjWorldOri * m_mirrorX; + MT_Matrix3x3 cameraWorldOri( + mirrorWorldX[0], mirrorWorldY[0], mirrorWorldZ[0], + mirrorWorldX[1], mirrorWorldY[1], mirrorWorldZ[1], + mirrorWorldX[2], mirrorWorldY[2], mirrorWorldZ[2]); + m_camera->GetSGNode()->SetLocalOrientation(cameraWorldOri); + m_camera->GetSGNode()->UpdateWorldData(0.0); + // compute camera frustrum: + // get position of mirror relative to camera: offset = mirrorPos-cameraPos + MT_Vector3 mirrorOffset = mirrorWorldPos - cameraWorldPos; + // convert to camera orientation + mirrorOffset = mirrorOffset * cameraWorldOri; + // scale mirror size to world scale: + // get closest local axis for mirror Y and X axis and scale height and width by local axis scale + MT_Scalar x, y; + x = fabs(m_mirrorY[0]); + y = fabs(m_mirrorY[1]); + float height = (x > y) ? + ((x > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): + ((y > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); + x = fabs(m_mirrorX[0]); + y = fabs(m_mirrorX[1]); + float width = (x > y) ? + ((x > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): + ((y > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); + width *= m_mirrorHalfWidth; + height *= m_mirrorHalfHeight; + // left = offsetx-width + // right = offsetx+width + // top = offsety+height + // bottom = offsety-height + // near = -offsetz + // far = near+100 + frustrum.x1 = mirrorOffset[0]-width; + frustrum.x2 = mirrorOffset[0]+width; + frustrum.y1 = mirrorOffset[1]-height; + frustrum.y2 = mirrorOffset[1]+height; + frustrum.camnear = -mirrorOffset[2]; + frustrum.camfar = -mirrorOffset[2]+m_clip; + } // Store settings to be restored later - const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); + const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); RAS_Rect area = m_canvas->GetWindowArea(); - // The screen area that ImageViewport will copy is also the rendering zone - 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_engine->SetWorldSettings(m_scene->GetWorldInfo()); - m_rendertools->SetAuxilaryClientInfo(m_scene); - m_rasterizer->DisplayFog(); - // matrix calculation, don't apply any of the stereo mode - m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO); - if (m_mirror) - { - // frustrum was computed above - // get frustrum matrix and set projection matrix + // The screen area that ImageViewport will copy is also the rendering zone + 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_engine->SetWorldSettings(m_scene->GetWorldInfo()); + m_rendertools->SetAuxilaryClientInfo(m_scene); + m_rasterizer->DisplayFog(); + // matrix calculation, don't apply any of the stereo mode + m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO); + if (m_mirror) + { + // frustrum was computed above + // get frustrum matrix and set projection matrix MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + 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(); bool orthographic = !m_camera->GetCameraData()->m_perspective; float nearfrust = m_camera->GetCameraNear(); float farfrust = m_camera->GetCameraFar(); - float aspect_ratio = 1.0f; - Scene *blenderScene = m_scene->GetBlenderScene(); + float aspect_ratio = 1.0f; + Scene *blenderScene = m_scene->GetBlenderScene(); MT_Matrix4x4 projmat; // compute the aspect ratio from frame blender scene settings so that render to texture - // works the same in Blender and in Blender player - if (blenderScene->r.ysch != 0) - aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp); + // works the same in Blender and in Blender player + if (blenderScene->r.ysch != 0) + aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp); if (orthographic) { RAS_FramingManager::ComputeDefaultOrtho( - nearfrust, - farfrust, - m_camera->GetScale(), - aspect_ratio, - frustrum - ); + nearfrust, + farfrust, + m_camera->GetScale(), + aspect_ratio, + frustrum + ); projmat = m_rasterizer->GetOrthoMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); - } else + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + } else { RAS_FramingManager::ComputeDefaultFrustum( - nearfrust, - farfrust, - lens, - aspect_ratio, - frustrum); + nearfrust, + farfrust, + lens, + aspect_ratio, + frustrum); projmat = m_rasterizer->GetFrustumMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); } m_camera->SetProjectionMatrix(projmat); } @@ -257,8 +257,8 @@ void ImageRender::Render() m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldOrientation(), m_camera->NodeGetWorldPosition(), m_camera->GetCameraData()->m_perspective); m_camera->SetModelviewMatrix(viewmat); - // restore the stereo mode now that the matrix is computed - m_rasterizer->SetStereoMode(stereomode); + // restore the stereo mode now that the matrix is computed + m_rasterizer->SetStereoMode(stereomode); m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); @@ -328,11 +328,11 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get background color PyObject * getBackground (PyImage * self, void * closure) { - return Py_BuildValue("[BBBB]", - getImageRender(self)->getBackground(0), - getImageRender(self)->getBackground(1), - getImageRender(self)->getBackground(2), - getImageRender(self)->getBackground(3)); + return Py_BuildValue("[BBBB]", + getImageRender(self)->getBackground(0), + getImageRender(self)->getBackground(1), + getImageRender(self)->getBackground(2), + getImageRender(self)->getBackground(3)); } // set color @@ -433,24 +433,24 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds PyObject * scene; // reference object for mirror PyObject * observer; - // object holding the mirror - PyObject * mirror; - // material of the mirror - short materialID = 0; + // object holding the mirror + PyObject * mirror; + // material of the mirror + short materialID = 0; // parameter keywords static const char *kwlist[] = {"scene", "observer", "mirror", "material", NULL}; // get parameters if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|h", - const_cast<char**>(kwlist), &scene, &observer, &mirror, &materialID)) + const_cast<char**>(kwlist), &scene, &observer, &mirror, &materialID)) return -1; try { // get scene pointer KX_Scene * scenePtr (NULL); - if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) - scenePtr = static_cast<KX_Scene*>BGE_PROXY_REF(scene); + if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) + scenePtr = static_cast<KX_Scene*>BGE_PROXY_REF(scene); else - THRWEXCP(SceneInvalid, S_OK); + THRWEXCP(SceneInvalid, S_OK); if(scenePtr==NULL) /* incase the python proxy reference is invalid */ THRWEXCP(SceneInvalid, S_OK); @@ -458,11 +458,11 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get observer pointer KX_GameObject * observerPtr (NULL); if (observer != NULL && PyObject_TypeCheck(observer, &KX_GameObject::Type)) - observerPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(observer); - else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type)) - observerPtr = static_cast<KX_Camera*>BGE_PROXY_REF(observer); + observerPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(observer); + else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type)) + observerPtr = static_cast<KX_Camera*>BGE_PROXY_REF(observer); else - THRWEXCP(ObserverInvalid, S_OK); + THRWEXCP(ObserverInvalid, S_OK); if(observerPtr==NULL) /* incase the python proxy reference is invalid */ THRWEXCP(ObserverInvalid, S_OK); @@ -470,27 +470,27 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get mirror pointer KX_GameObject * mirrorPtr (NULL); if (mirror != NULL && PyObject_TypeCheck(mirror, &KX_GameObject::Type)) - mirrorPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(mirror); + mirrorPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(mirror); else - THRWEXCP(MirrorInvalid, S_OK); + THRWEXCP(MirrorInvalid, S_OK); if(mirrorPtr==NULL) /* incase the python proxy reference is invalid */ THRWEXCP(MirrorInvalid, S_OK); - // locate the material in the mirror + // locate the material in the mirror RAS_IPolyMaterial * material = getMaterial(mirror, materialID); if (material == NULL) - THRWEXCP(MaterialNotAvail, S_OK); + THRWEXCP(MaterialNotAvail, S_OK); // get pointer to image structure PyImage * self = reinterpret_cast<PyImage*>(pySelf); // create source object - if (self->m_image != NULL) - { - delete self->m_image; - self->m_image = NULL; - } + if (self->m_image != NULL) + { + delete self->m_image; + self->m_image = NULL; + } self->m_image = new ImageRender(scenePtr, observerPtr, mirrorPtr, material); } catch (Exception & exp) @@ -530,7 +530,7 @@ static PyGetSetDef imageMirrorGetSets[] = {(char*)"clip", (getter)getClip, (setter)setClip, (char*)"clipping distance", NULL}, // attribute from ImageRender {(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}, @@ -552,164 +552,164 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj m_scene(scene), m_observer(observer), m_mirror(mirror), - m_clip(100.f) + m_clip(100.f) { - // this constructor is used for automatic planar mirror - // create a camera, take all data by default, in any case we will recompute the frustrum on each frame + // this constructor is used for automatic planar mirror + // create a camera, take all data by default, in any case we will recompute the frustrum on each frame RAS_CameraData camdata; - vector<RAS_TexVert*> mirrorVerts; - vector<RAS_TexVert*>::iterator it; - float mirrorArea = 0.f; - float mirrorNormal[3] = {0.f, 0.f, 0.f}; - float mirrorUp[3]; - float dist, vec[3], axis[3]; - float zaxis[3] = {0.f, 0.f, 1.f}; - float yaxis[3] = {0.f, 1.f, 0.f}; - float mirrorMat[3][3]; - float left, right, top, bottom, back; + vector<RAS_TexVert*> mirrorVerts; + vector<RAS_TexVert*>::iterator it; + float mirrorArea = 0.f; + float mirrorNormal[3] = {0.f, 0.f, 0.f}; + float mirrorUp[3]; + float dist, vec[3], axis[3]; + float zaxis[3] = {0.f, 0.f, 1.f}; + float yaxis[3] = {0.f, 1.f, 0.f}; + float mirrorMat[3][3]; + float left, right, top, bottom, back; // make sure this camera will delete its node m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata, true, true); m_camera->SetName("__mirror__cam__"); - // don't add the camera to the scene object list, it doesn't need to be accessible - m_owncamera = true; - // retrieve rendering objects - 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++) - { - RAS_MeshObject* mesh = mirror->GetMesh(meshIndex); - int numPolygons = mesh->NumPolygons(); - for (int polygonIndex=0; polygonIndex < numPolygons; polygonIndex++) - { - RAS_Polygon* polygon = mesh->GetPolygon(polygonIndex); - if (polygon->GetMaterial()->GetPolyMaterial() == mat) - { - RAS_TexVert *v1, *v2, *v3, *v4; - float normal[3]; - float area; - // this polygon is part of the mirror, - v1 = polygon->GetVertex(0); - v2 = polygon->GetVertex(1); - v3 = polygon->GetVertex(2); - mirrorVerts.push_back(v1); - mirrorVerts.push_back(v2); - mirrorVerts.push_back(v3); - 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 = fabs(area); - mirrorArea += area; - mul_v3_fl(normal, area); - add_v3_v3v3(mirrorNormal, mirrorNormal, normal); - } - } - } - if (mirrorVerts.size() == 0 || mirrorArea < FLT_EPSILON) - { - // no vertex or zero size mirror - THRWEXCP(MirrorSizeInvalid, S_OK); - } - // compute average normal of mirror faces - mul_v3_fl(mirrorNormal, 1.0f/mirrorArea); - if (normalize_v3(mirrorNormal) == 0.f) - { - // no normal - THRWEXCP(MirrorNormalInvalid, S_OK); - } - // the mirror plane has an equation of the type ax+by+cz = d where (a,b,c) is the normal vector + // don't add the camera to the scene object list, it doesn't need to be accessible + m_owncamera = true; + // retrieve rendering objects + 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++) + { + RAS_MeshObject* mesh = mirror->GetMesh(meshIndex); + int numPolygons = mesh->NumPolygons(); + for (int polygonIndex=0; polygonIndex < numPolygons; polygonIndex++) + { + RAS_Polygon* polygon = mesh->GetPolygon(polygonIndex); + if (polygon->GetMaterial()->GetPolyMaterial() == mat) + { + RAS_TexVert *v1, *v2, *v3, *v4; + float normal[3]; + float area; + // this polygon is part of the mirror, + v1 = polygon->GetVertex(0); + v2 = polygon->GetVertex(1); + v3 = polygon->GetVertex(2); + mirrorVerts.push_back(v1); + mirrorVerts.push_back(v2); + mirrorVerts.push_back(v3); + 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 = fabs(area); + mirrorArea += area; + mul_v3_fl(normal, area); + add_v3_v3v3(mirrorNormal, mirrorNormal, normal); + } + } + } + if (mirrorVerts.size() == 0 || mirrorArea < FLT_EPSILON) + { + // no vertex or zero size mirror + THRWEXCP(MirrorSizeInvalid, S_OK); + } + // compute average normal of mirror faces + mul_v3_fl(mirrorNormal, 1.0f/mirrorArea); + if (normalize_v3(mirrorNormal) == 0.f) + { + // no normal + THRWEXCP(MirrorNormalInvalid, S_OK); + } + // the mirror plane has an equation of the type ax+by+cz = d where (a,b,c) is the normal vector // if the mirror is more vertical then horizontal, the Z axis is the up direction. // 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])) + fabs(mirrorNormal[2]) > fabs(mirrorNormal[0])) { // the mirror is more horizontal than vertical - copy_v3_v3(axis, yaxis); + copy_v3_v3(axis, yaxis); } else { // the mirror is more vertical than horizontal - copy_v3_v3(axis, zaxis); + copy_v3_v3(axis, zaxis); + } + dist = dot_v3v3(mirrorNormal, axis); + if (fabs(dist) < FLT_EPSILON) + { + // the mirror is already fully aligned with up axis + copy_v3_v3(mirrorUp, axis); + } + else + { + // projection of axis to mirror plane through normal + copy_v3_v3(vec, mirrorNormal); + mul_v3_fl(vec, dist); + sub_v3_v3v3(mirrorUp, axis, vec); + if (normalize_v3(mirrorUp) == 0.f) + { + // should not happen + THRWEXCP(MirrorHorizontal, S_OK); + return; + } + } + // compute rotation matrix between local coord and mirror coord + // to match camera orientation, we select mirror z = -normal, y = up, x = y x z + negate_v3_v3(mirrorMat[2], mirrorNormal); + copy_v3_v3(mirrorMat[1], mirrorUp); + cross_v3_v3v3(mirrorMat[0], mirrorMat[1], mirrorMat[2]); + // transpose to make it a orientation matrix from local space to mirror space + transpose_m3(mirrorMat); + // transform all vertex to plane coordinates and determine mirror position + left = FLT_MAX; + right = -FLT_MAX; + bottom = FLT_MAX; + top = -FLT_MAX; + back = -FLT_MAX; // most backward vertex (=highest Z coord in mirror space) + for (it = mirrorVerts.begin(); it != mirrorVerts.end(); it++) + { + copy_v3_v3(vec, (float*)(*it)->getXYZ()); + mul_m3_v3(mirrorMat, vec); + if (vec[0] < left) + left = vec[0]; + if (vec[0] > right) + right = vec[0]; + if (vec[1] < bottom) + bottom = vec[1]; + if (vec[1] > top) + top = vec[1]; + if (vec[2] > back) + back = vec[2]; + } + // now store this information in the object for later rendering + m_mirrorHalfWidth = (right-left)*0.5f; + m_mirrorHalfHeight = (top-bottom)*0.5f; + if (m_mirrorHalfWidth < 0.01f || m_mirrorHalfHeight < 0.01f) + { + // mirror too small + THRWEXCP(MirrorTooSmall, S_OK); } - dist = dot_v3v3(mirrorNormal, axis); - if (fabs(dist) < FLT_EPSILON) - { - // the mirror is already fully aligned with up axis - copy_v3_v3(mirrorUp, axis); - } - else - { - // projection of axis to mirror plane through normal - copy_v3_v3(vec, mirrorNormal); - mul_v3_fl(vec, dist); - sub_v3_v3v3(mirrorUp, axis, vec); - if (normalize_v3(mirrorUp) == 0.f) - { - // should not happen - THRWEXCP(MirrorHorizontal, S_OK); - return; - } - } - // compute rotation matrix between local coord and mirror coord - // to match camera orientation, we select mirror z = -normal, y = up, x = y x z - negate_v3_v3(mirrorMat[2], mirrorNormal); - copy_v3_v3(mirrorMat[1], mirrorUp); - cross_v3_v3v3(mirrorMat[0], mirrorMat[1], mirrorMat[2]); - // transpose to make it a orientation matrix from local space to mirror space - transpose_m3(mirrorMat); - // transform all vertex to plane coordinates and determine mirror position - left = FLT_MAX; - right = -FLT_MAX; - bottom = FLT_MAX; - top = -FLT_MAX; - back = -FLT_MAX; // most backward vertex (=highest Z coord in mirror space) - for (it = mirrorVerts.begin(); it != mirrorVerts.end(); it++) - { - copy_v3_v3(vec, (float*)(*it)->getXYZ()); - mul_m3_v3(mirrorMat, vec); - if (vec[0] < left) - left = vec[0]; - if (vec[0] > right) - right = vec[0]; - if (vec[1] < bottom) - bottom = vec[1]; - if (vec[1] > top) - top = vec[1]; - if (vec[2] > back) - back = vec[2]; - } - // now store this information in the object for later rendering - m_mirrorHalfWidth = (right-left)*0.5f; - m_mirrorHalfHeight = (top-bottom)*0.5f; - if (m_mirrorHalfWidth < 0.01f || m_mirrorHalfHeight < 0.01f) - { - // mirror too small - THRWEXCP(MirrorTooSmall, S_OK); - } - // mirror position in mirror coord - vec[0] = (left+right)*0.5f; - vec[1] = (top+bottom)*0.5f; - vec[2] = back; - // convert it in local space: transpose again the matrix to get back to mirror to local transform - transpose_m3(mirrorMat); - mul_m3_v3(mirrorMat, vec); - // mirror position in local space - m_mirrorPos.setValue(vec[0], vec[1], vec[2]); - // mirror normal vector (pointed towards the back of the mirror) in local space - m_mirrorZ.setValue(-mirrorNormal[0], -mirrorNormal[1], -mirrorNormal[2]); - m_mirrorY.setValue(mirrorUp[0], mirrorUp[1], mirrorUp[2]); - m_mirrorX = m_mirrorY.cross(m_mirrorZ); - m_render = true; + // mirror position in mirror coord + vec[0] = (left+right)*0.5f; + vec[1] = (top+bottom)*0.5f; + vec[2] = back; + // convert it in local space: transpose again the matrix to get back to mirror to local transform + transpose_m3(mirrorMat); + mul_m3_v3(mirrorMat, vec); + // mirror position in local space + m_mirrorPos.setValue(vec[0], vec[1], vec[2]); + // mirror normal vector (pointed towards the back of the mirror) in local space + m_mirrorZ.setValue(-mirrorNormal[0], -mirrorNormal[1], -mirrorNormal[2]); + m_mirrorY.setValue(mirrorUp[0], mirrorUp[1], mirrorUp[2]); + m_mirrorX = m_mirrorY.cross(m_mirrorZ); + m_render = true; setBackground(0, 0, 255, 255); } |