vertex_buffer.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "std3d.h"
00025 
00026 #include "nel/3d/vertex_buffer.h"
00027 #include "nel/misc/vector.h"
00028 #include "nel/misc/fast_mem.h"
00029 #include "nel/3d/driver.h"
00030 using namespace NLMISC;
00031 
00032 
00033 namespace NL3D
00034 {
00035 
00036 // --------------------------------------------------
00037 
00038 const uint CVertexBuffer::SizeType[NumType]=
00039 {
00040     1*sizeof(double),
00041     1*sizeof(float),
00042     1*sizeof(short),
00043     2*sizeof(double),
00044     2*sizeof(float),
00045     2*sizeof(short),
00046     3*sizeof(double),
00047     3*sizeof(float),
00048     3*sizeof(short),
00049     4*sizeof(double),
00050     4*sizeof(float),
00051     4*sizeof(short),
00052     4*sizeof(char),
00053 };
00054 
00055 
00056 const uint CVertexBuffer::NumComponentsType[NumType] =
00057 {
00058     1,
00059     1,
00060     1,
00061     2,
00062     2,
00063     2,
00064     3,
00065     3,
00066     3,
00067     4,
00068     4,
00069     4,
00070     4
00071 };
00072 
00073 
00074 // --------------------------------------------------
00075 
00076 const CVertexBuffer::TType CVertexBuffer::DefaultValueType[NumValue]=
00077 {
00078     Float3,     // Position
00079     Float3,     // Normal
00080     Float2,     // TexCoord0
00081     Float2,     // TexCoord1
00082     Float2,     // TexCoord2
00083     Float2,     // TexCoord3
00084     Float2,     // TexCoord4
00085     Float2,     // TexCoord5
00086     Float2,     // TexCoord6
00087     Float2,     // TexCoord7
00088     UChar4,     // Primary color
00089     UChar4,     // Secondary color
00090     Float4,     // 4 Weights
00091     UChar4,     // PaletteSkin
00092     Float1,     // Fog
00093     Float1,     // Empty
00094 };
00095 
00096 
00097 // --------------------------------------------------
00098 
00099 void CVertexBuffer::construct()
00100 {
00101     /* ***********************************************
00102      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00103      *  It can be loaded/called through CAsyncFileManager for instance
00104      * ***********************************************/
00105     _Flags = 0;
00106     _Capacity = 0;
00107     _NbVerts = 0;
00108     _InternalFlags = 0;
00109     _VertexSize = 0;
00110     _VertexColorFormat = TRGBA;
00111     _LockCounter = 0;
00112     _LockedBuffer = NULL;
00113     _PreferredMemory = RAMPreferred;
00114     _Location = NotResident;
00115     _ResidentSize = 0;
00116     _KeepLocalMemory = false;
00117 
00118     // Default routing
00119     uint i;
00120     for (i=0; i<MaxStage; i++)
00121         _UVRouting[i] = i;
00122 }
00123 
00124 // --------------------------------------------------
00125 
00126 CVertexBuffer::CVertexBuffer()
00127 {
00128     construct();
00129 }
00130 
00131 CVertexBuffer::CVertexBuffer(const char *name)
00132 {
00133     construct();
00134     _Name = name;
00135 }
00136 
00137 
00138 // --------------------------------------------------
00139 
00140 CVertexBuffer::CVertexBuffer(const CVertexBuffer &vb) : CRefCount()
00141 {
00142     /* ***********************************************
00143      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00144      *  It can be loaded/called through CAsyncFileManager for instance
00145      * ***********************************************/
00146 
00147     _Flags = 0;
00148     _Capacity = 0;
00149     _NbVerts = 0;
00150     _VertexSize = 0;
00151     _LockCounter = 0;
00152     _LockedBuffer = NULL;
00153     _PreferredMemory = RAMPreferred;
00154     _Location = NotResident;
00155     _ResidentSize = 0;
00156     _KeepLocalMemory = false;
00157 
00158     operator=(vb);
00159 
00160     // Default routing
00161     uint i;
00162     for (i=0; i<MaxStage; i++)
00163         _UVRouting[i] = i;
00164 }
00165 
00166 // --------------------------------------------------
00167 
00168 CVertexBuffer::~CVertexBuffer()
00169 {
00170     /* ***********************************************
00171      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00172      *  It can be loaded/called through CAsyncFileManager for instance
00173      * ***********************************************/
00174 
00175     if (DrvInfos)
00176         DrvInfos->VertexBufferPtr = NULL;   // Tell the driver info to not restaure memory when it will die
00177 
00178     // Must kill the drv mirror of this VB.
00179     DrvInfos.kill();
00180 }
00181 
00182 // --------------------------------------------------
00183 
00184 CVertexBuffer   &CVertexBuffer::operator=(const CVertexBuffer &vb)
00185 {
00186     nlassertex (!isLocked(), ("The vertex buffer is locked."));
00187     nlassertex (!vb.isLocked(), ("Source buffer is locked."));
00188 
00189     // Single value
00190     _VertexSize = vb._VertexSize;
00191     _Flags = vb._Flags;
00192     _InternalFlags = vb._InternalFlags;
00193     _NbVerts = vb._NbVerts;
00194     _Capacity = vb._Capacity;
00195     _NonResidentVertices = vb._NonResidentVertices;
00196     _VertexColorFormat = vb._VertexColorFormat;
00197     _PreferredMemory = vb._PreferredMemory;
00198     _KeepLocalMemory = vb._KeepLocalMemory;
00199     uint i;
00200     _LockCounter = 0;
00201     _LockedBuffer = NULL;
00202 
00203     // Arraies
00204     for (uint value=0; value<NumValue; value++)
00205     {
00206         _Offset[value]= vb._Offset[value];
00207         _Type[value]= vb._Type[value];
00208     }
00209 
00210     // Copy the routing
00211     for (i=0; i<MaxStage; i++)
00212         _UVRouting[i] = vb._UVRouting[i];
00213 
00214     // Set touch flags
00215     _InternalFlags |= TouchedAll;
00216     _Location = NotResident;
00217     _ResidentSize = 0;
00218 
00219     return *this;
00220 }
00221 
00222 // --------------------------------------------------
00223 void CVertexBuffer::copyVertices(CVertexBuffer &dest) const
00224 {
00225     nlassert(_PreferredMemory != RAMVolatile);
00226     nlassert(_PreferredMemory != AGPVolatile);
00227     // copy setup
00228     dest = *this;
00229     CVertexBufferReadWrite srcDatas;
00230     const_cast<CVertexBuffer *>(this)->lock(srcDatas);
00231     nlassert(dest.getLocation() == NotResident);
00232     CVertexBufferReadWrite destDatas;
00233     dest.lock(destDatas); // will be in vram
00234     NLMISC::CFastMem::memcpy (destDatas.getVertexCoordPointer(), srcDatas.getVertexCoordPointer(), getVertexSize() * getNumVertices());
00235 }
00236 
00237 // --------------------------------------------------
00238 
00239 bool CVertexBuffer::setVertexFormat(uint32 flags)
00240 {
00241     nlassertex (!isLocked(), ("The vertex buffer is locked."));
00242 
00243     uint    i;
00244 
00245     // Clear extended values
00246     clearValueEx ();
00247 
00248     // Position ?
00249     if (flags & PositionFlag)
00250     {
00251         // Add a standard position value
00252         addValueEx (Position, Float3);
00253     }
00254 
00255     // Normal ?
00256     if (flags & NormalFlag)
00257     {
00258         // Add a standard normal value
00259         addValueEx (Normal, Float3);
00260     }
00261 
00262     // For each uv values
00263     for(i=0 ; i<MaxStage ; i++)
00264     {
00265         // UV ?
00266         if (flags & (TexCoord0Flag<<i))
00267         {
00268             // Add a standard uv value
00269             addValueEx ((TValue)(TexCoord0+i), Float2);
00270         }
00271     }
00272 
00273     // Fog ?
00274     if (flags & FogFlag)
00275     {
00276         // Add a standard primary color value
00277         addValueEx (Fog, Float1);
00278     }
00279 
00280     // Primary color ?
00281     if (flags & PrimaryColorFlag)
00282     {
00283         // Add a standard primary color value
00284         addValueEx (PrimaryColor, UChar4);
00285     }
00286 
00287     // Secondary color ?
00288     if (flags & SecondaryColorFlag)
00289     {
00290         // Add a standard primary color value
00291         addValueEx (SecondaryColor, UChar4);
00292     }
00293 
00294     // Weight ?
00295     if (flags & WeightFlag)
00296     {
00297         // Add a standard primary color value
00298         addValueEx (Weight, Float4);
00299     }
00300 
00301     // Palette skin ?
00302     if ((flags & PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag)
00303     {
00304         // Add a standard primary color value
00305         addValueEx (PaletteSkin, UChar4);
00306     }
00307 
00308     // Compute the vertex buffer
00309     initEx ();
00310 
00311     // Force non resident
00312     restaureNonResidentMemory();
00313 
00314     return (true);
00315 }
00316 
00317 // --------------------------------------------------
00318 
00319 CVertexBuffer::TValue CVertexBuffer::getValueIdByNumberEx (uint valueNumber)
00320 {
00321     // See NV_vertex_program spec, or driver_opengl_vertex.cpp:: GLVertexAttribIndex.
00322     static  TValue  lut[16]= {
00323         Position,
00324         Weight,
00325         Normal,
00326         PrimaryColor,
00327         SecondaryColor,
00328         Fog,
00329         PaletteSkin,
00330         Empty,
00331         TexCoord0,
00332         TexCoord1,
00333         TexCoord2,
00334         TexCoord3,
00335         TexCoord4,
00336         TexCoord5,
00337         TexCoord6,
00338         TexCoord7,
00339     };
00340 
00341     return lut[valueNumber];
00342 }
00343 
00344 // --------------------------------------------------
00345 
00346 void CVertexBuffer::clearValueEx ()
00347 {
00348     nlassertex (!isLocked(), ("The vertex buffer is locked."));
00349 
00350     // Reset format flags
00351     _Flags=0;
00352 }
00353 
00354 
00355 // --------------------------------------------------
00356 
00357 void CVertexBuffer::dumpFormat() const
00358 {
00359     for(uint k = 0; k < NumValue; ++k)
00360     {
00361         if (_Flags & (1 << k))
00362         {
00363             std::string result = "Component :";
00364             switch(k)
00365             {
00366                 case Position:      result += "Position"; break;
00367                 case Normal:        result += "Normal"; break;
00368                 case TexCoord0:     result += "TexCoord0"; break;
00369                 case TexCoord1:     result += "TexCoord1"; break;
00370                 case TexCoord2:     result += "TexCoord2"; break;
00371                 case TexCoord3:     result += "TexCoord3"; break;
00372                 case TexCoord4:     result += "TexCoord4"; break;
00373                 case TexCoord5:     result += "TexCoord5"; break;
00374                 case TexCoord6:     result += "TexCoord6"; break;
00375                 case TexCoord7:     result += "TexCoord7"; break;
00376                 case PrimaryColor:  result += "PrimaryColor"; break;
00377                 case SecondaryColor:result += "SecondaryColor"; break;
00378                 case Weight:        result += "Weight"; break;
00379                 case PaletteSkin:   result += "PaletteSkin"; break;
00380                 case Fog:           result += "Fog"; break;
00381                 case Empty:         result += "Empty"; break;
00382                 case NumValue:      result += "NumValue"; break;
00383                 default:
00384                     result += "???";
00385                 break;
00386             }
00387             result += "; type :";
00388             switch(_Type[k])
00389             {
00390                 case Double1:  result +="Double1"; break;
00391                 case Float1:   result +="Float1";  break;
00392                 case Short1:   result +="Short1";  break;
00393                 case Double2:  result +="Double2"; break;
00394                 case Float2:   result +="Float2";  break;
00395                 case Short2:   result +="Short2";  break;
00396                 case Double3:  result +="Double3"; break;
00397                 case Float3:   result +="Float3";  break;
00398                 case Short3:   result +="Short3";  break;
00399                 case Double4:  result +="Double4"; break;
00400                 case Float4:   result +="Float4";  break;
00401                 case Short4:   result +="Short4";  break;
00402                 case UChar4:   result +="UChar4";  break;
00403                 default:
00404                     result += "???";
00405                 break;
00406             }
00407             nlinfo(result.c_str());
00408         }
00409     }
00410 }
00411 
00412 
00413 // --------------------------------------------------
00414 
00415 void CVertexBuffer::addValueEx (TValue valueId, TType type)
00416 {
00417     nlassertex (!isLocked(), ("The vertex buffer is locked."));
00418 
00419     // Reset format flags
00420     _Flags |= 1<<valueId;
00421 
00422     // Set the type
00423     _Type[valueId]=(uint8)type;
00424 
00425     uint numComp = NumComponentsType[type];
00426     // unfortunately, some vertex program implementations don't allow any type for any value
00427     switch (valueId)
00428     {
00429         case Position:          nlassert(numComp >= 2); break;
00430         case Normal:            nlassert(numComp == 3); break;
00431         case PrimaryColor:      nlassert(numComp == 4); break;
00432         case SecondaryColor:    nlassert(numComp == 4); break;
00433         case Weight:            nlassert(numComp == 4); break;
00434         case PaletteSkin:       nlassert(numComp == 4); break;
00435         case Fog:               nlassert(numComp == 4); break;
00436         default: break;
00437     }
00438 }
00439 
00440 // --------------------------------------------------
00441 
00442 bool CVertexBuffer::hasValueEx(TValue valueId) const
00443 {
00444     return (_Flags & (1 << valueId)) != 0;
00445 }
00446 
00447 // --------------------------------------------------
00448 
00449 void CVertexBuffer::initEx ()
00450 {
00451     nlassert (!isLocked());
00452 
00453     // Calc vertex size and set value's offset
00454     _VertexSize=0;
00455     for (uint value=0; value<NumValue; value++)
00456     {
00457         // Value used ?
00458         if (_Flags&(1<<value))
00459         {
00460             // Set offset
00461             _Offset[value]=_VertexSize;
00462 
00463             // New size
00464             _VertexSize+=SizeType[_Type[value]];
00465         }
00466     }
00467 
00468     // Reset number of vertices
00469     _NbVerts=0;
00470 
00471     // Compute new capacity
00472     if (_VertexSize)
00473         _Capacity = _NonResidentVertices.size()/_VertexSize;
00474     else
00475         _Capacity = 0;
00476 
00477     // Force non resident
00478     restaureNonResidentMemory();
00479 }
00480 
00481 // --------------------------------------------------
00482 
00483 void CVertexBuffer::reserve(uint32 n)
00484 {
00485     nlassert (!isLocked());
00486     if (_Capacity != n)
00487     {
00488         _Capacity= n;
00489         _NbVerts=std::min (_NbVerts,_Capacity);
00490 
00491         // Force non resident
00492         restaureNonResidentMemory();
00493     }
00494 }
00495 
00496 // --------------------------------------------------
00497 
00498 void CVertexBuffer::setNumVertices(uint32 n)
00499 {
00500     if(_Capacity<n)
00501     {
00502         reserve(n);
00503     }
00504     if(_NbVerts != n)
00505     {
00506         _InternalFlags |= TouchedNumVertices;
00507         _NbVerts=n;
00508     }
00509 }
00510 
00511 // --------------------------------------------------
00512 
00513 void    CVertexBuffer::deleteAllVertices()
00514 {
00515     if (_Capacity)
00516     {
00517         nlassert (!isLocked());
00518         // free memory.
00519         contReset(_NonResidentVertices);
00520         _Capacity= 0;
00521         if(_NbVerts!=0)
00522         {
00523             _NbVerts=0;
00524             _InternalFlags |= TouchedNumVertices;
00525         }
00526 
00527         // Force non resident
00528         restaureNonResidentMemory();
00529 
00530         // Delete driver info
00531         nlassert (DrvInfos == NULL);
00532     }
00533 }
00534 
00535 // --------------------------------------------------
00536 
00537 uint16      CVertexBuffer::remapV2Flags (uint32 oldFlags, uint& weightCount)
00538 {
00539     // Old flags
00540     const uint32 OLD_IDRV_VF_XYZ = 0x00000001;
00541     const uint32 OLD_IDRV_VF_W0 = 0x00000002;
00542     const uint32 OLD_IDRV_VF_W1 = 0x00000004;
00543     const uint32 OLD_IDRV_VF_W2 = 0x00000008;
00544     const uint32 OLD_IDRV_VF_W3 = 0x00000010;
00545     const uint32 OLD_IDRV_VF_NORMAL = 0x00000020;
00546     const uint32 OLD_IDRV_VF_COLOR = 0x00000040;
00547     const uint32 OLD_IDRV_VF_SPECULAR = 0x00000080;
00548     const uint32 OLD_IDRV_VF_UV0 = 0x00000100;
00549     const uint32 OLD_IDRV_VF_UV1 = 0x00000200;
00550     const uint32 OLD_IDRV_VF_UV2 = 0x00000400;
00551     const uint32 OLD_IDRV_VF_UV3 = 0x00000800;
00552     const uint32 OLD_IDRV_VF_UV4 = 0x00001000;
00553     const uint32 OLD_IDRV_VF_UV5 = 0x00002000;
00554     const uint32 OLD_IDRV_VF_UV6 = 0x00004000;
00555     const uint32 OLD_IDRV_VF_UV7 = 0x00008000;
00556     const uint32 OLD_IDRV_VF_PALETTE_SKIN = 0x00010000 | OLD_IDRV_VF_W0 | OLD_IDRV_VF_W1 | OLD_IDRV_VF_W2 | OLD_IDRV_VF_W3;
00557 
00558     // Old Flags
00559     uint16 newFlags=0;
00560 
00561     // Number of weight values
00562     weightCount=0;
00563 
00564     // Remap the flags
00565     if (oldFlags&OLD_IDRV_VF_XYZ)
00566         newFlags|=PositionFlag;
00567     if (oldFlags&OLD_IDRV_VF_NORMAL)
00568         newFlags|=NormalFlag;
00569     if (oldFlags&OLD_IDRV_VF_COLOR)
00570         newFlags|=PrimaryColorFlag;
00571     if (oldFlags&OLD_IDRV_VF_SPECULAR)
00572         newFlags|=SecondaryColorFlag;
00573     if (oldFlags&OLD_IDRV_VF_UV0)
00574         newFlags|=TexCoord0Flag;
00575     if (oldFlags&OLD_IDRV_VF_UV1)
00576         newFlags|=TexCoord1Flag;
00577     if (oldFlags&OLD_IDRV_VF_UV2)
00578         newFlags|=TexCoord2Flag;
00579     if (oldFlags&OLD_IDRV_VF_UV3)
00580         newFlags|=TexCoord3Flag;
00581     if (oldFlags&OLD_IDRV_VF_UV4)
00582         newFlags|=TexCoord4Flag;
00583     if (oldFlags&OLD_IDRV_VF_UV5)
00584         newFlags|=TexCoord5Flag;
00585     if (oldFlags&OLD_IDRV_VF_UV6)
00586         newFlags|=TexCoord6Flag;
00587     if (oldFlags&OLD_IDRV_VF_UV7)
00588         newFlags|=TexCoord7Flag;
00589     if (oldFlags&OLD_IDRV_VF_W0)
00590     {
00591         weightCount=1;
00592         newFlags|=WeightFlag;
00593     }
00594     if (oldFlags&OLD_IDRV_VF_W1)
00595     {
00596         weightCount=2;
00597         newFlags|=WeightFlag;
00598     }
00599     if (oldFlags&OLD_IDRV_VF_W2)
00600     {
00601         weightCount=3;
00602         newFlags|=WeightFlag;
00603     }
00604     if (oldFlags&OLD_IDRV_VF_W3)
00605     {
00606         weightCount=4;
00607         newFlags|=WeightFlag;
00608     }
00609     if (oldFlags&(OLD_IDRV_VF_PALETTE_SKIN))
00610         newFlags|=PaletteSkinFlag;
00611 
00612     // Return the new flags
00613     return newFlags;
00614 }
00615 
00616 // --------------------------------------------------
00617 
00618 void        CVertexBuffer::serialOldV1Minus(NLMISC::IStream &f, sint ver)
00619 {
00620     /* ***********************************************
00621      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00622      *  It can be loaded/called through CAsyncFileManager for instance
00623      * ***********************************************/
00624 
00625     /*
00626     Version 1:
00627         - PaletteSkin version.
00628     Version 0:
00629         - base verison.
00630     */
00631 
00632     // old Flags
00633     uint32 oldFlags;
00634 
00635     // Serial VBuffers format/size.
00636     //=============================
00637     f.serial(oldFlags);
00638 
00639     // Remap the flags
00640     uint weightCount;
00641     uint16 newFlags=remapV2Flags (oldFlags, weightCount);
00642 
00643     // Must be reading
00644     nlassert (f.isReading());
00645 
00646     // Set default value type
00647     uint i;
00648     for (i=0; i<NumValue; i++)
00649         _Type[i]=DefaultValueType[i];
00650 
00651     uint32 nbVert;  // Read only
00652     f.serial(nbVert);
00653     reserve(0);
00654     setVertexFormat(newFlags);
00655     setNumVertices(nbVert);
00656     // All other infos (but _NonResidentVertices) are computed by setVertexFormat() and setNumVertices().
00657 
00658     // Weight count ?
00659     switch (weightCount)
00660     {
00661     case 1:
00662         _Type[Weight]=Float1;
00663         break;
00664     case 2:
00665         _Type[Weight]=Float2;
00666         break;
00667     case 3:
00668         _Type[Weight]=Float3;
00669         break;
00670     case 4:
00671         _Type[Weight]=Float4;
00672         break;
00673     }
00674 
00675     // Serial VBuffers components.
00676     //============================
00677     for(sint id=0;id<(sint)_NbVerts;id++)
00678     {
00679         uint8 *pointer = &(*_NonResidentVertices.begin());
00680         uint stridedId = id * _VertexSize;
00681         // XYZ.
00682         if(_Flags & PositionFlag)
00683         {
00684             CVector     &vert= *(CVector*)(pointer + stridedId + _Offset[Position]);
00685             f.serial(vert);
00686         }
00687         // Normal
00688         if(_Flags & NormalFlag)
00689         {
00690             CVector     &norm= *(CVector*)(pointer + stridedId + _Offset[Normal]);
00691             f.serial(norm);
00692         }
00693         // Uvs.
00694         for(i=0;i<MaxStage;i++)
00695         {
00696             if(_Flags & (TexCoord0Flag<<i))
00697             {
00698                 CUV     &uv= *(CUV*)(pointer + stridedId + _Offset[TexCoord0+i]);
00699                 f.serial(uv);
00700             }
00701         }
00702         // Color.
00703         if(_Flags & PrimaryColorFlag)
00704         {
00705             CRGBA       &col= *(CRGBA*)(pointer + stridedId + _Offset[PrimaryColor]);
00706             f.serial(col);
00707         }
00708         // Specular.
00709         if(_Flags & SecondaryColorFlag)
00710         {
00711             CRGBA       &col= *(CRGBA*)(pointer + stridedId + _Offset[SecondaryColor]);
00712             f.serial(col);
00713         }
00714         // Weights
00715         for(i=0;i<weightCount;i++)
00716         {
00717             // Weight channel available ?
00718             float   &w= *(float*)(pointer + stridedId + _Offset[Weight] + i*sizeof(float));
00719             f.serial(w);
00720         }
00721         // CPaletteSkin (version 1+ only).
00722         if((ver>=1) && ((_Flags & PaletteSkinFlag) == CVertexBuffer::PaletteSkinFlag) )
00723         {
00724             CPaletteSkin    &ps= *(CPaletteSkin*)(pointer + stridedId + _Offset[PaletteSkin]);
00725             f.serial(ps);
00726         }
00727 
00728     }
00729 
00730     // Set touch flags
00731     _InternalFlags = 0;
00732     if(f.isReading())
00733     {
00734         // Force non resident
00735         restaureNonResidentMemory();
00736     }
00737 }
00738 
00739 // --------------------------------------------------
00740 
00741 void        CVertexBuffer::serial(NLMISC::IStream &f)
00742 {
00743     /* ***********************************************
00744      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00745      *  It can be loaded/called through CAsyncFileManager for instance
00746      * ***********************************************/
00747 
00748     /*
00749     Version 2:
00750         - cut to use serialHeader() serialSubset().
00751     Version 1:
00752         - PaletteSkin version.
00753     Version 0:
00754         - base verison.
00755     */
00756     nlassert (!isLocked());
00757     sint    ver= f.serialVersion(2);
00758 
00759     if (ver<2)
00760     {
00761         // old serial method
00762         serialOldV1Minus(f, ver);
00763     }
00764     else
00765     {
00766         // read write the header of the VBuffer.
00767         serialHeader(f);
00768 
00769         // read write the entire subset.
00770         serialSubset(f, 0, _NbVerts);
00771     }
00772 }
00773 
00774 // --------------------------------------------------
00775 
00776 void        CVertexBuffer::serialHeader(NLMISC::IStream &f)
00777 {
00778     /* ***********************************************
00779      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00780      *  It can be loaded/called through CAsyncFileManager for instance
00781      * ***********************************************/
00782 
00783     /*
00784     Version 3:
00785         - Preferred memory.
00786     Version 2:
00787         - Vertex color format management.
00788     Version 1:
00789         - Extended vertex format management.
00790     Version 0:
00791         - base verison of the header serialisation.
00792     */
00793     sint    ver= f.serialVersion(3);    // Hulud
00794 
00795     // Serial VBuffers format/size.
00796     //=============================
00797 
00798     // Flags
00799     uint16 flags=_Flags;
00800 
00801     if (ver<1)
00802     {
00803         // Must be reading
00804         nlassert (f.isReading());
00805 
00806         // Serial old flags
00807         uint32 oldFlags;
00808         f.serial(oldFlags);
00809 
00810         // Remap flags
00811         uint weightCount;
00812         flags=remapV2Flags (oldFlags, weightCount);
00813 
00814         // Set default value type
00815         for (uint i=0; i<NumValue; i++)
00816             _Type[i]=DefaultValueType[i];
00817 
00818         // weight count ?
00819         switch (weightCount)
00820         {
00821         case 1:
00822             _Type[Weight]=Float1;
00823             break;
00824         case 2:
00825             _Type[Weight]=Float2;
00826             break;
00827         case 3:
00828             _Type[Weight]=Float3;
00829             break;
00830         case 4:
00831             _Type[Weight]=Float4;
00832             break;
00833         }
00834     }
00835     else
00836     {
00837         // Serial new vertex flags
00838         f.serial(flags);
00839 
00840         // Serial type of values
00841         for (uint i=0; i<NumValue; i++)
00842         {
00843             if (!(flags & (1 << i)))
00844             {
00845                 _Type[i] = DefaultValueType[i];
00846             }
00847             f.serial (_Type[i]);
00848         }
00849     }
00850 
00851     // Serial nb vertices
00852     uint32 nbVerts=_NbVerts;
00853     f.serial(nbVerts);
00854 
00855     if(f.isReading())
00856     {
00857         reserve(0);
00858 
00859         // Init vertex format setup
00860         clearValueEx ();
00861 
00862         // Init vertex format
00863         for (uint i=0; i<NumValue; i++)
00864         {
00865             // Setup this value ?
00866             if (flags&(1<<i))
00867             {
00868                 // Add a value
00869                 addValueEx ((TValue)i, (TType)_Type[i]);
00870             }
00871         }
00872 
00873         // Build final vertex format
00874         initEx ();
00875 
00876         // Set num of vertices
00877         setNumVertices(nbVerts);
00878     }
00879     // All other infos (but _NonResidentVertices) are computed by initEx() and setNumVertices().
00880 
00881     if (ver>=2)
00882         f.serial (_VertexColorFormat);
00883 
00884     if (ver>=3)
00885     {
00886         f.serialEnum(_PreferredMemory);
00887         f.serial(_Name);
00888     }
00889     else
00890     {
00891         // Init preferred memory
00892         if(f.isReading())
00893         {
00894             _PreferredMemory = RAMPreferred;
00895             _Name = "";
00896         }
00897     }
00898 }
00899 
00900 
00901 // --------------------------------------------------
00902 uint    CVertexBuffer::	getNumTexCoordUsed() const
00903 {
00904     for (sint k = (MaxStage - 1); k >= 0; --k)
00905     {
00906         if (_Flags & (TexCoord0Flag << k))  return (uint) (k + 1);
00907     }
00908     return 0;
00909 }
00910 
00911 // --------------------------------------------------
00912 
00913 uint8       CVertexBuffer::getNumWeight () const
00914 {
00915     // Num weight
00916     switch (_Type[Weight])
00917     {
00918     case Float1:
00919         return 1;
00920     case Float2:
00921         return 2;
00922     case Float3:
00923         return 3;
00924     case Float4:
00925         return 4;
00926     }
00927 
00928     // No weight
00929     return 0;
00930 }
00931 
00932 // --------------------------------------------------
00933 
00934 void        CVertexBuffer::serialSubset(NLMISC::IStream &f, uint vertexStart, uint vertexEnd)
00935 {
00936     /* ***********************************************
00937      *  WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
00938      *  It can be loaded/called through CAsyncFileManager for instance
00939      * ***********************************************/
00940 
00941     /*
00942     Version 2:
00943         - UVRouting
00944     Version 1:
00945         - weight is 4 float in standard format.
00946     Version 0:
00947         - base verison of a vbuffer subset serialisation.
00948     */
00949     sint ver = f.serialVersion(2);
00950 
00951 
00952     // Serial VBuffers components.
00953     //============================
00954     nlassert(vertexStart<_NbVerts || _NbVerts==0);
00955     nlassert(vertexEnd<=_NbVerts);
00956     for(uint id=vertexStart; id<vertexEnd; id++)
00957     {
00958         // For each value
00959         for (uint value=0; value<NumValue; value++)
00960         {
00961             // Value used ?
00962             if (_Flags&(1<<value))
00963             {
00964                 // Get the pointer on it
00965                 void *ptr=(void*)((&(*_NonResidentVertices.begin()))+id*_VertexSize+getValueOffEx ((TValue)value));
00966                 f.serialBuffer ((uint8*)ptr, SizeType[_Type[value]]);
00967             }
00968         }
00969     }
00970 
00971     // Serial the UV Routing table
00972     //============================
00973     if (ver>=2)
00974     {
00975         f.serialBuffer (_UVRouting, sizeof(uint8)*MaxStage);
00976     }
00977     else
00978     {
00979         // Reset the table
00980         uint i;
00981         for (i=0; i<MaxStage; i++)
00982             _UVRouting[i] = i;
00983     }
00984 
00985     // Set touch flags
00986     if(f.isReading())
00987     {
00988         // Force non resident
00989         restaureNonResidentMemory();
00990     }
00991 }
00992 
00993 // --------------------------------------------------
00994 
00995 bool CVertexBuffer::setVertexColorFormat (TVertexColorType format)
00996 {
00997     // If resident, quit
00998     if (isResident())
00999         return false;
01000 
01001     nlassert (!isLocked());
01002 
01003     // Format is not good ?
01004     if ((TVertexColorType)_VertexColorFormat != format)
01005     {
01006         // Diffuse or specualr component ?
01007         if (_Flags & (PrimaryColorFlag|SecondaryColorFlag))
01008         {
01009             uint i;
01010             uint32 *ptr0 = (_Flags&PrimaryColorFlag)?(uint32*)&(_NonResidentVertices[_Offset[PrimaryColor]]):NULL;
01011             uint32 *ptr1 = (_Flags&SecondaryColorFlag)?(uint32*)&(_NonResidentVertices[_Offset[SecondaryColor]]):NULL;
01012             for (i=0; i<_NbVerts; i++)
01013             {
01014                 if (ptr0)
01015                 {
01016                     const register uint32 value = *ptr0;
01017 #ifdef NL_LITTLE_ENDIAN
01018                     *ptr0 = (value&0xff00ff00)|((value&0xff)<<16)|((value&0xff0000)>>16);
01019 #else // NL_LITTLE_ENDIAN
01020                     *ptr0 = (value&0x00ff00ff)|((value&0xff00)<<16)|((value&0xff000000)>>16);
01021 #endif // NL_LITTLE_ENDIAN
01022                     ptr0 = (uint32*)(((uint8*)ptr0)+_VertexSize);
01023                 }
01024                 if (ptr1)
01025                 {
01026                     const register uint32 value = *ptr1;
01027 #ifdef NL_LITTLE_ENDIAN
01028                     *ptr1 = (value&0xff00ff00)|((value&0xff)<<16)|((value&0xff0000)>>16);
01029 #else // NL_LITTLE_ENDIAN
01030                     *ptr1 = (value&0x00ff00ff)|((value&0xff00)<<16)|((value&0xff000000)>>16);
01031 #endif // NL_LITTLE_ENDIAN
01032                     ptr1 = (uint32*)(((uint8*)ptr1)+_VertexSize);
01033                 }
01034             }
01035         }
01036         _VertexColorFormat = (uint8)format;
01037 
01038         // Force non resident
01039         restaureNonResidentMemory();
01040     }
01041     return true;
01042 }
01043 
01044 // --------------------------------------------------
01045 
01046 void CVertexBuffer::setPreferredMemory (TPreferredMemory preferredMemory, bool keepLocalMemory)
01047 {
01048     if ((_PreferredMemory != preferredMemory) || (_KeepLocalMemory != keepLocalMemory))
01049     {
01050         _PreferredMemory = preferredMemory;
01051         _KeepLocalMemory = keepLocalMemory;
01052 
01053         // Force non resident
01054         restaureNonResidentMemory();
01055     }
01056 }
01057 
01058 // --------------------------------------------------
01059 void CVertexBuffer::setLocation (TLocation newLocation)
01060 {
01061     // Upload ?
01062     if (newLocation != NotResident)
01063     {
01064         // The driver must have setuped the driver info
01065         nlassert (DrvInfos);
01066 
01067         // Current size of the buffer
01068         const uint size = ((_PreferredMemory==RAMVolatile)||(_PreferredMemory==AGPVolatile))?_NbVerts*_VertexSize:_Capacity*_VertexSize;
01069 
01070         // The buffer must not be resident
01071         if (_Location != NotResident)
01072             setLocation (NotResident);
01073 
01074         // Copy the buffer containt
01075         uint8 *dest = DrvInfos->lock (0, size, false);
01076         nlassert (size<=_NonResidentVertices.size());   // Internal buffer must have the good size
01077         memcpy (dest, &(_NonResidentVertices[0]), size);
01078         DrvInfos->unlock(0, 0);
01079 
01080         // Reset the non resident container if not a static preferred memory and not put in RAM
01081         if ((_PreferredMemory != StaticPreferred) && (_Location != RAMResident) && !_KeepLocalMemory)
01082             contReset(_NonResidentVertices);
01083 
01084         // Clear touched flags
01085         resetTouchFlags ();
01086 
01087         _Location = newLocation;
01088         _ResidentSize = size;
01089     }
01090     else
01091     {
01092         // Current size of the buffer
01093         const uint size = _Capacity*_VertexSize;
01094 
01095         // Resize the non resident buffer
01096         _NonResidentVertices.resize (size);
01097 
01098         // If resident in RAM, backup the data in non resident memory
01099         if ((_Location == RAMResident) && (_PreferredMemory != RAMVolatile) && (_PreferredMemory != AGPVolatile) && !_KeepLocalMemory)
01100         {
01101             // The driver must have setuped the driver info
01102             nlassert (DrvInfos);
01103 
01104             // Copy the old buffer data
01105             const uint8 *src = DrvInfos->lock (0, _ResidentSize, true);
01106             if (!_NonResidentVertices.empty())
01107                 memcpy (&(_NonResidentVertices[0]), src, std::min (size, (uint)_ResidentSize));
01108             DrvInfos->unlock(0, 0);
01109         }
01110 
01111         _Location = NotResident;
01112         _ResidentSize = 0;
01113 
01114         // Touch the buffer
01115         _InternalFlags |= TouchedAll;
01116     }
01117 }
01118 
01119 // --------------------------------------------------
01120 void CVertexBuffer::restaureNonResidentMemory()
01121 {
01122     setLocation (NotResident);
01123 
01124     if (DrvInfos)
01125         DrvInfos->VertexBufferPtr = NULL;   // Tell the driver info to not restaure memory when it will die
01126 
01127     // Must kill the drv mirror of this VB.
01128     DrvInfos.kill();
01129 }
01130 
01131 // --------------------------------------------------
01132 
01133 void CVertexBuffer::fillBuffer ()
01134 {
01135     if (DrvInfos && _KeepLocalMemory)
01136     {
01137         // Copy the local memory in local memory
01138         const uint size = _NbVerts*_VertexSize;
01139         nlassert (size<=_NonResidentVertices.size());
01140         uint8 *dest = DrvInfos->lock (0, size, false);
01141         NLMISC::CFastMem::memcpy (dest, &(_NonResidentVertices[0]), size);
01142         DrvInfos->unlock(0, size);
01143     }
01144 }
01145 
01146 // --------------------------------------------------
01147 
01148 // CPaletteSkin serial (no version chek).
01149 void    CPaletteSkin::serial(NLMISC::IStream &f)
01150 {
01151     f.serial(MatrixId[0], MatrixId[1], MatrixId[2], MatrixId[3]);
01152 }
01153 
01154 // --------------------------------------------------
01155 
01156 IVBDrvInfos::~IVBDrvInfos()
01157 {
01158     _Driver->removeVBDrvInfoPtr(_DriverIterator);
01159 }
01160 
01161 // --------------------------------------------------
01162 // CVertexBufferReadWrite
01163 // --------------------------------------------------
01164 
01165 NLMISC::CVector* CVertexBufferReadWrite::getVertexCoordPointer(uint idx)
01166 {
01167     nlassert (_Parent->checkLockedBuffer());
01168     uint8*  ptr;
01169 
01170     ptr=_Parent->_LockedBuffer;
01171     ptr+=(idx*_Parent->_VertexSize);
01172     return((NLMISC::CVector*)ptr);
01173 }
01174 
01175 // --------------------------------------------------
01176 
01177 NLMISC::CVector* CVertexBufferReadWrite::getNormalCoordPointer(uint idx)
01178 {
01179     nlassert (_Parent->checkLockedBuffer());
01180     uint8*  ptr;
01181 
01182     if ( !(_Parent->_Flags & CVertexBuffer::NormalFlag) )
01183     {
01184         return(NULL);
01185     }
01186     ptr=_Parent->_LockedBuffer;
01187     ptr+=_Parent->_Offset[CVertexBuffer::Normal];
01188     ptr+=idx*_Parent->_VertexSize;
01189     return((NLMISC::CVector*)ptr);
01190 }
01191 
01192 // --------------------------------------------------
01193 
01194 void* CVertexBufferReadWrite::getColorPointer(uint idx)
01195 {
01196     nlassert (_Parent->checkLockedBuffer());
01197     uint8*  ptr;
01198 
01199     if ( !(_Parent->_Flags & CVertexBuffer::PrimaryColorFlag) )
01200     {
01201         return(NULL);
01202     }
01203     ptr=_Parent->_LockedBuffer;
01204     ptr+=_Parent->_Offset[CVertexBuffer::PrimaryColor];
01205     ptr+=idx*_Parent->_VertexSize;
01206     return((void*)ptr);
01207 }
01208 
01209 // --------------------------------------------------
01210 
01211 void* CVertexBufferReadWrite::getSpecularPointer(uint idx)
01212 {
01213     nlassert (_Parent->checkLockedBuffer());
01214     uint8*  ptr;
01215 
01216     if ( !(_Parent->_Flags & CVertexBuffer::SecondaryColorFlag) )
01217     {
01218         return(NULL);
01219     }
01220     ptr=_Parent->_LockedBuffer;
01221     ptr+=_Parent->_Offset[CVertexBuffer::SecondaryColor];
01222     ptr+=idx*_Parent->_VertexSize;
01223     return((void*)ptr);
01224 }
01225 
01226 // --------------------------------------------------
01227 
01228 NLMISC::CUV* CVertexBufferReadWrite::getTexCoordPointer(uint idx, uint8 stage)
01229 {
01230     nlassert (_Parent->checkLockedBuffer());
01231     uint8*  ptr;
01232 
01233     if ( !(_Parent->_Flags & (CVertexBuffer::TexCoord0Flag<<stage)) )
01234     {
01235         return(NULL);
01236     }
01237     ptr=_Parent->_LockedBuffer;
01238     ptr+=_Parent->_Offset[CVertexBuffer::TexCoord0+stage];
01239     ptr+=idx*_Parent->_VertexSize;
01240     return((NLMISC::CUV*)ptr);
01241 }
01242 
01243 // --------------------------------------------------
01244 
01245 float* CVertexBufferReadWrite::getWeightPointer(uint idx, uint8 wgt)
01246 {
01247     nlassert (_Parent->checkLockedBuffer());
01248     uint8*  ptr;
01249 
01250     nlassert(wgt<CVertexBuffer::MaxWeight);
01251     if( !(_Parent->_Flags & CVertexBuffer::WeightFlag))
01252         return NULL;
01253 
01254     ptr=(uint8*)(&_Parent->_LockedBuffer[idx*_Parent->_VertexSize]);
01255     ptr+=_Parent->_Offset[CVertexBuffer::Weight]+wgt*sizeof(float);
01256 
01257     return (float*)ptr;
01258 }
01259 
01260 // --------------------------------------------------
01261 
01262 CPaletteSkin* CVertexBufferReadWrite::getPaletteSkinPointer(uint idx)
01263 {
01264     nlassert (_Parent->checkLockedBuffer());
01265     uint8*  ptr;
01266 
01267     if ( (_Parent->_Flags & CVertexBuffer::PaletteSkinFlag) != CVertexBuffer::PaletteSkinFlag )
01268     {
01269         return(NULL);
01270     }
01271     ptr=_Parent->_LockedBuffer;
01272     ptr+=_Parent->_Offset[CVertexBuffer::PaletteSkin];
01273     ptr+=idx*_Parent->_VertexSize;
01274     return((CPaletteSkin*)ptr);
01275 }
01276 
01277 // --------------------------------------------------
01278 
01279 void CVertexBufferReadWrite::touchVertices (uint first, uint last)
01280 {
01281     nlassert (_Parent->checkLockedBuffer());
01282     _First = first;
01283     _Last = last;
01284 }
01285 
01286 // --------------------------------------------------
01287 // CVertexBufferRead
01288 // --------------------------------------------------
01289 
01290 const NLMISC::CVector* CVertexBufferRead::getVertexCoordPointer(uint idx) const
01291 {
01292     nlassert (_Parent->checkLockedBuffer());
01293     const uint8*    ptr;
01294 
01295     ptr=_Parent->_LockedBuffer;
01296     ptr+=(idx*_Parent->_VertexSize);
01297     return((const NLMISC::CVector*)ptr);
01298 }
01299 
01300 // --------------------------------------------------
01301 
01302 const NLMISC::CVector* CVertexBufferRead::getNormalCoordPointer(uint idx) const
01303 {
01304     nlassert (_Parent->checkLockedBuffer());
01305     const uint8*    ptr;
01306 
01307     if ( !(_Parent->_Flags & CVertexBuffer::NormalFlag) )
01308     {
01309         return(NULL);
01310     }
01311     ptr=_Parent->_LockedBuffer;
01312     ptr+=_Parent->_Offset[CVertexBuffer::Normal];
01313     ptr+=idx*_Parent->_VertexSize;
01314     return((const NLMISC::CVector*)ptr);
01315 }
01316 
01317 // --------------------------------------------------
01318 
01319 const void* CVertexBufferRead::getColorPointer(uint idx) const
01320 {
01321     nlassert (_Parent->checkLockedBuffer());
01322     const uint8*    ptr;
01323 
01324     if ( !(_Parent->_Flags & CVertexBuffer::PrimaryColorFlag) )
01325     {
01326         return(NULL);
01327     }
01328     ptr=_Parent->_LockedBuffer;
01329     ptr+=_Parent->_Offset[CVertexBuffer::PrimaryColor];
01330     ptr+=idx*_Parent->_VertexSize;
01331     return((const void*)ptr);
01332 }
01333 
01334 // --------------------------------------------------
01335 
01336 const void* CVertexBufferRead::getSpecularPointer(uint idx) const
01337 {
01338     nlassert (_Parent->checkLockedBuffer());
01339     const uint8*    ptr;
01340 
01341     if ( !(_Parent->_Flags & CVertexBuffer::SecondaryColorFlag) )
01342     {
01343         return(NULL);
01344     }
01345     ptr=_Parent->_LockedBuffer;
01346     ptr+=_Parent->_Offset[CVertexBuffer::SecondaryColor];
01347     ptr+=idx*_Parent->_VertexSize;
01348     return((const void*)ptr);
01349 }
01350 
01351 // --------------------------------------------------
01352 
01353 const NLMISC::CUV* CVertexBufferRead::getTexCoordPointer(uint idx, uint8 stage) const
01354 {
01355     nlassert (_Parent->checkLockedBuffer());
01356     const uint8*    ptr;
01357 
01358     if ( !(_Parent->_Flags & (CVertexBuffer::TexCoord0Flag<<stage)) )
01359     {
01360         return(NULL);
01361     }
01362     ptr=_Parent->_LockedBuffer;
01363     ptr+=_Parent->_Offset[CVertexBuffer::TexCoord0+stage];
01364     ptr+=idx*_Parent->_VertexSize;
01365     return((const NLMISC::CUV*)ptr);
01366 }
01367 
01368 // --------------------------------------------------
01369 
01370 const float* CVertexBufferRead::getWeightPointer(uint idx, uint8 wgt) const
01371 {
01372     nlassert (_Parent->checkLockedBuffer());
01373     const uint8*    ptr;
01374 
01375     nlassert(wgt<CVertexBuffer::MaxWeight);
01376     if( !(_Parent->_Flags & CVertexBuffer::WeightFlag))
01377         return NULL;
01378 
01379     ptr=(uint8*)(&_Parent->_LockedBuffer[idx*_Parent->_VertexSize]);
01380     ptr+=_Parent->_Offset[CVertexBuffer::Weight]+wgt*sizeof(float);
01381 
01382     return (float*)ptr;
01383 }
01384 
01385 // --------------------------------------------------
01386 
01387 const CPaletteSkin* CVertexBufferRead::getPaletteSkinPointer(uint idx) const
01388 {
01389     nlassert (_Parent->checkLockedBuffer());
01390     const uint8*    ptr;
01391 
01392     if ( (_Parent->_Flags & CVertexBuffer::PaletteSkinFlag) != CVertexBuffer::PaletteSkinFlag )
01393     {
01394         return(NULL);
01395     }
01396     ptr=_Parent->_LockedBuffer;
01397     ptr+=_Parent->_Offset[CVertexBuffer::PaletteSkin];
01398     ptr+=idx*_Parent->_VertexSize;
01399     return((const CPaletteSkin*)ptr);
01400 }
01401 
01402 // --------------------------------------------------
01403 
01404 }
01405 
01406 
01407 
01408 
01409 
01410 
01411 
01412 
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421 
01422 
01423 
01424 
01425 

Generated on Thu Jan 7 08:26:32 2010 for NeL by  doxygen 1.6.1