// NeL - MMORPG Framework
// 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 .
#include "std3d.h"
#include "nel/3d/cube_map_builder.h"
#include "nel/3d/texture_cube.h"
#include "nel/3d/texture_mem.h"
#include "nel/misc/vector.h"
#include "nel/misc/rgba.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NL3D
{
// utility function : build a side of a cube map
static uint8 *BuildCubeMapTex(const NLMISC::CVector &start,
const NLMISC::CVector &uDir,
const NLMISC::CVector &vDir,
uint size,
ICubeMapFunctor &f
)
{
NLMISC::CRGBA *map = new NLMISC::CRGBA[size * size];
NLMISC::CRGBA *destTexel = map;
NLMISC::CVector currN = start;
NLMISC::CVector uStep = (2.f / size) * uDir;
NLMISC::CVector vStep = (2.f / size) * vDir;
for (uint y = 0; y < size; ++y)
{
NLMISC::CVector hCurrN = currN;
for (uint x = 0; x < size; ++x)
{
destTexel[x + y *size] = f(hCurrN.normed());
hCurrN += uStep;
}
currN += vStep;
}
return (uint8 *) map;
}
// utility function : build a side of a cube map, with luminance only
static uint8 *BuildCubeMapTexLuminance(const NLMISC::CVector &start,
const NLMISC::CVector &uDir,
const NLMISC::CVector &vDir,
uint size,
ICubeMapFunctor &f
)
{
uint8 *map = new uint8[size * size];
uint8 *destTexel = map;
NLMISC::CVector currN = start;
NLMISC::CVector uStep = (2.f / size) * uDir;
NLMISC::CVector vStep = (2.f / size) * vDir;
for (uint y = 0; y < size; ++y)
{
NLMISC::CVector hCurrN = currN;
for (uint x = 0; x < size; ++x)
{
destTexel[x + y *size] = f(hCurrN.normed()).A;
hCurrN += uStep;
}
currN += vStep;
}
return map;
}
CTextureCube *BuildCubeMap(sint mapSize, ICubeMapFunctor &f, bool luminanceOnly /* = false*/, const std::string &shareName /* = "" */)
{
CUniquePtr cubeMap(new CTextureCube);
CUniquePtr faces[6];
/// this gives the start (unormalized normal for each face for u,v = 0, 0)
static const NLMISC::CVector start[] =
{
NLMISC::CVector(1, 1, 1), /// positive_x
NLMISC::CVector(-1, 1, -1), /// negative_x
NLMISC::CVector(-1, 1, -1), /// positive_y
NLMISC::CVector(-1, -1, 1), /// negative_y
NLMISC::CVector(-1, 1, 1), /// positive_z
NLMISC::CVector(1, 1, -1) /// negative_z
};
static const NLMISC::CVector uDir[] =
{
NLMISC::CVector::K, /// positive_x
- NLMISC::CVector::K, /// negative_x
- NLMISC::CVector::I, /// positive_y
- NLMISC::CVector::I, /// negative_y
NLMISC::CVector::I, /// positive_z
-NLMISC::CVector::I, /// negative_z
};
static const NLMISC::CVector vDir[] =
{
- NLMISC::CVector::J, /// positive_x
- NLMISC::CVector::J, /// negative_x
NLMISC::CVector::K, /// positive_y
- NLMISC::CVector::K, /// negative_y
NLMISC::CVector::J, /// positive_z
NLMISC::CVector::J, /// negative_z
};
uint k;
/// build all faces
for (k = 0; k < 6; ++k)
{
faces[k].reset(new CTextureMem);
uint8 *map = luminanceOnly ? BuildCubeMapTexLuminance(start[k], uDir[k], vDir[k], mapSize, f)
: BuildCubeMapTex(start[k], uDir[k], vDir[k], mapSize, f);
faces[k]->setPointer(map,
mapSize * mapSize * sizeof(uint8) * (luminanceOnly ? 1 : 4),
true,
false,
mapSize,
mapSize,
luminanceOnly ? CBitmap::Luminance : CBitmap::RGBA
);
if (!shareName.empty())
{
faces[k]->setShareName(shareName + (char) ('0' + k));
}
}
static const CTextureCube::TFace toTC[] = { CTextureCube::positive_x, CTextureCube::negative_x,
CTextureCube::positive_z, CTextureCube::negative_z,
CTextureCube::negative_y, CTextureCube::positive_y };
/// assign faces
for (k = 0; k < 6; ++k)
{
cubeMap->setTexture(toTC[k], faces[k].release());
}
return cubeMap.release();
}
} // NL3D