00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/vertex_buffer.h"
00029 #include "nel/misc/vector.h"
00030 #include "3d/driver.h"
00031 using namespace NLMISC;
00032
00033
00034 namespace NL3D
00035 {
00036
00037
00038
00039 const uint CVertexBuffer::SizeType[NumType]=
00040 {
00041 1*sizeof(double),
00042 1*sizeof(float),
00043 1*sizeof(short),
00044 2*sizeof(double),
00045 2*sizeof(float),
00046 2*sizeof(short),
00047 3*sizeof(double),
00048 3*sizeof(float),
00049 3*sizeof(short),
00050 4*sizeof(double),
00051 4*sizeof(float),
00052 4*sizeof(short),
00053 4*sizeof(char),
00054 };
00055
00056
00057
00058 const CVertexBuffer::TType CVertexBuffer::DefaultValueType[NumValue]=
00059 {
00060 Float3,
00061 Float3,
00062 Float2,
00063 Float2,
00064 Float2,
00065 Float2,
00066 Float2,
00067 Float2,
00068 Float2,
00069 Float2,
00070 UChar4,
00071 UChar4,
00072 Float4,
00073 UChar4,
00074 Float1,
00075 Float1,
00076 };
00077
00078
00079
00080 CVertexBuffer::CVertexBuffer()
00081 {
00082 _Flags = 0;
00083 _Capacity = 0;
00084 _NbVerts = 0;
00085 _InternalFlags = 0;
00086 _VertexSize = 0;
00087 }
00088
00089
00090
00091 CVertexBuffer::CVertexBuffer(const CVertexBuffer &vb)
00092 {
00093 _Flags = 0;
00094 _Capacity = 0;
00095 _NbVerts = 0;
00096 _VertexSize = 0;
00097 operator=(vb);
00098 }
00099
00100
00101
00102 CVertexBuffer::~CVertexBuffer()
00103 {
00104
00105 DrvInfos.kill();
00106 }
00107
00108
00109
00110 CVertexBuffer &CVertexBuffer::operator=(const CVertexBuffer &vb)
00111 {
00112
00113 _VertexSize = vb._VertexSize;
00114 _Flags = vb._Flags;
00115 _InternalFlags = vb._InternalFlags;
00116 _NbVerts = vb._NbVerts;
00117 _Capacity = vb._Capacity;
00118 _Verts = vb._Verts;
00119
00120
00121 for (uint value=0; value<NumValue; value++)
00122 {
00123 _Offset[value]= vb._Offset[value];
00124 _Type[value]= vb._Type[value];
00125 }
00126
00127
00128 _InternalFlags |= TouchedAll;
00129
00130 return *this;
00131 }
00132
00133
00134
00135 bool CVertexBuffer::setVertexFormat(uint32 flags)
00136 {
00137 uint i;
00138
00139
00140 clearValueEx ();
00141
00142
00143 if (flags & PositionFlag)
00144 {
00145
00146 addValueEx (Position, Float3);
00147 }
00148
00149
00150 if (flags & NormalFlag)
00151 {
00152
00153 addValueEx (Normal, Float3);
00154 }
00155
00156
00157 for(i=0 ; i<MaxStage ; i++)
00158 {
00159
00160 if (flags & (TexCoord0Flag<<i))
00161 {
00162
00163 addValueEx ((TValue)(TexCoord0+i), Float2);
00164 }
00165 }
00166
00167
00168 if (flags & FogFlag)
00169 {
00170
00171 addValueEx (Fog, Float1);
00172 }
00173
00174
00175 if (flags & PrimaryColorFlag)
00176 {
00177
00178 addValueEx (PrimaryColor, UChar4);
00179 }
00180
00181
00182 if (flags & SecondaryColorFlag)
00183 {
00184
00185 addValueEx (SecondaryColor, UChar4);
00186 }
00187
00188
00189 if (flags & WeightFlag)
00190 {
00191
00192 addValueEx (Weight, Float4);
00193 }
00194
00195
00196 if ((flags & PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag)
00197 {
00198
00199 addValueEx (PaletteSkin, UChar4);
00200 }
00201
00202
00203 initEx ();
00204
00205 return (true);
00206 }
00207
00208
00209
00210 CVertexBuffer::TValue CVertexBuffer::getValueIdByNumberEx (uint valueNumber)
00211 {
00212
00213 static TValue lut[16]= {
00214 Position,
00215 Weight,
00216 Normal,
00217 PrimaryColor,
00218 SecondaryColor,
00219 Fog,
00220 PaletteSkin,
00221 Empty,
00222 TexCoord0,
00223 TexCoord1,
00224 TexCoord2,
00225 TexCoord3,
00226 TexCoord4,
00227 TexCoord5,
00228 TexCoord6,
00229 TexCoord7,
00230 };
00231
00232 return lut[valueNumber];
00233 }
00234
00235
00236
00237 void CVertexBuffer::clearValueEx ()
00238 {
00239
00240 _Flags=0;
00241 }
00242
00243
00244
00245 void CVertexBuffer::addValueEx (TValue valueId, TType type)
00246 {
00247
00248 _Flags |= 1<<valueId;
00249
00250
00251 _Type[valueId]=(uint8)type;
00252 }
00253
00254
00255
00256 bool CVertexBuffer::hasValueEx(TValue valueId) const
00257 {
00258 return (_Flags & (1 << valueId)) != 0;
00259 }
00260
00261
00262
00263 void CVertexBuffer::initEx ()
00264 {
00265
00266 _InternalFlags=TouchedAll;
00267
00268
00269 _VertexSize=0;
00270 for (uint value=0; value<NumValue; value++)
00271 {
00272
00273 if (_Flags&(1<<value))
00274 {
00275
00276 _Offset[value]=_VertexSize;
00277
00278
00279 _VertexSize+=SizeType[_Type[value]];
00280 }
00281 }
00282
00283
00284 _NbVerts=0;
00285
00286
00287 if (_VertexSize)
00288 _Capacity = _Verts.size()/_VertexSize;
00289 else
00290 _Capacity = 0;
00291 }
00292
00293
00294
00295 void CVertexBuffer::reserve(uint32 n)
00296 {
00297 _Verts.resize(n*_VertexSize);
00298 _Capacity= n;
00299 }
00300
00301
00302
00303 void CVertexBuffer::setNumVertices(uint32 n)
00304 {
00305 if(_Capacity<n)
00306 {
00307 reserve(n);
00308 }
00309 if(_NbVerts != n)
00310 {
00311 _InternalFlags |= TouchedNumVertices;
00312 _NbVerts=n;
00313 }
00314 }
00315
00316
00317
00318 void CVertexBuffer::deleteAllVertices()
00319 {
00320
00321 contReset(_Verts);
00322 _Capacity= 0;
00323 if(_NbVerts!=0)
00324 {
00325 _NbVerts=0;
00326 _InternalFlags |= TouchedNumVertices;
00327 }
00328 }
00329
00330
00331
00332 void* CVertexBuffer::getVertexCoordPointer(uint idx)
00333 {
00334 uint8* ptr;
00335
00336 ptr=&(*_Verts.begin());
00337 ptr+=(idx*_VertexSize);
00338 return((void*)ptr);
00339 }
00340
00341
00342
00343 void* CVertexBuffer::getNormalCoordPointer(uint idx)
00344 {
00345 uint8* ptr;
00346
00347 if ( !(_Flags & NormalFlag) )
00348 {
00349 return(NULL);
00350 }
00351 ptr=&(*_Verts.begin());
00352 ptr+=_Offset[Normal];
00353 ptr+=idx*_VertexSize;
00354 return((void*)ptr);
00355 }
00356
00357
00358
00359 void* CVertexBuffer::getColorPointer(uint idx)
00360 {
00361 uint8* ptr;
00362
00363 if ( !(_Flags & PrimaryColorFlag) )
00364 {
00365 return(NULL);
00366 }
00367 ptr=&(*_Verts.begin());
00368 ptr+=_Offset[PrimaryColor];
00369 ptr+=idx*_VertexSize;
00370 return((void*)ptr);
00371 }
00372
00373
00374
00375 void* CVertexBuffer::getSpecularPointer(uint idx)
00376 {
00377 uint8* ptr;
00378
00379 if ( !(_Flags & SecondaryColorFlag) )
00380 {
00381 return(NULL);
00382 }
00383 ptr=&(*_Verts.begin());
00384 ptr+=_Offset[SecondaryColor];
00385 ptr+=idx*_VertexSize;
00386 return((void*)ptr);
00387 }
00388
00389
00390
00391 void* CVertexBuffer::getTexCoordPointer(uint idx, uint8 stage)
00392 {
00393 uint8* ptr;
00394
00395 if ( !(_Flags & (TexCoord0Flag<<stage)) )
00396 {
00397 return(NULL);
00398 }
00399 ptr=&(*_Verts.begin());
00400 ptr+=_Offset[TexCoord0+stage];
00401 ptr+=idx*_VertexSize;
00402 return((void*)ptr);
00403 }
00404
00405
00406
00407 void* CVertexBuffer::getWeightPointer(uint idx, uint8 wgt)
00408 {
00409 uint8* ptr;
00410
00411 nlassert(wgt<MaxWeight);
00412 if( !(_Flags & WeightFlag))
00413 return NULL;
00414
00415 ptr=(uint8*)(&_Verts[idx*_VertexSize]);
00416 ptr+=_Offset[Weight]+wgt*sizeof(float);
00417
00418 return ptr;
00419 }
00420
00421
00422
00423 void* CVertexBuffer::getPaletteSkinPointer(uint idx)
00424 {
00425 uint8* ptr;
00426
00427 if ( (_Flags & PaletteSkinFlag) != CVertexBuffer::PaletteSkinFlag )
00428 {
00429 return(NULL);
00430 }
00431 ptr=&(*_Verts.begin());
00432 ptr+=_Offset[PaletteSkin];
00433 ptr+=idx*_VertexSize;
00434 return((void*)ptr);
00435 }
00436
00437
00438
00439
00441
00443
00444
00445
00446
00447 const void* CVertexBuffer::getVertexCoordPointer(uint idx) const
00448 {
00449 const uint8* ptr;
00450
00451 ptr=&(*_Verts.begin());
00452 ptr+=(idx*_VertexSize);
00453 return((void*)ptr);
00454 }
00455
00456
00457
00458 const void* CVertexBuffer::getNormalCoordPointer(uint idx) const
00459 {
00460 const uint8* ptr;
00461
00462 if ( !(_Flags & NormalFlag) )
00463 {
00464 return(NULL);
00465 }
00466 ptr=&(*_Verts.begin());
00467 ptr+=_Offset[Normal];
00468 ptr+=idx*_VertexSize;
00469 return((void*)ptr);
00470 }
00471
00472
00473
00474 const void* CVertexBuffer::getColorPointer(uint idx) const
00475 {
00476 const uint8* ptr;
00477
00478 if ( !(_Flags & PrimaryColorFlag) )
00479 {
00480 return(NULL);
00481 }
00482 ptr=&(*_Verts.begin());
00483 ptr+=_Offset[PrimaryColor];
00484 ptr+=idx*_VertexSize;
00485 return((void*)ptr);
00486 }
00487
00488
00489
00490 const void* CVertexBuffer::getSpecularPointer(uint idx) const
00491 {
00492 const uint8* ptr;
00493
00494 if ( !(_Flags & SecondaryColorFlag) )
00495 {
00496 return(NULL);
00497 }
00498 ptr=&(*_Verts.begin());
00499 ptr+=_Offset[SecondaryColor];
00500 ptr+=idx*_VertexSize;
00501 return((void*)ptr);
00502 }
00503
00504
00505
00506 const void* CVertexBuffer::getTexCoordPointer(uint idx, uint8 stage) const
00507 {
00508 const uint8* ptr;
00509
00510 if ( !(_Flags & (TexCoord0Flag<<stage)) )
00511 {
00512 return(NULL);
00513 }
00514 ptr=&(*_Verts.begin());
00515 ptr+=_Offset[TexCoord0+stage];
00516 ptr+=idx*_VertexSize;
00517 return((void*)ptr);
00518 }
00519
00520
00521
00522 const void* CVertexBuffer::getWeightPointer(uint idx, uint8 wgt) const
00523 {
00524 const uint8* ptr;
00525
00526 nlassert(wgt<MaxWeight);
00527 if( !(_Flags & WeightFlag))
00528 return NULL;
00529
00530 ptr=(uint8*)(&_Verts[idx*_VertexSize]);
00531 ptr+=_Offset[Weight]+wgt*sizeof(float);
00532
00533 return ptr;
00534 }
00535
00536
00537
00538 const void* CVertexBuffer::getPaletteSkinPointer(uint idx) const
00539 {
00540 const uint8* ptr;
00541
00542 if ( (_Flags & PaletteSkinFlag) != CVertexBuffer::PaletteSkinFlag )
00543 {
00544 return(NULL);
00545 }
00546 ptr=&(*_Verts.begin());
00547 ptr+=_Offset[PaletteSkin];
00548 ptr+=idx*_VertexSize;
00549 return((void*)ptr);
00550 }
00551
00552
00553
00554 uint16 CVertexBuffer::remapV2Flags (uint32 oldFlags, uint& weightCount)
00555 {
00556
00557 const uint32 OLD_IDRV_VF_XYZ = 0x00000001;
00558 const uint32 OLD_IDRV_VF_W0 = 0x00000002;
00559 const uint32 OLD_IDRV_VF_W1 = 0x00000004;
00560 const uint32 OLD_IDRV_VF_W2 = 0x00000008;
00561 const uint32 OLD_IDRV_VF_W3 = 0x00000010;
00562 const uint32 OLD_IDRV_VF_NORMAL = 0x00000020;
00563 const uint32 OLD_IDRV_VF_COLOR = 0x00000040;
00564 const uint32 OLD_IDRV_VF_SPECULAR = 0x00000080;
00565 const uint32 OLD_IDRV_VF_UV0 = 0x00000100;
00566 const uint32 OLD_IDRV_VF_UV1 = 0x00000200;
00567 const uint32 OLD_IDRV_VF_UV2 = 0x00000400;
00568 const uint32 OLD_IDRV_VF_UV3 = 0x00000800;
00569 const uint32 OLD_IDRV_VF_UV4 = 0x00001000;
00570 const uint32 OLD_IDRV_VF_UV5 = 0x00002000;
00571 const uint32 OLD_IDRV_VF_UV6 = 0x00004000;
00572 const uint32 OLD_IDRV_VF_UV7 = 0x00008000;
00573 const uint32 OLD_IDRV_VF_PALETTE_SKIN = 0x00010000 | OLD_IDRV_VF_W0 | OLD_IDRV_VF_W1 | OLD_IDRV_VF_W2 | OLD_IDRV_VF_W3;
00574
00575
00576 uint16 newFlags=0;
00577
00578
00579 weightCount=0;
00580
00581
00582 if (oldFlags&OLD_IDRV_VF_XYZ)
00583 newFlags|=PositionFlag;
00584 if (oldFlags&OLD_IDRV_VF_NORMAL)
00585 newFlags|=NormalFlag;
00586 if (oldFlags&OLD_IDRV_VF_COLOR)
00587 newFlags|=PrimaryColorFlag;
00588 if (oldFlags&OLD_IDRV_VF_SPECULAR)
00589 newFlags|=SecondaryColorFlag;
00590 if (oldFlags&OLD_IDRV_VF_UV0)
00591 newFlags|=TexCoord0Flag;
00592 if (oldFlags&OLD_IDRV_VF_UV1)
00593 newFlags|=TexCoord1Flag;
00594 if (oldFlags&OLD_IDRV_VF_UV2)
00595 newFlags|=TexCoord2Flag;
00596 if (oldFlags&OLD_IDRV_VF_UV3)
00597 newFlags|=TexCoord3Flag;
00598 if (oldFlags&OLD_IDRV_VF_UV4)
00599 newFlags|=TexCoord4Flag;
00600 if (oldFlags&OLD_IDRV_VF_UV5)
00601 newFlags|=TexCoord5Flag;
00602 if (oldFlags&OLD_IDRV_VF_UV6)
00603 newFlags|=TexCoord6Flag;
00604 if (oldFlags&OLD_IDRV_VF_UV7)
00605 newFlags|=TexCoord7Flag;
00606 if (oldFlags&OLD_IDRV_VF_W0)
00607 {
00608 weightCount=1;
00609 newFlags|=WeightFlag;
00610 }
00611 if (oldFlags&OLD_IDRV_VF_W1)
00612 {
00613 weightCount=2;
00614 newFlags|=WeightFlag;
00615 }
00616 if (oldFlags&OLD_IDRV_VF_W2)
00617 {
00618 weightCount=3;
00619 newFlags|=WeightFlag;
00620 }
00621 if (oldFlags&OLD_IDRV_VF_W3)
00622 {
00623 weightCount=4;
00624 newFlags|=WeightFlag;
00625 }
00626 if (oldFlags&(OLD_IDRV_VF_PALETTE_SKIN))
00627 newFlags|=PaletteSkinFlag;
00628
00629
00630 return newFlags;
00631 }
00632
00633
00634
00635 void CVertexBuffer::serialOldV1Minus(NLMISC::IStream &f, sint ver)
00636 {
00637
00638
00639
00640
00641
00642
00643
00644
00645 uint32 oldFlags;
00646
00647
00648
00649 f.serial(oldFlags);
00650
00651
00652 uint weightCount;
00653 uint16 newFlags=remapV2Flags (oldFlags, weightCount);
00654
00655
00656 nlassert (f.isReading());
00657
00658
00659 uint i;
00660 for (i=0; i<NumValue; i++)
00661 _Type[i]=DefaultValueType[i];
00662
00663 uint32 nbVert;
00664 f.serial(nbVert);
00665 reserve(0);
00666 setVertexFormat(newFlags);
00667 setNumVertices(nbVert);
00668
00669
00670
00671 switch (weightCount)
00672 {
00673 case 1:
00674 _Type[Weight]=Float1;
00675 break;
00676 case 2:
00677 _Type[Weight]=Float2;
00678 break;
00679 case 3:
00680 _Type[Weight]=Float3;
00681 break;
00682 case 4:
00683 _Type[Weight]=Float4;
00684 break;
00685 }
00686
00687
00688
00689 for(sint id=0;id<(sint)_NbVerts;id++)
00690 {
00691
00692 if(_Flags & PositionFlag)
00693 {
00694 CVector &vert= *(CVector*)getVertexCoordPointer(id);
00695 f.serial(vert);
00696 }
00697
00698 if(_Flags & NormalFlag)
00699 {
00700 CVector &norm= *(CVector*)getNormalCoordPointer(id);
00701 f.serial(norm);
00702 }
00703
00704 for(i=0;i<MaxStage;i++)
00705 {
00706 if(_Flags & (TexCoord0Flag<<i))
00707 {
00708 CUV &uv= *(CUV*)getTexCoordPointer(id, i);
00709 f.serial(uv);
00710 }
00711 }
00712
00713 if(_Flags & PrimaryColorFlag)
00714 {
00715 CRGBA &col= *(CRGBA*)getColorPointer(id);
00716 f.serial(col);
00717 }
00718
00719 if(_Flags & SecondaryColorFlag)
00720 {
00721 CRGBA &col= *(CRGBA*)getSpecularPointer(id);
00722 f.serial(col);
00723 }
00724
00725 for(i=0;i<weightCount;i++)
00726 {
00727
00728 float &w= *(float*)getWeightPointer(id, i);
00729 f.serial(w);
00730 }
00731
00732 if((ver>=1) && ((_Flags & PaletteSkinFlag) == CVertexBuffer::PaletteSkinFlag) )
00733 {
00734 CPaletteSkin &ps= *(CPaletteSkin*)getPaletteSkinPointer(id);
00735 f.serial(ps);
00736 }
00737
00738 }
00739
00740
00741 _InternalFlags = 0;
00742 if(f.isReading())
00743 _InternalFlags |= TouchedAll;
00744 }
00745
00746
00747
00748 void CVertexBuffer::serial(NLMISC::IStream &f)
00749 {
00750
00751
00752
00753
00754
00755
00756
00757
00758 sint ver= f.serialVersion(2);
00759
00760 if (ver<2)
00761 {
00762
00763 serialOldV1Minus(f, ver);
00764 }
00765 else
00766 {
00767
00768 serialHeader(f);
00769
00770
00771 serialSubset(f, 0, _NbVerts);
00772 }
00773 }
00774
00775
00776
00777 void CVertexBuffer::serialHeader(NLMISC::IStream &f)
00778 {
00779
00780
00781
00782
00783
00784
00785 sint ver= f.serialVersion(1);
00786
00787
00788
00789
00790
00791 uint16 flags=_Flags;
00792
00793 if (ver<1)
00794 {
00795
00796 nlassert (f.isReading());
00797
00798
00799 uint32 oldFlags;
00800 f.serial(oldFlags);
00801
00802
00803 uint weightCount;
00804 flags=remapV2Flags (oldFlags, weightCount);
00805
00806
00807 for (uint i=0; i<NumValue; i++)
00808 _Type[i]=DefaultValueType[i];
00809
00810
00811 switch (weightCount)
00812 {
00813 case 1:
00814 _Type[Weight]=Float1;
00815 break;
00816 case 2:
00817 _Type[Weight]=Float2;
00818 break;
00819 case 3:
00820 _Type[Weight]=Float3;
00821 break;
00822 case 4:
00823 _Type[Weight]=Float4;
00824 break;
00825 }
00826 }
00827 else
00828 {
00829
00830 f.serial(flags);
00831
00832
00833 for (uint i=0; i<NumValue; i++)
00834 f.serial (_Type[i]);
00835 }
00836
00837
00838 uint32 nbVerts=_NbVerts;
00839 f.serial(nbVerts);
00840
00841 if(f.isReading())
00842 {
00843 reserve(0);
00844
00845
00846 clearValueEx ();
00847
00848
00849 for (uint i=0; i<NumValue; i++)
00850 {
00851
00852 if (flags&(1<<i))
00853 {
00854
00855 addValueEx ((TValue)i, (TType)_Type[i]);
00856 }
00857 }
00858
00859
00860 initEx ();
00861
00862
00863 setNumVertices(nbVerts);
00864 }
00865
00866 }
00867
00868
00869
00870 uint CVertexBuffer:: getNumTexCoordUsed() const
00871 {
00872 for (sint k = (MaxStage - 1); k >= 0; --k)
00873 {
00874 if (_Flags & (TexCoord0Flag << k)) return (uint) (k + 1);
00875 }
00876 return 0;
00877 }
00878
00879
00880
00881 uint8 CVertexBuffer::getNumWeight () const
00882 {
00883
00884 switch (_Type[Weight])
00885 {
00886 case Float1:
00887 return 1;
00888 case Float2:
00889 return 2;
00890 case Float3:
00891 return 3;
00892 case Float4:
00893 return 4;
00894 }
00895
00896
00897 return 0;
00898 }
00899
00900
00901
00902 void CVertexBuffer::serialSubset(NLMISC::IStream &f, uint vertexStart, uint vertexEnd)
00903 {
00904
00905
00906
00907
00908
00909
00910 sint ver= f.serialVersion(1);
00911
00912
00913
00914
00915 nlassert(vertexStart<_NbVerts || _NbVerts==0);
00916 nlassert(vertexEnd<=_NbVerts);
00917 for(uint id=vertexStart; id<vertexEnd; id++)
00918 {
00919
00920 for (uint value=0; value<NumValue; value++)
00921 {
00922
00923 if (_Flags&(1<<value))
00924 {
00925
00926 void *ptr=getValueEx ((TValue)value, id);
00927 f.serialBuffer ((uint8*)ptr, SizeType[_Type[value]]);
00928 }
00929 }
00930 }
00931
00932
00933 if(f.isReading())
00934 _InternalFlags |= TouchedAll;
00935 }
00936
00937
00938
00939
00940 void CPaletteSkin::serial(NLMISC::IStream &f)
00941 {
00942 f.serial(MatrixId[0], MatrixId[1], MatrixId[2], MatrixId[3]);
00943 }
00944
00945
00946
00947 IVBDrvInfos::~IVBDrvInfos()
00948 {
00949 _Driver->removeVBDrvInfoPtr(_DriverIterator);
00950 }
00951
00952
00953
00954 }