khanat-opennel-code/code/nel/src/3d/heat_haze.cpp
acemtp@users.sourceforge.net d5c601ffa5 initial version
2010-05-06 02:08:41 +02:00

115 lines
3.4 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "std3d.h"
#include "nel/3d/heat_haze.h"
#include "nel/3d/scene.h"
#include "nel/3d/deform_2d.h"
#include "nel/misc/vector_2f.h"
namespace NL3D
{
struct CSinWave : public CDeform2d::IPerturbUV
{
virtual ~CSinWave() {}
float Phase;
virtual void perturbUV(float x, float y, float &du, float &dv) const
{
du = 0.01f * sinf(25.f * y + Phase);
dv = 0.05f * cosf(19.3f * x + Phase);
}
} _SinWave;
void CHeatHaze::performHeatHaze(uint width, uint height, CScene &s, IDriver *drv)
{
NLMISC::CMatrix m = s.getCam()->getMatrix();
NLMISC::CMatrix im = m.inverted();
// compute the shape of the horizon
// first we compute the direction of the world up vector in the viewer basis.
NLMISC::CVector up = im * NLMISC::CVector::K;
// project onto the I and K vectors
float upNorm = (up.x * up.x + up.z * up.z);
const float threshold = 10E-4f;
if (upNorm < threshold) return; // the viewer is looking above or below himlself
// Compute the right vector. This is done by intersecting the horizon plane with a near plane.
// to do this, we transform the horizon plane into the view basis.This may be optimized, but is not critical.
//
NLMISC::CPlane h;
h.make(NLMISC::CVector::K, NLMISC::CVector::Null);
h = h * m; // note : this multiply by the transposition of m
// intersect with near plane : we got y = 0, which gives us, as a right vector :
// if c is not 0, we got : x = 1 and z = (-a - d) / c as a working solution.
// Else we got x = (- d - c )/ a and z = 1
NLMISC::CVector right;
if (fabsf(h.c) > threshold)
{
right.set(1, 0, (h.a + h.d) / - h.c );
}
else
{
right.set( (h.d + h.c) / h.a, 0, 1);
}
right.normalize();
// now, find a point on screen that lay on the horizon line
static std::vector<NLMISC::CVector2f> poly(4);
const sint xCenter = width >> 1;
const sint yCenter = height >> 1;
const float horizonHeight = (float) (height >> 2);
const float horizonWidth = (float) (width >> 2);
NLMISC::CVector tmp ;
tmp = horizonWidth * right + horizonHeight * up;
poly[0] = NLMISC::CVector2f(xCenter + tmp.x, yCenter + tmp.z) ;
tmp = horizonWidth * right - horizonHeight * up;
poly[1] = NLMISC::CVector2f(xCenter + tmp.x, yCenter + tmp.z) ;
tmp = - horizonWidth * right - horizonHeight * up;
poly[2] = NLMISC::CVector2f(xCenter + tmp.x, yCenter + tmp.z);
tmp = - horizonWidth * right + horizonHeight * up;
poly[3] = NLMISC::CVector2f(xCenter + tmp.x, yCenter + tmp.z);
CDeform2d::doDeform(poly, drv, &_SinWave);
}
} // NL3D