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/flare_model.h"
00029 #include "3d/flare_shape.h"
00030 #include "3d/driver.h"
00031 #include "3d/material.h"
00032 #include "3d/dru.h"
00033 #include "3d/scene.h"
00034 #include "3d/render_trav.h"
00035
00036
00037
00038 namespace NL3D {
00039
00040
00041
00042
00043
00044 CFlareModel::CFlareModel() : _Intensity(0)
00045 {
00046 setTransparency(true);
00047 setOpacity(false);
00048 }
00049
00050 void CFlareModel::registerBasic()
00051 {
00052
00053 CMOT::registerModel(FlareModelClassId, TransformShapeId, CFlareModel::creator);
00054 CMOT::registerObs(RenderTravId, FlareModelClassId, CFlareRenderObs::creator);
00055 }
00056
00057
00058
00059
00060 void CFlareRenderObs::traverse(IObs *caller)
00061 {
00062 CRenderTrav *trav = NLMISC::safe_cast<CRenderTrav *>(Trav);
00063 CFlareModel *m = NLMISC::safe_cast<CFlareModel *>(Model);
00064 IDriver *drv = trav->getDriver();
00065 if (trav->isCurrentPassOpaque()) return;
00066
00067
00068
00069
00070 const CVector upt = HrcObs->WorldMatrix.getPos();
00071 const CVector pt = trav->ViewMatrix * upt;
00072
00073
00074
00075 if (pt.y <= trav->Near)
00076 {
00077 return;
00078 }
00079
00080 nlassert(m->Shape);
00081 CFlareShape *fs = NLMISC::safe_cast<CFlareShape *>((IShape *) m->Shape);
00082
00083
00084 if (pt.y > fs->getMaxViewDist())
00085 {
00086 return;
00087 }
00088
00089 float distIntensity;
00090
00091 if (fs->getFlareAtInfiniteDist())
00092 {
00093 distIntensity = 1.f;
00094 }
00095 else
00096 {
00097
00098 const float distRatio = pt.y / fs->getMaxViewDist();
00099 distIntensity = distRatio > fs->getMaxViewDistRatio() ? 1.f - (distRatio - fs->getMaxViewDistRatio()) / (1.f - fs->getMaxViewDistRatio()) : 1.f;
00100 }
00101
00102
00103 uint32 width, height;
00104 drv->getWindowSize(width, height);
00105 const float middleX = .5f * (trav->Left + trav->Right);
00106 const float middleZ = .5f * (trav->Bottom + trav->Top);
00107 const sint xPos = (width>>1) + (sint) (width * (((trav->Near * pt.x) / pt.y) - middleX) / (trav->Right - trav->Left));
00108 const sint yPos = (height>>1) - (sint) (height * (((trav->Near * pt.z) / pt.y) - middleZ) / (trav->Top - trav->Bottom));
00109
00110
00111 static std::vector<float> v(1);
00112 NLMISC::CRect rect(xPos, height - yPos, 1, 1);
00113 drv->getZBufferPart(v, rect);
00114
00115
00116 const float z = (float) (1.0 - (1.0 / pt.y - 1.0 / trav->Far) / (1.0 /trav->Near - 1.0 / trav->Far));
00117
00118
00119 if (!v.size() || z > v[0])
00120 {
00121 float p = fs->getPersistence();
00122 if (fs == 0)
00123 {
00124 m->_Intensity = 0;
00125 return;
00126 }
00127 else
00128 {
00129 m->_Intensity -= 1.f / p * (float)m->_Scene->getEllapsedTime();
00130 if (m->_Intensity < 0.f)
00131 {
00132 m->_Intensity = 0.f;
00133 return;
00134 }
00135 }
00136 }
00137 else
00138 {
00139 float p = fs->getPersistence();
00140 if (fs == 0)
00141 {
00142 m->_Intensity = 1;
00143 }
00144 else
00145 {
00146 m->_Intensity += 1.f / p * (float)m->_Scene->getEllapsedTime();
00147 if (m->_Intensity > 1.f) m->_Intensity = 1.f;
00148 }
00149 }
00150
00151 static CMaterial material;
00152 static CVertexBuffer vb;
00153
00154 static bool setupDone = false;
00155
00156
00157 if (!setupDone)
00158 {
00159 material.setBlend(true);
00160 material.setBlendFunc(CMaterial::one, CMaterial::one);
00161 material.setZWrite(false);
00162 material.setZFunc(CMaterial::always);
00163 material.setLighting(false);
00164 material.setDoubleSided(true);
00165
00166
00167 vb.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag);
00168 vb.setNumVertices(4);
00169 vb.setTexCoord(0, 0, NLMISC::CUV(1, 0));
00170 vb.setTexCoord(1, 0, NLMISC::CUV(1, 1));
00171 vb.setTexCoord(2, 0, NLMISC::CUV(0, 1));
00172 vb.setTexCoord(3, 0, NLMISC::CUV(0, 0));
00173
00174 setupDone = true;
00175 }
00176
00177
00178
00179
00180
00181 drv->activeVertexProgram(NULL);
00182 drv->setupModelMatrix(CMatrix::Identity);
00183 drv->activeVertexBuffer(vb);
00184
00185
00186
00187
00188 const float zPos = 0.5f * (trav->Near + trav->Far);
00189 const float zPosDivNear = zPos / trav->Near;
00190
00191
00192 const float aX = ( (trav->Right - trav->Left) / (float) width) * zPosDivNear;
00193 const float bX = zPosDivNear * (middleX - 0.5f * (trav->Right - trav->Left));
00194
00195 const float aY = - ( (trav->Top - trav->Bottom) / (float) height) * zPosDivNear;
00196 const float bY = zPosDivNear * (middleZ + 0.5f * (trav->Top - trav->Bottom));
00197
00198 const CVector I = trav->CamMatrix.getI();
00199 const CVector J = trav->CamMatrix.getJ();
00200 const CVector K = trav->CamMatrix.getK();
00201
00202 CRGBA col;
00203 CRGBA flareColor = fs->getColor();
00204 const float norm = sqrtf((float) (((xPos - (width>>1)) * (xPos - (width>>1)) + (yPos - (height>>1))*(yPos - (height>>1)))))
00205 / (float) (width>>1);
00206
00207
00208 if (fs->hasDazzle())
00209 {
00210 if (norm < fs->getDazzleAttenuationRange())
00211 {
00212 float dazzleIntensity = 1.f - norm / fs->getDazzleAttenuationRange();
00213 CRGBA dazzleColor = fs->getDazzleColor();
00214 col.modulateFromui(dazzleColor, (uint) (255.f * m->_Intensity * dazzleIntensity));
00215 material.setColor(col);
00216 material.setTexture(0, NULL);
00217
00218 const CVector dazzleCenter = trav->CamPos + zPos * J;
00219 const CVector dI = (width>>1) * aX * I;
00220 const CVector dK = (height>>1) * bX * K;
00221
00222 vb.setVertexCoord(0, dazzleCenter + dI + dK);
00223 vb.setVertexCoord(1, dazzleCenter + dI - dK);
00224 vb.setVertexCoord(2, dazzleCenter - dI - dK);
00225 vb.setVertexCoord(3, dazzleCenter - dI + dK);
00226
00227 drv->renderQuads(material, 0, 1);
00228 }
00229 }
00230 if (!fs->getAttenuable() )
00231 {
00232 col.modulateFromui(flareColor, (uint) (255.f * distIntensity * m->_Intensity));
00233 }
00234 else
00235 {
00236 if (norm > fs->getAttenuationRange() || fs->getAttenuationRange() == 0.f)
00237 {
00238 return;
00239 }
00240 col.modulateFromui(flareColor, (uint) (255.f * distIntensity * m->_Intensity * (1.f - norm / fs->getAttenuationRange() )));
00241 }
00242
00243
00244 material.setColor(col);
00245
00246 CVector scrPos;
00247
00248
00249
00250 const float dX = fs->getFlareSpacing() * ((sint) (width >> 1) - xPos);
00251 const float dY = fs->getFlareSpacing() * ((sint) (height >> 1) - yPos);
00252
00253 float size;
00254
00255 uint k = 0;
00256 ITexture *tex;
00257
00258 if (fs->getFirstFlareKeepSize())
00259 {
00260 tex = fs->getTexture(0);
00261 if (tex)
00262 {
00263 size = fs->getSize(0);
00264
00265 vb.setVertexCoord(0, upt + size * (I + K) );
00266 vb.setVertexCoord(1, upt + size * (I - K) );
00267 vb.setVertexCoord(2, upt + size * (-I - K) );
00268 vb.setVertexCoord(3, upt + size * (-I + K) );
00269
00270
00271 material.setTexture(0, tex);
00272 drv->renderQuads(material, 0, 1);
00273 k = 1;
00274 }
00275 }
00276 else
00277 {
00278 k = 0;
00279 }
00280
00281 for (; k < MaxFlareNum; ++k)
00282 {
00283 tex = fs->getTexture(k);
00284 if (tex)
00285 {
00286
00287
00288 scrPos = (aX * (xPos + dX * fs->getRelativePos(k)) + bX) * I
00289 + zPos * J + (aY * (yPos + dY * fs->getRelativePos(k)) + bY) * K + trav->CamMatrix.getPos();
00290
00291
00292
00293
00294 size = fs->getSize(k) / trav->Near;
00295 vb.setVertexCoord(0, scrPos + size * (I + K) );
00296 vb.setVertexCoord(1, scrPos + size * (I - K) );
00297 vb.setVertexCoord(2, scrPos + size * (-I - K) );
00298 vb.setVertexCoord(3, scrPos + size * (-I + K) );
00299 material.setTexture(0, tex);
00300 drv->renderQuads(material, 0, 1);
00301 }
00302
00303 }
00304 this->traverseSons();
00305 }
00306
00307
00308
00309 }