1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
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
;
35 // ------------------------------------------------------------------------------------------------
36 CCloud::CCloud (CCloudScape
*pCloudScape
)
38 _CloudScape
= pCloudScape
;
39 _Driver
= _CloudScape
->_Driver
;
40 CloudPower
= 255; // Max Power
43 CloudDiffuse
= CRGBA(255,255,255,255);
44 CloudAmbient
= CRGBA(120,140,160,255);
48 _UStart
= _VStart
= _WStart
= NULL
;
51 // ------------------------------------------------------------------------------------------------
59 // ------------------------------------------------------------------------------------------------
60 void CCloud::init (uint32 nVoxelW
, uint32 nVoxelH
, uint32 nVoxelD
, float rBaseFreq
, uint32 nNbOctave
)
65 _BaseFreq
= rBaseFreq
;
69 _NbOctave
= nNbOctave
;
70 _UStart
= new double[_NbOctave
];
71 _VStart
= new double[_NbOctave
];
72 _WStart
= new double[_NbOctave
];
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);
88 _NbH
= 2 << (vdpo2
/ 2);
90 _NbH
= 1 << (vdpo2
/ 2);
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
)
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
122 CVertexBuffer
&rVB
= _CloudScape
->_VertexBuffer
;
123 uint32 nVSize
= rVB
.getVertexSize ();
125 CVertexBufferReadWrite 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
,
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);
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));
170 // Apply attenuation texture (not needed to resetup position again (done when clearing to black))
172 CVertexBufferReadWrite 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 ()
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
;
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
217 // Set the frustum and viewport on all the billboards to clear them
218 _Driver
->setFrustum (0, 1, 0, 1, -1, 1, false);
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
);
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
250 CVertexBufferReadWrite 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
;
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
;
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);
307 _Driver
->setRenderTarget (NULL
);
309 _CloudTexTmp
->Tex
->setFilterMode (ITexture::Linear
, ITexture::LinearMipMapOff
);
313 // ------------------------------------------------------------------------------------------------
314 void CCloud::reset (NL3D::CCamera
*pViewer
)
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)
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);
342 CVertexBuffer
&rVB
= _CloudScape
->_VertexBuffer
;
344 CVertexBufferReadWrite 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);
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);
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
;
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;
401 // ------------------------------------------------------------------------------------------------
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 ////////////////////////////////////////////////////////////////////////
413 _Driver
->setupScissor (s
);
414 _Driver
->setupViewport (CViewport());
415 _Driver
->setFrustum (0.0f
, 1.0f
, 0.0f
, 1.0f
, -1.0f
, 1.0f
, false);
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
;
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
;
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
)
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 ();
478 _Driver
->activeVertexBuffer (rVB
);
483 for (j
= 0; j
< _NbH
; ++j
)
485 for (i
= 0; i
< _NbW
; ++i
)
490 CVertexBufferReadWrite 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
;
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
;
544 if (fabsf(Center
.y
-Viewer
.y
) > fabsf(Center
.z
-Viewer
.z
))
564 mat
.setRot(I
,J
,K
, true);
565 mat
.setPos(CVector(Viewer
.x
, Viewer
.y
, Viewer
.z
));
569 for (i
= 0; i
< 2; ++i
)
570 for (j
= 0; j
< 2; ++j
)
571 for (k
= 0; k
< 2; ++k
)
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;
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
)
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;
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
)
608 uint32 sizeTMP
= _OldBillSize
;
609 uint8
*MemTMP
= _MemOldBill
;
610 CSmartPtr
<CTextureMem
> TexTMP
= _TexOldBill
;
612 _OldBillSize
= _BillSize
;
613 _MemOldBill
= _MemBill
;
614 _TexOldBill
= _TexBill
;
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
;
650 float Left
, Right
, Top
, Bottom
, Near
, Far
;
652 calcBill (Viewer
, Center
, Size
, I
, J
, K
, Left
, Right
, Top
, Bottom
, Near
, Far
);
656 mat
.setRot(I
,J
,K
, true);
657 mat
.setPos(CVector(Viewer
.x
, Viewer
.y
, Viewer
.z
));
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
;
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);
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
;
703 _WaitState
= _WaitState
- 1;
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
;
722 float Left
, Right
, Top
, Bottom
, Near
, Far
;
724 if ((_MemBill
== NULL
) || (_MemOldBill
== NULL
))
730 if (Time
> FuturTime
)
733 // take old computed bill.
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;*/
748 calcBill (Viewer
, Center
, Size
, I
, J
, K
, Left
, Right
, Top
, Bottom
, Near
, Far
);
749 CVector lct
= Viewer
+ J
*Near
;
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
;
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
;
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
;
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
);
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);
815 if (_CloudScape
->isDebugQuadEnabled())
817 static CMaterial
*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));*/
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));
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);
865 ViewMatrix
.identity ();
866 ViewMatrix
.setRot (I
,J
,K
, true);
868 Scissor
.initFullScreen();
869 _Driver
->setupScissor (Scissor
);
870 _Driver
->setupViewport (CViewport());
871 _Driver
->setupViewMatrix (ViewMatrix
);
872 _Driver
->setupModelMatrix (CMatrix::Identity
);