Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / 3d / computed_string.cpp
blob3d5bdff862709b48810f803f1131a13a956b6d11
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/3d/computed_string.h"
23 #include "nel/3d/texture.h"
24 #include "nel/3d/index_buffer.h"
25 #include "nel/3d/material.h"
26 #include "nel/3d/frustum.h"
27 #include "nel/3d/viewport.h"
28 #include "nel/3d/debug_vb.h"
30 #include "nel/misc/smart_ptr.h"
31 #include "nel/misc/debug.h"
33 #include "nel/misc/file.h"
34 #include "nel/misc/fast_mem.h"
36 using namespace std;
38 #ifdef DEBUG_NEW
39 #define new DEBUG_NEW
40 #endif
42 namespace NL3D {
45 /*------------------------------------------------------------------*\
46 getHotSpotVector()
47 \*------------------------------------------------------------------*/
48 CVector CComputedString::getHotSpotVector(THotSpot hotspot)
50 CVector hotspotVector(0,0,0);
52 if (hotspot==MiddleLeft)
53 hotspotVector = CVector(0,0,-StringHeight/2);
55 if (hotspot==TopLeft)
56 hotspotVector = CVector(0,0,-StringHeight);
58 if (hotspot==MiddleBottom)
59 hotspotVector = CVector(-StringWidth/2,0,0);
61 if (hotspot==MiddleMiddle)
62 hotspotVector = CVector(-StringWidth/2,0,-StringHeight/2);
64 if (hotspot==MiddleTop)
65 hotspotVector = CVector(-StringWidth/2,0,-StringHeight);
67 if (hotspot==BottomRight)
68 hotspotVector = CVector(-StringWidth,0,0);
70 if (hotspot==MiddleRight)
71 hotspotVector = CVector(-StringWidth,0,-StringHeight/2);
73 if (hotspot==TopRight)
74 hotspotVector = CVector(-StringWidth,0,-StringHeight);
76 return hotspotVector;
80 /*------------------------------------------------------------------*\
81 render2D()
82 \*------------------------------------------------------------------*/
83 void CComputedString::render2D (IDriver& driver,
84 float x, float z,
85 THotSpot hotspot,
86 float scaleX, float scaleZ,
87 float rotateY,
88 bool useScreenAR43, bool roundToNearestPixel
91 if (Vertices.getNumVertices() == 0)
92 return;
94 // get window size
95 uint32 wndWidth, wndHeight;
96 driver.getWindowSize(wndWidth, wndHeight);
97 CViewport vp;
98 driver.getViewport(vp);
99 wndWidth = (uint32)((float)wndWidth * vp.getWidth());
100 wndHeight = (uint32)((float)wndHeight * vp.getHeight());
101 // scale to window size.
102 x*= wndWidth;
103 z*= wndHeight;
105 driver.setFrustum(0, (float)wndWidth, 0, (float)wndHeight, -1, 1, false); // resX/resY
107 // Computing hotspot translation vector
108 CVector hotspotVector = getHotSpotVector(hotspot);
110 // transformation matrix initialized to identity
111 CMatrix matrix;
112 matrix.identity();
114 // view matrix <-> identity
115 driver.setupViewMatrix(matrix);
117 // model matrix :
118 // centering to hotspot, then scaling, rotating, and translating.
119 matrix.translate(CVector(x,0,z));
120 matrix.rotateY(rotateY);
121 matrix.scale(CVector(scaleX,1,scaleZ));
122 // scale the string to follow window aspect Ratio
123 if(useScreenAR43)
125 matrix.scale(CVector((3.0f*wndWidth)/(4.0f*wndHeight),1,1));
127 matrix.translate(hotspotVector);
128 // if roundToNearestPixel, then snap the position to the nearest pixel
129 if( roundToNearestPixel)
131 CVector pos= matrix.getPos();
132 pos.x= (float)floor(pos.x+0.5f);
133 pos.z= (float)floor(pos.z+0.5f);
134 matrix.setPos(pos);
136 // setup the matrix
137 driver.setupModelMatrix(matrix);
139 driver.activeVertexBuffer(Vertices);
141 // rendering each primitives
142 Material->setZFunc (CMaterial::always);
143 Material->setZWrite (false);
144 Material->setColor (Color);
145 // Clamp for selection
146 uint32 nNumQuad= Vertices.getNumVertices()/4;
147 driver.renderRawQuads (*Material, SelectStart*4, min(nNumQuad, SelectSize) );
151 /*------------------------------------------------------------------*\
152 render3D()
153 \*------------------------------------------------------------------*/
154 void CComputedString::render3D (IDriver& driver, const CMatrix &matrixp, THotSpot hotspot)
156 if (Vertices.getNumVertices() == 0)
157 return;
159 CMatrix matrix = matrixp;
161 // get window size
162 uint32 wndWidth, wndHeight;
163 driver.getWindowSize(wndWidth, wndHeight);
164 // scale according to window height (backward compatibility)
165 matrix.scale(1.0f/wndHeight);
167 // Computing hotspot translation vector
168 CVector hotspotVector = getHotSpotVector(hotspot);
169 matrix.translate(hotspotVector);
171 // render
172 driver.setupModelMatrix(matrix);
173 driver.activeVertexBuffer(Vertices);
175 // Rendering each primitive blocks
176 Material->setZFunc (CMaterial::lessequal);
177 Material->setZWrite (true);
178 Material->setColor (Color);
179 // Clamp for selection
180 uint32 nNumQuad= Vertices.getNumVertices()/4;
181 driver.renderRawQuads (*Material, SelectStart*4, min(nNumQuad, SelectSize) );
185 /*------------------------------------------------------------------*\
186 render2DClip()
187 \*------------------------------------------------------------------*/
188 void CComputedString::render2DClip (IDriver& driver, CRenderStringBuffer &rdrBuffer,
189 float x, float z,
190 float xmin, float zmin, float xmax, float zmax)
192 if (Vertices.getNumVertices() == 0)
193 return;
194 if(SelectSize==0)
195 return;
197 // get window size
198 uint32 wndWidth, wndHeight;
199 driver.getWindowSize(wndWidth, wndHeight);
200 // scale to window size.
201 x*= wndWidth;
202 z*= wndHeight;
203 xmin*= wndWidth;
204 xmax*= wndWidth;
205 zmin*= wndHeight;
206 zmax*= wndHeight;
208 // Test String Bound against clip window
209 // If entirely out skip
210 if (((x+XMin) > xmax) || ((x+XMax) < xmin) ||
211 ((z+ZMin) > zmax) || ((z+ZMax) < zmin))
212 return;
214 // test if entirely in.
215 bool allIn;
216 allIn= ((x+XMin) >= xmin) && ((x+XMax) <= xmax) &&
217 ((z+ZMin) >= zmin) && ((z+ZMax) <= zmax);
220 // How many quad to render?
221 uint nNumQuadSrc= Vertices.getNumVertices()/4;
222 nNumQuadSrc= min(nNumQuadSrc, (uint)SelectSize);
224 // Enlarge dest Buffer if needed
225 if( (rdrBuffer.NumQuads+nNumQuadSrc)*4 > rdrBuffer.Vertices.getNumVertices() )
227 rdrBuffer.Vertices.setNumVertices( (rdrBuffer.NumQuads+nNumQuadSrc)*4 );
230 // prepare copy.
231 CVertexBuffer::TVertexColorType vtype = driver.getVertexColorFormat();
232 Vertices.setVertexColorFormat (vtype);
233 rdrBuffer.Vertices.setVertexColorFormat (vtype);
234 CVertexBufferReadWrite srcvba;
235 Vertices.lock (srcvba);
236 CVertexBufferReadWrite dstvba;
237 rdrBuffer.Vertices.lock (dstvba);
238 sint ofsSrcUV= Vertices.getTexCoordOff();
239 sint ofsDstUV= rdrBuffer.Vertices.getTexCoordOff();
240 sint ofsDstColor= rdrBuffer.Vertices.getColorOff();
241 uint8 *srcPtr= (uint8*)srcvba.getVertexCoordPointer();
242 uint8 *dstPtr= (uint8*)dstvba.getVertexCoordPointer(rdrBuffer.NumQuads*4);
243 sint srcSize= Vertices.getVertexSize();
244 sint dstSize= rdrBuffer.Vertices.getVertexSize();
246 // decal src for selection
247 srcPtr+= SelectStart*4 * srcSize;
249 CRGBA mCol = Color;
251 // **** clipping?
252 if(allIn)
254 // copy All vertices
255 uint numVerts= nNumQuadSrc*4;
256 uint count = 4;
257 uint lastIndex = 0;
258 for(uint i=0;i<numVerts;i++)
260 if(count==4)
262 if(!LetterColors.empty())
264 if(LetterColors.getIndex(lastIndex)==i/4)
266 mCol.modulateFromColor(Color, LetterColors.getColor(lastIndex));
268 if(lastIndex+1<LetterColors.size())
270 lastIndex++;
275 count = 0;
278 // copy and translate pos
279 CHECK_VBA_RANGE(srcvba, srcPtr, Vertices.getVertexSize());
280 CHECK_VBA_RANGE(dstvba, dstPtr, rdrBuffer.Vertices.getVertexSize())
281 ((CVector*)dstPtr)->x= x + ((CVector*)srcPtr)->x;
282 ((CVector*)dstPtr)->y= ((CVector*)srcPtr)->y;
283 ((CVector*)dstPtr)->z= z + ((CVector*)srcPtr)->z;
284 // uv
285 *((CUV*)(dstPtr+ofsDstUV))= *((CUV*)(srcPtr+ofsSrcUV));
286 // color
287 if (vtype == CVertexBuffer::TRGBA)
288 *((CRGBA*)(dstPtr+ofsDstColor))= mCol;
289 else
290 *((CBGRA*)(dstPtr+ofsDstColor))= mCol;
292 // next
293 srcPtr+= srcSize;
294 dstPtr+= dstSize;
295 count++;
298 // update the rdrBuffer
299 rdrBuffer.NumQuads+= nNumQuadSrc;
301 else
303 uint nNumQuadClipped= 0;
305 // the real number of vertices to compute (with selection)
306 uint numVerts= nNumQuadSrc*4;
308 // clip into VerticesClipped
309 CVector *pIniPos0 = (CVector*)srcPtr;
310 CVector *pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
311 CVector *pClipPos0 = (CVector*)dstPtr;
312 CVector *pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
313 CVector *pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
314 CVector *pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
315 CUV *pClipUV0 = (CUV*)(dstPtr + ofsDstUV );
316 CUV *pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
317 CUV *pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
318 CUV *pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
319 float ratio;
321 uint lastIndex = 0;
323 for (uint32 i = 0; i < numVerts; i+=4)
325 if (((x+pIniPos0->x) > xmax) || ((x+pIniPos2->x) < xmin) ||
326 ((z+pIniPos0->z) > zmax) || ((z+pIniPos2->z) < zmin))
328 // Totally clipped do nothing
330 else
332 if(!LetterColors.empty())
334 if(LetterColors.getIndex(lastIndex)==(i/4))
336 mCol.modulateFromColor(Color, LetterColors.getColor(lastIndex));
338 if(lastIndex+1<LetterColors.size())
340 lastIndex++;
345 // copy with no clip
346 // v0
347 *((CVector*) (dstPtr + dstSize*0))= *((CVector*) (srcPtr + srcSize*0));
348 *((CUV*) (dstPtr + dstSize*0 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*0 + ofsSrcUV));
349 if (vtype == CVertexBuffer::TRGBA)
350 *((CRGBA*) (dstPtr + dstSize*0 + ofsDstColor))= mCol;
351 else
352 *((CBGRA*) (dstPtr + dstSize*0 + ofsDstColor))= mCol;
353 // v1
354 *((CVector*) (dstPtr + dstSize*1))= *((CVector*) (srcPtr + srcSize*1));
355 *((CUV*) (dstPtr + dstSize*1 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*1 + ofsSrcUV));
356 if (vtype == CVertexBuffer::TRGBA)
357 *((CRGBA*) (dstPtr + dstSize*1 + ofsDstColor))= mCol;
358 else
359 *((CBGRA*) (dstPtr + dstSize*1 + ofsDstColor))= mCol;
360 // v2
361 *((CVector*) (dstPtr + dstSize*2))= *((CVector*) (srcPtr + srcSize*2));
362 *((CUV*) (dstPtr + dstSize*2 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*2 + ofsSrcUV));
363 if (vtype == CVertexBuffer::TRGBA)
364 *((CRGBA*) (dstPtr + dstSize*2 + ofsDstColor))= mCol;
365 else
366 *((CBGRA*) (dstPtr + dstSize*2 + ofsDstColor))= mCol;
367 // v3
368 *((CVector*) (dstPtr + dstSize*3))= *((CVector*) (srcPtr + srcSize*3));
369 *((CUV*) (dstPtr + dstSize*3 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*3 + ofsSrcUV));
370 if (vtype == CVertexBuffer::TRGBA)
371 *((CRGBA*) (dstPtr + dstSize*3 + ofsDstColor))= mCol;
372 else
373 *((CBGRA*) (dstPtr + dstSize*3 + ofsDstColor))= mCol;
375 // translate dest
376 pClipPos0->x += x; pClipPos1->x += x; pClipPos2->x += x; pClipPos3->x += x;
377 pClipPos0->z += z; pClipPos1->z += z; pClipPos2->z += z; pClipPos3->z += z;
378 if ((pClipPos0->x >= xmin) && (pClipPos0->z >= zmin) && (pClipPos2->x <= xmax) && (pClipPos2->z <= zmax))
380 // Not clipped
382 else
384 // Partially clipped
386 if (pClipPos0->x < xmin)
388 ratio = ((float)(xmin - pClipPos0->x))/((float)(pClipPos1->x - pClipPos0->x));
389 pClipPos3->x = pClipPos0->x = xmin;
390 pClipUV0->U += ratio*(pClipUV1->U - pClipUV0->U);
391 pClipUV3->U += ratio*(pClipUV2->U - pClipUV3->U);
394 if (pClipPos0->z < zmin)
396 ratio = ((float)(zmin - pClipPos0->z))/((float)(pClipPos3->z - pClipPos0->z));
397 pClipPos1->z = pClipPos0->z = zmin;
398 pClipUV0->V += ratio*(pClipUV3->V - pClipUV0->V);
399 pClipUV1->V += ratio*(pClipUV2->V - pClipUV1->V);
402 if (pClipPos2->x > xmax)
404 ratio = ((float)(xmax - pClipPos2->x))/((float)(pClipPos3->x - pClipPos2->x));
405 pClipPos2->x = pClipPos1->x = xmax;
406 pClipUV2->U += ratio*(pClipUV3->U - pClipUV2->U);
407 pClipUV1->U += ratio*(pClipUV0->U - pClipUV1->U);
410 if (pClipPos2->z > zmax)
412 ratio = ((float)(zmax - pClipPos2->z))/((float)(pClipPos1->z - pClipPos2->z));
413 pClipPos2->z = pClipPos3->z = zmax;
414 pClipUV2->V += ratio*(pClipUV1->V - pClipUV2->V);
415 pClipUV3->V += ratio*(pClipUV0->V - pClipUV3->V);
419 // next quad out
420 ++nNumQuadClipped;
421 pClipPos0 = (CVector*)(((uint8*)pClipPos0) + dstSize*4);
422 pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
423 pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
424 pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
425 pClipUV0 = (CUV*)( ((uint8*)pClipUV0) + dstSize*4 );
426 pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
427 pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
428 pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
429 dstPtr+= 4*dstSize;
431 // next quad in
432 pIniPos0 = (CVector*)(((uint8*)pIniPos0) + srcSize*4);
433 pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
434 srcPtr+= 4*srcSize;
437 // update the rdrBuffer
438 rdrBuffer.NumQuads+= nNumQuadClipped;
442 /*------------------------------------------------------------------*\
443 render2DUnProjected()
444 \*------------------------------------------------------------------*/
445 void CComputedString::render2DUnProjected (IDriver& driver, CRenderStringBuffer &rdrBuffer, class NL3D::CFrustum &frustum,
446 const NLMISC::CMatrix &scaleMatrix, float x, float z, float depth, float xmin, float zmin, float xmax, float zmax)
448 if (Vertices.getNumVertices() == 0)
449 return;
450 if(SelectSize==0)
451 return;
453 // get window size
454 uint32 wndWidth, wndHeight;
455 driver.getWindowSize(wndWidth, wndHeight);
456 // scale to window size.
457 x*= wndWidth;
458 z*= wndHeight;
459 xmin*= wndWidth;
460 xmax*= wndWidth;
461 zmin*= wndHeight;
462 zmax*= wndHeight;
464 // Test String Bound against clip window
465 // If entirely out skip
466 if (((x+XMin) > xmax) || ((x+XMax) < xmin) ||
467 ((z+ZMin) > zmax) || ((z+ZMax) < zmin))
468 return;
470 // test if entirely in.
471 bool allIn;
472 allIn= ((x+XMin) >= (xmin-0.001f)) && ((x+XMax) <= (xmax+0.001f)) &&
473 ((z+ZMin) >= (zmin-0.001f)) && ((z+ZMax) <= (zmax+0.001f));
476 // How many quad to render?
477 uint nNumQuadSrc= Vertices.getNumVertices()/4;
478 nNumQuadSrc= min(nNumQuadSrc, (uint)SelectSize);
480 // Enlarge dest Buffer if needed
481 if( (rdrBuffer.NumQuads+nNumQuadSrc)*4 > rdrBuffer.Vertices.getNumVertices() )
483 rdrBuffer.Vertices.setNumVertices( (rdrBuffer.NumQuads+nNumQuadSrc)*4 );
486 // prepare copy.
487 CVertexBuffer::TVertexColorType vtype = driver.getVertexColorFormat();
488 Vertices.setVertexColorFormat (vtype);
489 rdrBuffer.Vertices.setVertexColorFormat (vtype);
490 CVertexBufferReadWrite srcvba;
491 Vertices.lock (srcvba);
492 CVertexBufferReadWrite dstvba;
493 rdrBuffer.Vertices.lock (dstvba);
494 sint ofsSrcUV= Vertices.getTexCoordOff();
495 sint ofsDstUV= rdrBuffer.Vertices.getTexCoordOff();
496 sint ofsDstColor= rdrBuffer.Vertices.getColorOff();
497 uint8 *srcPtr= (uint8*)srcvba.getVertexCoordPointer();
498 uint8 *dstPtr= (uint8*)dstvba.getVertexCoordPointer(rdrBuffer.NumQuads*4);
499 sint srcSize= Vertices.getVertexSize();
500 sint dstSize= rdrBuffer.Vertices.getVertexSize();
502 // decal src for selection
503 srcPtr+= SelectStart*4 * srcSize;
505 uint8 *dstPtrBackup = dstPtr;
507 // **** clipping?
508 if(allIn)
510 // copy All vertices
511 uint numVerts= nNumQuadSrc*4;
512 for(uint i=0;i<numVerts;i++)
514 // copy and translate pos
515 CHECK_VBA_RANGE(dstvba, dstPtr, Vertices.getVertexSize());
516 CHECK_VBA_RANGE(srcvba, srcPtr, rdrBuffer.Vertices.getVertexSize());
517 ((CVector*)dstPtr)->x= x + ((CVector*)srcPtr)->x;
518 ((CVector*)dstPtr)->z= z + ((CVector*)srcPtr)->z;
520 // uv
521 *((CUV*)(dstPtr+ofsDstUV))= *((CUV*)(srcPtr+ofsSrcUV));
522 // color
523 if (vtype == CVertexBuffer::TRGBA)
524 *((CRGBA*)(dstPtr+ofsDstColor))= Color;
525 else
526 *((CBGRA*)(dstPtr+ofsDstColor))= Color;
528 // next
529 srcPtr+= srcSize;
530 dstPtr+= dstSize;
533 // update the rdrBuffer
534 rdrBuffer.NumQuads+= nNumQuadSrc;
536 else
538 uint nNumQuadClipped= 0;
540 // the real number of vertices to compute (with selection)
541 uint numVerts= nNumQuadSrc*4;
543 // clip into VerticesClipped
544 CVector *pIniPos0 = (CVector*)srcPtr;
545 CVector *pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
546 CVector *pClipPos0 = (CVector*)dstPtr;
547 CVector *pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
548 CVector *pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
549 CVector *pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
550 CUV *pClipUV0 = (CUV*)(dstPtr + ofsDstUV );
551 CUV *pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
552 CUV *pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
553 CUV *pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
554 float ratio;
555 for (uint32 i = 0; i < numVerts; i+=4)
557 if (((x+pIniPos0->x) > xmax) || ((x+pIniPos2->x) < xmin) ||
558 ((z+pIniPos0->z) > zmax) || ((z+pIniPos2->z) < zmin))
560 // Totally clipped do nothing
562 else
564 // copy with no clip
565 // v0
566 *((CVector*) (dstPtr + dstSize*0))= *((CVector*) (srcPtr + srcSize*0));
567 *((CUV*) (dstPtr + dstSize*0 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*0 + ofsSrcUV));
568 if (vtype == CVertexBuffer::TRGBA)
569 *((CRGBA*) (dstPtr + dstSize*0 + ofsDstColor))= Color;
570 else
571 *((CBGRA*) (dstPtr + dstSize*0 + ofsDstColor))= Color;
572 // v1
573 *((CVector*) (dstPtr + dstSize*1))= *((CVector*) (srcPtr + srcSize*1));
574 *((CUV*) (dstPtr + dstSize*1 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*1 + ofsSrcUV));
575 if (vtype == CVertexBuffer::TRGBA)
576 *((CRGBA*) (dstPtr + dstSize*1 + ofsDstColor))= Color;
577 else
578 *((CBGRA*) (dstPtr + dstSize*1 + ofsDstColor))= Color;
579 // v2
580 *((CVector*) (dstPtr + dstSize*2))= *((CVector*) (srcPtr + srcSize*2));
581 *((CUV*) (dstPtr + dstSize*2 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*2 + ofsSrcUV));
582 if (vtype == CVertexBuffer::TRGBA)
583 *((CRGBA*) (dstPtr + dstSize*2 + ofsDstColor))= Color;
584 else
585 *((CBGRA*) (dstPtr + dstSize*2 + ofsDstColor))= Color;
586 // v3
587 *((CVector*) (dstPtr + dstSize*3))= *((CVector*) (srcPtr + srcSize*3));
588 *((CUV*) (dstPtr + dstSize*3 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*3 + ofsSrcUV));
589 if (vtype == CVertexBuffer::TRGBA)
590 *((CRGBA*) (dstPtr + dstSize*3 + ofsDstColor))= Color;
591 else
592 *((CBGRA*) (dstPtr + dstSize*3 + ofsDstColor))= Color;
595 // translate dest
596 pClipPos0->x += x; pClipPos1->x += x; pClipPos2->x += x; pClipPos3->x += x;
597 pClipPos0->z += z; pClipPos1->z += z; pClipPos2->z += z; pClipPos3->z += z;
598 if ((pClipPos0->x >= xmin) && (pClipPos0->z >= zmin) && (pClipPos2->x <= xmax) && (pClipPos2->z <= zmax))
600 // Not clipped
602 else
604 // Partially clipped
606 if (pClipPos0->x < xmin)
608 ratio = ((float)(xmin - pClipPos0->x))/((float)(pClipPos1->x - pClipPos0->x));
609 pClipPos3->x = pClipPos0->x = xmin;
610 pClipUV0->U += ratio*(pClipUV1->U - pClipUV0->U);
611 pClipUV3->U += ratio*(pClipUV2->U - pClipUV3->U);
614 if (pClipPos0->z < zmin)
616 ratio = ((float)(zmin - pClipPos0->z))/((float)(pClipPos3->z - pClipPos0->z));
617 pClipPos1->z = pClipPos0->z = zmin;
618 pClipUV0->V += ratio*(pClipUV3->V - pClipUV0->V);
619 pClipUV1->V += ratio*(pClipUV2->V - pClipUV1->V);
622 if (pClipPos2->x > xmax)
624 ratio = ((float)(xmax - pClipPos2->x))/((float)(pClipPos3->x - pClipPos2->x));
625 pClipPos2->x = pClipPos1->x = xmax;
626 pClipUV2->U += ratio*(pClipUV3->U - pClipUV2->U);
627 pClipUV1->U += ratio*(pClipUV0->U - pClipUV1->U);
630 if (pClipPos2->z > zmax)
632 ratio = ((float)(zmax - pClipPos2->z))/((float)(pClipPos1->z - pClipPos2->z));
633 pClipPos2->z = pClipPos3->z = zmax;
634 pClipUV2->V += ratio*(pClipUV1->V - pClipUV2->V);
635 pClipUV3->V += ratio*(pClipUV0->V - pClipUV3->V);
639 // next quad out
640 ++nNumQuadClipped;
641 pClipPos0 = (CVector*)(((uint8*)pClipPos0) + dstSize*4);
642 pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
643 pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
644 pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
645 pClipUV0 = (CUV*)( ((uint8*)pClipUV0) + dstSize*4 );
646 pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
647 pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
648 pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
649 dstPtr+= 4*dstSize;
651 // next quad in
652 pIniPos0 = (CVector*)(((uint8*)pIniPos0) + srcSize*4);
653 pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
654 srcPtr+= 4*srcSize;
657 // update the rdrBuffer
658 rdrBuffer.NumQuads+= nNumQuadClipped;
661 const float OOW = 1.f / (float)wndWidth;
662 const float OOH = 1.f / (float)wndHeight;
664 while (dstPtrBackup != dstPtr)
666 // preset unprojection
667 CVector tmp;
668 tmp.x = ((CVector*)dstPtrBackup)->x * OOW;
669 tmp.y = ((CVector*)dstPtrBackup)->z * OOH;
670 tmp.z = depth;
671 // mul by user scale matrix
672 tmp= scaleMatrix * tmp;
673 // Unproject it
674 *((CVector*)dstPtrBackup) = frustum.unProjectZ(tmp);
675 dstPtrBackup += dstSize;
680 // ***************************************************************************
681 CRenderStringBuffer::CRenderStringBuffer()
683 // Use color per vertex
684 Vertices.setVertexFormat (CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::PrimaryColorFlag);
685 Vertices.setPreferredMemory (CVertexBuffer::RAMVolatile, true);
686 Vertices.setName("CRenderStringBuffer");
687 NumQuads= 0;
691 // ***************************************************************************
692 CRenderStringBuffer::~CRenderStringBuffer()
697 // ***************************************************************************
698 void CRenderStringBuffer::flush(IDriver& driver, CMaterial *fontMat)
700 if(NumQuads==0)
701 return;
703 // get window size
704 uint32 wndWidth, wndHeight;
705 driver.getWindowSize(wndWidth, wndHeight);
707 // **** setup driver context
708 driver.setFrustum(0, (float)wndWidth, 0, (float)wndHeight, -1, 1, false); // resX/resY
710 // view matrix and model matrix <-> identity
711 driver.setupViewMatrix (CMatrix::Identity);
712 driver.setupModelMatrix (CMatrix::Identity);
714 // setup material
715 fontMat->setZFunc (CMaterial::always);
716 fontMat->setZWrite (false);
718 // setup vertices clipped
719 driver.activeVertexBuffer (Vertices);
721 // *** rendering
722 driver.renderRawQuads (*fontMat, 0, NumQuads );
724 // *** reset
725 NumQuads= 0;
729 // ***************************************************************************
730 void CRenderStringBuffer::flushUnProjected(IDriver& driver, CMaterial *fontMat, bool zwrite)
732 if(NumQuads==0)
733 return;
735 // setup material
736 fontMat->setZFunc (CMaterial::lessequal);
737 fontMat->setZWrite (zwrite);
739 // setup vertices clipped
740 driver.activeVertexBuffer (Vertices);
742 // *** rendering
743 driver.renderRawQuads (*fontMat, 0, NumQuads );
745 // *** reset
746 NumQuads= 0;
750 } // NL3D