1/*********************************************************************** 2 created: Tue Mar 3 2009 3 author: Paul D Turner (parts based on original code by Thomas Suter) 4*************************************************************************/ 5/*************************************************************************** 6 * Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining 9 * a copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be 17 * included in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 ***************************************************************************/ 27#include "CEGUI/RendererModules/Irrlicht/RenderTarget.h" 28#include "CEGUI/GeometryBuffer.h" 29#include "CEGUI/RenderQueue.h" 30#include "CEGUI/RendererModules/Irrlicht/GeometryBuffer.h" 31 32// Start of CEGUI namespace section 33namespace CEGUI 34{ 35//----------------------------------------------------------------------------// 36template <typename T> 37IrrlichtRenderTarget<T>::IrrlichtRenderTarget(IrrlichtRenderer& owner, 38 irr::video::IVideoDriver& driver) : 39 d_owner(owner), 40 d_driver(driver), 41 d_area(0, 0, 0, 0), 42 d_matrixValid(false), 43 d_viewDistance(0), 44#if IRRLICHT_VERSION_MAJOR > 1 || (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) 45 d_xViewDir(1.0f) 46#else 47 d_xViewDir(driver.getDriverType() != irr::video::EDT_OPENGL ? 1.0f : -1.0f) 48#endif 49{ 50} 51 52//----------------------------------------------------------------------------// 53template <typename T> 54IrrlichtRenderTarget<T>::~IrrlichtRenderTarget() 55{ 56} 57 58//----------------------------------------------------------------------------// 59template <typename T> 60void IrrlichtRenderTarget<T>::draw(const GeometryBuffer& buffer) 61{ 62 buffer.draw(); 63} 64 65//----------------------------------------------------------------------------// 66template <typename T> 67void IrrlichtRenderTarget<T>::draw(const RenderQueue& queue) 68{ 69 queue.draw(); 70} 71 72//----------------------------------------------------------------------------// 73template <typename T> 74void IrrlichtRenderTarget<T>::setArea(const Rectf& area) 75{ 76 d_area = area; 77 d_matrixValid = false; 78 79 RenderTargetEventArgs args(this); 80 T::fireEvent(RenderTarget::EventAreaChanged, args); 81} 82 83//----------------------------------------------------------------------------// 84template <typename T> 85const Rectf& IrrlichtRenderTarget<T>::getArea() const 86{ 87 return d_area; 88} 89 90//----------------------------------------------------------------------------// 91template <typename T> 92void IrrlichtRenderTarget<T>::activate() 93{ 94 irr::core::rect<irr::s32> vp(static_cast<irr::s32>(d_area.left()), 95 static_cast<irr::s32>(d_area.top()), 96 static_cast<irr::s32>(d_area.right()), 97 static_cast<irr::s32>(d_area.bottom())); 98 d_driver.setViewPort(vp); 99 100 if (!d_matrixValid) 101 updateMatrix(); 102 103 d_driver.setTransform(irr::video::ETS_PROJECTION, d_matrix); 104 d_driver.setTransform(irr::video::ETS_VIEW, irr::core::matrix4()); 105} 106 107//----------------------------------------------------------------------------// 108template <typename T> 109void IrrlichtRenderTarget<T>::deactivate() 110{ 111} 112 113//----------------------------------------------------------------------------// 114template <typename T> 115void IrrlichtRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff, 116 const Vector2f& p_in, 117 Vector2f& p_out) const 118{ 119 if (!d_matrixValid) 120 updateMatrix(); 121 122 const IrrlichtGeometryBuffer& gb = 123 static_cast<const IrrlichtGeometryBuffer&>(buff); 124 125 const irr::f32 midx = d_area.getWidth() * 0.5f; 126 const irr::f32 midy = d_area.getHeight() * 0.5f; 127 128 // viewport matrix 129 const irr::f32 vpmat_[] = 130 { 131 midx, 0, 0, 0, 132 0, -midy, 0, 0, 133 0, 0, 1, 0, 134 d_area.left() + midx, d_area.top() + midy, 0, 1 135 }; 136 irr::core::matrix4 vpmat; 137 vpmat.setM(vpmat_); 138 139 // matrices used for projecting and unprojecting points 140 const irr::core::matrix4 proj(gb.getMatrix() * d_matrix * vpmat); 141 irr::core::matrix4 unproj(proj); 142 unproj.makeInverse(); 143 144 irr::core::vector3df in; 145 146 // unproject the ends of the ray 147 in.X = midx; 148 in.Y = midy; 149 in.Z = -d_viewDistance; 150 irr::core::vector3df r1; 151 unproj.transformVect(r1, in); 152 in.X = p_in.d_x; 153 in.Y = p_in.d_y; 154 in.Z = 0; 155 irr::core::vector3df r2; 156 unproj.transformVect(r2, in); 157 // calculate vector of picking ray 158 const irr::core::vector3df rv(r1 - r2); 159 160 // project points to orientate them with GeometryBuffer plane 161 in.X = 0.0; 162 in.Y = 0.0; 163 irr::core::vector3df p1; 164 proj.transformVect(p1, in); 165 in.X = 1.0; 166 in.Y = 0.0; 167 irr::core::vector3df p2; 168 proj.transformVect(p2, in); 169 in.X = 0.0; 170 in.Y = 1.0; 171 irr::core::vector3df p3; 172 proj.transformVect(p3, in); 173 174 // calculate the plane normal 175 const irr::core::vector3df pn((p2 - p1).crossProduct(p3 - p1)); 176 // calculate distance from origin 177 const irr::f32 plen = pn.getLength(); 178 const irr::f32 dist = -(p1.X * (pn.X / plen) + 179 p1.Y * (pn.Y / plen) + 180 p1.Z * (pn.Z / plen)); 181 182 // calculate intersection of ray and plane 183 const irr::f32 pn_dot_rv = pn.dotProduct(rv); 184 const irr::f32 tmp = pn_dot_rv != 0.0 ? 185 (pn.dotProduct(r1) + dist) / pn_dot_rv : 186 0.0f; 187 188 p_out.d_x = static_cast<float>(r1.X - rv.X * tmp) * d_viewDistance; 189 p_out.d_y = static_cast<float>(r1.Y - rv.Y * tmp) * d_viewDistance; 190} 191 192//----------------------------------------------------------------------------// 193template <typename T> 194void IrrlichtRenderTarget<T>::updateMatrix() const 195{ 196 const float w = d_area.getWidth(); 197 const float h = d_area.getHeight(); 198 const float aspect = w / h; 199 const float midx = w * 0.5f; 200 const float midy = h * 0.5f; 201 d_viewDistance = midx / (aspect * 0.267949192431123f); 202 203 d_matrix.buildProjectionMatrixPerspectiveFovRH(0.523598776f, aspect, 204 d_viewDistance * 0.5f, 205 d_viewDistance * 2.0f); 206 207 irr::core::matrix4 tmp; 208 tmp.buildCameraLookAtMatrixRH( 209 irr::core::vector3df(d_xViewDir * midx, midy, -d_viewDistance), 210 irr::core::vector3df(d_xViewDir * midx, midy, 1), 211 irr::core::vector3df(0, -1, 0)); 212 213 d_matrix *= tmp; 214 215 d_matrixValid = true; 216} 217 218//----------------------------------------------------------------------------// 219 220} // End of CEGUI namespace section 221