Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / cloud.cpp
blobbfd83ba800158787d33a7acdc33ba1674d07373e
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
18 #include "nel/3d/material.h"
19 #include "nel/3d/cloud.h"
20 #include "nel/3d/cloud_scape.h"
21 #include "nel/3d/noise_3d.h"
22 #include "nel/3d/scissor.h"
23 #include "nel/3d/viewport.h"
24 #include "nel/3d/driver.h"
26 using namespace NLMISC;
28 #ifdef DEBUG_NEW
29 #define new DEBUG_NEW
30 #endif
32 namespace NL3D
35 // ------------------------------------------------------------------------------------------------
36 CCloud::CCloud (CCloudScape *pCloudScape)
38 _CloudScape = pCloudScape;
39 _Driver = _CloudScape->_Driver;
40 CloudPower = 255; // Max Power
41 LastCloudPower = 255;
42 CloudDistAtt = 0;
43 CloudDiffuse = CRGBA(255,255,255,255);
44 CloudAmbient = CRGBA(120,140,160,255);
45 _WaitState = 0;
46 _BillSize = 0;
47 _OldBillSize = 0;
48 _UStart = _VStart = _WStart = NULL;
51 // ------------------------------------------------------------------------------------------------
52 CCloud::~CCloud()
54 delete _UStart;
55 delete _VStart;
56 delete _WStart;
59 // ------------------------------------------------------------------------------------------------
60 void CCloud::init (uint32 nVoxelW, uint32 nVoxelH, uint32 nVoxelD, float rBaseFreq, uint32 nNbOctave)
62 if (_UStart != NULL)
63 return;
65 _BaseFreq = rBaseFreq;
66 _BillSize = 0;
67 _OldBillSize = 0;
69 _NbOctave = nNbOctave;
70 _UStart = new double[_NbOctave];
71 _VStart = new double[_NbOctave];
72 _WStart = new double[_NbOctave];
74 uint32 i;
75 for (i = 0; i < _NbOctave; ++i)
77 _UStart[i] = ((double)rand())/RAND_MAX;
78 _VStart[i] = ((double)rand())/RAND_MAX;
79 _WStart[i] = ((double)rand())/RAND_MAX;
82 _Width = raiseToNextPowerOf2 (nVoxelW);
83 _Height = raiseToNextPowerOf2 (nVoxelH);
84 _Depth = raiseToNextPowerOf2 (nVoxelD);
85 uint32 vdpo2 = getPowerOf2(_Depth);
86 _NbW = 1 << (vdpo2 / 2);
87 if ((vdpo2 & 1) != 0)
88 _NbH = 2 << (vdpo2 / 2);
89 else
90 _NbH = 1 << (vdpo2 / 2);
92 _MemBill = NULL;
93 _MemOldBill = NULL;
95 float scale = 20.0f + 10.0f*((float)rand())/RAND_MAX;;
96 _Size.x = scale * _Width/_Depth;
97 scale = 20.0f + 10.0f*((float)rand())/RAND_MAX;;
98 _Size.y = scale * _Height/_Depth;
99 scale = 20.0f + 10.0f*((float)rand())/RAND_MAX;;
100 _Size.z = scale * _Depth/_Depth;
105 // ------------------------------------------------------------------------------------------------
106 void CCloud::generate (CNoise3d &noise)
108 float dU, dV, dW;
109 uint32 nOct;
110 CQuadUV qc;
112 //nldebug("calling CCloud::generate(...)");
114 // Active the render target
115 _Driver->setRenderTarget (_CloudTexTmp->Tex, 0, 0, _Width*_NbW, _Height*_NbH);
116 _Driver->setFrustum (0, (float)_CloudTexTmp->Tex->getWidth(), 0, (float)_CloudTexTmp->Tex->getHeight(), -1, 1, false);
118 // Setup the matrices view&model, viewport and frustum
119 setMode2D ();
121 // Clear background
122 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
123 uint32 nVSize = rVB.getVertexSize ();
125 CVertexBufferReadWrite vba;
126 rVB.lock (vba);
127 CVector *pVertices = vba.getVertexCoordPointer (0);
128 *pVertices = CVector(0.0f, 0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
129 *pVertices = CVector((float)_NbW*_Width,0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
130 *pVertices = CVector((float)_NbW*_Width,(float)_NbH*_Height,0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
131 *pVertices = CVector(0.0f, (float)_NbH*_Height,0.0f);
132 _CloudScape->_MatClear.setColor (CRGBA(0,0,0,0));
135 _Driver->activeVertexBuffer (rVB);
136 _Driver->renderRawQuads (_CloudScape->_MatClear, 0, 1);
138 // Create cloud from noise
139 for (nOct = 0; nOct < _NbOctave; ++nOct)
141 dU = (_BaseFreq*((float)_Width)/noise.getWidth())*(1<<nOct);
142 dV = (_BaseFreq*((float)_Height)/noise.getHeight())*(1<<nOct);
143 dW = (_BaseFreq*((float)_Depth)/noise.getDepth())*(1<<nOct);
146 noise.renderGrid (_NbW, _NbH, _Width, _Height,
147 (float)_UStart[nOct], (float)_VStart[nOct], (float)_WStart[nOct], dU, dV, dW,
148 1.0f/(2<<nOct));
150 /* This is the same thing as a renderGrid which is optimized to do that
151 qc.Uv0 = CUV((float)_UStart[nOct], (float)_VStart[nOct]);
152 qc.Uv1 = CUV((float)_UStart[nOct]+dU, (float)_VStart[nOct]);
153 qc.Uv2 = CUV((float)_UStart[nOct]+dU, (float)_VStart[nOct]+dV);
154 qc.Uv3 = CUV((float)_UStart[nOct], (float)_VStart[nOct]+dV);
155 uint32 i,j;
156 for (j = 0; j < _NbH; ++j)
158 for (i = 0; i < _NbW; ++i)
160 qc.V0 = CVector((float)i*_Width, (float)j*_Height, 0.0f);
161 qc.V1 = CVector((float)(i+1)*_Width, (float)j*_Height, 0.0f);
162 qc.V2 = CVector((float)(i+1)*_Width, (float)(j+1)*_Height, 0.0f);
163 qc.V3 = CVector((float)i*_Width, (float)(j+1)*_Height, 0.0f);
164 noise.render (qc, (float)_WStart[nOct]+dW*(i+(float)j*_NbW)/(((float)_NbW)*_NbH), 1.0f/(2<<nOct));
167 noise.flush ();
170 // Apply attenuation texture (not needed to resetup position again (done when clearing to black))
172 CVertexBufferReadWrite vba;
173 rVB.lock (vba);
174 CUV *pUV = vba.getTexCoordPointer (0, 0);
175 pUV->U = 0.0f; pUV->V = 0.0f; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
176 pUV->U = 1.0f; pUV->V = 0.0f; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
177 pUV->U = 1.0f; pUV->V = 1.0f; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
178 pUV->U = 0.0f; pUV->V = 1.0f;
180 uint8 colpow = (uint8)(255-(((uint32)CloudPower*(255-(uint32)CloudDistAtt)) / 255));
181 _CloudTexClamp->ToClamp.setColor (CRGBA(255, 255, 255, colpow));
182 _Driver->activeVertexBuffer (rVB);
183 _Driver->renderRawQuads (_CloudTexClamp->ToClamp, 0, 1);
185 // Restore render target
186 _Driver->setRenderTarget (NULL);
188 _CloudTexTmp->Tex->setFilterMode (ITexture::Nearest, ITexture::NearestMipMapOff);
192 // ------------------------------------------------------------------------------------------------
193 void CCloud::light ()
196 uint32 i, j;
198 // Destination position for lighting accumulation buffer from (0, 0) size (_Width, _Height)
199 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
200 uint32 nVSize = rVB.getVertexSize ();
202 CVertexBufferReadWrite vba;
203 rVB.lock (vba);
204 CVector *pVertices = vba.getVertexCoordPointer (0);
205 *pVertices = CVector((float)0.0f, (float)0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
206 *pVertices = CVector((float)1.f, (float)0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
207 *pVertices = CVector((float)1.f, (float)1.f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
208 *pVertices = CVector((float)0.0f, (float)1.f, 0.0f);
211 // Active the render target
212 _Driver->setRenderTarget (_CloudTexTmp->TexBuffer, 0, 0, _Width, _Height);
214 // Setup the matrices view&model, viewport and frustum
215 setMode2D ();
217 // Set the frustum and viewport on all the billboards to clear them
218 _Driver->setFrustum (0, 1, 0, 1, -1, 1, false);
219 CViewport viewport;
220 viewport.init (0, 0, 1, 1);
221 _Driver->setupViewport (viewport);
223 // Clear the screen accumulator for lighting
224 CloudDiffuse.A = 255;
225 // _CloudScape->_MatClear.setColor (CloudDiffuse);
226 _Driver->activeVertexBuffer (rVB);
227 _Driver->clear2D (CloudDiffuse);
229 CUV *pUV;
230 // Lighting : render the alpha of one layer into rgb of the screen
231 float oneOverNbW = 1.0f/_NbW;
232 float oneOverNbH = 1.0f/_NbH;
233 uint32 previ = 0, prevj = 0;
234 _Driver->activeVertexBuffer (rVB);
235 for (j = 0; j < _NbH; ++j)
237 for (i = 0; i < _NbW; ++i)
239 // Active the render target
240 _Driver->setRenderTarget (_CloudTexTmp->TexBuffer, 0, 0, _Width, _Height);
242 // Set the frustum and viewport on the current billboard
243 viewport.init (0, 0, 1, 1);
244 _Driver->setupViewport (viewport);
246 // Add the alpha of the previous layer into the RGB of the destination
247 if ((i+j) > 0)
250 CVertexBufferReadWrite vba;
251 rVB.lock (vba);
253 _Driver->setColorMask (true, true, true, false);
254 pUV = vba.getTexCoordPointer (0, 0);
255 pUV->U = previ*oneOverNbW; pUV->V = prevj*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
256 pUV->U = (previ+1)*oneOverNbW; pUV->V = prevj*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
257 pUV->U = (previ+1)*oneOverNbW; pUV->V = (prevj+1)*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
258 pUV->U = previ*oneOverNbW; pUV->V = (prevj+1)*oneOverNbH;
261 _Driver->renderRawQuads (_CloudTexTmp->ToLightRGB, 0, 1);
263 // Replace the alpha of the destination by the alpha of the current layer
264 _Driver->setColorMask (false, false, false, true);
267 CVertexBufferReadWrite vba;
268 rVB.lock (vba);
270 pUV = vba.getTexCoordPointer (0, 0);
271 pUV->U = i*oneOverNbW; pUV->V = j*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
272 pUV->U = (i+1)*oneOverNbW; pUV->V = j*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
273 pUV->U = (i+1)*oneOverNbW; pUV->V = (j+1)*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
274 pUV->U = i*oneOverNbW; pUV->V = (j+1)*oneOverNbH;
277 _Driver->renderRawQuads (_CloudTexTmp->ToLightAlpha, 0, 1);
279 // Copy the billboard
280 _Driver->setColorMask (true, true, true, true);
282 /* The copy target trick. If not available, render the temporary texture in Tex2 */
283 if (!_Driver->copyTargetToTexture (_CloudTexTmp->Tex2, i*_Width, j*_Height, 0, 0, 0, 0, 0))
285 _Driver->setRenderTarget (_CloudTexTmp->Tex2, i*_Width, j*_Height, _Width, _Height);
286 viewport.init ((float)i*oneOverNbW, (float)j*oneOverNbH, oneOverNbW, oneOverNbH);
287 _Driver->setupViewport (viewport);
290 CVertexBufferReadWrite vba;
291 rVB.lock (vba);
293 pUV = vba.getTexCoordPointer (0, 0);
294 pUV->U = 0; pUV->V = 0; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
295 pUV->U = 1; pUV->V = 0; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
296 pUV->U = 1; pUV->V = 1; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
297 pUV->U = 0; pUV->V = 1;
300 _Driver->renderRawQuads (_CloudTexTmp->MatCopy, 0, 1);
303 previ = i;
304 prevj = j;
307 _Driver->setRenderTarget (NULL);
309 _CloudTexTmp->Tex->setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
313 // ------------------------------------------------------------------------------------------------
314 void CCloud::reset (NL3D::CCamera *pViewer)
316 if (_BillSize != 4)
318 _BillSize = 4;
319 _MemBill = new uint8[4*_BillSize*_BillSize];
320 _TexBill = new CTextureMem (_MemBill, 4*_BillSize*_BillSize, true, false, _BillSize, _BillSize);
321 _TexBill->setWrapS (ITexture::Clamp);
322 _TexBill->setWrapT (ITexture::Clamp);
323 _TexBill->setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
324 _TexBill->generate();
325 _TexBill->setReleasable (false);
326 _TexBill->setRenderTarget (true);
328 if (_OldBillSize != 4)
330 _OldBillSize = 4;
331 _MemOldBill = new uint8[4*_OldBillSize*_OldBillSize];
332 _TexOldBill = new CTextureMem (_MemOldBill, 4*_OldBillSize*_OldBillSize, true, false, _OldBillSize, _OldBillSize);
333 _TexOldBill->setWrapS (ITexture::Clamp);
334 _TexOldBill->setWrapT (ITexture::Clamp);
335 _TexOldBill->setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
336 _TexOldBill->generate();
337 _TexOldBill->setReleasable (false);
338 _TexOldBill->setRenderTarget (true);
341 // Clear background
342 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
344 CVertexBufferReadWrite vba;
345 rVB.lock (vba);
346 uint32 nVSize = rVB.getVertexSize ();
347 CVector *pVertices = vba.getVertexCoordPointer (0);
348 *pVertices = CVector(0.0f, 0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
349 *pVertices = CVector(5.0f, 0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
350 *pVertices = CVector(5.0f, 5.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
351 *pVertices = CVector(0.0f, 5.0f, 0.0f);
352 _CloudScape->_MatClear.setColor (CRGBA(0,0,0,0));
354 _Driver->activeVertexBuffer (rVB);
356 _Driver->setRenderTarget (_TexBill, 0, 0, 4, 4);
357 setMode2D ();
358 _Driver->setFrustum (0, 4, 0, 4, -1, 1, false);
359 _Driver->renderRawQuads (_CloudScape->_MatClear, 0, 1);
360 _Driver->setRenderTarget (_TexOldBill, 0, 0, 4, 4);
361 setMode2D ();
362 _Driver->renderRawQuads (_CloudScape->_MatClear, 0, 1);
363 _Driver->setRenderTarget (NULL);
365 // CMatrix CamMat = pViewer->getMatrix();
366 // CVector Viewer = CamMat.getPos();
367 CVector Viewer = CVector(0,0,0);
368 CVector Center = CVector (_Pos.x+_Size.x/2, _Pos.y+_Size.y/2, _Pos.z+_Size.z/2);
369 CVector Size = _Size;
370 CVector I, J, K;
371 float Left, Right, Top, Bottom, Near, Far;
373 calcBill (Viewer, Center, Size, I, J, K, Left, Right, Top, Bottom, Near, Far);
375 _BillOldCenter = _BillCenter;
376 _BillViewer = Viewer;
377 _BillCenter = Center;
379 calcBill (Viewer, Center, Size, I, J, K, Left, Right, Top, Bottom, Near, Far);
381 _BillOldCenter = _BillCenter;
382 _BillViewer = Viewer;
383 _BillCenter = Center;
387 // ------------------------------------------------------------------------------------------------
388 void CCloud::anim (double dt, double dt2)
390 for (uint32 nOct = 0; nOct < _NbOctave; ++nOct)
392 _UStart[nOct] += dt*(1<<nOct) / 5000.0;
393 _VStart[nOct] += dt*(1<<nOct) / 5000.0;
394 _WStart[nOct] += dt*(1<<nOct) / 5000.0;
396 //_Pos.x += dt2;
397 //Time += dt2;
401 // ------------------------------------------------------------------------------------------------
402 void CCloud::disp ()
404 CQuadUV qc;
405 qc.Uv0 = CUV(0.0f, 0.0f);
406 qc.Uv1 = CUV(1.0f, 0.0f);
407 qc.Uv2 = CUV(1.0f, 1.0f);
408 qc.Uv3 = CUV(0.0f, 1.0f);
410 ////////////////////////////////////////////////////////////////////////
411 CScissor s;
412 s.initFullScreen();
413 _Driver->setupScissor (s);
414 _Driver->setupViewport (CViewport());
415 _Driver->setFrustum (0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, false);
416 CVector I(1,0,0);
417 CVector J(0,0,1);
418 CVector K(0,-1,0);
419 CMatrix ViewMatrix;
420 ViewMatrix.identity();
421 ViewMatrix.setRot(I,J,K, true);
422 _Driver->setupViewMatrix(ViewMatrix);
423 _Driver->setupModelMatrix(CMatrix::Identity);
424 ////////////////////////////////////////////////////////////////////////
426 uint32 w = _NbW*_Width;
427 uint32 h = _NbH*_Height;
428 qc.V0 = CVector(0.0f/800.0f, 0.0f/600.0f, 0.0f);
429 qc.V1 = CVector(w/800.0f, 0.0f/600.0f, 0.0f);
430 qc.V2 = CVector(w/800.0f, h/600.0f, 0.0f);
431 qc.V3 = CVector(0.0f/800.0f, h/600.0f, 0.0f);
432 static CMaterial *dispMat = NULL;
433 if (dispMat == NULL)
435 dispMat = new CMaterial;
436 dispMat->initUnlit();
437 dispMat->setTexture(0, _CloudTexTmp->Tex);
438 dispMat->texEnvOpRGB(0, CMaterial::Replace);
439 //dispMat->texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcAlpha);
440 dispMat->texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor);
441 dispMat->setZFunc(CMaterial::always);
442 dispMat->setZWrite(false);
443 dispMat->setDoubleSided(true);
444 dispMat->setBlend (false);
447 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
449 CVertexBufferReadWrite vba;
450 rVB.lock (vba);
451 vba.setVertexCoord (0, qc.V0);
452 vba.setVertexCoord (1, qc.V1);
453 vba.setVertexCoord (2, qc.V2);
454 vba.setVertexCoord (3, qc.V3);
455 vba.setTexCoord (0, 0, qc.Uv0);
456 vba.setTexCoord (1, 0, qc.Uv1);
457 vba.setTexCoord (2, 0, qc.Uv2);
458 vba.setTexCoord (3, 0, qc.Uv3);
460 _Driver->activeVertexBuffer (rVB);
461 _Driver->renderRawQuads (*dispMat, 0, 1);
465 // ------------------------------------------------------------------------------------------------
466 void CCloud::dispXYZ (CMaterial *pMat)
468 CQuadUV qc;
469 uint32 i,j;
471 float oneOverNbW = 1.0f / _NbW;
472 float oneOverNbH = 1.0f / _NbH;
473 float oneOverNbWNbH = 1.0f / (_NbW*_NbH);
474 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
475 uint32 nVSize = rVB.getVertexSize ();
476 CVector *pVertices;
477 CUV *pUV;
478 _Driver->activeVertexBuffer (rVB);
480 if (pMat == NULL)
481 return;
483 for (j = 0; j < _NbH; ++j)
485 for (i = 0; i < _NbW; ++i)
487 uint32 d = i+j*_NbW;
490 CVertexBufferReadWrite vba;
491 rVB.lock (vba);
493 pVertices = vba.getVertexCoordPointer (0);
494 *pVertices = CVector(_Pos.x, _Pos.y, _Pos.z+_Size.z*(_NbW*_NbH-d)*oneOverNbWNbH); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
495 *pVertices = CVector(_Pos.x+_Size.x, _Pos.y, _Pos.z+_Size.z*(_NbW*_NbH-d)*oneOverNbWNbH); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
496 *pVertices = CVector(_Pos.x+_Size.x, _Pos.y+_Size.y, _Pos.z+_Size.z*(_NbW*_NbH-d)*oneOverNbWNbH); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
497 *pVertices = CVector(_Pos.x, _Pos.y+_Size.y, _Pos.z+_Size.z*(_NbW*_NbH-d)*oneOverNbWNbH);
499 pUV = vba.getTexCoordPointer (0, 0);
500 pUV->U = i*oneOverNbW; pUV->V = j*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
501 pUV->U = (i+1)*oneOverNbW; pUV->V = j*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
502 pUV->U = (i+1)*oneOverNbW; pUV->V = (j+1)*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
503 pUV->U = i*oneOverNbW; pUV->V = (j+1)*oneOverNbH;
505 pUV = vba.getTexCoordPointer (0, 1);
506 pUV->U = i*oneOverNbW; pUV->V = j*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
507 pUV->U = (i+1)*oneOverNbW; pUV->V = j*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
508 pUV->U = (i+1)*oneOverNbW; pUV->V = (j+1)*oneOverNbH; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
509 pUV->U = i*oneOverNbW; pUV->V = (j+1)*oneOverNbH;
512 _Driver->renderRawQuads (*pMat, 0, 1);
517 CVertexBufferReadWrite vba;
518 rVB.lock (vba);
519 CVector *pVertices = vba.getVertexCoordPointer (0);
520 *pVertices = CVector((float)0.25f, 0, (float)0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
521 *pVertices = CVector((float)0.75f, 0, (float)0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
522 *pVertices = CVector((float)0.75f, 0, (float)0.75f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
523 *pVertices = CVector((float)0.25f, 0, (float)0.75f);
527 // ------------------------------------------------------------------------------------------------
528 // in ; viewer, center
529 // out I,J,K, left,right,top,bottom,near,far
530 void CCloud::calcBill (const CVector &Viewer, const CVector &Center, const CVector &Size, CVector &I, CVector &J, CVector &K,
531 float &Left, float &Right, float &Top, float &Bottom, float &Near, float &Far)
534 CVector ViewDir = Center - Viewer;
535 ViewDir.normalize();
537 Left = 1000.0f;
538 Right = -1000.0f;
539 Top = -1000.0f;
540 Bottom = 1000.0f;
541 Near = 1000.0f;
542 Far = -1000.0f;
544 if (fabsf(Center.y-Viewer.y) > fabsf(Center.z-Viewer.z))
546 K.set(0, 0, 1);
547 J= ViewDir;
548 I= J^K;
549 K= I^J;
551 else
553 K.set(0, 1, 0);
554 J= ViewDir;
555 I= J^K;
556 K= I^J;
558 I.normalize();
559 J.normalize();
560 K.normalize();
562 CMatrix mat;
563 mat.identity();
564 mat.setRot(I,J,K, true);
565 mat.setPos(CVector(Viewer.x, Viewer.y, Viewer.z));
566 mat.invert();
568 uint32 i, j, k;
569 for (i = 0; i < 2; ++i)
570 for (j = 0; j < 2; ++j)
571 for (k = 0; k < 2; ++k)
573 CVector v;
574 if (i == 0) v.x = Center.x-Size.x/2; else v.x = Center.x+Size.x/2;
575 if (j == 0) v.y = Center.y-Size.y/2; else v.y = Center.y+Size.y/2;
576 if (k == 0) v.z = Center.z-Size.z/2; else v.z = Center.z+Size.z/2;
577 v = mat.mulPoint(v);
578 if (v.y < Near) Near = v.y;
579 if (v.y > Far) Far = v.y;
582 for (i = 0; i < 2; ++i)
583 for (j = 0; j < 2; ++j)
584 for (k = 0; k < 2; ++k)
586 CVector v;
587 if (i == 0) v.x = Center.x-Size.x/2; else v.x = Center.x+Size.x/2;
588 if (j == 0) v.y = Center.y-Size.y/2; else v.y = Center.y+Size.y/2;
589 if (k == 0) v.z = Center.z-Size.z/2; else v.z = Center.z+Size.z/2;
590 v = mat.mulPoint(v);
591 v.x = v.x / (v.y/Near);
592 v.z = v.z / (v.y/Near);
593 if (v.x < Left) Left = v.x;
594 if (v.x > Right) Right = v.x;
595 if (v.z < Bottom) Bottom = v.z;
596 if (v.z > Top) Top = v.z;
601 // ------------------------------------------------------------------------------------------------
602 // Create the billboard (in the screen at pos (NbW*Width, 0)
603 void CCloud::genBill (CCamera *pCam, uint32 nBillSize)
605 // Render target
607 // Compute the Bill
608 uint32 sizeTMP = _OldBillSize;
609 uint8 *MemTMP = _MemOldBill;
610 CSmartPtr<CTextureMem> TexTMP = _TexOldBill;
612 _OldBillSize = _BillSize;
613 _MemOldBill = _MemBill;
614 _TexOldBill = _TexBill;
615 _BillSize = sizeTMP;
616 _MemBill = MemTMP;
617 _TexBill = TexTMP;
619 // Check the new size of the billboard
620 if (nBillSize != _BillSize)
622 _BillSize = nBillSize;
623 _MemBill = new uint8[4*_BillSize*_BillSize];
624 _TexBill = new CTextureMem (_MemBill, 4*_BillSize*_BillSize, true, false, _BillSize, _BillSize);
625 //for (i = 0; i < 4*_BillSize*_BillSize; ++i) _MemBill[i] = (uint8)i;
626 _TexBill->setWrapS (ITexture::Clamp);
627 _TexBill->setWrapT (ITexture::Clamp);
628 _TexBill->setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
629 _TexBill->setReleasable (false);
630 _TexBill->setRenderTarget (true);
631 _TexBill->generate();
634 // Render target size
635 uint32 textureW = _TexBill->getWidth();
636 uint32 textureH = _TexBill->getHeight();
637 _Driver->setRenderTarget (_TexBill, 0, 0, _BillSize, _BillSize);
639 CViewport viewport, viewportOLD;
640 viewportOLD.initFullScreen();
641 viewport.init(0.0f, 0.0f, ((float)_BillSize+1)/((float)textureW), ((float)_BillSize+1)/((float)textureH));
642 _Driver->setupViewport (viewport);
644 //CMatrix CamMat = pCam->getMatrix();
645 //CVector Viewer = CamMat.getPos();
646 CVector Viewer = CVector (0,0,0);
647 CVector Center = CVector (_Pos.x+_Size.x/2, _Pos.y+_Size.y/2, _Pos.z+_Size.z/2);
648 CVector Size = _Size;
649 CVector I, J, K;
650 float Left, Right, Top, Bottom, Near, Far;
652 calcBill (Viewer, Center, Size, I, J, K, Left, Right, Top, Bottom, Near, Far);
654 CMatrix mat;
655 mat.identity();
656 mat.setRot(I,J,K, true);
657 mat.setPos(CVector(Viewer.x, Viewer.y, Viewer.z));
658 mat.invert();
660 // Clear background for cloud creation
661 _Driver->setFrustum(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, false);
662 _Driver->setupViewMatrix (CMatrix::Identity);
663 _Driver->setupModelMatrix (CMatrix::Identity);
665 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
666 uint32 nVSize = rVB.getVertexSize ();
668 CVertexBufferReadWrite vba;
669 rVB.lock (vba);
671 CVector *pVertices = vba.getVertexCoordPointer (0);
672 *pVertices = CVector(0.0f, 0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
673 *pVertices = CVector(1.0f, 0.0f, 0.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
674 *pVertices = CVector(1.0f, 0.0f, 1.0f); pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
675 *pVertices = CVector(0.0f, 0.0f, 1.0f);
679 _CloudScape->_MatClear.setColor (CRGBA(0,0,0,0));
680 _Driver->activeVertexBuffer (rVB);
681 _Driver->renderRawQuads (_CloudScape->_MatClear, 0, 1);
683 // Render
684 _Driver->setFrustum(Left, Right, Bottom, Top, Near, Far);
685 _Driver->setupViewMatrix(mat);
686 _Driver->setupModelMatrix (CMatrix::Identity);
688 _CloudTexTmp->ToBill.setColor (CloudAmbient);
690 dispXYZ (&_CloudTexTmp->ToBill);
692 // Restore render target
693 _Driver->setRenderTarget (NULL);
695 // This is the end of render to texture like so reset all stuff
696 _Driver->setupViewport (viewportOLD);
698 _BillOldCenter = _BillCenter;
699 _BillViewer = Viewer;
700 _BillCenter = Center;
702 if (_WaitState > 0)
703 _WaitState = _WaitState - 1;
705 _LastX = _Pos.x;
709 // ------------------------------------------------------------------------------------------------
710 void CCloud::dispBill (CCamera *pCam)
712 // CMatrix CamMat = pCam->getMatrix();
713 // CVector Viewer = CamMat.getPos();
714 CVector Viewer = CVector (0,0,0);
715 CVector Center = CVector (_Pos.x+_Size.x/2, _Pos.y+_Size.y/2, _Pos.z+_Size.z/2);
716 CVector Size = _Size;
718 // Prepare vertices.
719 CQuadUV qc;
721 CVector I, J, K;
722 float Left, Right, Top, Bottom, Near, Far;
724 if ((_MemBill == NULL) || (_MemOldBill == NULL))
725 return;
727 if (_WaitState > 0)
728 return;
730 if (Time > FuturTime)
731 Time = FuturTime;
733 // take old computed bill.
734 Viewer= _BillViewer;
735 /* Center= _BillCenter*((float)(Trans)/(float)TransTotal) +
736 _BillOldCenter*((float)(TransTotal-Trans)/(float)TransTotal);
738 calcBill (Viewer, Center, Size, I, J, K, Left, Right, Top, Bottom, Near, Far);
741 CVector lct = Viewer + J*Near;
742 qc.V0 = lct + I*Left + K*Bottom;
743 qc.V1 = lct + I*Right + K*Bottom;
744 qc.V2 = lct + I*Right + K*Top;
745 qc.V3 = lct + I*Left + K*Top;*/
747 Center= _BillCenter;
748 calcBill (Viewer, Center, Size, I, J, K, Left, Right, Top, Bottom, Near, Far);
749 CVector lct = Viewer + J*Near;
750 CQuadUV qc0;
751 qc0.V0 = lct + I*Left + K*Bottom;
752 qc0.V1 = lct + I*Right + K*Bottom;
753 qc0.V2 = lct + I*Right + K*Top;
754 qc0.V3 = lct + I*Left + K*Top;
756 Center= _BillOldCenter;
757 calcBill (Viewer, Center, Size, I, J, K, Left, Right, Top, Bottom, Near, Far);
758 lct = Viewer + J*Near;
759 CQuadUV qc1;
760 qc1.V0 = lct + I*Left + K*Bottom;
761 qc1.V1 = lct + I*Right + K*Bottom;
762 qc1.V2 = lct + I*Right + K*Top;
763 qc1.V3 = lct + I*Left + K*Top;
765 float a0= ((float)(Time)/(float)FuturTime);
766 float a1= (float)(FuturTime-Time)/(float)FuturTime;
767 qc.V0= qc0.V0*a0 + qc1.V0*a1;
768 qc.V1= qc0.V1*a0 + qc1.V1*a1;
769 qc.V2= qc0.V2*a0 + qc1.V2*a1;
770 qc.V3= qc0.V3*a0 + qc1.V3*a1;
772 qc.Uv0 = CUV(0, 0);
773 qc.Uv1 = CUV(1, 0);
774 qc.Uv2 = CUV(1, 1);
775 qc.Uv3 = CUV(0, 1);
777 // Display TexBill with intensity : Trans / TransTotal
778 // and TexOldBill with intensity : (TransTotal-Trans) / TransTotal
780 _CloudScape->_MatBill.setTexture (0, _TexOldBill);
781 _CloudScape->_MatBill.setTexture (1, _TexBill);
782 _CloudScape->_MatBill.setColor (CRGBA(255, 255, 255, (uint8)(255*((float)Time/(float)FuturTime))));
783 CVertexBuffer &rVB = _CloudScape->_VertexBuffer;
785 CVertexBufferReadWrite vba;
786 rVB.lock (vba);
788 uint32 nVSize = rVB.getVertexSize ();
789 CVector *pVertices = vba.getVertexCoordPointer (0);
790 *pVertices = qc.V0; pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
791 *pVertices = qc.V1; pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
792 *pVertices = qc.V2; pVertices = (CVector*)( ((uint8*)pVertices) + nVSize );
793 *pVertices = qc.V3;
795 CUV *pUV = vba.getTexCoordPointer (0, 0);
796 pUV->U = 0; pUV->V = 0; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
797 pUV->U = 1; pUV->V = 0; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
798 pUV->U = 1; pUV->V = 1; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
799 pUV->U = 0; pUV->V = 1;
801 pUV = vba.getTexCoordPointer (0, 1);
802 pUV->U = 0; pUV->V = 0; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
803 pUV->U = 1; pUV->V = 0; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
804 pUV->U = 1; pUV->V = 1; pUV = (CUV*)( ((uint8*)pUV) + nVSize );
805 pUV->U = 0; pUV->V = 1;
808 _Driver->activeVertexBuffer (rVB);
809 _Driver->renderRawQuads (_CloudScape->_MatBill, 0, 1);
811 //nlinfo ("ok");
814 // Debug
815 if (_CloudScape->isDebugQuadEnabled())
817 static CMaterial *mTmp = NULL;
818 if (mTmp == NULL)
820 mTmp = new CMaterial();
821 mTmp->setBlend(false);
822 mTmp->setDoubleSided(true);
824 /*if (_BillSize <= 4)
825 mTmp->setColor(CRGBA(0,127,0,255));
826 else if (_BillSize == 8)
827 mTmp->setColor(CRGBA(0,255,0,255));
828 else if (_BillSize == 16)
829 mTmp->setColor(CRGBA(127,255,0,255));
830 else if (_BillSize == 32)
831 mTmp->setColor(CRGBA(255,255,0,255));
832 else if (_BillSize == 64)
833 mTmp->setColor(CRGBA(255,127,0,255));
834 else if (_BillSize == 128)
835 mTmp->setColor(CRGBA(255,0,0,255));
836 else if (_BillSize == 256)
837 mTmp->setColor(CRGBA(127,0,0,255));*/
839 if (FuturTime <= 4)
840 mTmp->setColor(CRGBA(0,127,0,255));
841 else if (FuturTime <= 8)
842 mTmp->setColor(CRGBA(0,255,0,255));
843 else if (FuturTime <= 12)
844 mTmp->setColor(CRGBA(127,255,0,255));
845 else if (FuturTime <= 16)
846 mTmp->setColor(CRGBA(255,255,0,255));
847 else if (FuturTime <= 20)
848 mTmp->setColor(CRGBA(255,127,0,255));
849 else
850 mTmp->setColor(CRGBA(255,0,0,255));
852 _Driver->setPolygonMode(IDriver::Line);
853 _Driver->renderRawQuads (*mTmp, 0, 1);
854 _Driver->setPolygonMode(IDriver::Filled);
860 // ------------------------------------------------------------------------------------------------
861 void CCloud::setMode2D ()
863 CVector I(1,0,0), J(0,0,1), K(0,-1,0);
864 CMatrix ViewMatrix;
865 ViewMatrix.identity ();
866 ViewMatrix.setRot (I,J,K, true);
867 CScissor Scissor;
868 Scissor.initFullScreen();
869 _Driver->setupScissor (Scissor);
870 _Driver->setupViewport (CViewport());
871 _Driver->setupViewMatrix (ViewMatrix);
872 _Driver->setupModelMatrix (CMatrix::Identity);
875 } // namespace NL3D