// NeL - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "std3d.h"
#include "nel/3d/computed_string.h"
#include "nel/3d/texture.h"
#include "nel/3d/index_buffer.h"
#include "nel/3d/material.h"
#include "nel/3d/frustum.h"
#include "nel/3d/viewport.h"
#include "nel/misc/smart_ptr.h"
#include "nel/misc/debug.h"
#include "nel/misc/file.h"
#include "nel/misc/fast_mem.h"
using namespace std;
namespace NL3D {
/*------------------------------------------------------------------*\
getHotSpotVector()
\*------------------------------------------------------------------*/
CVector CComputedString::getHotSpotVector(THotSpot hotspot)
{
CVector hotspotVector(0,0,0);
if (hotspot==MiddleLeft)
hotspotVector = CVector(0,0,-StringHeight/2);
if (hotspot==TopLeft)
hotspotVector = CVector(0,0,-StringHeight);
if (hotspot==MiddleBottom)
hotspotVector = CVector(-StringWidth/2,0,0);
if (hotspot==MiddleMiddle)
hotspotVector = CVector(-StringWidth/2,0,-StringHeight/2);
if (hotspot==MiddleTop)
hotspotVector = CVector(-StringWidth/2,0,-StringHeight);
if (hotspot==BottomRight)
hotspotVector = CVector(-StringWidth,0,0);
if (hotspot==MiddleRight)
hotspotVector = CVector(-StringWidth,0,-StringHeight/2);
if (hotspot==TopRight)
hotspotVector = CVector(-StringWidth,0,-StringHeight);
return hotspotVector;
}
/*------------------------------------------------------------------*\
render2D()
\*------------------------------------------------------------------*/
void CComputedString::render2D (IDriver& driver,
float x, float z,
THotSpot hotspot,
float scaleX, float scaleZ,
float rotateY,
bool useScreenAR43, bool roundToNearestPixel
)
{
if (Vertices.getNumVertices() == 0)
return;
// get window size
uint32 wndWidth, wndHeight;
driver.getWindowSize(wndWidth, wndHeight);
CViewport vp;
driver.getViewport(vp);
wndWidth = (uint32)((float)wndWidth * vp.getWidth());
wndHeight = (uint32)((float)wndHeight * vp.getHeight());
// scale to window size.
x*= wndWidth;
z*= wndHeight;
driver.setFrustum(0, (float)wndWidth, 0, (float)wndHeight, -1, 1, false); // resX/resY
// Computing hotspot translation vector
CVector hotspotVector = getHotSpotVector(hotspot);
// transformation matrix initialized to identity
CMatrix matrix;
matrix.identity();
// view matrix <-> identity
driver.setupViewMatrix(matrix);
// model matrix :
// centering to hotspot, then scaling, rotating, and translating.
matrix.translate(CVector(x,0,z));
matrix.rotateY(rotateY);
matrix.scale(CVector(scaleX,1,scaleZ));
// scale the string to follow window aspect Ratio
if(useScreenAR43)
{
matrix.scale(CVector((3.0f*wndWidth)/(4.0f*wndHeight),1,1));
}
matrix.translate(hotspotVector);
// if roundToNearestPixel, then snap the position to the nearest pixel
if( roundToNearestPixel)
{
CVector pos= matrix.getPos();
pos.x= (float)floor(pos.x+0.5f);
pos.z= (float)floor(pos.z+0.5f);
matrix.setPos(pos);
}
// setup the matrix
driver.setupModelMatrix(matrix);
driver.activeVertexBuffer(Vertices);
// rendering each primitives
Material->setZFunc (CMaterial::always);
Material->setZWrite (false);
Material->setColor (Color);
// Clamp for selection
uint32 nNumQuad= Vertices.getNumVertices()/4;
driver.renderRawQuads (*Material, SelectStart*4, min(nNumQuad, SelectSize) );
}
/*------------------------------------------------------------------*\
render3D()
\*------------------------------------------------------------------*/
void CComputedString::render3D (IDriver& driver, const CMatrix &matrixp, THotSpot hotspot)
{
if (Vertices.getNumVertices() == 0)
return;
CMatrix matrix = matrixp;
// get window size
uint32 wndWidth, wndHeight;
driver.getWindowSize(wndWidth, wndHeight);
// scale according to window height (backward compatibility)
matrix.scale(1.0f/wndHeight);
// Computing hotspot translation vector
CVector hotspotVector = getHotSpotVector(hotspot);
matrix.translate(hotspotVector);
// render
driver.setupModelMatrix(matrix);
driver.activeVertexBuffer(Vertices);
// Rendering each primitive blocks
Material->setZFunc (CMaterial::lessequal);
Material->setZWrite (true);
Material->setColor (Color);
// Clamp for selection
uint32 nNumQuad= Vertices.getNumVertices()/4;
driver.renderRawQuads (*Material, SelectStart*4, min(nNumQuad, SelectSize) );
}
/*------------------------------------------------------------------*\
render2DClip()
\*------------------------------------------------------------------*/
void CComputedString::render2DClip (IDriver& driver, CRenderStringBuffer &rdrBuffer,
float x, float z,
float xmin, float zmin, float xmax, float zmax)
{
if (Vertices.getNumVertices() == 0)
return;
if(SelectSize==0)
return;
// get window size
uint32 wndWidth, wndHeight;
driver.getWindowSize(wndWidth, wndHeight);
// scale to window size.
x*= wndWidth;
z*= wndHeight;
xmin*= wndWidth;
xmax*= wndWidth;
zmin*= wndHeight;
zmax*= wndHeight;
// Test String Bound against clip window
// If entirely out skip
if (((x+XMin) > xmax) || ((x+XMax) < xmin) ||
((z+ZMin) > zmax) || ((z+ZMax) < zmin))
return;
// test if entirely in.
bool allIn;
allIn= ((x+XMin) >= xmin) && ((x+XMax) <= xmax) &&
((z+ZMin) >= zmin) && ((z+ZMax) <= zmax);
// How many quad to render?
uint nNumQuadSrc= Vertices.getNumVertices()/4;
nNumQuadSrc= min(nNumQuadSrc, (uint)SelectSize);
// Enlarge dest Buffer if needed
if( (rdrBuffer.NumQuads+nNumQuadSrc)*4 > rdrBuffer.Vertices.getNumVertices() )
{
rdrBuffer.Vertices.setNumVertices( (rdrBuffer.NumQuads+nNumQuadSrc)*4 );
}
// prepare copy.
CVertexBuffer::TVertexColorType vtype = driver.getVertexColorFormat();
Vertices.setVertexColorFormat (vtype);
rdrBuffer.Vertices.setVertexColorFormat (vtype);
CVertexBufferReadWrite srcvba;
Vertices.lock (srcvba);
CVertexBufferReadWrite dstvba;
rdrBuffer.Vertices.lock (dstvba);
sint ofsSrcUV= Vertices.getTexCoordOff();
sint ofsDstUV= rdrBuffer.Vertices.getTexCoordOff();
sint ofsDstColor= rdrBuffer.Vertices.getColorOff();
uint8 *srcPtr= (uint8*)srcvba.getVertexCoordPointer();
uint8 *dstPtr= (uint8*)dstvba.getVertexCoordPointer(rdrBuffer.NumQuads*4);
sint srcSize= Vertices.getVertexSize();
sint dstSize= rdrBuffer.Vertices.getVertexSize();
// decal src for selection
srcPtr+= SelectStart*4 * srcSize;
CRGBA mCol = Color;
// **** clipping?
if(allIn)
{
// copy All vertices
uint numVerts= nNumQuadSrc*4;
uint count = 4;
uint lastIndex = 0;
for(uint i=0;ix= x + ((CVector*)srcPtr)->x;
((CVector*)dstPtr)->y= ((CVector*)srcPtr)->y;
((CVector*)dstPtr)->z= z + ((CVector*)srcPtr)->z;
// uv
*((CUV*)(dstPtr+ofsDstUV))= *((CUV*)(srcPtr+ofsSrcUV));
// color
if (vtype == CVertexBuffer::TRGBA)
*((CRGBA*)(dstPtr+ofsDstColor))= mCol;
else
*((CBGRA*)(dstPtr+ofsDstColor))= mCol;
// next
srcPtr+= srcSize;
dstPtr+= dstSize;
count++;
}
// update the rdrBuffer
rdrBuffer.NumQuads+= nNumQuadSrc;
}
else
{
uint nNumQuadClipped= 0;
// the real number of vertices to compute (with selection)
uint numVerts= nNumQuadSrc*4;
// clip into VerticesClipped
CVector *pIniPos0 = (CVector*)srcPtr;
CVector *pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
CVector *pClipPos0 = (CVector*)dstPtr;
CVector *pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
CVector *pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
CVector *pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
CUV *pClipUV0 = (CUV*)(dstPtr + ofsDstUV );
CUV *pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
CUV *pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
CUV *pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
float ratio;
uint lastIndex = 0;
for (uint32 i = 0; i < numVerts; i+=4)
{
if (((x+pIniPos0->x) > xmax) || ((x+pIniPos2->x) < xmin) ||
((z+pIniPos0->z) > zmax) || ((z+pIniPos2->z) < zmin))
{
// Totally clipped do nothing
}
else
{
if(!LetterColors.empty())
{
if(LetterColors.getIndex(lastIndex)==(i/4))
{
mCol.modulateFromColor(Color, LetterColors.getColor(lastIndex));
if(lastIndex+1x += x; pClipPos1->x += x; pClipPos2->x += x; pClipPos3->x += x;
pClipPos0->z += z; pClipPos1->z += z; pClipPos2->z += z; pClipPos3->z += z;
if ((pClipPos0->x >= xmin) && (pClipPos0->z >= zmin) && (pClipPos2->x <= xmax) && (pClipPos2->z <= zmax))
{
// Not clipped
}
else
{
// Partially clipped
if (pClipPos0->x < xmin)
{
ratio = ((float)(xmin - pClipPos0->x))/((float)(pClipPos1->x - pClipPos0->x));
pClipPos3->x = pClipPos0->x = xmin;
pClipUV0->U += ratio*(pClipUV1->U - pClipUV0->U);
pClipUV3->U += ratio*(pClipUV2->U - pClipUV3->U);
}
if (pClipPos0->z < zmin)
{
ratio = ((float)(zmin - pClipPos0->z))/((float)(pClipPos3->z - pClipPos0->z));
pClipPos1->z = pClipPos0->z = zmin;
pClipUV0->V += ratio*(pClipUV3->V - pClipUV0->V);
pClipUV1->V += ratio*(pClipUV2->V - pClipUV1->V);
}
if (pClipPos2->x > xmax)
{
ratio = ((float)(xmax - pClipPos2->x))/((float)(pClipPos3->x - pClipPos2->x));
pClipPos2->x = pClipPos1->x = xmax;
pClipUV2->U += ratio*(pClipUV3->U - pClipUV2->U);
pClipUV1->U += ratio*(pClipUV0->U - pClipUV1->U);
}
if (pClipPos2->z > zmax)
{
ratio = ((float)(zmax - pClipPos2->z))/((float)(pClipPos1->z - pClipPos2->z));
pClipPos2->z = pClipPos3->z = zmax;
pClipUV2->V += ratio*(pClipUV1->V - pClipUV2->V);
pClipUV3->V += ratio*(pClipUV0->V - pClipUV3->V);
}
}
// next quad out
++nNumQuadClipped;
pClipPos0 = (CVector*)(((uint8*)pClipPos0) + dstSize*4);
pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
pClipUV0 = (CUV*)( ((uint8*)pClipUV0) + dstSize*4 );
pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
dstPtr+= 4*dstSize;
}
// next quad in
pIniPos0 = (CVector*)(((uint8*)pIniPos0) + srcSize*4);
pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
srcPtr+= 4*srcSize;
}
// update the rdrBuffer
rdrBuffer.NumQuads+= nNumQuadClipped;
}
}
/*------------------------------------------------------------------*\
render2DUnProjected()
\*------------------------------------------------------------------*/
void CComputedString::render2DUnProjected (IDriver& driver, CRenderStringBuffer &rdrBuffer, class NL3D::CFrustum &frustum,
const NLMISC::CMatrix &scaleMatrix, float x, float z, float depth, float xmin, float zmin, float xmax, float zmax)
{
if (Vertices.getNumVertices() == 0)
return;
if(SelectSize==0)
return;
// get window size
uint32 wndWidth, wndHeight;
driver.getWindowSize(wndWidth, wndHeight);
// scale to window size.
x*= wndWidth;
z*= wndHeight;
xmin*= wndWidth;
xmax*= wndWidth;
zmin*= wndHeight;
zmax*= wndHeight;
// Test String Bound against clip window
// If entirely out skip
if (((x+XMin) > xmax) || ((x+XMax) < xmin) ||
((z+ZMin) > zmax) || ((z+ZMax) < zmin))
return;
// test if entirely in.
bool allIn;
allIn= ((x+XMin) >= (xmin-0.001f)) && ((x+XMax) <= (xmax+0.001f)) &&
((z+ZMin) >= (zmin-0.001f)) && ((z+ZMax) <= (zmax+0.001f));
// How many quad to render?
uint nNumQuadSrc= Vertices.getNumVertices()/4;
nNumQuadSrc= min(nNumQuadSrc, (uint)SelectSize);
// Enlarge dest Buffer if needed
if( (rdrBuffer.NumQuads+nNumQuadSrc)*4 > rdrBuffer.Vertices.getNumVertices() )
{
rdrBuffer.Vertices.setNumVertices( (rdrBuffer.NumQuads+nNumQuadSrc)*4 );
}
// prepare copy.
CVertexBuffer::TVertexColorType vtype = driver.getVertexColorFormat();
Vertices.setVertexColorFormat (vtype);
rdrBuffer.Vertices.setVertexColorFormat (vtype);
CVertexBufferReadWrite srcvba;
Vertices.lock (srcvba);
CVertexBufferReadWrite dstvba;
rdrBuffer.Vertices.lock (dstvba);
sint ofsSrcUV= Vertices.getTexCoordOff();
sint ofsDstUV= rdrBuffer.Vertices.getTexCoordOff();
sint ofsDstColor= rdrBuffer.Vertices.getColorOff();
uint8 *srcPtr= (uint8*)srcvba.getVertexCoordPointer();
uint8 *dstPtr= (uint8*)dstvba.getVertexCoordPointer(rdrBuffer.NumQuads*4);
sint srcSize= Vertices.getVertexSize();
sint dstSize= rdrBuffer.Vertices.getVertexSize();
// decal src for selection
srcPtr+= SelectStart*4 * srcSize;
uint8 *dstPtrBackup = dstPtr;
// **** clipping?
if(allIn)
{
// copy All vertices
uint numVerts= nNumQuadSrc*4;
for(uint i=0;ix= x + ((CVector*)srcPtr)->x;
((CVector*)dstPtr)->z= z + ((CVector*)srcPtr)->z;
// uv
*((CUV*)(dstPtr+ofsDstUV))= *((CUV*)(srcPtr+ofsSrcUV));
// color
if (vtype == CVertexBuffer::TRGBA)
*((CRGBA*)(dstPtr+ofsDstColor))= Color;
else
*((CBGRA*)(dstPtr+ofsDstColor))= Color;
// next
srcPtr+= srcSize;
dstPtr+= dstSize;
}
// update the rdrBuffer
rdrBuffer.NumQuads+= nNumQuadSrc;
}
else
{
uint nNumQuadClipped= 0;
// the real number of vertices to compute (with selection)
uint numVerts= nNumQuadSrc*4;
// clip into VerticesClipped
CVector *pIniPos0 = (CVector*)srcPtr;
CVector *pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
CVector *pClipPos0 = (CVector*)dstPtr;
CVector *pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
CVector *pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
CVector *pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
CUV *pClipUV0 = (CUV*)(dstPtr + ofsDstUV );
CUV *pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
CUV *pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
CUV *pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
float ratio;
for (uint32 i = 0; i < numVerts; i+=4)
{
if (((x+pIniPos0->x) > xmax) || ((x+pIniPos2->x) < xmin) ||
((z+pIniPos0->z) > zmax) || ((z+pIniPos2->z) < zmin))
{
// Totally clipped do nothing
}
else
{
// copy with no clip
// v0
*((CVector*) (dstPtr + dstSize*0))= *((CVector*) (srcPtr + srcSize*0));
*((CUV*) (dstPtr + dstSize*0 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*0 + ofsSrcUV));
if (vtype == CVertexBuffer::TRGBA)
*((CRGBA*) (dstPtr + dstSize*0 + ofsDstColor))= Color;
else
*((CBGRA*) (dstPtr + dstSize*0 + ofsDstColor))= Color;
// v1
*((CVector*) (dstPtr + dstSize*1))= *((CVector*) (srcPtr + srcSize*1));
*((CUV*) (dstPtr + dstSize*1 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*1 + ofsSrcUV));
if (vtype == CVertexBuffer::TRGBA)
*((CRGBA*) (dstPtr + dstSize*1 + ofsDstColor))= Color;
else
*((CBGRA*) (dstPtr + dstSize*1 + ofsDstColor))= Color;
// v2
*((CVector*) (dstPtr + dstSize*2))= *((CVector*) (srcPtr + srcSize*2));
*((CUV*) (dstPtr + dstSize*2 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*2 + ofsSrcUV));
if (vtype == CVertexBuffer::TRGBA)
*((CRGBA*) (dstPtr + dstSize*2 + ofsDstColor))= Color;
else
*((CBGRA*) (dstPtr + dstSize*2 + ofsDstColor))= Color;
// v3
*((CVector*) (dstPtr + dstSize*3))= *((CVector*) (srcPtr + srcSize*3));
*((CUV*) (dstPtr + dstSize*3 + ofsDstUV))= *((CUV*)(srcPtr + srcSize*3 + ofsSrcUV));
if (vtype == CVertexBuffer::TRGBA)
*((CRGBA*) (dstPtr + dstSize*3 + ofsDstColor))= Color;
else
*((CBGRA*) (dstPtr + dstSize*3 + ofsDstColor))= Color;
// translate dest
pClipPos0->x += x; pClipPos1->x += x; pClipPos2->x += x; pClipPos3->x += x;
pClipPos0->z += z; pClipPos1->z += z; pClipPos2->z += z; pClipPos3->z += z;
if ((pClipPos0->x >= xmin) && (pClipPos0->z >= zmin) && (pClipPos2->x <= xmax) && (pClipPos2->z <= zmax))
{
// Not clipped
}
else
{
// Partially clipped
if (pClipPos0->x < xmin)
{
ratio = ((float)(xmin - pClipPos0->x))/((float)(pClipPos1->x - pClipPos0->x));
pClipPos3->x = pClipPos0->x = xmin;
pClipUV0->U += ratio*(pClipUV1->U - pClipUV0->U);
pClipUV3->U += ratio*(pClipUV2->U - pClipUV3->U);
}
if (pClipPos0->z < zmin)
{
ratio = ((float)(zmin - pClipPos0->z))/((float)(pClipPos3->z - pClipPos0->z));
pClipPos1->z = pClipPos0->z = zmin;
pClipUV0->V += ratio*(pClipUV3->V - pClipUV0->V);
pClipUV1->V += ratio*(pClipUV2->V - pClipUV1->V);
}
if (pClipPos2->x > xmax)
{
ratio = ((float)(xmax - pClipPos2->x))/((float)(pClipPos3->x - pClipPos2->x));
pClipPos2->x = pClipPos1->x = xmax;
pClipUV2->U += ratio*(pClipUV3->U - pClipUV2->U);
pClipUV1->U += ratio*(pClipUV0->U - pClipUV1->U);
}
if (pClipPos2->z > zmax)
{
ratio = ((float)(zmax - pClipPos2->z))/((float)(pClipPos1->z - pClipPos2->z));
pClipPos2->z = pClipPos3->z = zmax;
pClipUV2->V += ratio*(pClipUV1->V - pClipUV2->V);
pClipUV3->V += ratio*(pClipUV0->V - pClipUV3->V);
}
}
// next quad out
++nNumQuadClipped;
pClipPos0 = (CVector*)(((uint8*)pClipPos0) + dstSize*4);
pClipPos1 = (CVector*)(((uint8*)pClipPos0) + dstSize);
pClipPos2 = (CVector*)(((uint8*)pClipPos1) + dstSize);
pClipPos3 = (CVector*)(((uint8*)pClipPos2) + dstSize);
pClipUV0 = (CUV*)( ((uint8*)pClipUV0) + dstSize*4 );
pClipUV1 = (CUV*)(((uint8*)pClipUV0) + dstSize);
pClipUV2 = (CUV*)(((uint8*)pClipUV1) + dstSize);
pClipUV3 = (CUV*)(((uint8*)pClipUV2) + dstSize);
dstPtr+= 4*dstSize;
}
// next quad in
pIniPos0 = (CVector*)(((uint8*)pIniPos0) + srcSize*4);
pIniPos2 = (CVector*)(((uint8*)pIniPos0) + srcSize*2);
srcPtr+= 4*srcSize;
}
// update the rdrBuffer
rdrBuffer.NumQuads+= nNumQuadClipped;
}
const float OOW = 1.f / (float)wndWidth;
const float OOH = 1.f / (float)wndHeight;
while (dstPtrBackup != dstPtr)
{
// preset unprojection
CVector tmp;
tmp.x = ((CVector*)dstPtrBackup)->x * OOW;
tmp.y = ((CVector*)dstPtrBackup)->z * OOH;
tmp.z = depth;
// mul by user scale matrix
tmp= scaleMatrix * tmp;
// Unproject it
*((CVector*)dstPtrBackup) = frustum.unProjectZ(tmp);
dstPtrBackup += dstSize;
}
}
// ***************************************************************************
CRenderStringBuffer::CRenderStringBuffer()
{
// Use color per vertex
Vertices.setVertexFormat (CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::PrimaryColorFlag);
Vertices.setPreferredMemory (CVertexBuffer::RAMVolatile, true);
Vertices.setName("CRenderStringBuffer");
NumQuads= 0;
}
// ***************************************************************************
CRenderStringBuffer::~CRenderStringBuffer()
{
}
// ***************************************************************************
void CRenderStringBuffer::flush(IDriver& driver, CMaterial *fontMat)
{
if(NumQuads==0)
return;
// get window size
uint32 wndWidth, wndHeight;
driver.getWindowSize(wndWidth, wndHeight);
// **** setup driver context
driver.setFrustum(0, (float)wndWidth, 0, (float)wndHeight, -1, 1, false); // resX/resY
// view matrix and model matrix <-> identity
driver.setupViewMatrix (CMatrix::Identity);
driver.setupModelMatrix (CMatrix::Identity);
// setup material
fontMat->setZFunc (CMaterial::always);
fontMat->setZWrite (false);
// setup vertices clipped
driver.activeVertexBuffer (Vertices);
// *** rendering
driver.renderRawQuads (*fontMat, 0, NumQuads );
// *** reset
NumQuads= 0;
}
// ***************************************************************************
void CRenderStringBuffer::flushUnProjected(IDriver& driver, CMaterial *fontMat, bool zwrite)
{
if(NumQuads==0)
return;
// setup material
fontMat->setZFunc (CMaterial::lessequal);
fontMat->setZWrite (zwrite);
// setup vertices clipped
driver.activeVertexBuffer (Vertices);
// *** rendering
driver.renderRawQuads (*fontMat, 0, NumQuads );
// *** reset
NumQuads= 0;
}
} // NL3D