diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h new file mode 100644 index 000000000..5adde3cb3 --- /dev/null +++ b/code/nel/include/nel/gui/view_renderer.h @@ -0,0 +1,591 @@ +// Ryzom - 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 . + + + +#ifndef NL_VIEW_RENDERER_H +#define NL_VIEW_RENDERER_H + +#include "nel/misc/types_nl.h" +#include "nel/misc/rgba.h" +#include "nel/misc/uv.h" +#include "nel/misc/plane.h" +#include "nel/3d/u_texture.h" +#include "nel/3d/u_material.h" +#include "nel/3d/u_text_context.h" +#include "nel/3d/u_driver.h" +#include "nel/3d/frustum.h" + +namespace NLGUI +{ + + // *************************************************************************** + #define VR_NUM_LAYER 32 + #define VR_BIAS_LAYER (VR_NUM_LAYER/2) + #define VR_LAYER_MAX (VR_NUM_LAYER-VR_BIAS_LAYER-1) + #define VR_LAYER_MIN (-VR_BIAS_LAYER) + + // *************************************************************************** + /** + * class rendering the views + * All the quads of the interface are displayed in the following order + * + * 3--2 + * | | + * 0--1 + * + * \author Matthieu 'TrapII' Besson + * \author Nevrax France + * \date 2002 + */ + class CViewRenderer + { + public: + enum TSystemTexture + { + QuantityCrossTexture= 0, + DefaultBrickTexture, + DefaultItemTexture, + ItemPlanTexture, + SkillTexture, + ItemEnchantedTexture, + DragCopyTexture, + ItemWornedTexture, + OutOfRangeTexture, + RegenTexture, + RegenBackTexture, + GlowStarTexture, + ItemLockedByOwnerTexture, + NumSystemTextures, + }; + + + public: + + /** That class hold a texture id. It handle texture id destruction. + * Please use this class in your view and not sint32 to hold a texture id + */ + class CTextureId + { + public: + + // Default constructor + CTextureId () + { + _TextureId = -2; + } + + // Destructor call deleteTextureId; + ~CTextureId (); + + // Set the texture id + bool setTexture (const char *textureName, sint32 offsetX = 0, sint32 offsetY = 0, sint32 width = -1, sint32 height = -1, + bool uploadDXTC=true, bool bReleasable=true); + + // Convert in texture id + operator sint32 () const + { + return _TextureId; + } + + void serial(NLMISC::IStream &f); + + private: + sint32 _TextureId; + }; + + private: + CViewRenderer(); + ~CViewRenderer(); + + public: + static CViewRenderer* getInstance(); + + /// setup the default values for everything + void setup(); + + /// init when TextContext and Driver are created + void init(); + + /// set the driver render states for the interface + void setRenderStates (); + + /// Delete all textures and the like and reset the view renderer + void reset(); + + /// Retrieves the 3d driver we are using + static NL3D::UDriver* getDriver(); + + /// Sets the current TextContext. + static void setTextContext( NL3D::UTextContext *textcontext ); + + /// Sets the current driver + static void setDriver( NL3D::UDriver *driver ); + + /* + * setClipWindow : set the current clipping window + * (this window do not inherit properties from parent or whatever) + */ + void setClipWindow (sint32 x, sint32 y, sint32 w, sint32 h); + + /* + * getClipWindow : get the current clipping region + */ + void getClipWindow (sint32 &x, sint32 &y, sint32 &w, sint32 &h) + { + x = _ClipX; + y = _ClipY; + w = _ClipW; + h = _ClipH; + } + + /* + * true if the clipping region is empty: clipW or clipH is <=0 + */ + bool isClipWindowEmpty() const {return _ClipW<=0 || _ClipH<=0;} + + /* + * checkNewScreenSize : check if the opengl screen size. This is SLOW ! + * NB: if the window is minimized (w==h==0), then the old screen size is kept, and isMinimized() return true + */ + void checkNewScreenSize (); + + /* + * getScreenSize : get the screen window size changed (at last checkNewScreenSize called) + */ + void getScreenSize (uint32 &w, uint32 &h); + + /* + * get OOW / OOH + */ + void getScreenOOSize (float &oow, float &ooh); + + /* + * is the Screen minimized? + */ + bool isMinimized() const {return _IsMinimized;} + + /* + * drawBitmap : this is the interface with all the views + * + */ + void drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flipv, + sint32 nTxId, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); + + /* + * Draw a simple wired quad. No flushing is done as the draw is done instantly (usually for debug) + */ + void drawWiredQuad(sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col = NLMISC::CRGBA::White); + + /* + * Draw a simple filled quad. No flushing is done as the draw is done instantly (usually for debug) + */ + void drawFilledQuad(sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col = NLMISC::CRGBA::White); + + /* + * drawBitmap : Tiled version + * \param tileOrigin 2 bits 1 - Left/Right (0/1) 2 - Bottom/Top (0/1) (0-BL)(1-BR)(2-TL)(3-TR) + * + */ + void drawRotFlipBitmapTiled (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flipv, + sint32 nTxId, uint tileOrigin, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); + + + + /* + * drawBitmap : draw a bitmap roted by 90 degrees in CW 'rot times' + * flipv is a boolean that indicates if there is a vertical flip + * this is a 1:1 ratio so if texture is x long there are x pixels on screen + */ + void draw11RotFlipBitmap (sint layerId, sint32 x, sint32 y, uint8 rot, bool flipv, sint32 nTxId, + const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); + + /** Draw an arbitrary quad (fast version) , possibly clipping it. Unlike draw11RotFlipBitmap & the like, texture is filtered here. + * quads are all batched in the same render layer + */ + void drawQuad(sint layerId, const NLMISC::CQuadUV &quadUV, sint32 nTxId, + NLMISC::CRGBA col, bool additif, bool filtered = true); + /** Draw a set of untextured triangle in the given layer. all triangles of the same layer are batched + */ + void drawUnclippedTriangles(sint layerId, const std::vector &tris, NLMISC::CRGBA col); + + /* + * Draw a text + */ + void drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, NL3D::UTextContext &textContext); + + /* + * loadTextures : load all textures associated with the interface + * this function add a globaltexture to the vector of global textures + */ + void loadTextures (const std::string &textureFileName, const std::string &uvFileName, bool uploadDXTC); + + /* + * createTexture : create a texture for the interface, possibly from an externally created texture + * If no external texture is given, then 'sGlobalTextureName' is the filename of the big texture + * You should call deleteTexture when the texture is not used anymore + * The method returns the texture id of the new texture + */ + sint32 createTexture (const std::string &sGlobalTextureName, // unique id identifying this big texture, (its filename if not externally created) + sint32 offsetX = 0, + sint32 offsetY = 0, + sint32 width = -1, + sint32 height = -1, + bool uploadDXTC=true, + bool bReleasable=true + ); + + + // change position of a sub-texture (inside its big texture) from the sub-texture filename + void updateTexturePos(const std::string &texturefileName, + sint32 offsetX = 0, + sint32 offsetY = 0, + sint32 width = -1, + sint32 height = -1 + ); + + /** Add / change a global texture from an externally created texture + * \param defaultTexWidth width to used when CTextureId::createTexture is used without giving the width (e.g width = -1), useful for cropped textures + * \param defaultTexHeight height to used when CTextureId::createTexture is used without giving the height (e.g height = -1), useful for cropped textures + */ + + void setExternalTexture(const std::string &sGlobalTextureName, + NL3D::UTexture *externalTexture = NULL, + uint32 externalTexWidth = 1, + uint32 externalTexHeight = 1, + uint32 defaultTexWidth = 1, + uint32 defaultTexHeight = 1 + ); + + /* + * deleteTexture : create a texture for the interface + */ + void deleteTexture (sint32 textureId); + + // get a global texture pointer from its name + NL3D::UTexture *getGlobalTexture(const std::string &name); + + /* + * Flush all parsed view and computed strings to screen + */ + void flush (); + + /** + * get a texture file pointer from a string name. O(logN) + * \param id : the id of the texture + * \return a texture file pointer. -1 if not found or if sName is empty() + */ + sint32 getTextureIdFromName (const std::string &sName) const; + std::string getTextureNameFromId (sint32 TxID); + void getTextureSizeFromId (sint32 id, sint32 &width, sint32 &height); + NLMISC::CRGBA getTextureColor(sint32 id, sint32 x, sint32 y); + + + /** + * \return the texture associated with the param figur + */ + sint32 getFigurTextureId(uint index) + { + nlassert(index < 10); + return _IndexesToTextureIds[index]; + } + + /** + * \return the texture for figur separator '-' + */ + sint32 getFigurSeparator() const { return _FigurSeparatorTextureId; } + + sint32 getFigurTextureW() const {return _WFigurTexture;} + sint32 getFigurTextureH() const {return _HFigurTexture;} + sint32 getFigurSeparatorW() const {return _WFigurSeparatorTexture;} + sint32 getFigurSeparatorH() const {return _HFigurSeparatorTexture;} + + + sint32 getFigurBlankTextureId () + { + return _FigurBlankId; + } + sint32 getBlankTextureId () + { + return _BlankId; + } + + + sint32 getTypoTextureW(char c); + sint32 getTypoTextureH(char c); + sint32 getTypoTextureId(char c); + + /// System Texture Manager. Used to avoid storing an id in each Ctrl for some texture code is aware of + // @{ + sint32 getSystemTextureId(TSystemTexture e) const {return _SystemTextures[e].Id;} + sint32 getSystemTextureW(TSystemTexture e) const {return _SystemTextures[e].W;} + sint32 getSystemTextureH(TSystemTexture e) const {return _SystemTextures[e].H;} + // @} + + /// For string rendering, get the RenderBuffer to the specified layer + NL3D::URenderStringBuffer *getStringRenderBuffer(sint layerId); + + + /** Custom Rendering Interface + * Note that this function is EXTREMLY SLOW so it should be used with care + * This function flush the quad cache, clip the quad passed with current clipping region + * and draw (with drawQuedUV2) it with the material passed in parameter. There is no cache operation done. + * uv used are from (0,0) -> (1,1) for the 2 stages + */ + void drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col, NL3D::UMaterial Mat); + // Same but we can control uv mapping of first stage + void drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, + const NLMISC::CUV &uv0Min, const NLMISC::CUV &uv0Max, + NLMISC::CRGBA col, NL3D::UMaterial Mat); + // Same but we can control uv mapping of 2 stages + void drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, + const NLMISC::CUV &uv0Min, const NLMISC::CUV &uv0Max, const NLMISC::CUV &uv1Min, const NLMISC::CUV &uv1Max, + NLMISC::CRGBA col, NL3D::UMaterial Mat); + + // **** World space interface methods + + /** Set the current Z in projCenter.z. + * If you want to scale the window position, set a scale!=1. projCenter.x/y is used as the + * pivot (in window coordinates) + */ + void setInterfaceDepth (const NLMISC::CVector &projCenter, float scale); + + // Activate world space transformation + void activateWorldSpaceMatrix (bool activate); + + // Set the screen to world space matrix + void setWorldSpaceFrustum (const NL3D::CFrustum &cameraFrustum); + + // Get the current Frustum + const NL3D::CFrustum &getFrustum () const + { + return _CameraFrustum; + } + + private: + /** + * init the map _IndexesToTextures + */ + void initIndexesToTextureIds (); + void initTypo (); + + bool needClipping (const NLMISC::CQuad &q); + + void clip (NLMISC::CQuadColorUV &qout, const NLMISC::CQuadColorUV &qin, uint rot); + void clip (NLMISC::CQuadColorUV2 &qout, const NLMISC::CQuadColorUV2 &qin); + private: + + // A layer is a vector of Quads. + class CLayer + { + public: + // unfiltered quads + std::vector Quads; + uint32 NbQuads; + std::vector Tris; + // filtered alpha blended quads + std::vector FilteredAlphaBlendedQuads; + // filtered alpha blended tris + std::vector FilteredAlphaBlendedTris; + // filtered additif blended quads + std::vector FilteredAdditifQuads; + // filtered additif blended tris + std::vector FilteredAdditifTris; + + CLayer() + { + NbQuads= 0; + } + }; + + // SGlobalTexture is a texture that regroup other texture. We store also current quads to render + struct SGlobalTexture + { + SGlobalTexture () + { + FromGlobaleTexture = true; + } + uint32 Width, Height; + uint32 DefaultWidth, DefaultHeight; + NL3D::UTexture *Texture; + std::string Name; + bool FromGlobaleTexture; + // Array of layers + CLayer Layers[VR_NUM_LAYER]; + }; + + // For each Layer, store a string Buffer + NL3D::URenderStringBuffer *_StringRBLayers[VR_NUM_LAYER]; + + // For each Layer, tells if empty or not + bool _EmptyLayer[VR_NUM_LAYER]; + + // SImage is one texture of the SGlobalTexture textures + struct SImage + { + std::string Name; + SGlobalTexture *GlobalTexturePtr; + NLMISC::CUV UVMin, UVMax; + + // Assign UV of this image to a quad depending on the flip and rot + void setupQuadUV(bool flipv, uint8 rot, NLMISC::CQuadColorUV &dest); + }; + + // *************************************************************************** + // \name Texture management + // *************************************************************************** + + // SImage accessors + SImage *getSImage(sint32 textureId) + { + return &(*(_SImageIterators[textureId])); + } + + + // Add a SImage + sint32 addSImage(const SImage &image) + { + uint i; + for (i=0; i<_SImageIterators.size(); i++) + { + // Free ? + if (_SImageIterators[i] == _SImages.end()) + break; + } + + // Nothing free ? + if (i == _SImageIterators.size()) + _SImageIterators.push_back(_SImages.end()); + + _SImages.push_back(image); + _SImageIterators[i] = _SImages.end(); + _SImageIterators[i]--; + return (sint32)i; + } + + // Remove a SImage + void removeSImage(sint32 textureId) + { + // Allocated ? + nlassert (_SImageIterators[textureId] != _SImages.end()); + + // Remove the image + _SImages.erase (_SImageIterators[textureId]); + + // Remove the index entry + _SImageIterators[textureId] = _SImages.end(); + } + + typedef std::list TGlobalTextureList; + typedef std::list TSImageList; + typedef std::vector::iterator> TSImageIterator; + + // List of global textures + TGlobalTextureList _GlobalTextures; + + // List of SImage + TSImageList _SImages; + + // Array used to convert a texture ID in _SImages iterator + TSImageIterator _SImageIterators; + + // *************************************************************************** + + typedef std::map TTextureMap; + TTextureMap _TextureMap; + + NL3D::UMaterial _Material; + + // Clip & screen system + sint32 _ClipX, _ClipY, _ClipW, _ClipH; + float _XMin, _XMax, _YMin, _YMax; + + sint32 _ScreenW, _ScreenH; + float _OneOverScreenW, _OneOverScreenH; + bool _IsMinimized; + + + //map linking a uint to a bitmap. Used to display figurs + std::vector _IndexesToTextureIds; + sint32 _FigurSeparatorTextureId; + sint32 _FigurBlankId, _BlankId; + sint32 _WFigurTexture; + sint32 _HFigurTexture; + sint32 _WFigurSeparatorTexture; + sint32 _HFigurSeparatorTexture; + NLMISC::CUV _BlankUV; + SGlobalTexture *_BlankGlobalTexture; + + // System textures + class CSystemTexture + { + public: + sint32 Id; + sint32 W; + sint32 H; + + CSystemTexture() + { + Id= -1; + W= H= 0; + } + }; + CSystemTexture _SystemTextures[NumSystemTextures]; + + // Typo texture + enum + { + NumTypoChar= 127, + }; + sint32 _TypoCharToTextureIds[NumTypoChar]; + sint32 _TypoCharWs[NumTypoChar]; + sint32 _TypoH; + + + void addSystemTexture(TSystemTexture e, const char *s); + void initSystemTextures(); + + /** + * put a new quad in the cache (call flush if texture different) + */ + void putQuadInLayer (SGlobalTexture >, sint layerId, const NLMISC::CQuadColorUV &qcoluv, uint rot); + + // World space interface methods + void worldSpaceTransformation (NLMISC::CQuadColorUV &qcoluv); + + bool _WorldSpaceTransformation; // Transform into world space + float _CurrentZ; // Current z used for the scene + NL3D::CFrustum _CameraFrustum; // Transform from screen space to world space + NLMISC::CMatrix _WorldSpaceMatrix; // Matrix to be applied for world space transformation + bool _WorldSpaceScale; + + + static CViewRenderer *instance; + static NL3D::UDriver *driver; + static NL3D::UTextContext *textcontext; + + public: + static std::set< std::string > *hwCursors; + static float hwCursorScale; + + }; + + +} + +#endif // NL_VIEW_RENDERER_H + +/* End of view_renderer.h */ diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp new file mode 100644 index 000000000..6e66c3edf --- /dev/null +++ b/code/nel/src/gui/view_renderer.cpp @@ -0,0 +1,1869 @@ +// Ryzom - 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 "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/uv.h" +#include "nel/misc/hierarchical_timer.h" +#include "nel/gui/view_renderer.h" + +using namespace NLMISC; +using namespace std; +using namespace NL3D; + +namespace NLGUI +{ + + CViewRenderer* CViewRenderer::instance = NULL; + NL3D::UDriver* CViewRenderer::driver = NULL; + NL3D::UTextContext* CViewRenderer::textcontext = NULL; + std::set< std::string >* CViewRenderer::hwCursors = NULL; + float CViewRenderer::hwCursorScale = 1.0f; + + CViewRenderer::CViewRenderer() + { + nlassert( CViewRenderer::driver != NULL ); + nlassert( CViewRenderer::textcontext != NULL ); + nlassert( CViewRenderer::hwCursors != NULL ); + setup(); + } + + CViewRenderer::~CViewRenderer() + { + for(uint i=0;igetWindowSize (w, h); + // not minimized? change coords + if(w!=0 && h!=0) + { + _IsMinimized= false; + _ScreenW = w; + _ScreenH = h; + if(_ScreenW>0) + _OneOverScreenW = 1.0f / (float)_ScreenW; + else + _OneOverScreenW = 1000; + if(_ScreenH>0) + _OneOverScreenH = 1.0f / (float)_ScreenH; + else + _OneOverScreenH = 1000; + } + else + { + // Keep old coordinates (suppose resolution won't change, even if typically false wen we swithch from outgame to ingame) + _IsMinimized= true; + } + } + + + /* + * getScreenSize : get the screen window size + */ + void CViewRenderer::getScreenSize (uint32 &w, uint32 &h) + { + w = _ScreenW; + h = _ScreenH; + } + + /* + * get OOW / OOH + */ + void CViewRenderer::getScreenOOSize (float &oow, float &ooh) + { + oow= _OneOverScreenW; + ooh= _OneOverScreenH; + } + + void CViewRenderer::setup() + { + _ClipX = _ClipY = 0; + _ClipW = 800; + _ClipH = 600; + _ScreenW = 800; + _ScreenH = 600; + _OneOverScreenW= 1.0f / (float)_ScreenW; + _OneOverScreenH= 1.0f / (float)_ScreenH; + _IsMinimized= false; + _WFigurTexture= 0; + _HFigurTexture= 0; + _WFigurSeparatorTexture = 0; + _FigurSeparatorTextureId = -1; + _FigurBlankId = -1; + _BlankId = -1; + _WorldSpaceTransformation = true; + _CurrentZ = 10; + for(uint i=0;icreateMaterial(); + + setRenderStates(); + + // Init all renderBuffer + for(uint i=0;icreateRenderBuffer(); + } + } + + void CViewRenderer::setRenderStates() + { + _Material.setDoubleSided(); + _Material.setZWrite(false); + _Material.setZFunc(UMaterial::always); + _Material.setBlend (true); + _Material.setBlendFunc (NL3D::UMaterial::srcalpha, NL3D::UMaterial::invsrcalpha); + _Material.setColor(CRGBA::White); + _Material.setTexture(0, NULL); + _Material.setTexture(1, NULL); + _Material.setTexture(2, NULL); + _Material.setTexture(3, NULL); + _Material.setZBias(0); + } + /* + * reset: reset the whole view renderer + */ + void CViewRenderer::reset() + { + TGlobalTextureList::iterator ite = _GlobalTextures.begin(); + while (ite != _GlobalTextures.end()) + { + UTextureFile *tf = dynamic_cast(ite->Texture); + if (tf) + { + driver->deleteTextureFile (tf); + } + ite++; + } + + _GlobalTextures.clear(); + _SImages.clear(); + _SImageIterators.clear(); + _TextureMap.clear(); + _IndexesToTextureIds.clear(); + } + + NL3D::UDriver* CViewRenderer::getDriver(){ + return driver; + } + + void CViewRenderer::setTextContext(NL3D::UTextContext *textcontext) + { + CViewRenderer::textcontext = textcontext; + } + + void CViewRenderer::setDriver( NL3D::UDriver *driver ) + { + CViewRenderer::driver = driver; + } + + // *************************************************************************** + void CViewRenderer::SImage::setupQuadUV(bool flipv, uint8 rot, CQuadColorUV &dest) + { + nlassert(rot<=3); + // Rotation is CW and flip is along x axis + // Flip is vertical flip (this means we invert all y for a constant x) + // The transforms are done in this order : first apply the flip (or not) and then rotate + static const CUV UVTab[8][4] = { + { CUV(0, 0), CUV(1, 0), CUV(1, 1), CUV(0, 1) }, // rot 0, no flip + { CUV(1, 0), CUV(1, 1), CUV(0, 1), CUV(0, 0) }, // rot 1, no flip + { CUV(1, 1), CUV(0, 1), CUV(0, 0), CUV(1, 0) }, // rot 2, no flip + { CUV(0, 1), CUV(0, 0), CUV(1, 0), CUV(1, 1) }, // rot 3, no flip + { CUV(1, 0), CUV(0, 0), CUV(0, 1), CUV(1, 1) }, // rot 0, flipped + { CUV(0, 0), CUV(0, 1), CUV(1, 1), CUV(1, 0) }, // rot 1, flipped + { CUV(0, 1), CUV(1, 1), CUV(1, 0), CUV(0, 0) }, // rot 2, flipped + { CUV(1, 1), CUV(1, 0), CUV(0, 0), CUV(0, 1) } // rot 3, flipped + }; + + // Take care that the origin in the texture is top left so to get the texture in bottom-up + // we have to start at Max and go at Min. For left and right this is Min to Max. + + float du = UVMax.U - UVMin.U; + float dv = UVMin.V - UVMax.V; + + uint idx = flipv*4 + rot; + + dest.Uv0 = CUV (UVMin.U + UVTab[idx][0].U * du, UVMax.V + UVTab[idx][0].V * dv); + dest.Uv1 = CUV (UVMin.U + UVTab[idx][1].U * du, UVMax.V + UVTab[idx][1].V * dv); + dest.Uv2 = CUV (UVMin.U + UVTab[idx][2].U * du, UVMax.V + UVTab[idx][2].V * dv); + dest.Uv3 = CUV (UVMin.U + UVTab[idx][3].U * du, UVMax.V + UVTab[idx][3].V * dv); + + /* // TRAP : Unrolled Version (To be tested to know if it is faster than the previous one) + if (flipv) + { + switch (rot) + { + case 0: + qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMax.V; + qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMax.V; + qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMin.V; + qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMin.V; + break; + case 1: + qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMax.V; + qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMin.V; + qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMin.V; + qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMax.V; + break; + case 2: + qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMin.V; + qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMin.V; + qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMax.V; + qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMax.V; + break; + case 3: + qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMin.V; + qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMax.V; + qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMax.V; + qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMin.V; + break; + } + } + else + { + switch (rot) + { + case 0: + qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMax.V; + qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMax.V; + qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMin.V; + qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMin.V; + break; + case 1: + qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMin.V; + qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMax.V; + qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMax.V; + qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMin.V; + break; + case 2: + qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMin.V; + qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMin.V; + qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMax.V; + qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMax.V; + break; + case 3: + qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMax.V; + qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMin.V; + qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMin.V; + qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMax.V; + break; + } + } + */ + } + // *************************************************************************** + + /* + * drawRotFlipBitmapTiled + */ + void CViewRenderer::drawRotFlipBitmapTiled (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flip, + sint32 nTxId, uint tileOrigin, const CRGBA &col) + { + static volatile bool draw = true; + if (!draw) return; + if (width <= 0 || height <= 0) return; + + if (nTxId < 0) return; + + // Is totally clipped ? + if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || + (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) + return; + + SImage &rI = *getSImage(nTxId); + + sint32 txw, txh; + // start to draw at the reference corner + getTextureSizeFromId (nTxId, txw, txh); + + if (rot > 3) rot = 3; + + sint32 startX = x, startY = y; + sint32 stepX = txw, stepY = txh; + + if (rot & 1) + { + std::swap(txw, txh); + } + + // choose new start pos & uvs depending on the reference corner + // Along x axis + if (tileOrigin & 1) // right or left ? + { // right + startX = x + width - txw; + stepX = -txw; + } + + // Along y axis + if (tileOrigin & 2) // bottom or top ? + { // top + startY = y + height - txh; + stepY = -txh; + } + + // Fit screen coordinates + + float fStartX = (float) startX * _OneOverScreenW; + float fStartY = (float) startY * _OneOverScreenH; + float fStepX = (float) stepX * _OneOverScreenW; + float fStepY = (float) stepY * _OneOverScreenH; + float fTxW = (float) txw * _OneOverScreenW; + float fTxH = (float) txh * _OneOverScreenH; + + CQuadColorUV qcoluv; + + qcoluv.Color0 = qcoluv.Color1 = qcoluv.Color2 = qcoluv.Color3 = col; + qcoluv.V0.z = qcoluv.V1.z = qcoluv.V2.z = qcoluv.V3.z = 0; + rI.setupQuadUV(flip,rot,qcoluv); + + uint numTileX = (uint32)((width - 1) / txw); + uint numTileY = (uint32)((height- 1) / txh); + + float currY = fStartY; + + sint32 oldClipX = _ClipX; + sint32 oldClipY = _ClipY; + sint32 oldClipW = _ClipW; + sint32 oldClipH = _ClipH; + if (x < _ClipX) { width -= _ClipX - x; x = _ClipX; } + if (y < _ClipY) { height -= _ClipY - y; y = _ClipY; } + if ((x+width) > (_ClipX+_ClipW)) width -= (x+width) - (_ClipX+_ClipW); + if ((y+height) > (_ClipY+_ClipH)) height -= (y+height) - (_ClipY+_ClipH); + setClipWindow (x, y, width, height); + + // draw result let the clipper clip the quads + for(uint py = 0; py <= numTileY; ++py) + { + float currX = fStartX; + for(uint px = 0; px <= numTileX; ++px) + { + /// There is room for speedup there + qcoluv.V0.x = currX; + qcoluv.V1.x = currX + fTxW; + qcoluv.V2.x = currX + fTxW; + qcoluv.V3.x = currX; + + qcoluv.V0.y = currY; + qcoluv.V1.y = currY; + qcoluv.V2.y = currY + fTxH; + qcoluv.V3.y = currY + fTxH; + + // Is NOT totally clipped ? + if ( !( (qcoluv.V0.x > _XMax) || (qcoluv.V2.x < _XMin) || + (qcoluv.V0.y > _YMax) || (qcoluv.V2.y < _YMin) ) ) + putQuadInLayer (*(rI.GlobalTexturePtr), layerId, qcoluv, rot); + + currX += fStepX; + } + currY += fStepY; + } + + setClipWindow (oldClipX, oldClipY, oldClipW, oldClipH); + } + + + /* + * drawBitmap + */ + void CViewRenderer::drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, + uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col) + { + if (width <= 0 || height <= 0) return; + + if (nTxId < 0) + return; + + + + float dstXmin, dstYmin, dstXmax, dstYmax; + + // Is totally clipped ? + if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || + (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) + return; + + dstXmin = (float)(x) * _OneOverScreenW; + dstYmin = (float)(y) * _OneOverScreenH; + dstXmax = (float)(x + width) * _OneOverScreenW; + dstYmax = (float)(y + height) * _OneOverScreenH; + + CQuadColorUV qcoluv; + qcoluv.V0.set (dstXmin, dstYmin, 0); + qcoluv.V1.set (dstXmax, dstYmin, 0); + qcoluv.V2.set (dstXmax, dstYmax, 0); + qcoluv.V3.set (dstXmin, dstYmax, 0); + + qcoluv.Color0 = qcoluv.Color1 = qcoluv.Color2 = qcoluv.Color3 = col; + + SImage &rI = *getSImage(nTxId); + + // Avoid switch in common case + if (!flipv && !rot) + { + qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMax.V; + qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMax.V; + qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMin.V; + qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMin.V; + } + // else standard case + else + { + if (rot > 3) + rot = 3; + + rI.setupQuadUV(flipv, rot, qcoluv); + } + + static volatile bool doRot[4] = { true, true, true, true }; + if (doRot[rot]) + { + putQuadInLayer (*(rI.GlobalTexturePtr), layerId, qcoluv, rot); + } + } + + + /* + * draw11RotBitmap + * sTx must be lowered !!! + */ + void CViewRenderer::draw11RotFlipBitmap (sint layerId, sint32 x, sint32 y, uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col) + { + if (nTxId < 0) + return; + + sint32 txw, txh; + SImage &rImage = *getSImage(nTxId); + txw = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width+0.5f); + txh = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height+0.5f); + + drawRotFlipBitmap (layerId, x, y, txw, txh, rot, flipv, nTxId, col); + } + + + inline void remapUV(CUV &dest, const CUV &src, const CUV &min, const CUV &max) + { + dest.set(src.U * (max.U - min.U) + min.U, src.V * (max.V - min.V) + min.V); + } + + void CViewRenderer::drawQuad(sint layerId, const NLMISC::CQuadUV &quadUV, sint32 nTxId, NLMISC::CRGBA col /*=NLMISC::CRGBA(255,255,255,255)*/, bool additif, bool filtered) + { + nlassert(!(additif && !filtered)); // not implemented yet! + if (nTxId < 0) + return; + CQuadColorUV normedQuad; + // + normedQuad.V0.set(quadUV.V0.x * _OneOverScreenW, quadUV.V0.y * _OneOverScreenH, 0.f); + normedQuad.V1.set(quadUV.V1.x * _OneOverScreenW, quadUV.V1.y * _OneOverScreenH, 0.f); + normedQuad.V2.set(quadUV.V2.x * _OneOverScreenW, quadUV.V2.y * _OneOverScreenH, 0.f); + normedQuad.V3.set(quadUV.V3.x * _OneOverScreenW, quadUV.V3.y * _OneOverScreenH, 0.f); + // + float qXMin = minof(normedQuad.V0.x, normedQuad.V1.x, normedQuad.V2.x, normedQuad.V3.x); + if (qXMin > _XMax) return; + float qXMax = maxof(normedQuad.V0.x, normedQuad.V1.x, normedQuad.V2.x, normedQuad.V3.x); + if (qXMax < _XMin) return; + float qYMin = minof(normedQuad.V0.y, normedQuad.V1.y, normedQuad.V2.y, normedQuad.V3.y); + if (qYMin > _YMax) return; + float qYMax = maxof(normedQuad.V0.y, normedQuad.V1.y, normedQuad.V2.y, normedQuad.V3.y); + if (qYMax < _YMin) return; + // + + + + SImage &rImage = *getSImage(nTxId); + SGlobalTexture > = *(rImage.GlobalTexturePtr); + CUV deltaUV(1.f / (float) gt.Width, 1.f / (float) gt.Height); + CUV cornerMin = rImage.UVMin + deltaUV; + CUV cornerMax = rImage.UVMax - deltaUV; + remapUV(normedQuad.Uv0, quadUV.Uv0, cornerMin, cornerMax); + remapUV(normedQuad.Uv1, quadUV.Uv1, cornerMin, cornerMax); + remapUV(normedQuad.Uv2, quadUV.Uv2, cornerMin, cornerMax); + remapUV(normedQuad.Uv3, quadUV.Uv3, cornerMin, cornerMax); + + // test if clipping is required + if (qXMin >= _XMin && qYMin >= _YMin && qXMax <= _XMax && qYMax <= _YMax) + { + // not clipped, easy case + normedQuad.Color0 = normedQuad.Color1 = normedQuad.Color2 = normedQuad.Color3 = col; + + if (_WorldSpaceTransformation) + { + worldSpaceTransformation (normedQuad); + } + + layerId+= VR_BIAS_LAYER; + nlassert(layerId>=0 && layerIdLayers[layerId]; + if (!filtered) + { + if (layer.NbQuads == layer.Quads.size()) + layer.Quads.push_back (normedQuad); + else + layer.Quads[layer.NbQuads] = normedQuad; + ++ layer.NbQuads; + } + else if (additif) layer.FilteredAdditifQuads.push_back(normedQuad); + else layer.FilteredAlphaBlendedQuads.push_back(normedQuad); + _EmptyLayer[layerId]= false; + } + else + { + // Partially clipped (slowest case) + // Must do the clip manually + static const uint maxNumCorners = 8; + // + static CVector outPos0[maxNumCorners]; + static CUV outUV0[maxNumCorners]; + static CVector outPos1[maxNumCorners]; + static CUV outUV1[maxNumCorners]; + // + outUV0[0] = normedQuad.Uv0; + outUV0[1] = normedQuad.Uv1; + outUV0[2] = normedQuad.Uv2; + outUV0[3] = normedQuad.Uv3; + // + outPos0[0] = normedQuad.V0; + outPos0[1] = normedQuad.V1; + outPos0[2] = normedQuad.V2; + outPos0[3] = normedQuad.V3; + // + CVector *pPos0 = outPos0; + CVector *pPos1 = outPos1; + CUV *pUV0 = outUV0; + CUV *pUV1 = outUV1; + // + sint count = 4; + // + if (qXMin < _XMin) + { + // clip left + CPlane clipper(-1.f, 0.f, 0.f, _XMin); + count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); + std::swap(pPos0, pPos1); + std::swap(pUV0, pUV1); + } + if (qXMax > _XMax) + { + // clip right + CPlane clipper(1.f, 0.f, 0.f, -_XMax); + count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); + std::swap(pPos0, pPos1); + std::swap(pUV0, pUV1); + } + // + if (qYMin < _YMin) + { + // clip bottom + CPlane clipper(0.f, -1.f, 0.f, _YMin); + count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); + std::swap(pPos0, pPos1); + std::swap(pUV0, pUV1); + } + if (qYMax > _YMax) + { + // clip top + CPlane clipper(0.f, 1.f, 0.f, -_YMax); + count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); + std::swap(pPos0, pPos1); + std::swap(pUV0, pUV1); + } + + nlassert(count <= (sint)maxNumCorners); + if (count >= 3) + { + count -= 2; + layerId+= VR_BIAS_LAYER; + nlassert(layerId>=0 && layerIdLayers[layerId]; + std::vector *tris; + if (!filtered) + { + tris = &layer.Tris; + } + else + { + tris = additif ? &layer.FilteredAdditifTris : &layer.FilteredAlphaBlendedTris; + } + tris->resize(tris->size() + count); + CTriangleColorUV *lastTri = &tris->back() + 1; + CTriangleColorUV *currTri = lastTri - count; + const CVector *firstPos = pPos0++; + const CUV *firstUV = pUV0++; + do + { + currTri->V0 = *firstPos; + currTri->V1 = *pPos0; + currTri->V2 = *(pPos0 + 1); + currTri->Color0 = col; + currTri->Color1 = col; + currTri->Color2 = col; + currTri->Uv0 = *firstUV; + currTri->Uv1 = *pUV0; + currTri->Uv2 = *(pUV0 + 1); + + pPos0 ++; + pUV0 ++; + ++currTri; + } + while (currTri != lastTri); + _EmptyLayer[layerId]= false; + } + } + } + + + void CViewRenderer::drawUnclippedTriangles(sint layerId, const std::vector &tris, NLMISC::CRGBA col) + { + if (tris.empty()) return; + if (!_BlankGlobalTexture) return; + // primary goal here is batching, so we prefer to draw the triangle with a blank texture rather than + // switching material and having to flush all primitives . + layerId+= VR_BIAS_LAYER; + nlassert(layerId>=0 && layerIdLayers[layerId]; + uint startCount = (uint)layer.FilteredAlphaBlendedTris.size(); + layer.FilteredAlphaBlendedTris.resize(startCount + tris.size()); + const NLMISC::CTriangle *src =&tris[0]; + const NLMISC::CTriangle *last = src + tris.size(); + NLMISC::CTriangleColorUV *dest = &layer.FilteredAlphaBlendedTris[0] + startCount; + _EmptyLayer[layerId]= false; + do + { + dest->V0.set(src->V0.x * _OneOverScreenW, src->V0.y * _OneOverScreenH, 0.f); + dest->V1.set(src->V1.x * _OneOverScreenW, src->V1.y * _OneOverScreenH, 0.f); + dest->V2.set(src->V2.x * _OneOverScreenW, src->V2.y * _OneOverScreenH, 0.f); + static volatile bool testOpaque = false; + if (testOpaque) + { + dest->Color0 = CRGBA::White; + dest->Color1 = CRGBA::White; + dest->Color2 = CRGBA::White; + dest->Uv0.set(0.f, 0.f); + dest->Uv1.set(1.f, 0.f); + dest->Uv2.set(1.f, 1.f); + } + else + { + dest->Color0 = col; + dest->Color1 = col; + dest->Color2 = col; + dest->Uv0 = _BlankUV; + dest->Uv1 = _BlankUV; + dest->Uv2 = _BlankUV; + } + ++ dest; + ++ src; + } + while (src != last); + } + + /* + * loadTextures + */ + void CViewRenderer::loadTextures (const std::string &textureFileName, const std::string &uvFileName, bool uploadDXTC) + { + SGlobalTexture gt; + // Load texture file + string filename = CPath::lookup (textureFileName, false); + if (filename == "") return; + CIFile ifTmp; + if (ifTmp.open(filename)) + CBitmap::loadSize (ifTmp, gt.Width, gt.Height); + gt.Texture = driver->createTextureFile (filename); + // Force to generate the texture now. This way we can extract the mouse bitmaps from it now without having to load it again. + // Its why we don't release it at the end, because it is likely to be uploaded soon) + CBitmap *texDatas = gt.Texture->generateDatas(); + // + gt.Name = filename; + gt.Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); + if(uploadDXTC) + gt.Texture->setUploadFormat(UTexture::DXTC5); + + // Load uv file + CIFile iFile; + filename = CPath::lookup (uvFileName, false); + if (filename == "") return; + if (!iFile.open(filename)) return; + + _GlobalTextures.push_back (gt); + + driver->setCursorScale( CViewRenderer::hwCursorScale ); + + char bufTmp[256], tgaName[256]; + string sTGAname; + float uvMinU, uvMinV, uvMaxU, uvMaxV; + while (!iFile.eof()) + { + iFile.getline (bufTmp, 256); + sscanf (bufTmp, "%s %f %f %f %f", tgaName, &uvMinU, &uvMinV, &uvMaxU, &uvMaxV); + SImage image; + image.UVMin.U = uvMinU; + image.UVMin.V = uvMinV; + image.UVMax.U = uvMaxU; + image.UVMax.V = uvMaxV; + sTGAname = toLower(string(tgaName)); + + string::size_type stripPng = sTGAname.find(".png"); + if (stripPng != string::npos) + { + sTGAname[stripPng + 1] = 't'; + sTGAname[stripPng + 2] = 'g'; + sTGAname[stripPng + 3] = 'a'; + } + + image.Name = sTGAname; + image.GlobalTexturePtr = &(_GlobalTextures.back()); + if (getTextureIdFromName(sTGAname) != -1) + { + string tmp = string("duplicate texture name in ") + textureFileName + "(" + sTGAname + ")"; + nlwarning(tmp.c_str()); + } + else + { + sint32 textureId = addSImage(image); + //nlwarning("SIMAGE ADDED: id = %x, name = %s", textureId, image.Name.c_str()); + // Insert in map. + _TextureMap.insert( make_pair(image.Name, textureId) ); + } + + // if this is a cursor texture, extract it now (supported for rgba only now, because of the blit) + if (texDatas && texDatas->getPixelFormat() == CBitmap::RGBA) + { + if( CViewRenderer::hwCursors->count( image.Name ) > 0 ) + { + uint x0 = (uint) (image.UVMin.U * gt.Width); + uint y0 = (uint) (image.UVMin.V * gt.Height); + uint x1 = (uint) (image.UVMax.U * gt.Width); + uint y1 = (uint) (image.UVMax.V * gt.Height); + if (x1 != x0 && y1 != y0) + { + CBitmap curs; + curs.resize(x1 - x0, y1 - y0); + curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0); + driver->addCursor(image.Name, curs); + } + } + } + } + + initIndexesToTextureIds (); + initSystemTextures(); + initTypo(); + } + + + + + void CViewRenderer::setExternalTexture(const std::string &sGlobalTextureName, + NL3D::UTexture *externalTexture, + uint32 externalTexWidth, + uint32 externalTexHeight, + uint32 defaultTexWidth, + uint32 defaultTexHeight + ) + { + if (sGlobalTextureName.empty()) + { + nlwarning("Can't create aglobal texture with an empty name"); + return; + } + // Look if already existing + string sLwrGTName = strlwr(sGlobalTextureName); + TGlobalTextureList::iterator ite = _GlobalTextures.begin(); + while (ite != _GlobalTextures.end()) + { + std::string sText = strlwr(ite->Name); + if (sText == sLwrGTName) + break; + ite++; + } + if (ite == _GlobalTextures.end()) + { + SGlobalTexture gtTmp; + gtTmp.FromGlobaleTexture = true; + + gtTmp.Name = sLwrGTName; + _GlobalTextures.push_back(gtTmp); + ite = _GlobalTextures.end(); + ite--; + } + ite->Width = externalTexWidth; + ite->Height = externalTexHeight; + ite->DefaultWidth = defaultTexWidth; + ite->DefaultHeight = defaultTexHeight; + ite->Texture = externalTexture; + } + + /* + * createTexture + */ + sint32 CViewRenderer::createTexture (const std::string &sGlobalTextureName, + sint32 offsetX, + sint32 offsetY, + sint32 width, + sint32 height, + bool uploadDXTC, + bool bReleasable + ) + { + if (sGlobalTextureName.empty()) return -1; + // Look if already existing + string sLwrGTName = strlwr(sGlobalTextureName); + TGlobalTextureList::iterator ite = _GlobalTextures.begin(); + while (ite != _GlobalTextures.end()) + { + std::string sText = strlwr(ite->Name); + if (sText == sLwrGTName) + break; + ite++; + } + + // If global texture not exists create it + if (ite == _GlobalTextures.end()) + { + SGlobalTexture gtTmp; + gtTmp.FromGlobaleTexture = false; + string filename = CPath::lookup (sLwrGTName, false); + if (filename == "") return -1; + CIFile ifTmp; + if (ifTmp.open(filename)) + { + CBitmap::loadSize (ifTmp, gtTmp.Width, gtTmp.Height); + gtTmp.DefaultWidth = gtTmp.Width; + gtTmp.DefaultHeight = gtTmp.Height; + if (gtTmp.Width == 0 || gtTmp.Height == 0) + { + nlwarning("Failed to load the texture '%s', please check image format", filename.c_str()); + } + } + gtTmp.Texture = driver->createTextureFile (sLwrGTName); + gtTmp.Name = sLwrGTName; + gtTmp.Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); + if(uploadDXTC) + gtTmp.Texture->setUploadFormat(UTexture::DXTC5); + gtTmp.Texture->setReleasable(bReleasable); + _GlobalTextures.push_back(gtTmp); + ite = _GlobalTextures.end(); + ite--; + } + + // Add a texture with reference to the i th global texture + SImage iTmp; + + // Set default parameters + if (width == -1) + width = ite->DefaultWidth; + if (height == -1) + height = ite->DefaultHeight; + + iTmp.Name = sLwrGTName; + iTmp.GlobalTexturePtr = &(*ite); + iTmp.UVMin = CUV(((float)offsetX)/ite->Width , ((float)offsetY)/ite->Height); + iTmp.UVMax = CUV(((float)offsetX+width)/ite->Width , ((float)offsetY+height)/ite->Height); + sint32 TextID = addSImage(iTmp); + //nlwarning("SIMAGE ADDED: id = %d, name = %s", TextID, iTmp.Name.c_str()); + + // Insert / replace in map. + // TMP TMP FIX NICO + //_TextureMap.insert( make_pair(iTmp.Name, TextID) ); + + + return TextID; + } + + void CViewRenderer::updateTexturePos(const std::string &texturefileName, sint32 offsetX /*=0*/, sint32 offsetY /*=0*/, sint32 width /*=-1*/, sint32 height /*=-1*/) + { + sint32 id = getTextureIdFromName (texturefileName); + if (id == -1) + { + nlwarning("Unknwown texture %s, can't update pos", texturefileName.c_str()); + return; + } + SImage *im = getSImage(id); + nlassert(im); + // Set default parameters + sint32 gw = im->GlobalTexturePtr->Width; + sint32 gh = im->GlobalTexturePtr->Height; + if (width == -1) + width = gw; + if (height == -1) + height = gh; + im->UVMin = CUV(((float)offsetX)/gw , ((float)offsetY)/gh); + im->UVMax = CUV(((float)offsetX+width)/gw, ((float)offsetY+height)/gh); + } + + + /* + * getGlobalTexture + */ + NL3D::UTexture *CViewRenderer::getGlobalTexture(const std::string &name) + { + string sLwrGTName = strlwr(name); + TGlobalTextureList::iterator ite = _GlobalTextures.begin(); + while (ite != _GlobalTextures.end()) + { + std::string sText = strlwr(ite->Name); + if (sText == sLwrGTName) + break; + ite++; + } + if (ite != _GlobalTextures.end()) + { + return ite->Texture; + } + return NULL; + } + + /* + * deleteTexture + */ + void CViewRenderer::deleteTexture (sint32 textureId) + { + // Checks + nlassert ((uint)textureId < _SImageIterators.size()); + if (_SImageIterators[textureId] == _SImages.end()) + { + nlwarning("Can't delete texture with name %s", getTextureNameFromId(textureId).c_str()); + nlassert(0); + return; + } + + // Backup global texture pointer + SGlobalTexture *gt = getSImage(textureId)->GlobalTexturePtr; + + // Erase only texture from global texture + if (!(gt->FromGlobaleTexture)) + { + //nlwarning("Removing texture with id %d", (int) textureId); + // Erase the SImage + //nlwarning("SIMAGE REMOVE : id = %x, name = %s", (int) textureId, getSImage(textureId)->Name.c_str()); + + + removeSImage (textureId); + + // Check if someone else use this global texture.. + TSImageList::iterator ite = _SImages.begin(); + while (ite != _SImages.end()) + { + // Same global texture ? + if (ite->GlobalTexturePtr == gt) + break; + + ite++; + } + + // Global texture still used ? + if (ite == _SImages.end()) + { + //nlwarning("REMOVE GLOBAL TEXTURE : id of simage = %x", (int) textureId); + // No, remove the global texture + for (TGlobalTextureList::iterator iteGT = _GlobalTextures.begin(); iteGT != _GlobalTextures.end(); iteGT++) + { + // This one ? + if (&(*iteGT) == gt) + { + // Remove this global texture + UTextureFile *tf = dynamic_cast(iteGT->Texture); + if (tf) + { + driver->deleteTextureFile (tf); + } + _GlobalTextures.erase (iteGT); + return; + } + } + // Global texture has not been found + nlstop; + } + } + } + + /* + * getTextureIdFromName + */ + sint32 CViewRenderer::getTextureIdFromName (const string &sName) const + { + if(sName.empty()) + return -1; + + // convert to lowCase + string nameLwr = toLower(sName); + + string::size_type stripPng = nameLwr.find(".png"); + if (stripPng != string::npos) + { + nameLwr[stripPng + 1] = 't'; + nameLwr[stripPng + 2] = 'g'; + nameLwr[stripPng + 3] = 'a'; + } + + // Search in map + TTextureMap::const_iterator it= _TextureMap.find(nameLwr); + if( it==_TextureMap.end() ) + return -1; + else + return it->second; + } + + /* + * getTextureNameFromId + */ + std::string CViewRenderer::getTextureNameFromId (sint32 TxID) + { + if ((TxID < 0) || (TxID >= (sint32)_SImageIterators.size())) + return ""; + SImage *img = getSImage(TxID); + return img->Name; + } + + /* + * getTextureSizeFromName + */ + void CViewRenderer::getTextureSizeFromId (sint32 id, sint32 &width, sint32 &height) + { + if ((id < 0) || (id >= (sint32)_SImageIterators.size())) + { + width = height = 0; + } + else + { + SImage &rImage = *getSImage(id); + width = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width+0.5f); + height = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height+0.5f); + } + } + /* + * getTextureColor + */ + CRGBA CViewRenderer::getTextureColor(sint32 id, sint32 x, sint32 y) + { + if ((id < 0) || (id >= (sint32)_SImageIterators.size())) + { + return CRGBA(255,255,255); + } + + SImage &rImage = *getSImage(id); + SGlobalTexture &rGT = *rImage.GlobalTexturePtr; + sint32 width, height; + width = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rGT.Width+0.5f); + height = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rGT.Height+0.5f); + float xRatio = ((float)x) / ((float)(width)); + float yRatio = ((float)y) / ((float)(height)); + UTexture *pTF = rGT.Texture; + sint32 xConv = (sint32)((rImage.UVMin.U + xRatio * (rImage.UVMax.U - rImage.UVMin.U))*rGT.Width+0.5f); + sint32 yConv = (rGT.Height-1)-(sint32)((rImage.UVMin.V + yRatio * (rImage.UVMax.V - rImage.UVMin.V))*rGT.Height+0.5f); + return pTF->getPixelColor(xConv, yConv); + } + + // *************************************************************************** + sint32 CViewRenderer::getTypoTextureW(char c) + { + if ((c>=0) && (c=0) && (cLayers[layerId]; + if(layer.NbQuads>0 || !layer.Tris.empty()) + { + // setup the global texture to material + _Material.setTexture(0, ite->Texture); + + // Special Case if _WorldSpaceTransformation and _WorldSpaceScale, enable bilinear + if(_WorldSpaceTransformation && _WorldSpaceScale) + ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff); + + // draw quads and empty list + if (layer.NbQuads != 0) + { + driver->drawQuads (&(layer.Quads[0]), layer.NbQuads, _Material); + layer.NbQuads = 0; + } + + if (!layer.Tris.empty()) + { + driver->drawTriangles(layer.Tris, _Material); + layer.Tris.clear(); + } + + // Special Case if _WorldSpaceTransformation and _WorldSpaceScale, reset + if(_WorldSpaceTransformation && _WorldSpaceScale) + ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); + } + if (!layer.FilteredAlphaBlendedQuads.empty() || + !layer.FilteredAlphaBlendedTris.empty() || + !layer.FilteredAdditifQuads.empty() || + !layer.FilteredAdditifTris.empty()) + { + // setup the global texture to material + _Material.setTexture(0, ite->Texture); + + // force filtering + ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff); + // alpha blended + if (!layer.FilteredAlphaBlendedQuads.empty()) + { + driver->drawQuads (&(layer.FilteredAlphaBlendedQuads[0]), (uint32)layer.FilteredAlphaBlendedQuads.size(), _Material); + layer.FilteredAlphaBlendedQuads.clear(); + } + if (!layer.FilteredAlphaBlendedTris.empty()) + { + driver->drawTriangles(layer.FilteredAlphaBlendedTris, _Material); + layer.FilteredAlphaBlendedTris.clear(); + } + // additif + if (!layer.FilteredAdditifQuads.empty() || + !layer.FilteredAdditifTris.empty()) + { + _Material.setBlendFunc (NL3D::UMaterial::one, NL3D::UMaterial::one); + if (!layer.FilteredAdditifQuads.empty()) + { + driver->drawQuads (&(layer.FilteredAdditifQuads[0]), (uint32)layer.FilteredAdditifQuads.size(), _Material); + layer.FilteredAdditifQuads.clear(); + } + if (!layer.FilteredAdditifTris.empty()) + { + driver->drawTriangles(layer.FilteredAdditifTris, _Material); + layer.FilteredAdditifTris.clear(); + } + // restore alpha blend + _Material.setBlendFunc (NL3D::UMaterial::srcalpha, NL3D::UMaterial::invsrcalpha); + } + ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); + } + ite++; + } + + // **** Display Computed Strings of this layer + if (_WorldSpaceTransformation) + textcontext->flushRenderBufferUnProjected(_StringRBLayers[layerId], false); + else + textcontext->flushRenderBuffer(_StringRBLayers[layerId]); + + // flushed + _EmptyLayer[layerId]= true; + } + } + + + /** + * init the map _IndexesToTextures + */ + void CViewRenderer::initIndexesToTextureIds() + { + char buf[20]; + _IndexesToTextureIds.clear(); + for (uint i = 0; i < 10; i++) + { + sprintf (buf, "numbers_%d.tga", i); + _IndexesToTextureIds.push_back (getTextureIdFromName(buf)); + } + _FigurSeparatorTextureId = getTextureIdFromName("Numbers_sep.tga"); + _FigurBlankId = getTextureIdFromName("numbers_blank.tga"); + _BlankId = getTextureIdFromName("blank.tga"); + + SImage *blank = getSImage(_BlankId); + if (blank) + { + _BlankGlobalTexture = blank->GlobalTexturePtr; + _BlankUV = 0.5f * (blank->UVMin + blank->UVMax); + } + else + { + _BlankUV.set(0.f, 0.f); + } + + + // Init size + if(_IndexesToTextureIds[0]!=-1) + { + getTextureSizeFromId (_IndexesToTextureIds[0], _WFigurTexture, _HFigurTexture); + } + if (_FigurSeparatorTextureId != -1) + { + getTextureSizeFromId (_FigurSeparatorTextureId, _WFigurSeparatorTexture, _HFigurSeparatorTexture); + } + + } + + /** + * + */ + void CViewRenderer::initTypo() + { + _TypoH = 0; + + // since filename dose not support special char (?,. ....), specify a map from char to string. + map specialCharMap; + specialCharMap['?']= "question"; + + + char buf[256]; + // For all supported chars (if tga exist) + for (uint i = 0; i < NumTypoChar; i++) + { + // Get the token string for this char. + string token; + map::iterator it= specialCharMap.find(i); + // General case + if(it==specialCharMap.end()) + token= (char)i; + else + token= it->second; + + // get the fileName + sprintf (buf, "typo_%s.tga", token.c_str()); + sint32 id = getTextureIdFromName(buf); + if(id>=0) + { + _TypoCharToTextureIds[i]= id; + sint32 w,h; + getTextureSizeFromId (id, w, h); + _TypoCharWs[i]= w; + _TypoH = h; + } + else + { + _TypoCharToTextureIds[i]= -1; + // simulate a space. + _TypoCharWs[i]= 1; + } + } + } + + + /** + * needClipping + */ + bool CViewRenderer::needClipping (const CQuad &q) + { + if ((q.V0.x >= _XMin) && (q.V0.y >= _YMin) && (q.V2.x <= _XMax) && (q.V2.y <= _YMax)) + return false; + else + return true; + } + + /** + * clip + */ + void CViewRenderer::clip (CQuadColorUV &qout, const CQuadColorUV &qin, uint rot) + { + float ratio; + + qout = qin; + + if (rot & 1) + { + // must reverse U & V during clipping + if (qin.V0.x < _XMin) + { + ratio = ((float)(_XMin - qin.V0.x))/((float)(qin.V1.x - qin.V0.x)); + qout.V3.x = qout.V0.x = _XMin; + qout.Uv0.V += ratio*(qin.Uv1.V-qin.Uv0.V); + qout.Uv3.V += ratio*(qin.Uv2.V-qin.Uv3.V); + } + + if (qin.V0.y < _YMin) + { + ratio = ((float)(_YMin - qin.V0.y))/((float)(qin.V3.y - qin.V0.y)); + qout.V1.y = qout.V0.y = _YMin; + qout.Uv0.U += ratio*(qin.Uv3.U-qin.Uv0.U); + qout.Uv1.U += ratio*(qin.Uv2.U-qin.Uv1.U); + } + + if (qin.V2.x > _XMax) + { + ratio = ((float)(_XMax - qin.V2.x))/((float)(qin.V3.x - qin.V2.x)); + qout.V2.x = qout.V1.x = _XMax; + qout.Uv2.V += ratio*(qin.Uv3.V-qin.Uv2.V); + qout.Uv1.V += ratio*(qin.Uv0.V-qin.Uv1.V); + } + + if (qin.V2.y > _YMax) + { + ratio = ((float)(_YMax - qin.V2.y))/((float)(qin.V1.y - qin.V2.y)); + qout.V2.y = qout.V3.y = _YMax; + qout.Uv2.U += ratio*(qin.Uv1.U-qin.Uv2.U); + qout.Uv3.U += ratio*(qin.Uv0.U-qin.Uv3.U); + } + } + else + { + if (qin.V0.x < _XMin) + { + ratio = ((float)(_XMin - qin.V0.x))/((float)(qin.V1.x - qin.V0.x)); + qout.V3.x = qout.V0.x = _XMin; + qout.Uv0.U += ratio*(qin.Uv1.U-qin.Uv0.U); + qout.Uv3.U += ratio*(qin.Uv2.U-qin.Uv3.U); + } + + if (qin.V0.y < _YMin) + { + ratio = ((float)(_YMin - qin.V0.y))/((float)(qin.V3.y - qin.V0.y)); + qout.V1.y = qout.V0.y = _YMin; + qout.Uv0.V += ratio*(qin.Uv3.V-qin.Uv0.V); + qout.Uv1.V += ratio*(qin.Uv2.V-qin.Uv1.V); + } + + if (qin.V2.x > _XMax) + { + ratio = ((float)(_XMax - qin.V2.x))/((float)(qin.V3.x - qin.V2.x)); + qout.V2.x = qout.V1.x = _XMax; + qout.Uv2.U += ratio*(qin.Uv3.U-qin.Uv2.U); + qout.Uv1.U += ratio*(qin.Uv0.U-qin.Uv1.U); + } + + if (qin.V2.y > _YMax) + { + ratio = ((float)(_YMax - qin.V2.y))/((float)(qin.V1.y - qin.V2.y)); + qout.V2.y = qout.V3.y = _YMax; + qout.Uv2.V += ratio*(qin.Uv1.V-qin.Uv2.V); + qout.Uv3.V += ratio*(qin.Uv0.V-qin.Uv3.V); + } + } + } + + /** + * clip with uv2 + */ + void CViewRenderer::clip (CQuadColorUV2 &qout, const CQuadColorUV2 &qin) + { + float ratio; + + qout = qin; + + if (qin.V0.x < _XMin) + { + ratio = ((float)(_XMin - qin.V0.x))/((float)(qin.V1.x - qin.V0.x)); + qout.V3.x = qout.V0.x = _XMin; + qout.Uv0.U += ratio*(qin.Uv1.U-qin.Uv0.U); + qout.Uv3.U += ratio*(qin.Uv2.U-qin.Uv3.U); + qout.Uv02.U += ratio*(qin.Uv12.U-qin.Uv02.U); + qout.Uv32.U += ratio*(qin.Uv22.U-qin.Uv32.U); + } + + if (qin.V0.y < _YMin) + { + ratio = ((float)(_YMin - qin.V0.y))/((float)(qin.V3.y - qin.V0.y)); + qout.V1.y = qout.V0.y = _YMin; + qout.Uv0.V += ratio*(qin.Uv3.V-qin.Uv0.V); + qout.Uv1.V += ratio*(qin.Uv2.V-qin.Uv1.V); + qout.Uv02.V += ratio*(qin.Uv32.V-qin.Uv02.V); + qout.Uv12.V += ratio*(qin.Uv22.V-qin.Uv12.V); + } + + if (qin.V2.x > _XMax) + { + ratio = ((float)(_XMax - qin.V2.x))/((float)(qin.V3.x - qin.V2.x)); + qout.V2.x = qout.V1.x = _XMax; + qout.Uv2.U += ratio*(qin.Uv3.U-qin.Uv2.U); + qout.Uv1.U += ratio*(qin.Uv0.U-qin.Uv1.U); + qout.Uv22.U += ratio*(qin.Uv32.U-qin.Uv22.U); + qout.Uv12.U += ratio*(qin.Uv02.U-qin.Uv12.U); + } + + if (qin.V2.y > _YMax) + { + ratio = ((float)(_YMax - qin.V2.y))/((float)(qin.V1.y - qin.V2.y)); + qout.V2.y = qout.V3.y = _YMax; + qout.Uv2.V += ratio*(qin.Uv1.V-qin.Uv2.V); + qout.Uv3.V += ratio*(qin.Uv0.V-qin.Uv3.V); + qout.Uv22.V += ratio*(qin.Uv12.V-qin.Uv22.V); + qout.Uv32.V += ratio*(qin.Uv02.V-qin.Uv32.V); + } + } + + + // *************************************************************************** + /** + * putQuadInLayer : put a quad in a specific layer of a specific texture + */ + void CViewRenderer::putQuadInLayer (SGlobalTexture >, sint layerId, const NLMISC::CQuadColorUV &qcoluv, uint rot) + { + layerId+= VR_BIAS_LAYER; + nlassert(layerId>=0 && layerId=0 && layerIddrawWiredQuad(x * _OneOverScreenW, y * _OneOverScreenH, (x + width) * _OneOverScreenW, (y + height) * _OneOverScreenH, col); + } + + // *************************************************************************** + void CViewRenderer::drawFilledQuad(sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col /*=NLMISC::CRGBA::White*/) + { + driver->drawQuad(x * _OneOverScreenW, y * _OneOverScreenH, (x + width) * _OneOverScreenW, (y + height) * _OneOverScreenH, col); + } + + + + // *************************************************************************** + void CViewRenderer::drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, CRGBA col, UMaterial Mat) + { + float dstXmin, dstYmin, dstXmax, dstYmax; + + // Is totally clipped ? + if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || + (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) + return; + + flush(); + + // Initialize quad + dstXmin = (float)(x) * _OneOverScreenW; + dstYmin = (float)(y) * _OneOverScreenH; + dstXmax = (float)(x + width) * _OneOverScreenW; + dstYmax = (float)(y + height) * _OneOverScreenH; + + CQuadColorUV2 qcoluv2; + qcoluv2.V0.set (dstXmin, dstYmin, 0); + qcoluv2.V1.set (dstXmax, dstYmin, 0); + qcoluv2.V2.set (dstXmax, dstYmax, 0); + qcoluv2.V3.set (dstXmin, dstYmax, 0); + + qcoluv2.Color0 = qcoluv2.Color1 = qcoluv2.Color2 = qcoluv2.Color3 = col; + + qcoluv2.Uv0.U = 0; qcoluv2.Uv0.V = 1; + qcoluv2.Uv1.U = 1; qcoluv2.Uv1.V = 1; + qcoluv2.Uv2.U = 1; qcoluv2.Uv2.V = 0; + qcoluv2.Uv3.U = 0; qcoluv2.Uv3.V = 0; + + qcoluv2.Uv02.U = 0; qcoluv2.Uv02.V = 1; + qcoluv2.Uv12.U = 1; qcoluv2.Uv12.V = 1; + qcoluv2.Uv22.U = 1; qcoluv2.Uv22.V = 0; + qcoluv2.Uv32.U = 0; qcoluv2.Uv32.V = 0; + + // Clipping part + CQuadColorUV2 qcoluv2_clipped; + if (!needClipping(qcoluv2)) + { + // No need to clip the quad + qcoluv2_clipped = qcoluv2; + } + else + { + clip (qcoluv2_clipped, qcoluv2); + } + + // World space transformation + if (_WorldSpaceTransformation) + worldSpaceTransformation (qcoluv2_clipped); + + // Draw clipped quad + driver->drawQuads (&qcoluv2_clipped, 1, Mat); + } + + // *************************************************************************** + void CViewRenderer::drawCustom(sint32 x, sint32 y, sint32 width, sint32 height, const NLMISC::CUV &uv0Min, const NLMISC::CUV &uv0Max, NLMISC::CRGBA col, NL3D::UMaterial Mat) + { + float dstXmin, dstYmin, dstXmax, dstYmax; + + // Is totally clipped ? + if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || + (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) + return; + + flush(); + + // Initialize quad + dstXmin = (float)(x) * _OneOverScreenW; + dstYmin = (float)(y) * _OneOverScreenH; + dstXmax = (float)(x + width) * _OneOverScreenW; + dstYmax = (float)(y + height) * _OneOverScreenH; + + CQuadColorUV qcoluv; + qcoluv.V0.set (dstXmin, dstYmin, 0); + qcoluv.V1.set (dstXmax, dstYmin, 0); + qcoluv.V2.set (dstXmax, dstYmax, 0); + qcoluv.V3.set (dstXmin, dstYmax, 0); + + qcoluv.Color0 = qcoluv.Color1 = qcoluv.Color2 = qcoluv.Color3 = col; + + qcoluv.Uv0.U = uv0Min.U; qcoluv.Uv0.V = uv0Max.V; + qcoluv.Uv1.U = uv0Max.U; qcoluv.Uv1.V = uv0Max.V; + qcoluv.Uv2.U = uv0Max.U; qcoluv.Uv2.V = uv0Min.V; + qcoluv.Uv3.U = uv0Min.U; qcoluv.Uv3.V = uv0Min.V; + + + // Clipping part + CQuadColorUV qcoluv_clipped; + if (!needClipping(qcoluv)) + { + // No need to clip the quad + qcoluv_clipped = qcoluv; + } + else + { + clip (qcoluv_clipped, qcoluv, 0); + } + + // Draw clipped quad + driver->drawQuads (&qcoluv_clipped, 1, Mat); + } + + // *************************************************************************** + void CViewRenderer::drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, + const CUV &uv0Min, const CUV &uv0Max, const CUV &uv1Min, const CUV &uv1Max, + NLMISC::CRGBA col, NL3D::UMaterial Mat) + { + float dstXmin, dstYmin, dstXmax, dstYmax; + + // Is totally clipped ? + if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || + (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) + return; + + flush(); + + // Initialize quad + dstXmin = (float)(x) * _OneOverScreenW; + dstYmin = (float)(y) * _OneOverScreenH; + dstXmax = (float)(x + width) * _OneOverScreenW; + dstYmax = (float)(y + height) * _OneOverScreenH; + + CQuadColorUV2 qcoluv2; + qcoluv2.V0.set (dstXmin, dstYmin, 0); + qcoluv2.V1.set (dstXmax, dstYmin, 0); + qcoluv2.V2.set (dstXmax, dstYmax, 0); + qcoluv2.V3.set (dstXmin, dstYmax, 0); + + qcoluv2.Color0 = qcoluv2.Color1 = qcoluv2.Color2 = qcoluv2.Color3 = col; + + qcoluv2.Uv0.U = uv0Min.U; qcoluv2.Uv0.V = uv0Max.V; + qcoluv2.Uv1.U = uv0Max.U; qcoluv2.Uv1.V = uv0Max.V; + qcoluv2.Uv2.U = uv0Max.U; qcoluv2.Uv2.V = uv0Min.V; + qcoluv2.Uv3.U = uv0Min.U; qcoluv2.Uv3.V = uv0Min.V; + + qcoluv2.Uv02.U = uv1Min.U; qcoluv2.Uv02.V = uv1Max.V; + qcoluv2.Uv12.U = uv1Max.U; qcoluv2.Uv12.V = uv1Max.V; + qcoluv2.Uv22.U = uv1Max.U; qcoluv2.Uv22.V = uv1Min.V; + qcoluv2.Uv32.U = uv1Min.U; qcoluv2.Uv32.V = uv1Min.V; + + // Clipping part + CQuadColorUV2 qcoluv2_clipped; + if (!needClipping(qcoluv2)) + { + // No need to clip the quad + qcoluv2_clipped = qcoluv2; + } + else + { + clip (qcoluv2_clipped, qcoluv2); + } + + // World space transformation + if (_WorldSpaceTransformation) + worldSpaceTransformation (qcoluv2_clipped); + + // Draw clipped quad + driver->drawQuads (&qcoluv2_clipped, 1, Mat); + } + + // *************************************************************************** + + CViewRenderer::CTextureId::~CTextureId () + { + if (_TextureId>=0) + CViewRenderer::getInstance()->deleteTexture(_TextureId); + _TextureId = -1; + } + + // *************************************************************************** + + bool CViewRenderer::CTextureId::setTexture (const char *textureName, sint32 offsetX, sint32 offsetY, sint32 width, sint32 height, + bool uploadDXTC, bool bReleasable) + { + CViewRenderer &rVR = *CViewRenderer::getInstance(); + if (_TextureId>=0) + rVR.deleteTexture(_TextureId); + _TextureId = rVR.getTextureIdFromName(textureName); + if (_TextureId<0) + _TextureId = rVR.createTexture (textureName, offsetX, offsetY, width, height, uploadDXTC, bReleasable); + + return _TextureId >= 0; + } + + // *************************************************************************** + void CViewRenderer::CTextureId::serial(NLMISC::IStream &f) + { + std::string texName; + if (f.isReading()) + { + f.serial(texName); + setTexture(texName.c_str()); + } + else + { + CViewRenderer &rVR = *CViewRenderer::getInstance(); + texName = rVR.getTextureNameFromId(_TextureId); + f.serial(texName); + } + } + + // *************************************************************************** + + void CViewRenderer::worldSpaceTransformation (NLMISC::CQuadColorUV &qcoluv) + { + // set the world Z + qcoluv.V0.z = _CurrentZ; + qcoluv.V1.z = _CurrentZ; + qcoluv.V2.z = _CurrentZ; + qcoluv.V3.z = _CurrentZ; + + // for scaled interface, apply the scale matrix + qcoluv.V0= _WorldSpaceMatrix * qcoluv.V0; + qcoluv.V1= _WorldSpaceMatrix * qcoluv.V1; + qcoluv.V2= _WorldSpaceMatrix * qcoluv.V2; + qcoluv.V3= _WorldSpaceMatrix * qcoluv.V3; + + // unproject + qcoluv.V0 = _CameraFrustum.unProjectZ(qcoluv.V0); + qcoluv.V1 = _CameraFrustum.unProjectZ(qcoluv.V1); + qcoluv.V2 = _CameraFrustum.unProjectZ(qcoluv.V2); + qcoluv.V3 = _CameraFrustum.unProjectZ(qcoluv.V3); + } + + // *************************************************************************** + + void CViewRenderer::setWorldSpaceFrustum (const NL3D::CFrustum &cameraFrustum) + { + _CameraFrustum = cameraFrustum; + } + + // *************************************************************************** + + void CViewRenderer::activateWorldSpaceMatrix (bool activate) + { + _WorldSpaceTransformation = activate; + if (!_Material.empty()) + _Material.setZFunc(activate?UMaterial::lessequal:UMaterial::always); + } + + // *************************************************************************** + + void CViewRenderer::drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, UTextContext &textContext) + { + if (_WorldSpaceTransformation) + { + textContext.printClipAtUnProjected(*getStringRenderBuffer(layerId), _CameraFrustum, _WorldSpaceMatrix, x, y, _CurrentZ, wordIndex, xmin, ymin, xmax, ymax); + } + else + { + textContext.printClipAt(*getStringRenderBuffer(layerId), x, y, wordIndex, xmin, ymin, xmax, ymax); + } + + // layer is no more empty + _EmptyLayer[layerId + VR_BIAS_LAYER]= false; + } + + // *************************************************************************** + + void CViewRenderer::setInterfaceDepth (const NLMISC::CVector &projCenter, float scale) + { + _CurrentZ = projCenter.z; + + // no scale? => identity matrix (faster) + if(scale==1) + { + _WorldSpaceMatrix.identity(); + _WorldSpaceScale= false; + } + else + { + _WorldSpaceMatrix.identity(); + // must be in 0..1 coordinate here... + CVector pos= projCenter; + pos.x*= _OneOverScreenW; + pos.y*= _OneOverScreenH; + // set a pivoted scale matrix + _WorldSpaceMatrix.translate(pos); + _WorldSpaceMatrix.scale(scale); + _WorldSpaceMatrix.translate(-pos); + _WorldSpaceScale= true; + } + } +} diff --git a/code/ryzom/client/src/interface_v3/ctrl_button.h b/code/ryzom/client/src/interface_v3/ctrl_button.h index 3b035b01c..8ff9686af 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_button.h +++ b/code/ryzom/client/src/interface_v3/ctrl_button.h @@ -20,7 +20,7 @@ #define RZ_CTRL_BUTTON_H #include "ctrl_base_button.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" namespace NLGUI { diff --git a/code/ryzom/client/src/interface_v3/ctrl_polygon.cpp b/code/ryzom/client/src/interface_v3/ctrl_polygon.cpp index 08d1fb691..bf404259b 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_polygon.cpp +++ b/code/ryzom/client/src/interface_v3/ctrl_polygon.cpp @@ -16,7 +16,7 @@ #include "stdpch.h" #include "ctrl_polygon.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" #include "interface_manager.h" diff --git a/code/ryzom/client/src/interface_v3/ctrl_polygon.h b/code/ryzom/client/src/interface_v3/ctrl_polygon.h index 356f37e55..4ad4cd34e 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_polygon.h +++ b/code/ryzom/client/src/interface_v3/ctrl_polygon.h @@ -19,8 +19,7 @@ #define RZ_CTRL_POLYGON_H #include "ctrl_base.h" -#include "view_renderer.h" -// +#include "nel/gui/view_renderer.h" #include "nel/misc/geom_ext.h" #include "nel/misc/polygon.h" diff --git a/code/ryzom/client/src/interface_v3/ctrl_quad.h b/code/ryzom/client/src/interface_v3/ctrl_quad.h index c2ce759cb..1f3f5328c 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_quad.h +++ b/code/ryzom/client/src/interface_v3/ctrl_quad.h @@ -19,7 +19,7 @@ #define RZ_CTRL_QUAD_H #include "ctrl_base.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" #include "nel/misc/geom_ext.h" /** Display of an arbitrary textured quad in the UI. The applied texture is filtered. diff --git a/code/ryzom/client/src/interface_v3/ctrl_text_button.h b/code/ryzom/client/src/interface_v3/ctrl_text_button.h index 6383f3374..965f3c42d 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_text_button.h +++ b/code/ryzom/client/src/interface_v3/ctrl_text_button.h @@ -20,7 +20,7 @@ #define NL_CTRL_TEXT_BUTTON_H #include "ctrl_base_button.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" namespace NLGUI diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h index 29b6d21ad..b683ea597 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.h +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.h @@ -46,7 +46,12 @@ class IListSheetBase; class CSBrickSheet; class CSPhraseSheet; class COutpostBuildingSheet; -class CViewRenderer; + +namespace NLGUI +{ + class CViewRenderer; +} + // *************************************************************************** /** Common info for CDBCtrlSheet and CDBGroupListSheet diff --git a/code/ryzom/client/src/interface_v3/group_in_scene.cpp b/code/ryzom/client/src/interface_v3/group_in_scene.cpp index ba1023f48..2e468acd9 100644 --- a/code/ryzom/client/src/interface_v3/group_in_scene.cpp +++ b/code/ryzom/client/src/interface_v3/group_in_scene.cpp @@ -23,7 +23,7 @@ #include "group_in_scene.h" #include "interface_manager.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" #include "nel/misc/xml_auto_ptr.h" using namespace std; diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index 42e465fc0..96b55998f 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -260,6 +260,8 @@ CInterfaceManager::CInterfaceManager( NL3D::UDriver *driver, NL3D::UTextContext this->textcontext = textcontext; CViewRenderer::setDriver( driver ); CViewRenderer::setTextContext( textcontext ); + CViewRenderer::hwCursorScale = ClientCfg.HardwareCursorScale; + CViewRenderer::hwCursors = &ClientCfg.HardwareCursors; CViewRenderer::getInstance(); _Instance = this; diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h index 717176359..374853162 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.h +++ b/code/ryzom/client/src/interface_v3/interface_manager.h @@ -32,7 +32,7 @@ #include "ctrl_base.h" #include "ctrl_scroll.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" // InterfaceV3 #include "interface_parser.h" diff --git a/code/ryzom/client/src/interface_v3/view_bitmap.h b/code/ryzom/client/src/interface_v3/view_bitmap.h index 670c6fdf7..ce3be1d6a 100644 --- a/code/ryzom/client/src/interface_v3/view_bitmap.h +++ b/code/ryzom/client/src/interface_v3/view_bitmap.h @@ -21,7 +21,7 @@ #include "view_base.h" #include "nel/3d/u_texture.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" /** * class implementing a bitmap view diff --git a/code/ryzom/client/src/interface_v3/view_pointer.cpp b/code/ryzom/client/src/interface_v3/view_pointer.cpp index 7a6740176..3cb386281 100644 --- a/code/ryzom/client/src/interface_v3/view_pointer.cpp +++ b/code/ryzom/client/src/interface_v3/view_pointer.cpp @@ -22,7 +22,7 @@ // #include "view_pointer.h" #include "interface_manager.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" #include "ctrl_col_pick.h" #include "group_paragraph.h" #include "group_html.h" diff --git a/code/ryzom/client/src/interface_v3/view_polygon.cpp b/code/ryzom/client/src/interface_v3/view_polygon.cpp index b033b2885..06c34025d 100644 --- a/code/ryzom/client/src/interface_v3/view_polygon.cpp +++ b/code/ryzom/client/src/interface_v3/view_polygon.cpp @@ -16,7 +16,7 @@ #include "stdpch.h" #include "view_polygon.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" #include "interface_manager.h" diff --git a/code/ryzom/client/src/interface_v3/view_polygon.h b/code/ryzom/client/src/interface_v3/view_polygon.h index cd07a2bba..581f96f4e 100644 --- a/code/ryzom/client/src/interface_v3/view_polygon.h +++ b/code/ryzom/client/src/interface_v3/view_polygon.h @@ -19,7 +19,7 @@ #define RZ_VIEW_POLYGON_H #include "view_base.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" // #include "nel/misc/geom_ext.h" #include "nel/misc/polygon.h" diff --git a/code/ryzom/client/src/interface_v3/view_quad.h b/code/ryzom/client/src/interface_v3/view_quad.h index 907f65962..3d6b82923 100644 --- a/code/ryzom/client/src/interface_v3/view_quad.h +++ b/code/ryzom/client/src/interface_v3/view_quad.h @@ -19,7 +19,7 @@ #define RZ_VIEW_QUAD_H #include "view_base.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" #include "nel/misc/geom_ext.h" /** Display of an arbitrary textured quad in the UI. The applied texture is filtered. diff --git a/code/ryzom/client/src/interface_v3/view_radar.h b/code/ryzom/client/src/interface_v3/view_radar.h index 888aadb78..accad18d2 100644 --- a/code/ryzom/client/src/interface_v3/view_radar.h +++ b/code/ryzom/client/src/interface_v3/view_radar.h @@ -21,7 +21,7 @@ #include "view_base.h" #include "nel/3d/u_texture.h" -#include "view_renderer.h" +#include "nel/gui/view_renderer.h" /** * class implementing a radar view diff --git a/code/ryzom/client/src/interface_v3/view_renderer.cpp b/code/ryzom/client/src/interface_v3/view_renderer.cpp deleted file mode 100644 index 6dfb1e977..000000000 --- a/code/ryzom/client/src/interface_v3/view_renderer.cpp +++ /dev/null @@ -1,1863 +0,0 @@ -// Ryzom - 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 "view_renderer.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/uv.h" -#include "nel/misc/hierarchical_timer.h" -#include "../client_cfg.h" - -using namespace NLMISC; -using namespace std; -using namespace NL3D; - -CViewRenderer* CViewRenderer::instance = NULL; -NL3D::UDriver* CViewRenderer::driver = NULL; -NL3D::UTextContext* CViewRenderer::textcontext = NULL; - -CViewRenderer::CViewRenderer() -{ - nlassert( driver != NULL ); - nlassert( textcontext != NULL ); - setup(); -} - -CViewRenderer::~CViewRenderer() -{ - for(uint i=0;igetWindowSize (w, h); - // not minimized? change coords - if(w!=0 && h!=0) - { - _IsMinimized= false; - _ScreenW = w; - _ScreenH = h; - if(_ScreenW>0) - _OneOverScreenW = 1.0f / (float)_ScreenW; - else - _OneOverScreenW = 1000; - if(_ScreenH>0) - _OneOverScreenH = 1.0f / (float)_ScreenH; - else - _OneOverScreenH = 1000; - } - else - { - // Keep old coordinates (suppose resolution won't change, even if typically false wen we swithch from outgame to ingame) - _IsMinimized= true; - } -} - - -/* - * getScreenSize : get the screen window size - */ -void CViewRenderer::getScreenSize (uint32 &w, uint32 &h) -{ - w = _ScreenW; - h = _ScreenH; -} - -/* - * get OOW / OOH - */ -void CViewRenderer::getScreenOOSize (float &oow, float &ooh) -{ - oow= _OneOverScreenW; - ooh= _OneOverScreenH; -} - -void CViewRenderer::setup() -{ - _ClipX = _ClipY = 0; - _ClipW = 800; - _ClipH = 600; - _ScreenW = 800; - _ScreenH = 600; - _OneOverScreenW= 1.0f / (float)_ScreenW; - _OneOverScreenH= 1.0f / (float)_ScreenH; - _IsMinimized= false; - _WFigurTexture= 0; - _HFigurTexture= 0; - _WFigurSeparatorTexture = 0; - _FigurSeparatorTextureId = -1; - _FigurBlankId = -1; - _BlankId = -1; - _WorldSpaceTransformation = true; - _CurrentZ = 10; - for(uint i=0;icreateMaterial(); - - setRenderStates(); - - // Init all renderBuffer - for(uint i=0;icreateRenderBuffer(); - } -} - -void CViewRenderer::setRenderStates() -{ - _Material.setDoubleSided(); - _Material.setZWrite(false); - _Material.setZFunc(UMaterial::always); - _Material.setBlend (true); - _Material.setBlendFunc (NL3D::UMaterial::srcalpha, NL3D::UMaterial::invsrcalpha); - _Material.setColor(CRGBA::White); - _Material.setTexture(0, NULL); - _Material.setTexture(1, NULL); - _Material.setTexture(2, NULL); - _Material.setTexture(3, NULL); - _Material.setZBias(0); -} -/* - * reset: reset the whole view renderer - */ -void CViewRenderer::reset() -{ - TGlobalTextureList::iterator ite = _GlobalTextures.begin(); - while (ite != _GlobalTextures.end()) - { - UTextureFile *tf = dynamic_cast(ite->Texture); - if (tf) - { - driver->deleteTextureFile (tf); - } - ite++; - } - - _GlobalTextures.clear(); - _SImages.clear(); - _SImageIterators.clear(); - _TextureMap.clear(); - _IndexesToTextureIds.clear(); -} - -NL3D::UDriver* CViewRenderer::getDriver(){ - return driver; -} - -void CViewRenderer::setTextContext(NL3D::UTextContext *textcontext) -{ - CViewRenderer::textcontext = textcontext; -} - -void CViewRenderer::setDriver( NL3D::UDriver *driver ) -{ - CViewRenderer::driver = driver; -} - -// *************************************************************************** -void CViewRenderer::SImage::setupQuadUV(bool flipv, uint8 rot, CQuadColorUV &dest) -{ - nlassert(rot<=3); - // Rotation is CW and flip is along x axis - // Flip is vertical flip (this means we invert all y for a constant x) - // The transforms are done in this order : first apply the flip (or not) and then rotate - static const CUV UVTab[8][4] = { - { CUV(0, 0), CUV(1, 0), CUV(1, 1), CUV(0, 1) }, // rot 0, no flip - { CUV(1, 0), CUV(1, 1), CUV(0, 1), CUV(0, 0) }, // rot 1, no flip - { CUV(1, 1), CUV(0, 1), CUV(0, 0), CUV(1, 0) }, // rot 2, no flip - { CUV(0, 1), CUV(0, 0), CUV(1, 0), CUV(1, 1) }, // rot 3, no flip - { CUV(1, 0), CUV(0, 0), CUV(0, 1), CUV(1, 1) }, // rot 0, flipped - { CUV(0, 0), CUV(0, 1), CUV(1, 1), CUV(1, 0) }, // rot 1, flipped - { CUV(0, 1), CUV(1, 1), CUV(1, 0), CUV(0, 0) }, // rot 2, flipped - { CUV(1, 1), CUV(1, 0), CUV(0, 0), CUV(0, 1) } // rot 3, flipped - }; - - // Take care that the origin in the texture is top left so to get the texture in bottom-up - // we have to start at Max and go at Min. For left and right this is Min to Max. - - float du = UVMax.U - UVMin.U; - float dv = UVMin.V - UVMax.V; - - uint idx = flipv*4 + rot; - - dest.Uv0 = CUV (UVMin.U + UVTab[idx][0].U * du, UVMax.V + UVTab[idx][0].V * dv); - dest.Uv1 = CUV (UVMin.U + UVTab[idx][1].U * du, UVMax.V + UVTab[idx][1].V * dv); - dest.Uv2 = CUV (UVMin.U + UVTab[idx][2].U * du, UVMax.V + UVTab[idx][2].V * dv); - dest.Uv3 = CUV (UVMin.U + UVTab[idx][3].U * du, UVMax.V + UVTab[idx][3].V * dv); - - /* // TRAP : Unrolled Version (To be tested to know if it is faster than the previous one) - if (flipv) - { - switch (rot) - { - case 0: - qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMax.V; - qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMax.V; - qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMin.V; - qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMin.V; - break; - case 1: - qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMax.V; - qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMin.V; - qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMin.V; - qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMax.V; - break; - case 2: - qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMin.V; - qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMin.V; - qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMax.V; - qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMax.V; - break; - case 3: - qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMin.V; - qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMax.V; - qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMax.V; - qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMin.V; - break; - } - } - else - { - switch (rot) - { - case 0: - qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMax.V; - qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMax.V; - qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMin.V; - qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMin.V; - break; - case 1: - qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMin.V; - qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMax.V; - qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMax.V; - qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMin.V; - break; - case 2: - qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMin.V; - qcoluv.Uv1.U = rI.UVMin.U; qcoluv.Uv1.V = rI.UVMin.V; - qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMax.V; - qcoluv.Uv3.U = rI.UVMax.U; qcoluv.Uv3.V = rI.UVMax.V; - break; - case 3: - qcoluv.Uv0.U = rI.UVMax.U; qcoluv.Uv0.V = rI.UVMax.V; - qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMin.V; - qcoluv.Uv2.U = rI.UVMin.U; qcoluv.Uv2.V = rI.UVMin.V; - qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMax.V; - break; - } - } - */ -} -// *************************************************************************** - -/* - * drawRotFlipBitmapTiled - */ -void CViewRenderer::drawRotFlipBitmapTiled (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flip, - sint32 nTxId, uint tileOrigin, const CRGBA &col) -{ - static volatile bool draw = true; - if (!draw) return; - if (width <= 0 || height <= 0) return; - - if (nTxId < 0) return; - - // Is totally clipped ? - if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || - (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) - return; - - SImage &rI = *getSImage(nTxId); - - sint32 txw, txh; - // start to draw at the reference corner - getTextureSizeFromId (nTxId, txw, txh); - - if (rot > 3) rot = 3; - - sint32 startX = x, startY = y; - sint32 stepX = txw, stepY = txh; - - if (rot & 1) - { - std::swap(txw, txh); - } - - // choose new start pos & uvs depending on the reference corner - // Along x axis - if (tileOrigin & 1) // right or left ? - { // right - startX = x + width - txw; - stepX = -txw; - } - - // Along y axis - if (tileOrigin & 2) // bottom or top ? - { // top - startY = y + height - txh; - stepY = -txh; - } - - // Fit screen coordinates - - float fStartX = (float) startX * _OneOverScreenW; - float fStartY = (float) startY * _OneOverScreenH; - float fStepX = (float) stepX * _OneOverScreenW; - float fStepY = (float) stepY * _OneOverScreenH; - float fTxW = (float) txw * _OneOverScreenW; - float fTxH = (float) txh * _OneOverScreenH; - - CQuadColorUV qcoluv; - - qcoluv.Color0 = qcoluv.Color1 = qcoluv.Color2 = qcoluv.Color3 = col; - qcoluv.V0.z = qcoluv.V1.z = qcoluv.V2.z = qcoluv.V3.z = 0; - rI.setupQuadUV(flip,rot,qcoluv); - - uint numTileX = (uint32)((width - 1) / txw); - uint numTileY = (uint32)((height- 1) / txh); - - float currY = fStartY; - - sint32 oldClipX = _ClipX; - sint32 oldClipY = _ClipY; - sint32 oldClipW = _ClipW; - sint32 oldClipH = _ClipH; - if (x < _ClipX) { width -= _ClipX - x; x = _ClipX; } - if (y < _ClipY) { height -= _ClipY - y; y = _ClipY; } - if ((x+width) > (_ClipX+_ClipW)) width -= (x+width) - (_ClipX+_ClipW); - if ((y+height) > (_ClipY+_ClipH)) height -= (y+height) - (_ClipY+_ClipH); - setClipWindow (x, y, width, height); - - // draw result let the clipper clip the quads - for(uint py = 0; py <= numTileY; ++py) - { - float currX = fStartX; - for(uint px = 0; px <= numTileX; ++px) - { - /// There is room for speedup there - qcoluv.V0.x = currX; - qcoluv.V1.x = currX + fTxW; - qcoluv.V2.x = currX + fTxW; - qcoluv.V3.x = currX; - - qcoluv.V0.y = currY; - qcoluv.V1.y = currY; - qcoluv.V2.y = currY + fTxH; - qcoluv.V3.y = currY + fTxH; - - // Is NOT totally clipped ? - if ( !( (qcoluv.V0.x > _XMax) || (qcoluv.V2.x < _XMin) || - (qcoluv.V0.y > _YMax) || (qcoluv.V2.y < _YMin) ) ) - putQuadInLayer (*(rI.GlobalTexturePtr), layerId, qcoluv, rot); - - currX += fStepX; - } - currY += fStepY; - } - - setClipWindow (oldClipX, oldClipY, oldClipW, oldClipH); -} - - -/* - * drawBitmap - */ -void CViewRenderer::drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, - uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col) -{ - if (width <= 0 || height <= 0) return; - - if (nTxId < 0) - return; - - - - float dstXmin, dstYmin, dstXmax, dstYmax; - - // Is totally clipped ? - if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || - (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) - return; - - dstXmin = (float)(x) * _OneOverScreenW; - dstYmin = (float)(y) * _OneOverScreenH; - dstXmax = (float)(x + width) * _OneOverScreenW; - dstYmax = (float)(y + height) * _OneOverScreenH; - - CQuadColorUV qcoluv; - qcoluv.V0.set (dstXmin, dstYmin, 0); - qcoluv.V1.set (dstXmax, dstYmin, 0); - qcoluv.V2.set (dstXmax, dstYmax, 0); - qcoluv.V3.set (dstXmin, dstYmax, 0); - - qcoluv.Color0 = qcoluv.Color1 = qcoluv.Color2 = qcoluv.Color3 = col; - - SImage &rI = *getSImage(nTxId); - - // Avoid switch in common case - if (!flipv && !rot) - { - qcoluv.Uv0.U = rI.UVMin.U; qcoluv.Uv0.V = rI.UVMax.V; - qcoluv.Uv1.U = rI.UVMax.U; qcoluv.Uv1.V = rI.UVMax.V; - qcoluv.Uv2.U = rI.UVMax.U; qcoluv.Uv2.V = rI.UVMin.V; - qcoluv.Uv3.U = rI.UVMin.U; qcoluv.Uv3.V = rI.UVMin.V; - } - // else standard case - else - { - if (rot > 3) - rot = 3; - - rI.setupQuadUV(flipv, rot, qcoluv); - } - - static volatile bool doRot[4] = { true, true, true, true }; - if (doRot[rot]) - { - putQuadInLayer (*(rI.GlobalTexturePtr), layerId, qcoluv, rot); - } -} - - -/* - * draw11RotBitmap - * sTx must be lowered !!! - */ -void CViewRenderer::draw11RotFlipBitmap (sint layerId, sint32 x, sint32 y, uint8 rot, bool flipv, sint32 nTxId, const CRGBA &col) -{ - if (nTxId < 0) - return; - - sint32 txw, txh; - SImage &rImage = *getSImage(nTxId); - txw = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width+0.5f); - txh = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height+0.5f); - - drawRotFlipBitmap (layerId, x, y, txw, txh, rot, flipv, nTxId, col); -} - - -inline void remapUV(CUV &dest, const CUV &src, const CUV &min, const CUV &max) -{ - dest.set(src.U * (max.U - min.U) + min.U, src.V * (max.V - min.V) + min.V); -} - -void CViewRenderer::drawQuad(sint layerId, const NLMISC::CQuadUV &quadUV, sint32 nTxId, NLMISC::CRGBA col /*=NLMISC::CRGBA(255,255,255,255)*/, bool additif, bool filtered) -{ - nlassert(!(additif && !filtered)); // not implemented yet! - if (nTxId < 0) - return; - CQuadColorUV normedQuad; - // - normedQuad.V0.set(quadUV.V0.x * _OneOverScreenW, quadUV.V0.y * _OneOverScreenH, 0.f); - normedQuad.V1.set(quadUV.V1.x * _OneOverScreenW, quadUV.V1.y * _OneOverScreenH, 0.f); - normedQuad.V2.set(quadUV.V2.x * _OneOverScreenW, quadUV.V2.y * _OneOverScreenH, 0.f); - normedQuad.V3.set(quadUV.V3.x * _OneOverScreenW, quadUV.V3.y * _OneOverScreenH, 0.f); - // - float qXMin = minof(normedQuad.V0.x, normedQuad.V1.x, normedQuad.V2.x, normedQuad.V3.x); - if (qXMin > _XMax) return; - float qXMax = maxof(normedQuad.V0.x, normedQuad.V1.x, normedQuad.V2.x, normedQuad.V3.x); - if (qXMax < _XMin) return; - float qYMin = minof(normedQuad.V0.y, normedQuad.V1.y, normedQuad.V2.y, normedQuad.V3.y); - if (qYMin > _YMax) return; - float qYMax = maxof(normedQuad.V0.y, normedQuad.V1.y, normedQuad.V2.y, normedQuad.V3.y); - if (qYMax < _YMin) return; - // - - - - SImage &rImage = *getSImage(nTxId); - SGlobalTexture > = *(rImage.GlobalTexturePtr); - CUV deltaUV(1.f / (float) gt.Width, 1.f / (float) gt.Height); - CUV cornerMin = rImage.UVMin + deltaUV; - CUV cornerMax = rImage.UVMax - deltaUV; - remapUV(normedQuad.Uv0, quadUV.Uv0, cornerMin, cornerMax); - remapUV(normedQuad.Uv1, quadUV.Uv1, cornerMin, cornerMax); - remapUV(normedQuad.Uv2, quadUV.Uv2, cornerMin, cornerMax); - remapUV(normedQuad.Uv3, quadUV.Uv3, cornerMin, cornerMax); - - // test if clipping is required - if (qXMin >= _XMin && qYMin >= _YMin && qXMax <= _XMax && qYMax <= _YMax) - { - // not clipped, easy case - normedQuad.Color0 = normedQuad.Color1 = normedQuad.Color2 = normedQuad.Color3 = col; - - if (_WorldSpaceTransformation) - { - worldSpaceTransformation (normedQuad); - } - - layerId+= VR_BIAS_LAYER; - nlassert(layerId>=0 && layerIdLayers[layerId]; - if (!filtered) - { - if (layer.NbQuads == layer.Quads.size()) - layer.Quads.push_back (normedQuad); - else - layer.Quads[layer.NbQuads] = normedQuad; - ++ layer.NbQuads; - } - else if (additif) layer.FilteredAdditifQuads.push_back(normedQuad); - else layer.FilteredAlphaBlendedQuads.push_back(normedQuad); - _EmptyLayer[layerId]= false; - } - else - { - // Partially clipped (slowest case) - // Must do the clip manually - static const uint maxNumCorners = 8; - // - static CVector outPos0[maxNumCorners]; - static CUV outUV0[maxNumCorners]; - static CVector outPos1[maxNumCorners]; - static CUV outUV1[maxNumCorners]; - // - outUV0[0] = normedQuad.Uv0; - outUV0[1] = normedQuad.Uv1; - outUV0[2] = normedQuad.Uv2; - outUV0[3] = normedQuad.Uv3; - // - outPos0[0] = normedQuad.V0; - outPos0[1] = normedQuad.V1; - outPos0[2] = normedQuad.V2; - outPos0[3] = normedQuad.V3; - // - CVector *pPos0 = outPos0; - CVector *pPos1 = outPos1; - CUV *pUV0 = outUV0; - CUV *pUV1 = outUV1; - // - sint count = 4; - // - if (qXMin < _XMin) - { - // clip left - CPlane clipper(-1.f, 0.f, 0.f, _XMin); - count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); - std::swap(pPos0, pPos1); - std::swap(pUV0, pUV1); - } - if (qXMax > _XMax) - { - // clip right - CPlane clipper(1.f, 0.f, 0.f, -_XMax); - count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); - std::swap(pPos0, pPos1); - std::swap(pUV0, pUV1); - } - // - if (qYMin < _YMin) - { - // clip bottom - CPlane clipper(0.f, -1.f, 0.f, _YMin); - count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); - std::swap(pPos0, pPos1); - std::swap(pUV0, pUV1); - } - if (qYMax > _YMax) - { - // clip top - CPlane clipper(0.f, 1.f, 0.f, -_YMax); - count = clipper.clipPolygonBack(pPos0, pUV0, pPos1, pUV1, count); - std::swap(pPos0, pPos1); - std::swap(pUV0, pUV1); - } - - nlassert(count <= (sint)maxNumCorners); - if (count >= 3) - { - count -= 2; - layerId+= VR_BIAS_LAYER; - nlassert(layerId>=0 && layerIdLayers[layerId]; - std::vector *tris; - if (!filtered) - { - tris = &layer.Tris; - } - else - { - tris = additif ? &layer.FilteredAdditifTris : &layer.FilteredAlphaBlendedTris; - } - tris->resize(tris->size() + count); - CTriangleColorUV *lastTri = &tris->back() + 1; - CTriangleColorUV *currTri = lastTri - count; - const CVector *firstPos = pPos0++; - const CUV *firstUV = pUV0++; - do - { - currTri->V0 = *firstPos; - currTri->V1 = *pPos0; - currTri->V2 = *(pPos0 + 1); - currTri->Color0 = col; - currTri->Color1 = col; - currTri->Color2 = col; - currTri->Uv0 = *firstUV; - currTri->Uv1 = *pUV0; - currTri->Uv2 = *(pUV0 + 1); - - pPos0 ++; - pUV0 ++; - ++currTri; - } - while (currTri != lastTri); - _EmptyLayer[layerId]= false; - } - } -} - - -void CViewRenderer::drawUnclippedTriangles(sint layerId, const std::vector &tris, NLMISC::CRGBA col) -{ - if (tris.empty()) return; - if (!_BlankGlobalTexture) return; - // primary goal here is batching, so we prefer to draw the triangle with a blank texture rather than - // switching material and having to flush all primitives . - layerId+= VR_BIAS_LAYER; - nlassert(layerId>=0 && layerIdLayers[layerId]; - uint startCount = (uint)layer.FilteredAlphaBlendedTris.size(); - layer.FilteredAlphaBlendedTris.resize(startCount + tris.size()); - const NLMISC::CTriangle *src =&tris[0]; - const NLMISC::CTriangle *last = src + tris.size(); - NLMISC::CTriangleColorUV *dest = &layer.FilteredAlphaBlendedTris[0] + startCount; - _EmptyLayer[layerId]= false; - do - { - dest->V0.set(src->V0.x * _OneOverScreenW, src->V0.y * _OneOverScreenH, 0.f); - dest->V1.set(src->V1.x * _OneOverScreenW, src->V1.y * _OneOverScreenH, 0.f); - dest->V2.set(src->V2.x * _OneOverScreenW, src->V2.y * _OneOverScreenH, 0.f); - static volatile bool testOpaque = false; - if (testOpaque) - { - dest->Color0 = CRGBA::White; - dest->Color1 = CRGBA::White; - dest->Color2 = CRGBA::White; - dest->Uv0.set(0.f, 0.f); - dest->Uv1.set(1.f, 0.f); - dest->Uv2.set(1.f, 1.f); - } - else - { - dest->Color0 = col; - dest->Color1 = col; - dest->Color2 = col; - dest->Uv0 = _BlankUV; - dest->Uv1 = _BlankUV; - dest->Uv2 = _BlankUV; - } - ++ dest; - ++ src; - } - while (src != last); -} - -/* - * loadTextures - */ -void CViewRenderer::loadTextures (const std::string &textureFileName, const std::string &uvFileName, bool uploadDXTC) -{ - SGlobalTexture gt; - // Load texture file - string filename = CPath::lookup (textureFileName, false); - if (filename == "") return; - CIFile ifTmp; - if (ifTmp.open(filename)) - CBitmap::loadSize (ifTmp, gt.Width, gt.Height); - gt.Texture = driver->createTextureFile (filename); - // Force to generate the texture now. This way we can extract the mouse bitmaps from it now without having to load it again. - // Its why we don't release it at the end, because it is likely to be uploaded soon) - CBitmap *texDatas = gt.Texture->generateDatas(); - // - gt.Name = filename; - gt.Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); - if(uploadDXTC) - gt.Texture->setUploadFormat(UTexture::DXTC5); - - // Load uv file - CIFile iFile; - filename = CPath::lookup (uvFileName, false); - if (filename == "") return; - if (!iFile.open(filename)) return; - - _GlobalTextures.push_back (gt); - - driver->setCursorScale(ClientCfg.HardwareCursorScale); - - char bufTmp[256], tgaName[256]; - string sTGAname; - float uvMinU, uvMinV, uvMaxU, uvMaxV; - while (!iFile.eof()) - { - iFile.getline (bufTmp, 256); - sscanf (bufTmp, "%s %f %f %f %f", tgaName, &uvMinU, &uvMinV, &uvMaxU, &uvMaxV); - SImage image; - image.UVMin.U = uvMinU; - image.UVMin.V = uvMinV; - image.UVMax.U = uvMaxU; - image.UVMax.V = uvMaxV; - sTGAname = toLower(string(tgaName)); - - string::size_type stripPng = sTGAname.find(".png"); - if (stripPng != string::npos) - { - sTGAname[stripPng + 1] = 't'; - sTGAname[stripPng + 2] = 'g'; - sTGAname[stripPng + 3] = 'a'; - } - - image.Name = sTGAname; - image.GlobalTexturePtr = &(_GlobalTextures.back()); - if (getTextureIdFromName(sTGAname) != -1) - { - string tmp = string("duplicate texture name in ") + textureFileName + "(" + sTGAname + ")"; - nlwarning(tmp.c_str()); - } - else - { - sint32 textureId = addSImage(image); - //nlwarning("SIMAGE ADDED: id = %x, name = %s", textureId, image.Name.c_str()); - // Insert in map. - _TextureMap.insert( make_pair(image.Name, textureId) ); - } - - // if this is a cursor texture, extract it now (supported for rgba only now, because of the blit) - if (texDatas && texDatas->getPixelFormat() == CBitmap::RGBA) - { - if (ClientCfg.HardwareCursors.count(image.Name)) - { - uint x0 = (uint) (image.UVMin.U * gt.Width); - uint y0 = (uint) (image.UVMin.V * gt.Height); - uint x1 = (uint) (image.UVMax.U * gt.Width); - uint y1 = (uint) (image.UVMax.V * gt.Height); - if (x1 != x0 && y1 != y0) - { - CBitmap curs; - curs.resize(x1 - x0, y1 - y0); - curs.blit(*texDatas, x0, y0, (x1 - x0), (y1 - y0), 0, 0); - driver->addCursor(image.Name, curs); - } - } - } - } - - initIndexesToTextureIds (); - initSystemTextures(); - initTypo(); -} - - - - -void CViewRenderer::setExternalTexture(const std::string &sGlobalTextureName, - NL3D::UTexture *externalTexture, - uint32 externalTexWidth, - uint32 externalTexHeight, - uint32 defaultTexWidth, - uint32 defaultTexHeight - ) -{ - if (sGlobalTextureName.empty()) - { - nlwarning("Can't create aglobal texture with an empty name"); - return; - } - // Look if already existing - string sLwrGTName = strlwr(sGlobalTextureName); - TGlobalTextureList::iterator ite = _GlobalTextures.begin(); - while (ite != _GlobalTextures.end()) - { - std::string sText = strlwr(ite->Name); - if (sText == sLwrGTName) - break; - ite++; - } - if (ite == _GlobalTextures.end()) - { - SGlobalTexture gtTmp; - gtTmp.FromGlobaleTexture = true; - - gtTmp.Name = sLwrGTName; - _GlobalTextures.push_back(gtTmp); - ite = _GlobalTextures.end(); - ite--; - } - ite->Width = externalTexWidth; - ite->Height = externalTexHeight; - ite->DefaultWidth = defaultTexWidth; - ite->DefaultHeight = defaultTexHeight; - ite->Texture = externalTexture; -} - -/* - * createTexture - */ -sint32 CViewRenderer::createTexture (const std::string &sGlobalTextureName, - sint32 offsetX, - sint32 offsetY, - sint32 width, - sint32 height, - bool uploadDXTC, - bool bReleasable - ) -{ - if (sGlobalTextureName.empty()) return -1; - // Look if already existing - string sLwrGTName = strlwr(sGlobalTextureName); - TGlobalTextureList::iterator ite = _GlobalTextures.begin(); - while (ite != _GlobalTextures.end()) - { - std::string sText = strlwr(ite->Name); - if (sText == sLwrGTName) - break; - ite++; - } - - // If global texture not exists create it - if (ite == _GlobalTextures.end()) - { - SGlobalTexture gtTmp; - gtTmp.FromGlobaleTexture = false; - string filename = CPath::lookup (sLwrGTName, false); - if (filename == "") return -1; - CIFile ifTmp; - if (ifTmp.open(filename)) - { - CBitmap::loadSize (ifTmp, gtTmp.Width, gtTmp.Height); - gtTmp.DefaultWidth = gtTmp.Width; - gtTmp.DefaultHeight = gtTmp.Height; - if (gtTmp.Width == 0 || gtTmp.Height == 0) - { - nlwarning("Failed to load the texture '%s', please check image format", filename.c_str()); - } - } - gtTmp.Texture = driver->createTextureFile (sLwrGTName); - gtTmp.Name = sLwrGTName; - gtTmp.Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); - if(uploadDXTC) - gtTmp.Texture->setUploadFormat(UTexture::DXTC5); - gtTmp.Texture->setReleasable(bReleasable); - _GlobalTextures.push_back(gtTmp); - ite = _GlobalTextures.end(); - ite--; - } - - // Add a texture with reference to the i th global texture - SImage iTmp; - - // Set default parameters - if (width == -1) - width = ite->DefaultWidth; - if (height == -1) - height = ite->DefaultHeight; - - iTmp.Name = sLwrGTName; - iTmp.GlobalTexturePtr = &(*ite); - iTmp.UVMin = CUV(((float)offsetX)/ite->Width , ((float)offsetY)/ite->Height); - iTmp.UVMax = CUV(((float)offsetX+width)/ite->Width , ((float)offsetY+height)/ite->Height); - sint32 TextID = addSImage(iTmp); - //nlwarning("SIMAGE ADDED: id = %d, name = %s", TextID, iTmp.Name.c_str()); - - // Insert / replace in map. - // TMP TMP FIX NICO - //_TextureMap.insert( make_pair(iTmp.Name, TextID) ); - - - return TextID; -} - -void CViewRenderer::updateTexturePos(const std::string &texturefileName, sint32 offsetX /*=0*/, sint32 offsetY /*=0*/, sint32 width /*=-1*/, sint32 height /*=-1*/) -{ - sint32 id = getTextureIdFromName (texturefileName); - if (id == -1) - { - nlwarning("Unknwown texture %s, can't update pos", texturefileName.c_str()); - return; - } - SImage *im = getSImage(id); - nlassert(im); - // Set default parameters - sint32 gw = im->GlobalTexturePtr->Width; - sint32 gh = im->GlobalTexturePtr->Height; - if (width == -1) - width = gw; - if (height == -1) - height = gh; - im->UVMin = CUV(((float)offsetX)/gw , ((float)offsetY)/gh); - im->UVMax = CUV(((float)offsetX+width)/gw, ((float)offsetY+height)/gh); -} - - -/* - * getGlobalTexture - */ -NL3D::UTexture *CViewRenderer::getGlobalTexture(const std::string &name) -{ - string sLwrGTName = strlwr(name); - TGlobalTextureList::iterator ite = _GlobalTextures.begin(); - while (ite != _GlobalTextures.end()) - { - std::string sText = strlwr(ite->Name); - if (sText == sLwrGTName) - break; - ite++; - } - if (ite != _GlobalTextures.end()) - { - return ite->Texture; - } - return NULL; -} - -/* - * deleteTexture - */ -void CViewRenderer::deleteTexture (sint32 textureId) -{ - // Checks - nlassert ((uint)textureId < _SImageIterators.size()); - if (_SImageIterators[textureId] == _SImages.end()) - { - nlwarning("Can't delete texture with name %s", getTextureNameFromId(textureId).c_str()); - nlassert(0); - return; - } - - // Backup global texture pointer - SGlobalTexture *gt = getSImage(textureId)->GlobalTexturePtr; - - // Erase only texture from global texture - if (!(gt->FromGlobaleTexture)) - { - //nlwarning("Removing texture with id %d", (int) textureId); - // Erase the SImage - //nlwarning("SIMAGE REMOVE : id = %x, name = %s", (int) textureId, getSImage(textureId)->Name.c_str()); - - - removeSImage (textureId); - - // Check if someone else use this global texture.. - TSImageList::iterator ite = _SImages.begin(); - while (ite != _SImages.end()) - { - // Same global texture ? - if (ite->GlobalTexturePtr == gt) - break; - - ite++; - } - - // Global texture still used ? - if (ite == _SImages.end()) - { - //nlwarning("REMOVE GLOBAL TEXTURE : id of simage = %x", (int) textureId); - // No, remove the global texture - for (TGlobalTextureList::iterator iteGT = _GlobalTextures.begin(); iteGT != _GlobalTextures.end(); iteGT++) - { - // This one ? - if (&(*iteGT) == gt) - { - // Remove this global texture - UTextureFile *tf = dynamic_cast(iteGT->Texture); - if (tf) - { - driver->deleteTextureFile (tf); - } - _GlobalTextures.erase (iteGT); - return; - } - } - // Global texture has not been found - nlstop; - } - } -} - -/* - * getTextureIdFromName - */ -sint32 CViewRenderer::getTextureIdFromName (const string &sName) const -{ - if(sName.empty()) - return -1; - - // convert to lowCase - string nameLwr = toLower(sName); - - string::size_type stripPng = nameLwr.find(".png"); - if (stripPng != string::npos) - { - nameLwr[stripPng + 1] = 't'; - nameLwr[stripPng + 2] = 'g'; - nameLwr[stripPng + 3] = 'a'; - } - - // Search in map - TTextureMap::const_iterator it= _TextureMap.find(nameLwr); - if( it==_TextureMap.end() ) - return -1; - else - return it->second; -} - -/* - * getTextureNameFromId - */ -std::string CViewRenderer::getTextureNameFromId (sint32 TxID) -{ - if ((TxID < 0) || (TxID >= (sint32)_SImageIterators.size())) - return ""; - SImage *img = getSImage(TxID); - return img->Name; -} - -/* - * getTextureSizeFromName - */ -void CViewRenderer::getTextureSizeFromId (sint32 id, sint32 &width, sint32 &height) -{ - if ((id < 0) || (id >= (sint32)_SImageIterators.size())) - { - width = height = 0; - } - else - { - SImage &rImage = *getSImage(id); - width = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rImage.GlobalTexturePtr->Width+0.5f); - height = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rImage.GlobalTexturePtr->Height+0.5f); - } -} -/* - * getTextureColor - */ -CRGBA CViewRenderer::getTextureColor(sint32 id, sint32 x, sint32 y) -{ - if ((id < 0) || (id >= (sint32)_SImageIterators.size())) - { - return CRGBA(255,255,255); - } - - SImage &rImage = *getSImage(id); - SGlobalTexture &rGT = *rImage.GlobalTexturePtr; - sint32 width, height; - width = (sint32)((rImage.UVMax.U - rImage.UVMin.U)*rGT.Width+0.5f); - height = (sint32)((rImage.UVMax.V - rImage.UVMin.V)*rGT.Height+0.5f); - float xRatio = ((float)x) / ((float)(width)); - float yRatio = ((float)y) / ((float)(height)); - UTexture *pTF = rGT.Texture; - sint32 xConv = (sint32)((rImage.UVMin.U + xRatio * (rImage.UVMax.U - rImage.UVMin.U))*rGT.Width+0.5f); - sint32 yConv = (rGT.Height-1)-(sint32)((rImage.UVMin.V + yRatio * (rImage.UVMax.V - rImage.UVMin.V))*rGT.Height+0.5f); - return pTF->getPixelColor(xConv, yConv); -} - -// *************************************************************************** -sint32 CViewRenderer::getTypoTextureW(char c) -{ - if ((c>=0) && (c=0) && (cLayers[layerId]; - if(layer.NbQuads>0 || !layer.Tris.empty()) - { - // setup the global texture to material - _Material.setTexture(0, ite->Texture); - - // Special Case if _WorldSpaceTransformation and _WorldSpaceScale, enable bilinear - if(_WorldSpaceTransformation && _WorldSpaceScale) - ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff); - - // draw quads and empty list - if (layer.NbQuads != 0) - { - driver->drawQuads (&(layer.Quads[0]), layer.NbQuads, _Material); - layer.NbQuads = 0; - } - - if (!layer.Tris.empty()) - { - driver->drawTriangles(layer.Tris, _Material); - layer.Tris.clear(); - } - - // Special Case if _WorldSpaceTransformation and _WorldSpaceScale, reset - if(_WorldSpaceTransformation && _WorldSpaceScale) - ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); - } - if (!layer.FilteredAlphaBlendedQuads.empty() || - !layer.FilteredAlphaBlendedTris.empty() || - !layer.FilteredAdditifQuads.empty() || - !layer.FilteredAdditifTris.empty()) - { - // setup the global texture to material - _Material.setTexture(0, ite->Texture); - - // force filtering - ite->Texture->setFilterMode(UTexture::Linear, UTexture::LinearMipMapOff); - // alpha blended - if (!layer.FilteredAlphaBlendedQuads.empty()) - { - driver->drawQuads (&(layer.FilteredAlphaBlendedQuads[0]), (uint32)layer.FilteredAlphaBlendedQuads.size(), _Material); - layer.FilteredAlphaBlendedQuads.clear(); - } - if (!layer.FilteredAlphaBlendedTris.empty()) - { - driver->drawTriangles(layer.FilteredAlphaBlendedTris, _Material); - layer.FilteredAlphaBlendedTris.clear(); - } - // additif - if (!layer.FilteredAdditifQuads.empty() || - !layer.FilteredAdditifTris.empty()) - { - _Material.setBlendFunc (NL3D::UMaterial::one, NL3D::UMaterial::one); - if (!layer.FilteredAdditifQuads.empty()) - { - driver->drawQuads (&(layer.FilteredAdditifQuads[0]), (uint32)layer.FilteredAdditifQuads.size(), _Material); - layer.FilteredAdditifQuads.clear(); - } - if (!layer.FilteredAdditifTris.empty()) - { - driver->drawTriangles(layer.FilteredAdditifTris, _Material); - layer.FilteredAdditifTris.clear(); - } - // restore alpha blend - _Material.setBlendFunc (NL3D::UMaterial::srcalpha, NL3D::UMaterial::invsrcalpha); - } - ite->Texture->setFilterMode(UTexture::Nearest, UTexture::NearestMipMapOff); - } - ite++; - } - - // **** Display Computed Strings of this layer - if (_WorldSpaceTransformation) - textcontext->flushRenderBufferUnProjected(_StringRBLayers[layerId], false); - else - textcontext->flushRenderBuffer(_StringRBLayers[layerId]); - - // flushed - _EmptyLayer[layerId]= true; - } -} - - -/** - * init the map _IndexesToTextures - */ -void CViewRenderer::initIndexesToTextureIds() -{ - char buf[20]; - _IndexesToTextureIds.clear(); - for (uint i = 0; i < 10; i++) - { - sprintf (buf, "numbers_%d.tga", i); - _IndexesToTextureIds.push_back (getTextureIdFromName(buf)); - } - _FigurSeparatorTextureId = getTextureIdFromName("Numbers_sep.tga"); - _FigurBlankId = getTextureIdFromName("numbers_blank.tga"); - _BlankId = getTextureIdFromName("blank.tga"); - - SImage *blank = getSImage(_BlankId); - if (blank) - { - _BlankGlobalTexture = blank->GlobalTexturePtr; - _BlankUV = 0.5f * (blank->UVMin + blank->UVMax); - } - else - { - _BlankUV.set(0.f, 0.f); - } - - - // Init size - if(_IndexesToTextureIds[0]!=-1) - { - getTextureSizeFromId (_IndexesToTextureIds[0], _WFigurTexture, _HFigurTexture); - } - if (_FigurSeparatorTextureId != -1) - { - getTextureSizeFromId (_FigurSeparatorTextureId, _WFigurSeparatorTexture, _HFigurSeparatorTexture); - } - -} - -/** - * - */ -void CViewRenderer::initTypo() -{ - _TypoH = 0; - - // since filename dose not support special char (?,. ....), specify a map from char to string. - map specialCharMap; - specialCharMap['?']= "question"; - - - char buf[256]; - // For all supported chars (if tga exist) - for (uint i = 0; i < NumTypoChar; i++) - { - // Get the token string for this char. - string token; - map::iterator it= specialCharMap.find(i); - // General case - if(it==specialCharMap.end()) - token= (char)i; - else - token= it->second; - - // get the fileName - sprintf (buf, "typo_%s.tga", token.c_str()); - sint32 id = getTextureIdFromName(buf); - if(id>=0) - { - _TypoCharToTextureIds[i]= id; - sint32 w,h; - getTextureSizeFromId (id, w, h); - _TypoCharWs[i]= w; - _TypoH = h; - } - else - { - _TypoCharToTextureIds[i]= -1; - // simulate a space. - _TypoCharWs[i]= 1; - } - } -} - - -/** - * needClipping - */ -bool CViewRenderer::needClipping (const CQuad &q) -{ - if ((q.V0.x >= _XMin) && (q.V0.y >= _YMin) && (q.V2.x <= _XMax) && (q.V2.y <= _YMax)) - return false; - else - return true; -} - -/** - * clip - */ -void CViewRenderer::clip (CQuadColorUV &qout, const CQuadColorUV &qin, uint rot) -{ - float ratio; - - qout = qin; - - if (rot & 1) - { - // must reverse U & V during clipping - if (qin.V0.x < _XMin) - { - ratio = ((float)(_XMin - qin.V0.x))/((float)(qin.V1.x - qin.V0.x)); - qout.V3.x = qout.V0.x = _XMin; - qout.Uv0.V += ratio*(qin.Uv1.V-qin.Uv0.V); - qout.Uv3.V += ratio*(qin.Uv2.V-qin.Uv3.V); - } - - if (qin.V0.y < _YMin) - { - ratio = ((float)(_YMin - qin.V0.y))/((float)(qin.V3.y - qin.V0.y)); - qout.V1.y = qout.V0.y = _YMin; - qout.Uv0.U += ratio*(qin.Uv3.U-qin.Uv0.U); - qout.Uv1.U += ratio*(qin.Uv2.U-qin.Uv1.U); - } - - if (qin.V2.x > _XMax) - { - ratio = ((float)(_XMax - qin.V2.x))/((float)(qin.V3.x - qin.V2.x)); - qout.V2.x = qout.V1.x = _XMax; - qout.Uv2.V += ratio*(qin.Uv3.V-qin.Uv2.V); - qout.Uv1.V += ratio*(qin.Uv0.V-qin.Uv1.V); - } - - if (qin.V2.y > _YMax) - { - ratio = ((float)(_YMax - qin.V2.y))/((float)(qin.V1.y - qin.V2.y)); - qout.V2.y = qout.V3.y = _YMax; - qout.Uv2.U += ratio*(qin.Uv1.U-qin.Uv2.U); - qout.Uv3.U += ratio*(qin.Uv0.U-qin.Uv3.U); - } - } - else - { - if (qin.V0.x < _XMin) - { - ratio = ((float)(_XMin - qin.V0.x))/((float)(qin.V1.x - qin.V0.x)); - qout.V3.x = qout.V0.x = _XMin; - qout.Uv0.U += ratio*(qin.Uv1.U-qin.Uv0.U); - qout.Uv3.U += ratio*(qin.Uv2.U-qin.Uv3.U); - } - - if (qin.V0.y < _YMin) - { - ratio = ((float)(_YMin - qin.V0.y))/((float)(qin.V3.y - qin.V0.y)); - qout.V1.y = qout.V0.y = _YMin; - qout.Uv0.V += ratio*(qin.Uv3.V-qin.Uv0.V); - qout.Uv1.V += ratio*(qin.Uv2.V-qin.Uv1.V); - } - - if (qin.V2.x > _XMax) - { - ratio = ((float)(_XMax - qin.V2.x))/((float)(qin.V3.x - qin.V2.x)); - qout.V2.x = qout.V1.x = _XMax; - qout.Uv2.U += ratio*(qin.Uv3.U-qin.Uv2.U); - qout.Uv1.U += ratio*(qin.Uv0.U-qin.Uv1.U); - } - - if (qin.V2.y > _YMax) - { - ratio = ((float)(_YMax - qin.V2.y))/((float)(qin.V1.y - qin.V2.y)); - qout.V2.y = qout.V3.y = _YMax; - qout.Uv2.V += ratio*(qin.Uv1.V-qin.Uv2.V); - qout.Uv3.V += ratio*(qin.Uv0.V-qin.Uv3.V); - } - } -} - -/** - * clip with uv2 - */ -void CViewRenderer::clip (CQuadColorUV2 &qout, const CQuadColorUV2 &qin) -{ - float ratio; - - qout = qin; - - if (qin.V0.x < _XMin) - { - ratio = ((float)(_XMin - qin.V0.x))/((float)(qin.V1.x - qin.V0.x)); - qout.V3.x = qout.V0.x = _XMin; - qout.Uv0.U += ratio*(qin.Uv1.U-qin.Uv0.U); - qout.Uv3.U += ratio*(qin.Uv2.U-qin.Uv3.U); - qout.Uv02.U += ratio*(qin.Uv12.U-qin.Uv02.U); - qout.Uv32.U += ratio*(qin.Uv22.U-qin.Uv32.U); - } - - if (qin.V0.y < _YMin) - { - ratio = ((float)(_YMin - qin.V0.y))/((float)(qin.V3.y - qin.V0.y)); - qout.V1.y = qout.V0.y = _YMin; - qout.Uv0.V += ratio*(qin.Uv3.V-qin.Uv0.V); - qout.Uv1.V += ratio*(qin.Uv2.V-qin.Uv1.V); - qout.Uv02.V += ratio*(qin.Uv32.V-qin.Uv02.V); - qout.Uv12.V += ratio*(qin.Uv22.V-qin.Uv12.V); - } - - if (qin.V2.x > _XMax) - { - ratio = ((float)(_XMax - qin.V2.x))/((float)(qin.V3.x - qin.V2.x)); - qout.V2.x = qout.V1.x = _XMax; - qout.Uv2.U += ratio*(qin.Uv3.U-qin.Uv2.U); - qout.Uv1.U += ratio*(qin.Uv0.U-qin.Uv1.U); - qout.Uv22.U += ratio*(qin.Uv32.U-qin.Uv22.U); - qout.Uv12.U += ratio*(qin.Uv02.U-qin.Uv12.U); - } - - if (qin.V2.y > _YMax) - { - ratio = ((float)(_YMax - qin.V2.y))/((float)(qin.V1.y - qin.V2.y)); - qout.V2.y = qout.V3.y = _YMax; - qout.Uv2.V += ratio*(qin.Uv1.V-qin.Uv2.V); - qout.Uv3.V += ratio*(qin.Uv0.V-qin.Uv3.V); - qout.Uv22.V += ratio*(qin.Uv12.V-qin.Uv22.V); - qout.Uv32.V += ratio*(qin.Uv02.V-qin.Uv32.V); - } -} - - -// *************************************************************************** -/** - * putQuadInLayer : put a quad in a specific layer of a specific texture - */ -void CViewRenderer::putQuadInLayer (SGlobalTexture >, sint layerId, const NLMISC::CQuadColorUV &qcoluv, uint rot) -{ - layerId+= VR_BIAS_LAYER; - nlassert(layerId>=0 && layerId=0 && layerIddrawWiredQuad(x * _OneOverScreenW, y * _OneOverScreenH, (x + width) * _OneOverScreenW, (y + height) * _OneOverScreenH, col); -} - -// *************************************************************************** -void CViewRenderer::drawFilledQuad(sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col /*=NLMISC::CRGBA::White*/) -{ - driver->drawQuad(x * _OneOverScreenW, y * _OneOverScreenH, (x + width) * _OneOverScreenW, (y + height) * _OneOverScreenH, col); -} - - - -// *************************************************************************** -void CViewRenderer::drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, CRGBA col, UMaterial Mat) -{ - float dstXmin, dstYmin, dstXmax, dstYmax; - - // Is totally clipped ? - if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || - (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) - return; - - flush(); - - // Initialize quad - dstXmin = (float)(x) * _OneOverScreenW; - dstYmin = (float)(y) * _OneOverScreenH; - dstXmax = (float)(x + width) * _OneOverScreenW; - dstYmax = (float)(y + height) * _OneOverScreenH; - - CQuadColorUV2 qcoluv2; - qcoluv2.V0.set (dstXmin, dstYmin, 0); - qcoluv2.V1.set (dstXmax, dstYmin, 0); - qcoluv2.V2.set (dstXmax, dstYmax, 0); - qcoluv2.V3.set (dstXmin, dstYmax, 0); - - qcoluv2.Color0 = qcoluv2.Color1 = qcoluv2.Color2 = qcoluv2.Color3 = col; - - qcoluv2.Uv0.U = 0; qcoluv2.Uv0.V = 1; - qcoluv2.Uv1.U = 1; qcoluv2.Uv1.V = 1; - qcoluv2.Uv2.U = 1; qcoluv2.Uv2.V = 0; - qcoluv2.Uv3.U = 0; qcoluv2.Uv3.V = 0; - - qcoluv2.Uv02.U = 0; qcoluv2.Uv02.V = 1; - qcoluv2.Uv12.U = 1; qcoluv2.Uv12.V = 1; - qcoluv2.Uv22.U = 1; qcoluv2.Uv22.V = 0; - qcoluv2.Uv32.U = 0; qcoluv2.Uv32.V = 0; - - // Clipping part - CQuadColorUV2 qcoluv2_clipped; - if (!needClipping(qcoluv2)) - { - // No need to clip the quad - qcoluv2_clipped = qcoluv2; - } - else - { - clip (qcoluv2_clipped, qcoluv2); - } - - // World space transformation - if (_WorldSpaceTransformation) - worldSpaceTransformation (qcoluv2_clipped); - - // Draw clipped quad - driver->drawQuads (&qcoluv2_clipped, 1, Mat); -} - -// *************************************************************************** -void CViewRenderer::drawCustom(sint32 x, sint32 y, sint32 width, sint32 height, const NLMISC::CUV &uv0Min, const NLMISC::CUV &uv0Max, NLMISC::CRGBA col, NL3D::UMaterial Mat) -{ - float dstXmin, dstYmin, dstXmax, dstYmax; - - // Is totally clipped ? - if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || - (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) - return; - - flush(); - - // Initialize quad - dstXmin = (float)(x) * _OneOverScreenW; - dstYmin = (float)(y) * _OneOverScreenH; - dstXmax = (float)(x + width) * _OneOverScreenW; - dstYmax = (float)(y + height) * _OneOverScreenH; - - CQuadColorUV qcoluv; - qcoluv.V0.set (dstXmin, dstYmin, 0); - qcoluv.V1.set (dstXmax, dstYmin, 0); - qcoluv.V2.set (dstXmax, dstYmax, 0); - qcoluv.V3.set (dstXmin, dstYmax, 0); - - qcoluv.Color0 = qcoluv.Color1 = qcoluv.Color2 = qcoluv.Color3 = col; - - qcoluv.Uv0.U = uv0Min.U; qcoluv.Uv0.V = uv0Max.V; - qcoluv.Uv1.U = uv0Max.U; qcoluv.Uv1.V = uv0Max.V; - qcoluv.Uv2.U = uv0Max.U; qcoluv.Uv2.V = uv0Min.V; - qcoluv.Uv3.U = uv0Min.U; qcoluv.Uv3.V = uv0Min.V; - - - // Clipping part - CQuadColorUV qcoluv_clipped; - if (!needClipping(qcoluv)) - { - // No need to clip the quad - qcoluv_clipped = qcoluv; - } - else - { - clip (qcoluv_clipped, qcoluv, 0); - } - - // Draw clipped quad - driver->drawQuads (&qcoluv_clipped, 1, Mat); -} - -// *************************************************************************** -void CViewRenderer::drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, - const CUV &uv0Min, const CUV &uv0Max, const CUV &uv1Min, const CUV &uv1Max, - NLMISC::CRGBA col, NL3D::UMaterial Mat) -{ - float dstXmin, dstYmin, dstXmax, dstYmax; - - // Is totally clipped ? - if ((x > (_ClipX+_ClipW)) || ((x+width) < _ClipX) || - (y > (_ClipY+_ClipH)) || ((y+height) < _ClipY)) - return; - - flush(); - - // Initialize quad - dstXmin = (float)(x) * _OneOverScreenW; - dstYmin = (float)(y) * _OneOverScreenH; - dstXmax = (float)(x + width) * _OneOverScreenW; - dstYmax = (float)(y + height) * _OneOverScreenH; - - CQuadColorUV2 qcoluv2; - qcoluv2.V0.set (dstXmin, dstYmin, 0); - qcoluv2.V1.set (dstXmax, dstYmin, 0); - qcoluv2.V2.set (dstXmax, dstYmax, 0); - qcoluv2.V3.set (dstXmin, dstYmax, 0); - - qcoluv2.Color0 = qcoluv2.Color1 = qcoluv2.Color2 = qcoluv2.Color3 = col; - - qcoluv2.Uv0.U = uv0Min.U; qcoluv2.Uv0.V = uv0Max.V; - qcoluv2.Uv1.U = uv0Max.U; qcoluv2.Uv1.V = uv0Max.V; - qcoluv2.Uv2.U = uv0Max.U; qcoluv2.Uv2.V = uv0Min.V; - qcoluv2.Uv3.U = uv0Min.U; qcoluv2.Uv3.V = uv0Min.V; - - qcoluv2.Uv02.U = uv1Min.U; qcoluv2.Uv02.V = uv1Max.V; - qcoluv2.Uv12.U = uv1Max.U; qcoluv2.Uv12.V = uv1Max.V; - qcoluv2.Uv22.U = uv1Max.U; qcoluv2.Uv22.V = uv1Min.V; - qcoluv2.Uv32.U = uv1Min.U; qcoluv2.Uv32.V = uv1Min.V; - - // Clipping part - CQuadColorUV2 qcoluv2_clipped; - if (!needClipping(qcoluv2)) - { - // No need to clip the quad - qcoluv2_clipped = qcoluv2; - } - else - { - clip (qcoluv2_clipped, qcoluv2); - } - - // World space transformation - if (_WorldSpaceTransformation) - worldSpaceTransformation (qcoluv2_clipped); - - // Draw clipped quad - driver->drawQuads (&qcoluv2_clipped, 1, Mat); -} - -// *************************************************************************** - -CViewRenderer::CTextureId::~CTextureId () -{ - if (_TextureId>=0) - CViewRenderer::getInstance()->deleteTexture(_TextureId); - _TextureId = -1; -} - -// *************************************************************************** - -bool CViewRenderer::CTextureId::setTexture (const char *textureName, sint32 offsetX, sint32 offsetY, sint32 width, sint32 height, - bool uploadDXTC, bool bReleasable) -{ - CViewRenderer &rVR = *CViewRenderer::getInstance(); - if (_TextureId>=0) - rVR.deleteTexture(_TextureId); - _TextureId = rVR.getTextureIdFromName(textureName); - if (_TextureId<0) - _TextureId = rVR.createTexture (textureName, offsetX, offsetY, width, height, uploadDXTC, bReleasable); - - return _TextureId >= 0; -} - -// *************************************************************************** -void CViewRenderer::CTextureId::serial(NLMISC::IStream &f) -{ - std::string texName; - if (f.isReading()) - { - f.serial(texName); - setTexture(texName.c_str()); - } - else - { - CViewRenderer &rVR = *CViewRenderer::getInstance(); - texName = rVR.getTextureNameFromId(_TextureId); - f.serial(texName); - } -} - -// *************************************************************************** - -void CViewRenderer::worldSpaceTransformation (NLMISC::CQuadColorUV &qcoluv) -{ - // set the world Z - qcoluv.V0.z = _CurrentZ; - qcoluv.V1.z = _CurrentZ; - qcoluv.V2.z = _CurrentZ; - qcoluv.V3.z = _CurrentZ; - - // for scaled interface, apply the scale matrix - qcoluv.V0= _WorldSpaceMatrix * qcoluv.V0; - qcoluv.V1= _WorldSpaceMatrix * qcoluv.V1; - qcoluv.V2= _WorldSpaceMatrix * qcoluv.V2; - qcoluv.V3= _WorldSpaceMatrix * qcoluv.V3; - - // unproject - qcoluv.V0 = _CameraFrustum.unProjectZ(qcoluv.V0); - qcoluv.V1 = _CameraFrustum.unProjectZ(qcoluv.V1); - qcoluv.V2 = _CameraFrustum.unProjectZ(qcoluv.V2); - qcoluv.V3 = _CameraFrustum.unProjectZ(qcoluv.V3); -} - -// *************************************************************************** - -void CViewRenderer::setWorldSpaceFrustum (const NL3D::CFrustum &cameraFrustum) -{ - _CameraFrustum = cameraFrustum; -} - -// *************************************************************************** - -void CViewRenderer::activateWorldSpaceMatrix (bool activate) -{ - _WorldSpaceTransformation = activate; - if (!_Material.empty()) - _Material.setZFunc(activate?UMaterial::lessequal:UMaterial::always); -} - -// *************************************************************************** - -void CViewRenderer::drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, UTextContext &textContext) -{ - if (_WorldSpaceTransformation) - { - textContext.printClipAtUnProjected(*getStringRenderBuffer(layerId), _CameraFrustum, _WorldSpaceMatrix, x, y, _CurrentZ, wordIndex, xmin, ymin, xmax, ymax); - } - else - { - textContext.printClipAt(*getStringRenderBuffer(layerId), x, y, wordIndex, xmin, ymin, xmax, ymax); - } - - // layer is no more empty - _EmptyLayer[layerId + VR_BIAS_LAYER]= false; -} - -// *************************************************************************** - -void CViewRenderer::setInterfaceDepth (const NLMISC::CVector &projCenter, float scale) -{ - _CurrentZ = projCenter.z; - - // no scale? => identity matrix (faster) - if(scale==1) - { - _WorldSpaceMatrix.identity(); - _WorldSpaceScale= false; - } - else - { - _WorldSpaceMatrix.identity(); - // must be in 0..1 coordinate here... - CVector pos= projCenter; - pos.x*= _OneOverScreenW; - pos.y*= _OneOverScreenH; - // set a pivoted scale matrix - _WorldSpaceMatrix.translate(pos); - _WorldSpaceMatrix.scale(scale); - _WorldSpaceMatrix.translate(-pos); - _WorldSpaceScale= true; - } -} diff --git a/code/ryzom/client/src/interface_v3/view_renderer.h b/code/ryzom/client/src/interface_v3/view_renderer.h deleted file mode 100644 index cc96cee34..000000000 --- a/code/ryzom/client/src/interface_v3/view_renderer.h +++ /dev/null @@ -1,579 +0,0 @@ -// Ryzom - 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 . - - - -#ifndef NL_VIEW_RENDERER_H -#define NL_VIEW_RENDERER_H - -#include "nel/misc/types_nl.h" -#include "nel/3d/u_texture.h" -#include "nel/3d/u_text_context.h" -#include "nel/3d/u_driver.h" -#include "nel/misc/rgba.h" -#include "nel/misc/uv.h" -#include "nel/3d/frustum.h" - -// *************************************************************************** -#define VR_NUM_LAYER 32 -#define VR_BIAS_LAYER (VR_NUM_LAYER/2) -#define VR_LAYER_MAX (VR_NUM_LAYER-VR_BIAS_LAYER-1) -#define VR_LAYER_MIN (-VR_BIAS_LAYER) - -// *************************************************************************** -/** - * class rendering the views - * All the quads of the interface are displayed in the following order - * - * 3--2 - * | | - * 0--1 - * - * \author Matthieu 'TrapII' Besson - * \author Nevrax France - * \date 2002 - */ -class CViewRenderer -{ -public: - enum TSystemTexture - { - QuantityCrossTexture= 0, - DefaultBrickTexture, - DefaultItemTexture, - ItemPlanTexture, - SkillTexture, - ItemEnchantedTexture, - DragCopyTexture, - ItemWornedTexture, - OutOfRangeTexture, - RegenTexture, - RegenBackTexture, - GlowStarTexture, - ItemLockedByOwnerTexture, - NumSystemTextures, - }; - - -public: - - /** That class hold a texture id. It handle texture id destruction. - * Please use this class in your view and not sint32 to hold a texture id - */ - class CTextureId - { - public: - - // Default constructor - CTextureId () - { - _TextureId = -2; - } - - // Destructor call deleteTextureId; - ~CTextureId (); - - // Set the texture id - bool setTexture (const char *textureName, sint32 offsetX = 0, sint32 offsetY = 0, sint32 width = -1, sint32 height = -1, - bool uploadDXTC=true, bool bReleasable=true); - - // Convert in texture id - operator sint32 () const - { - return _TextureId; - } - - void serial(NLMISC::IStream &f); - - private: - sint32 _TextureId; - }; - -private: - CViewRenderer(); - ~CViewRenderer(); - -public: - static CViewRenderer* getInstance(); - - /// setup the default values for everything - void setup(); - - /// init when TextContext and Driver are created - void init(); - - /// set the driver render states for the interface - void setRenderStates (); - - /// Delete all textures and the like and reset the view renderer - void reset(); - - /// Retrieves the 3d driver we are using - static NL3D::UDriver* getDriver(); - - /// Sets the current TextContext. - static void setTextContext( NL3D::UTextContext *textcontext ); - - /// Sets the current driver - static void setDriver( NL3D::UDriver *driver ); - - /* - * setClipWindow : set the current clipping window - * (this window do not inherit properties from parent or whatever) - */ - void setClipWindow (sint32 x, sint32 y, sint32 w, sint32 h); - - /* - * getClipWindow : get the current clipping region - */ - void getClipWindow (sint32 &x, sint32 &y, sint32 &w, sint32 &h) - { - x = _ClipX; - y = _ClipY; - w = _ClipW; - h = _ClipH; - } - - /* - * true if the clipping region is empty: clipW or clipH is <=0 - */ - bool isClipWindowEmpty() const {return _ClipW<=0 || _ClipH<=0;} - - /* - * checkNewScreenSize : check if the opengl screen size. This is SLOW ! - * NB: if the window is minimized (w==h==0), then the old screen size is kept, and isMinimized() return true - */ - void checkNewScreenSize (); - - /* - * getScreenSize : get the screen window size changed (at last checkNewScreenSize called) - */ - void getScreenSize (uint32 &w, uint32 &h); - - /* - * get OOW / OOH - */ - void getScreenOOSize (float &oow, float &ooh); - - /* - * is the Screen minimized? - */ - bool isMinimized() const {return _IsMinimized;} - - /* - * drawBitmap : this is the interface with all the views - * - */ - void drawRotFlipBitmap (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flipv, - sint32 nTxId, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); - - /* - * Draw a simple wired quad. No flushing is done as the draw is done instantly (usually for debug) - */ - void drawWiredQuad(sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col = NLMISC::CRGBA::White); - - /* - * Draw a simple filled quad. No flushing is done as the draw is done instantly (usually for debug) - */ - void drawFilledQuad(sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col = NLMISC::CRGBA::White); - - /* - * drawBitmap : Tiled version - * \param tileOrigin 2 bits 1 - Left/Right (0/1) 2 - Bottom/Top (0/1) (0-BL)(1-BR)(2-TL)(3-TR) - * - */ - void drawRotFlipBitmapTiled (sint layerId, sint32 x, sint32 y, sint32 width, sint32 height, uint8 rot, bool flipv, - sint32 nTxId, uint tileOrigin, const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); - - - - /* - * drawBitmap : draw a bitmap roted by 90 degrees in CW 'rot times' - * flipv is a boolean that indicates if there is a vertical flip - * this is a 1:1 ratio so if texture is x long there are x pixels on screen - */ - void draw11RotFlipBitmap (sint layerId, sint32 x, sint32 y, uint8 rot, bool flipv, sint32 nTxId, - const NLMISC::CRGBA &col = NLMISC::CRGBA(255,255,255,255)); - - /** Draw an arbitrary quad (fast version) , possibly clipping it. Unlike draw11RotFlipBitmap & the like, texture is filtered here. - * quads are all batched in the same render layer - */ - void drawQuad(sint layerId, const NLMISC::CQuadUV &quadUV, sint32 nTxId, - NLMISC::CRGBA col, bool additif, bool filtered = true); - /** Draw a set of untextured triangle in the given layer. all triangles of the same layer are batched - */ - void drawUnclippedTriangles(sint layerId, const std::vector &tris, NLMISC::CRGBA col); - - /* - * Draw a text - */ - void drawText (sint layerId, float x, float y, uint wordIndex, float xmin, float ymin, float xmax, float ymax, NL3D::UTextContext &textContext); - - /* - * loadTextures : load all textures associated with the interface - * this function add a globaltexture to the vector of global textures - */ - void loadTextures (const std::string &textureFileName, const std::string &uvFileName, bool uploadDXTC); - - /* - * createTexture : create a texture for the interface, possibly from an externally created texture - * If no external texture is given, then 'sGlobalTextureName' is the filename of the big texture - * You should call deleteTexture when the texture is not used anymore - * The method returns the texture id of the new texture - */ - sint32 createTexture (const std::string &sGlobalTextureName, // unique id identifying this big texture, (its filename if not externally created) - sint32 offsetX = 0, - sint32 offsetY = 0, - sint32 width = -1, - sint32 height = -1, - bool uploadDXTC=true, - bool bReleasable=true - ); - - - // change position of a sub-texture (inside its big texture) from the sub-texture filename - void updateTexturePos(const std::string &texturefileName, - sint32 offsetX = 0, - sint32 offsetY = 0, - sint32 width = -1, - sint32 height = -1 - ); - - /** Add / change a global texture from an externally created texture - * \param defaultTexWidth width to used when CTextureId::createTexture is used without giving the width (e.g width = -1), useful for cropped textures - * \param defaultTexHeight height to used when CTextureId::createTexture is used without giving the height (e.g height = -1), useful for cropped textures - */ - - void setExternalTexture(const std::string &sGlobalTextureName, - NL3D::UTexture *externalTexture = NULL, - uint32 externalTexWidth = 1, - uint32 externalTexHeight = 1, - uint32 defaultTexWidth = 1, - uint32 defaultTexHeight = 1 - ); - - /* - * deleteTexture : create a texture for the interface - */ - void deleteTexture (sint32 textureId); - - // get a global texture pointer from its name - NL3D::UTexture *getGlobalTexture(const std::string &name); - - /* - * Flush all parsed view and computed strings to screen - */ - void flush (); - - /** - * get a texture file pointer from a string name. O(logN) - * \param id : the id of the texture - * \return a texture file pointer. -1 if not found or if sName is empty() - */ - sint32 getTextureIdFromName (const std::string &sName) const; - std::string getTextureNameFromId (sint32 TxID); - void getTextureSizeFromId (sint32 id, sint32 &width, sint32 &height); - NLMISC::CRGBA getTextureColor(sint32 id, sint32 x, sint32 y); - - - /** - * \return the texture associated with the param figur - */ - sint32 getFigurTextureId(uint index) - { - nlassert(index < 10); - return _IndexesToTextureIds[index]; - } - - /** - * \return the texture for figur separator '-' - */ - sint32 getFigurSeparator() const { return _FigurSeparatorTextureId; } - - sint32 getFigurTextureW() const {return _WFigurTexture;} - sint32 getFigurTextureH() const {return _HFigurTexture;} - sint32 getFigurSeparatorW() const {return _WFigurSeparatorTexture;} - sint32 getFigurSeparatorH() const {return _HFigurSeparatorTexture;} - - - sint32 getFigurBlankTextureId () - { - return _FigurBlankId; - } - sint32 getBlankTextureId () - { - return _BlankId; - } - - - sint32 getTypoTextureW(char c); - sint32 getTypoTextureH(char c); - sint32 getTypoTextureId(char c); - - /// System Texture Manager. Used to avoid storing an id in each Ctrl for some texture code is aware of - // @{ - sint32 getSystemTextureId(TSystemTexture e) const {return _SystemTextures[e].Id;} - sint32 getSystemTextureW(TSystemTexture e) const {return _SystemTextures[e].W;} - sint32 getSystemTextureH(TSystemTexture e) const {return _SystemTextures[e].H;} - // @} - - /// For string rendering, get the RenderBuffer to the specified layer - NL3D::URenderStringBuffer *getStringRenderBuffer(sint layerId); - - - /** Custom Rendering Interface - * Note that this function is EXTREMLY SLOW so it should be used with care - * This function flush the quad cache, clip the quad passed with current clipping region - * and draw (with drawQuedUV2) it with the material passed in parameter. There is no cache operation done. - * uv used are from (0,0) -> (1,1) for the 2 stages - */ - void drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, NLMISC::CRGBA col, NL3D::UMaterial Mat); - // Same but we can control uv mapping of first stage - void drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, - const NLMISC::CUV &uv0Min, const NLMISC::CUV &uv0Max, - NLMISC::CRGBA col, NL3D::UMaterial Mat); - // Same but we can control uv mapping of 2 stages - void drawCustom (sint32 x, sint32 y, sint32 width, sint32 height, - const NLMISC::CUV &uv0Min, const NLMISC::CUV &uv0Max, const NLMISC::CUV &uv1Min, const NLMISC::CUV &uv1Max, - NLMISC::CRGBA col, NL3D::UMaterial Mat); - - // **** World space interface methods - - /** Set the current Z in projCenter.z. - * If you want to scale the window position, set a scale!=1. projCenter.x/y is used as the - * pivot (in window coordinates) - */ - void setInterfaceDepth (const NLMISC::CVector &projCenter, float scale); - - // Activate world space transformation - void activateWorldSpaceMatrix (bool activate); - - // Set the screen to world space matrix - void setWorldSpaceFrustum (const NL3D::CFrustum &cameraFrustum); - - // Get the current Frustum - const NL3D::CFrustum &getFrustum () const - { - return _CameraFrustum; - } - -private: - /** - * init the map _IndexesToTextures - */ - void initIndexesToTextureIds (); - void initTypo (); - - bool needClipping (const NLMISC::CQuad &q); - - void clip (NLMISC::CQuadColorUV &qout, const NLMISC::CQuadColorUV &qin, uint rot); - void clip (NLMISC::CQuadColorUV2 &qout, const NLMISC::CQuadColorUV2 &qin); -private: - - // A layer is a vector of Quads. - class CLayer - { - public: - // unfiltered quads - std::vector Quads; - uint32 NbQuads; - std::vector Tris; - // filtered alpha blended quads - std::vector FilteredAlphaBlendedQuads; - // filtered alpha blended tris - std::vector FilteredAlphaBlendedTris; - // filtered additif blended quads - std::vector FilteredAdditifQuads; - // filtered additif blended tris - std::vector FilteredAdditifTris; - - CLayer() - { - NbQuads= 0; - } - }; - - // SGlobalTexture is a texture that regroup other texture. We store also current quads to render - struct SGlobalTexture - { - SGlobalTexture () - { - FromGlobaleTexture = true; - } - uint32 Width, Height; - uint32 DefaultWidth, DefaultHeight; - NL3D::UTexture *Texture; - std::string Name; - bool FromGlobaleTexture; - // Array of layers - CLayer Layers[VR_NUM_LAYER]; - }; - - // For each Layer, store a string Buffer - NL3D::URenderStringBuffer *_StringRBLayers[VR_NUM_LAYER]; - - // For each Layer, tells if empty or not - bool _EmptyLayer[VR_NUM_LAYER]; - - // SImage is one texture of the SGlobalTexture textures - struct SImage - { - std::string Name; - SGlobalTexture *GlobalTexturePtr; - NLMISC::CUV UVMin, UVMax; - - // Assign UV of this image to a quad depending on the flip and rot - void setupQuadUV(bool flipv, uint8 rot, NLMISC::CQuadColorUV &dest); - }; - - // *************************************************************************** - // \name Texture management - // *************************************************************************** - - // SImage accessors - SImage *getSImage(sint32 textureId) - { - return &(*(_SImageIterators[textureId])); - } - - - // Add a SImage - sint32 addSImage(const SImage &image) - { - uint i; - for (i=0; i<_SImageIterators.size(); i++) - { - // Free ? - if (_SImageIterators[i] == _SImages.end()) - break; - } - - // Nothing free ? - if (i == _SImageIterators.size()) - _SImageIterators.push_back(_SImages.end()); - - _SImages.push_back(image); - _SImageIterators[i] = _SImages.end(); - _SImageIterators[i]--; - return (sint32)i; - } - - // Remove a SImage - void removeSImage(sint32 textureId) - { - // Allocated ? - nlassert (_SImageIterators[textureId] != _SImages.end()); - - // Remove the image - _SImages.erase (_SImageIterators[textureId]); - - // Remove the index entry - _SImageIterators[textureId] = _SImages.end(); - } - - typedef std::list TGlobalTextureList; - typedef std::list TSImageList; - typedef std::vector::iterator> TSImageIterator; - - // List of global textures - TGlobalTextureList _GlobalTextures; - - // List of SImage - TSImageList _SImages; - - // Array used to convert a texture ID in _SImages iterator - TSImageIterator _SImageIterators; - - // *************************************************************************** - - typedef std::map TTextureMap; - TTextureMap _TextureMap; - - NL3D::UMaterial _Material; - - // Clip & screen system - sint32 _ClipX, _ClipY, _ClipW, _ClipH; - float _XMin, _XMax, _YMin, _YMax; - - sint32 _ScreenW, _ScreenH; - float _OneOverScreenW, _OneOverScreenH; - bool _IsMinimized; - - - //map linking a uint to a bitmap. Used to display figurs - std::vector _IndexesToTextureIds; - sint32 _FigurSeparatorTextureId; - sint32 _FigurBlankId, _BlankId; - sint32 _WFigurTexture; - sint32 _HFigurTexture; - sint32 _WFigurSeparatorTexture; - sint32 _HFigurSeparatorTexture; - NLMISC::CUV _BlankUV; - SGlobalTexture *_BlankGlobalTexture; - - // System textures - class CSystemTexture - { - public: - sint32 Id; - sint32 W; - sint32 H; - - CSystemTexture() - { - Id= -1; - W= H= 0; - } - }; - CSystemTexture _SystemTextures[NumSystemTextures]; - - // Typo texture - enum - { - NumTypoChar= 127, - }; - sint32 _TypoCharToTextureIds[NumTypoChar]; - sint32 _TypoCharWs[NumTypoChar]; - sint32 _TypoH; - - - void addSystemTexture(TSystemTexture e, const char *s); - void initSystemTextures(); - - /** - * put a new quad in the cache (call flush if texture different) - */ - void putQuadInLayer (SGlobalTexture >, sint layerId, const NLMISC::CQuadColorUV &qcoluv, uint rot); - - // World space interface methods - void worldSpaceTransformation (NLMISC::CQuadColorUV &qcoluv); - - bool _WorldSpaceTransformation; // Transform into world space - float _CurrentZ; // Current z used for the scene - NL3D::CFrustum _CameraFrustum; // Transform from screen space to world space - NLMISC::CMatrix _WorldSpaceMatrix; // Matrix to be applied for world space transformation - bool _WorldSpaceScale; - - - static CViewRenderer *instance; - static NL3D::UDriver *driver; - static NL3D::UTextContext *textcontext; -}; - - -#endif // NL_VIEW_RENDERER_H - -/* End of view_renderer.h */ diff --git a/code/ryzom/client/src/r2/displayer_visual_activity_sequence.cpp b/code/ryzom/client/src/r2/displayer_visual_activity_sequence.cpp index 95b8f089b..a15d4492a 100644 --- a/code/ryzom/client/src/r2/displayer_visual_activity_sequence.cpp +++ b/code/ryzom/client/src/r2/displayer_visual_activity_sequence.cpp @@ -21,7 +21,7 @@ // #include "../interface_v3/ctrl_quad.h" #include "../interface_v3/interface_manager.h" -#include "../interface_v3/view_renderer.h" +#include "nel/gui/view_renderer.h" using namespace NLMISC; diff --git a/code/ryzom/client/src/r2/displayer_visual_entity.cpp b/code/ryzom/client/src/r2/displayer_visual_entity.cpp index 744d99246..f92dcf0e2 100644 --- a/code/ryzom/client/src/r2/displayer_visual_entity.cpp +++ b/code/ryzom/client/src/r2/displayer_visual_entity.cpp @@ -54,7 +54,7 @@ #include "../pacs_client.h" #include "../time_client.h" // -#include "../interface_v3/view_renderer.h" +#include "nel/gui/view_renderer.h" // #include "../sheet_manager.h" diff --git a/code/ryzom/client/src/r2/island_collision.h b/code/ryzom/client/src/r2/island_collision.h index ffb8b19ff..f1c8de182 100644 --- a/code/ryzom/client/src/r2/island_collision.h +++ b/code/ryzom/client/src/r2/island_collision.h @@ -26,7 +26,7 @@ #include "nel/3d/texture_user.h" #include "nel/3d/packed_world.h" // -#include "../interface_v3/view_renderer.h" +#include "nel/gui/view_renderer.h" #include "../interface_v3/interface_element.h" namespace NL3D diff --git a/code/ryzom/client/src/r2/prim_render.cpp b/code/ryzom/client/src/r2/prim_render.cpp index c932643d8..9d6c16393 100644 --- a/code/ryzom/client/src/r2/prim_render.cpp +++ b/code/ryzom/client/src/r2/prim_render.cpp @@ -26,7 +26,7 @@ #include "../interface_v3/ctrl_quad.h" #include "../interface_v3/ctrl_polygon.h" #include "../interface_v3/interface_manager.h" -#include "../interface_v3/view_renderer.h" +#include "nel/gui/view_renderer.h" #include "../interface_v3/group_map.h"