00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/texture_bump.h"
00029
00030
00031 namespace NL3D {
00032
00033
00035 static void BuildDsDt(uint32 *src, sint width, sint height, uint16 *dest, bool absolute)
00036 {
00037 #define GET_HGT(x, y) ((sint) ((src[(uint) (x) % width + ((uint) (y) % height) * width] & 0x00ff00) >> 8))
00038 sint x, y;
00039 for (x = 0; x < width; ++x)
00040 {
00041 for (y = 0; y < height; ++y)
00042 {
00043 sint off = x + y * width;
00044 sint16 ds = (sint16) (GET_HGT(x + 1, y) - GET_HGT(x - 1, y));
00045 sint16 dt = (sint16) (GET_HGT(x, y + 1) - GET_HGT(x, y - 1));
00046
00047 if (!absolute)
00048 {
00049
00050 dest[off] = (uint16) ((ds & 0xff) | ((dt & 0xff) << 8));
00051 }
00052 else
00053 {
00054 dest[off] = (uint16) (abs(ds) | (abs(dt) << 8));
00055 }
00056 }
00057 }
00058 }
00059
00061 static float NormalizeDsDt(uint16 *src, sint width, sint height, bool absolute)
00062 {
00063 const uint size = width * height;
00064 uint highestDelta = 0;
00065 uint k;
00066
00068 if (absolute)
00069 {
00070 for (k = 0; k < size; ++k)
00071 {
00072 highestDelta = std::max(highestDelta, (uint) (src[k] & 255));
00073 highestDelta = std::max(highestDelta, (uint) src[k] >> 8);
00074 }
00075
00076 if (highestDelta == 0)
00077 {
00078 return 1.f;
00079 }
00080 float normalizationFactor = 255.f / highestDelta;
00081 for (k = 0; k < size; ++k)
00082 {
00083 uint8 du = (uint8) ((uint) (src[k] & 0xff) * normalizationFactor);
00084 uint16 dv = (uint16) (((uint) src[k] >> 8) * normalizationFactor);
00085 src[k] = (uint16) du | (dv << 8);
00086 }
00087 return 1.f / normalizationFactor;
00088 }
00089 else
00090 {
00091 for (k = 0; k < size; ++k)
00092 {
00093 highestDelta = std::max(highestDelta, (uint) ::abs((sint) (sint8) (src[k] & 255)));
00094 highestDelta = std::max(highestDelta, (uint) ::abs((sint) (sint8) (src[k] >> 8)));
00095 }
00096
00097 if (highestDelta == 0)
00098 {
00099 return 1.f;
00100 }
00101 float normalizationFactor = 127.f / highestDelta;
00102 for (k = 0; k < size; ++k)
00103 {
00104 float fdu = (sint8) (src[k] & 255) * normalizationFactor;
00105 float fdv = (sint8) (src[k] >> 8) * normalizationFactor;
00106 NLMISC::clamp(fdu, -128, 127);
00107 NLMISC::clamp(fdv, -128, 127);
00108 uint8 du = (uint8) (sint8) fdu;
00109 uint8 dv = (uint8) (sint8) fdv;
00110 src[k] = (uint16) du | (((uint16) dv) << 8);
00111 }
00112 return 1.f / normalizationFactor;
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121 CTextureBump::CTextureBump() : _NormalizationFactor(0.f),
00122 _DisableSharing(false),
00123 _UseAbsoluteOffsets(false),
00124 _ForceNormalize(true)
00125 {
00126
00127 ITexture::setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
00128 }
00129
00131 void CTextureBump::setFilterMode(TMagFilter magf, TMinFilter minf)
00132 {
00133 nlstop;
00134 }
00135
00136 void CTextureBump::setHeightMap(ITexture *heightMap)
00137 {
00138 if (heightMap != _HeightMap)
00139 {
00140 _HeightMap = heightMap;
00141 touch();
00142 }
00143 }
00144
00145
00147 void CTextureBump::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00148 {
00150 sint ver = f.serialVersion(2);
00151 ITexture::serial(f);
00152 ITexture *tex = NULL;
00153 if (f.isReading())
00154 {
00155 f.serialPolyPtr(tex);
00156 _HeightMap = tex;
00157 touch();
00158 }
00159 else
00160 {
00161 tex = _HeightMap;
00162 f.serialPolyPtr(tex);
00163 }
00164 f.serial(_DisableSharing);
00165 if (ver >= 1)
00166 {
00167 f.serial(_UseAbsoluteOffsets);
00168 }
00169 if (ver >= 2)
00170 {
00171 f.serial(_ForceNormalize);
00172 }
00173 }
00174
00176 void CTextureBump::doGenerate()
00177 {
00178 if (!_HeightMap)
00179 {
00180 makeDummy();
00181 return;
00182 }
00183
00184 _HeightMap->generate();
00185 if (!_HeightMap->convertToType(CBitmap::RGBA))
00186 {
00187 makeDummy();
00188 return;
00189 }
00190 releaseMipMaps();
00191 uint width = _HeightMap->getWidth();
00192 uint height = _HeightMap->getHeight();
00193 CBitmap::resize(_HeightMap->getWidth(), _HeightMap->getHeight(), CBitmap::DsDt);
00194
00195 BuildDsDt((uint32 *) &(_HeightMap->getPixels()[0]), width, height, (uint16 *) &(getPixels()[0]), _UseAbsoluteOffsets);
00196
00197
00198 if (_ForceNormalize)
00199 {
00200 _NormalizationFactor = NormalizeDsDt((uint16 *) &(getPixels()[0]), width, height, _UseAbsoluteOffsets);
00201 }
00202
00203 if (_HeightMap->getReleasable())
00204 {
00205 _HeightMap->release();
00206 }
00207 }
00208
00210 void CTextureBump::release()
00211 {
00212 ITexture::release();
00213 if (_HeightMap != NULL)
00214 {
00215 if (_HeightMap->getReleasable())
00216 {
00217 _HeightMap->release();
00218 }
00219 }
00220 }
00221
00222
00224 bool CTextureBump::supportSharing() const
00225 {
00226 return !_DisableSharing && _HeightMap && _HeightMap->supportSharing();
00227 }
00228
00229
00231 std::string CTextureBump::getShareName() const
00232 {
00233 nlassert(supportSharing());
00234 return "BumpDsDt:" + _HeightMap->getShareName();
00235 }
00236
00237
00238 }