Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / vertex_buffer.cpp
blobbdc9d495ffc8125abd81209f305d2b2af645ee5c
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/vertex_buffer.h"
20 #include "nel/misc/vector.h"
21 #include "nel/misc/fast_mem.h"
22 #include "nel/3d/driver.h"
24 using namespace NLMISC;
26 #ifdef DEBUG_NEW
27 #define new DEBUG_NEW
28 #endif
30 namespace NL3D
33 // --------------------------------------------------
35 const uint CVertexBuffer::SizeType[NumType]=
37 1*sizeof(double),
38 1*sizeof(float),
39 1*sizeof(short),
40 2*sizeof(double),
41 2*sizeof(float),
42 2*sizeof(short),
43 3*sizeof(double),
44 3*sizeof(float),
45 3*sizeof(short),
46 4*sizeof(double),
47 4*sizeof(float),
48 4*sizeof(short),
49 4*sizeof(char),
53 const uint CVertexBuffer::NumComponentsType[NumType] =
71 // --------------------------------------------------
73 const CVertexBuffer::TType CVertexBuffer::DefaultValueType[NumValue]=
75 Float3, // Position
76 Float3, // Normal
77 Float2, // TexCoord0
78 Float2, // TexCoord1
79 Float2, // TexCoord2
80 Float2, // TexCoord3
81 Float2, // TexCoord4
82 Float2, // TexCoord5
83 Float2, // TexCoord6
84 Float2, // TexCoord7
85 UChar4, // Primary color
86 UChar4, // Secondary color
87 Float4, // 4 Weights
88 UChar4, // PaletteSkin
89 Float1, // Fog
90 Float1, // Empty
94 // --------------------------------------------------
96 void CVertexBuffer::construct()
98 /* ***********************************************
99 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
100 * It can be loaded/called through CAsyncFileManager for instance
101 * ***********************************************/
102 _Flags = 0;
103 _Capacity = 0;
104 _NbVerts = 0;
105 _InternalFlags = 0;
106 _VertexSize = 0;
107 _VertexColorFormat = TRGBA;
108 _LockCounter = 0;
109 _LockedBuffer = NULL;
110 _PreferredMemory = RAMPreferred;
111 _Location = NotResident;
112 _ResidentSize = 0;
113 _KeepLocalMemory = false;
115 // Default routing
116 uint i;
117 for (i=0; i<MaxStage; i++)
118 _UVRouting[i] = i;
121 // --------------------------------------------------
123 CVertexBuffer::CVertexBuffer()
125 construct();
128 CVertexBuffer::CVertexBuffer(const char *name)
130 construct();
131 _Name = name;
135 // --------------------------------------------------
137 CVertexBuffer::CVertexBuffer(const CVertexBuffer &vb) : CRefCount()
139 /* ***********************************************
140 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
141 * It can be loaded/called through CAsyncFileManager for instance
142 * ***********************************************/
144 _Flags = 0;
145 _Capacity = 0;
146 _NbVerts = 0;
147 _VertexSize = 0;
148 _LockCounter = 0;
149 _LockedBuffer = NULL;
150 _PreferredMemory = RAMPreferred;
151 _Location = NotResident;
152 _ResidentSize = 0;
153 _KeepLocalMemory = false;
155 operator=(vb);
157 // Default routing
158 uint i;
159 for (i=0; i<MaxStage; i++)
160 _UVRouting[i] = i;
163 // --------------------------------------------------
165 CVertexBuffer::~CVertexBuffer()
167 /* ***********************************************
168 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
169 * It can be loaded/called through CAsyncFileManager for instance
170 * ***********************************************/
172 if (DrvInfos)
173 DrvInfos->VertexBufferPtr = NULL; // Tell the driver info to not restore memory when it will die
175 // Must kill the drv mirror of this VB.
176 DrvInfos.kill();
179 // --------------------------------------------------
181 CVertexBuffer &CVertexBuffer::operator=(const CVertexBuffer &vb)
183 nlassertex (!isLocked(), ("The vertex buffer is locked."));
184 nlassertex (!vb.isLocked(), ("Source buffer is locked."));
186 // Single value
187 _VertexSize = vb._VertexSize;
188 _Flags = vb._Flags;
189 _InternalFlags = vb._InternalFlags;
190 _NbVerts = vb._NbVerts;
191 _Capacity = vb._Capacity;
192 _NonResidentVertices = vb._NonResidentVertices;
193 _VertexColorFormat = vb._VertexColorFormat;
194 _PreferredMemory = vb._PreferredMemory;
195 _KeepLocalMemory = vb._KeepLocalMemory;
196 uint i;
197 _LockCounter = 0;
198 _LockedBuffer = NULL;
200 // Arraies
201 for (uint value=0; value<NumValue; value++)
203 _Offset[value]= vb._Offset[value];
204 _Type[value]= vb._Type[value];
207 // Copy the routing
208 for (i=0; i<MaxStage; i++)
209 _UVRouting[i] = vb._UVRouting[i];
211 // Set touch flags
212 _InternalFlags |= TouchedAll;
213 _Location = NotResident;
214 _ResidentSize = 0;
216 return *this;
219 // --------------------------------------------------
220 void CVertexBuffer::copyVertices(CVertexBuffer &dest) const
222 nlassert(_PreferredMemory != RAMVolatile);
223 nlassert(_PreferredMemory != AGPVolatile);
224 // copy setup
225 dest = *this;
226 CVertexBufferReadWrite srcDatas;
227 const_cast<CVertexBuffer *>(this)->lock(srcDatas);
228 nlassert(dest.getLocation() == NotResident);
229 CVertexBufferReadWrite destDatas;
230 dest.lock(destDatas); // will be in vram
231 NLMISC::CFastMem::memcpy (destDatas.getVertexCoordPointer(), srcDatas.getVertexCoordPointer(), getVertexSize() * getNumVertices());
234 // --------------------------------------------------
236 bool CVertexBuffer::setVertexFormat(uint32 flags)
238 nlassertex (!isLocked(), ("The vertex buffer is locked."));
240 uint i;
242 // Clear extended values
243 clearValueEx ();
245 // Position ?
246 if (flags & PositionFlag)
248 // Add a standard position value
249 addValueEx (Position, Float3);
252 // Normal ?
253 if (flags & NormalFlag)
255 // Add a standard normal value
256 addValueEx (Normal, Float3);
259 // For each uv values
260 for(i=0 ; i<MaxStage ; i++)
262 // UV ?
263 if (flags & (TexCoord0Flag<<i))
265 // Add a standard uv value
266 addValueEx ((TValue)(TexCoord0+i), Float2);
270 // Fog ?
271 if (flags & FogFlag)
273 // Add a standard primary color value
274 addValueEx (Fog, Float1);
277 // Primary color ?
278 if (flags & PrimaryColorFlag)
280 // Add a standard primary color value
281 addValueEx (PrimaryColor, UChar4);
284 // Secondary color ?
285 if (flags & SecondaryColorFlag)
287 // Add a standard primary color value
288 addValueEx (SecondaryColor, UChar4);
291 // Weight ?
292 if (flags & WeightFlag)
294 // Add a standard primary color value
295 addValueEx (Weight, Float4);
298 // Palette skin ?
299 if ((flags & PaletteSkinFlag)==CVertexBuffer::PaletteSkinFlag)
301 // Add a standard primary color value
302 addValueEx (PaletteSkin, UChar4);
305 // Compute the vertex buffer
306 initEx ();
308 // Force non resident
309 restoreNonResidentMemory();
311 return (true);
314 // --------------------------------------------------
316 CVertexBuffer::TValue CVertexBuffer::getValueIdByNumberEx (uint valueNumber)
318 // See NV_vertex_program spec, or driver_opengl_vertex.cpp:: GLVertexAttribIndex.
319 static TValue lut[16]= {
320 Position,
321 Weight,
322 Normal,
323 PrimaryColor,
324 SecondaryColor,
325 Fog,
326 PaletteSkin,
327 Empty,
328 TexCoord0,
329 TexCoord1,
330 TexCoord2,
331 TexCoord3,
332 TexCoord4,
333 TexCoord5,
334 TexCoord6,
335 TexCoord7,
338 return lut[valueNumber];
341 // --------------------------------------------------
343 void CVertexBuffer::clearValueEx ()
345 nlassertex (!isLocked(), ("The vertex buffer is locked."));
347 // Reset format flags
348 _Flags=0;
352 // --------------------------------------------------
354 void CVertexBuffer::dumpFormat() const
356 for(uint k = 0; k < NumValue; ++k)
358 if (_Flags & (1 << k))
360 std::string result = "Component :";
361 switch(k)
363 case Position: result += "Position"; break;
364 case Normal: result += "Normal"; break;
365 case TexCoord0: result += "TexCoord0"; break;
366 case TexCoord1: result += "TexCoord1"; break;
367 case TexCoord2: result += "TexCoord2"; break;
368 case TexCoord3: result += "TexCoord3"; break;
369 case TexCoord4: result += "TexCoord4"; break;
370 case TexCoord5: result += "TexCoord5"; break;
371 case TexCoord6: result += "TexCoord6"; break;
372 case TexCoord7: result += "TexCoord7"; break;
373 case PrimaryColor: result += "PrimaryColor"; break;
374 case SecondaryColor:result += "SecondaryColor"; break;
375 case Weight: result += "Weight"; break;
376 case PaletteSkin: result += "PaletteSkin"; break;
377 case Fog: result += "Fog"; break;
378 case Empty: result += "Empty"; break;
379 case NumValue: result += "NumValue"; break;
380 default:
381 result += "???";
382 break;
384 result += "; type :";
385 switch(_Type[k])
387 case Double1: result +="Double1"; break;
388 case Float1: result +="Float1"; break;
389 case Short1: result +="Short1"; break;
390 case Double2: result +="Double2"; break;
391 case Float2: result +="Float2"; break;
392 case Short2: result +="Short2"; break;
393 case Double3: result +="Double3"; break;
394 case Float3: result +="Float3"; break;
395 case Short3: result +="Short3"; break;
396 case Double4: result +="Double4"; break;
397 case Float4: result +="Float4"; break;
398 case Short4: result +="Short4"; break;
399 case UChar4: result +="UChar4"; break;
400 default:
401 result += "???";
402 break;
404 nlinfo(result.c_str());
410 // --------------------------------------------------
412 void CVertexBuffer::addValueEx (TValue valueId, TType type)
414 nlassertex (!isLocked(), ("The vertex buffer is locked."));
416 // Reset format flags
417 _Flags |= 1<<valueId;
419 // Set the type
420 _Type[valueId]=(uint8)type;
422 uint numComp = NumComponentsType[type];
423 // unfortunately, some vertex program implementations don't allow any type for any value
424 switch (valueId)
426 case Position: nlassert(numComp >= 2); break;
427 case Normal: nlassert(numComp == 3); break;
428 case PrimaryColor: nlassert(numComp == 4); break;
429 case SecondaryColor: nlassert(numComp == 4); break;
430 case Weight: nlassert(numComp == 4); break;
431 case PaletteSkin: nlassert(numComp == 4); break;
432 case Fog: nlassert(numComp == 4); break;
433 default: break;
437 // --------------------------------------------------
439 bool CVertexBuffer::hasValueEx(TValue valueId) const
441 return (_Flags & (1 << valueId)) != 0;
444 // --------------------------------------------------
446 void CVertexBuffer::initEx ()
448 nlassert (!isLocked());
450 // Calc vertex size and set value's offset
451 _VertexSize=0;
452 for (uint value=0; value<NumValue; value++)
454 // Value used ?
455 if (_Flags&(1<<value))
457 // Set offset
458 _Offset[value]=_VertexSize;
460 // New size
461 _VertexSize+=SizeType[_Type[value]];
465 // Reset number of vertices
466 _NbVerts=0;
468 // Compute new capacity
469 if (_VertexSize)
470 _Capacity = (uint32)_NonResidentVertices.size()/_VertexSize;
471 else
472 _Capacity = 0;
474 // Force non resident
475 restoreNonResidentMemory();
478 // --------------------------------------------------
480 void CVertexBuffer::reserve(uint32 n)
482 nlassert (!isLocked());
483 if (_Capacity != n)
485 _Capacity= n;
486 _NbVerts=std::min (_NbVerts,_Capacity);
488 // Force non resident
489 restoreNonResidentMemory();
493 // --------------------------------------------------
495 void CVertexBuffer::setNumVertices(uint32 n)
497 if(_Capacity<n)
499 reserve(n);
501 if(_NbVerts != n)
503 _InternalFlags |= TouchedNumVertices;
504 _NbVerts=n;
508 // --------------------------------------------------
510 void CVertexBuffer::deleteAllVertices()
512 if (_Capacity)
514 nlassert (!isLocked());
515 // free memory.
516 contReset(_NonResidentVertices);
517 _Capacity= 0;
518 if(_NbVerts!=0)
520 _NbVerts=0;
521 _InternalFlags |= TouchedNumVertices;
524 // Force non resident
525 restoreNonResidentMemory();
527 // Delete driver info
528 nlassert (DrvInfos == NULL);
532 // --------------------------------------------------
534 uint16 CVertexBuffer::remapV2Flags (uint32 oldFlags, uint& weightCount)
536 // Old flags
537 const uint32 OLD_IDRV_VF_XYZ = 0x00000001;
538 const uint32 OLD_IDRV_VF_W0 = 0x00000002;
539 const uint32 OLD_IDRV_VF_W1 = 0x00000004;
540 const uint32 OLD_IDRV_VF_W2 = 0x00000008;
541 const uint32 OLD_IDRV_VF_W3 = 0x00000010;
542 const uint32 OLD_IDRV_VF_NORMAL = 0x00000020;
543 const uint32 OLD_IDRV_VF_COLOR = 0x00000040;
544 const uint32 OLD_IDRV_VF_SPECULAR = 0x00000080;
545 const uint32 OLD_IDRV_VF_UV0 = 0x00000100;
546 const uint32 OLD_IDRV_VF_UV1 = 0x00000200;
547 const uint32 OLD_IDRV_VF_UV2 = 0x00000400;
548 const uint32 OLD_IDRV_VF_UV3 = 0x00000800;
549 const uint32 OLD_IDRV_VF_UV4 = 0x00001000;
550 const uint32 OLD_IDRV_VF_UV5 = 0x00002000;
551 const uint32 OLD_IDRV_VF_UV6 = 0x00004000;
552 const uint32 OLD_IDRV_VF_UV7 = 0x00008000;
553 const uint32 OLD_IDRV_VF_PALETTE_SKIN = 0x00010000 | OLD_IDRV_VF_W0 | OLD_IDRV_VF_W1 | OLD_IDRV_VF_W2 | OLD_IDRV_VF_W3;
555 // Old Flags
556 uint16 newFlags=0;
558 // Number of weight values
559 weightCount=0;
561 // Remap the flags
562 if (oldFlags&OLD_IDRV_VF_XYZ)
563 newFlags|=PositionFlag;
564 if (oldFlags&OLD_IDRV_VF_NORMAL)
565 newFlags|=NormalFlag;
566 if (oldFlags&OLD_IDRV_VF_COLOR)
567 newFlags|=PrimaryColorFlag;
568 if (oldFlags&OLD_IDRV_VF_SPECULAR)
569 newFlags|=SecondaryColorFlag;
570 if (oldFlags&OLD_IDRV_VF_UV0)
571 newFlags|=TexCoord0Flag;
572 if (oldFlags&OLD_IDRV_VF_UV1)
573 newFlags|=TexCoord1Flag;
574 if (oldFlags&OLD_IDRV_VF_UV2)
575 newFlags|=TexCoord2Flag;
576 if (oldFlags&OLD_IDRV_VF_UV3)
577 newFlags|=TexCoord3Flag;
578 if (oldFlags&OLD_IDRV_VF_UV4)
579 newFlags|=TexCoord4Flag;
580 if (oldFlags&OLD_IDRV_VF_UV5)
581 newFlags|=TexCoord5Flag;
582 if (oldFlags&OLD_IDRV_VF_UV6)
583 newFlags|=TexCoord6Flag;
584 if (oldFlags&OLD_IDRV_VF_UV7)
585 newFlags|=TexCoord7Flag;
586 if (oldFlags&OLD_IDRV_VF_W0)
588 weightCount=1;
589 newFlags|=WeightFlag;
591 if (oldFlags&OLD_IDRV_VF_W1)
593 weightCount=2;
594 newFlags|=WeightFlag;
596 if (oldFlags&OLD_IDRV_VF_W2)
598 weightCount=3;
599 newFlags|=WeightFlag;
601 if (oldFlags&OLD_IDRV_VF_W3)
603 weightCount=4;
604 newFlags|=WeightFlag;
606 if (oldFlags&(OLD_IDRV_VF_PALETTE_SKIN))
607 newFlags|=PaletteSkinFlag;
609 // Return the new flags
610 return newFlags;
613 // --------------------------------------------------
615 void CVertexBuffer::serialOldV1Minus(NLMISC::IStream &f, sint ver)
617 /* ***********************************************
618 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
619 * It can be loaded/called through CAsyncFileManager for instance
620 * ***********************************************/
623 Version 1:
624 - PaletteSkin version.
625 Version 0:
626 - base verison.
629 // old Flags
630 uint32 oldFlags;
632 // Serial VBuffers format/size.
633 //=============================
634 f.serial(oldFlags);
636 // Remap the flags
637 uint weightCount;
638 uint16 newFlags=remapV2Flags (oldFlags, weightCount);
640 // Must be reading
641 nlassert (f.isReading());
643 // Set default value type
644 uint i;
645 for (i=0; i<NumValue; i++)
646 _Type[i]=DefaultValueType[i];
648 uint32 nbVert; // Read only
649 f.serial(nbVert);
650 reserve(0);
651 setVertexFormat(newFlags);
652 setNumVertices(nbVert);
653 // All other infos (but _NonResidentVertices) are computed by setVertexFormat() and setNumVertices().
655 // Weight count ?
656 switch (weightCount)
658 case 1:
659 _Type[Weight]=Float1;
660 break;
661 case 2:
662 _Type[Weight]=Float2;
663 break;
664 case 3:
665 _Type[Weight]=Float3;
666 break;
667 case 4:
668 _Type[Weight]=Float4;
669 break;
672 // Serial VBuffers components.
673 //============================
674 for(sint id=0;id<(sint)_NbVerts;id++)
676 uint8 *pointer = &(*_NonResidentVertices.begin());
677 uint stridedId = id * _VertexSize;
678 // XYZ.
679 if(_Flags & PositionFlag)
681 CVector &vert= *(CVector*)(pointer + stridedId + _Offset[Position]);
682 f.serial(vert);
684 // Normal
685 if(_Flags & NormalFlag)
687 CVector &norm= *(CVector*)(pointer + stridedId + _Offset[Normal]);
688 f.serial(norm);
690 // Uvs.
691 for(i=0;i<MaxStage;i++)
693 if(_Flags & (TexCoord0Flag<<i))
695 CUV &uv= *(CUV*)(pointer + stridedId + _Offset[TexCoord0+i]);
696 f.serial(uv);
699 // Color.
700 if(_Flags & PrimaryColorFlag)
702 CRGBA &col= *(CRGBA*)(pointer + stridedId + _Offset[PrimaryColor]);
703 f.serial(col);
705 // Specular.
706 if(_Flags & SecondaryColorFlag)
708 CRGBA &col= *(CRGBA*)(pointer + stridedId + _Offset[SecondaryColor]);
709 f.serial(col);
711 // Weights
712 for(i=0;i<weightCount;i++)
714 // Weight channel available ?
715 float &w= *(float*)(pointer + stridedId + _Offset[Weight] + i*sizeof(float));
716 f.serial(w);
718 // CPaletteSkin (version 1+ only).
719 if((ver>=1) && ((_Flags & PaletteSkinFlag) == CVertexBuffer::PaletteSkinFlag) )
721 CPaletteSkin &ps= *(CPaletteSkin*)(pointer + stridedId + _Offset[PaletteSkin]);
722 f.serial(ps);
727 // Set touch flags
728 _InternalFlags = 0;
729 if(f.isReading())
731 // Force non resident
732 restoreNonResidentMemory();
736 // --------------------------------------------------
738 void CVertexBuffer::serial(NLMISC::IStream &f)
740 /* ***********************************************
741 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
742 * It can be loaded/called through CAsyncFileManager for instance
743 * ***********************************************/
746 Version 2:
747 - cut to use serialHeader() serialSubset().
748 Version 1:
749 - PaletteSkin version.
750 Version 0:
751 - base verison.
753 nlassert (!isLocked());
754 sint ver= f.serialVersion(2);
756 if (ver<2)
758 // old serial method
759 serialOldV1Minus(f, ver);
761 else
763 // read write the header of the VBuffer.
764 serialHeader(f);
766 // read write the entire subset.
767 serialSubset(f, 0, _NbVerts);
771 // --------------------------------------------------
773 void CVertexBuffer::serialHeader(NLMISC::IStream &f)
775 /* ***********************************************
776 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
777 * It can be loaded/called through CAsyncFileManager for instance
778 * ***********************************************/
781 Version 3:
782 - Preferred memory.
783 Version 2:
784 - Vertex color format management.
785 Version 1:
786 - Extended vertex format management.
787 Version 0:
788 - base verison of the header serialisation.
790 sint ver= f.serialVersion(3); // Hulud
792 // Serial VBuffers format/size.
793 //=============================
795 // Flags
796 uint16 flags=_Flags;
798 if (ver<1)
800 // Must be reading
801 nlassert (f.isReading());
803 // Serial old flags
804 uint32 oldFlags;
805 f.serial(oldFlags);
807 // Remap flags
808 uint weightCount;
809 flags=remapV2Flags (oldFlags, weightCount);
811 // Set default value type
812 for (uint i=0; i<NumValue; i++)
813 _Type[i]=DefaultValueType[i];
815 // weight count ?
816 switch (weightCount)
818 case 1:
819 _Type[Weight]=Float1;
820 break;
821 case 2:
822 _Type[Weight]=Float2;
823 break;
824 case 3:
825 _Type[Weight]=Float3;
826 break;
827 case 4:
828 _Type[Weight]=Float4;
829 break;
832 else
834 // Serial new vertex flags
835 f.serial(flags);
837 // Serial type of values
838 for (uint i=0; i<NumValue; i++)
840 if (!(flags & (1 << i)))
842 _Type[i] = DefaultValueType[i];
844 f.serial (_Type[i]);
848 // Serial nb vertices
849 uint32 nbVerts=_NbVerts;
850 f.serial(nbVerts);
852 if(f.isReading())
854 reserve(0);
856 // Init vertex format setup
857 clearValueEx ();
859 // Init vertex format
860 for (uint i=0; i<NumValue; i++)
862 // Setup this value ?
863 if (flags&(1<<i))
865 // Add a value
866 addValueEx ((TValue)i, (TType)_Type[i]);
870 // Build final vertex format
871 initEx ();
873 // Set num of vertices
874 setNumVertices(nbVerts);
876 // All other infos (but _NonResidentVertices) are computed by initEx() and setNumVertices().
878 if (ver>=2)
879 f.serial (_VertexColorFormat);
881 if (ver>=3)
883 f.serialEnum(_PreferredMemory);
884 f.serial(_Name);
886 else
888 // Init preferred memory
889 if(f.isReading())
891 _PreferredMemory = RAMPreferred;
892 _Name.clear();
898 // --------------------------------------------------
899 uint CVertexBuffer:: getNumTexCoordUsed() const
901 for (sint k = (MaxStage - 1); k >= 0; --k)
903 if (_Flags & (TexCoord0Flag << k)) return (uint) (k + 1);
905 return 0;
908 // --------------------------------------------------
910 uint8 CVertexBuffer::getNumWeight () const
912 // Num weight
913 switch (_Type[Weight])
915 case Float1:
916 return 1;
917 case Float2:
918 return 2;
919 case Float3:
920 return 3;
921 case Float4:
922 return 4;
925 // No weight
926 return 0;
929 // --------------------------------------------------
931 void CVertexBuffer::serialSubset(NLMISC::IStream &f, uint vertexStart, uint vertexEnd)
933 /* ***********************************************
934 * WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
935 * It can be loaded/called through CAsyncFileManager for instance
936 * ***********************************************/
939 Version 2:
940 - UVRouting
941 Version 1:
942 - weight is 4 float in standard format.
943 Version 0:
944 - base verison of a vbuffer subset serialisation.
946 sint ver = f.serialVersion(2);
949 // Serial VBuffers components.
950 //============================
951 nlassert(vertexStart<_NbVerts || _NbVerts==0);
952 nlassert(vertexEnd<=_NbVerts);
953 for(uint id=vertexStart; id<vertexEnd; id++)
955 // For each value
956 for (uint value=0; value<NumValue; value++)
958 // Value used ?
959 if (_Flags&(1<<value))
961 // Get the pointer on it
962 void *ptr=(void*)((&(*_NonResidentVertices.begin()))+id*_VertexSize+getValueOffEx ((TValue)value));
963 f.serialBuffer ((uint8*)ptr, SizeType[_Type[value]]);
968 // Serial the UV Routing table
969 //============================
970 if (ver>=2)
972 f.serialBuffer (_UVRouting, sizeof(uint8)*MaxStage);
974 else
976 // Reset the table
977 uint i;
978 for (i=0; i<MaxStage; i++)
979 _UVRouting[i] = i;
982 // Set touch flags
983 if(f.isReading())
985 // Force non resident
986 restoreNonResidentMemory();
990 // --------------------------------------------------
992 bool CVertexBuffer::setVertexColorFormat (TVertexColorType format)
994 // If resident, quit
995 if (isResident())
996 return false;
998 nlassert (!isLocked());
1000 // Format is not good ?
1001 if ((TVertexColorType)_VertexColorFormat != format)
1003 // Diffuse or specualr component ?
1004 if (_Flags & (PrimaryColorFlag|SecondaryColorFlag))
1006 uint i;
1007 uint32 *ptr0 = (_Flags&PrimaryColorFlag)?(uint32*)&(_NonResidentVertices[_Offset[PrimaryColor]]):NULL;
1008 uint32 *ptr1 = (_Flags&SecondaryColorFlag)?(uint32*)&(_NonResidentVertices[_Offset[SecondaryColor]]):NULL;
1009 for (i=0; i<_NbVerts; i++)
1011 if (ptr0)
1013 const register uint32 value = *ptr0;
1014 #ifdef NL_LITTLE_ENDIAN
1015 *ptr0 = (value&0xff00ff00)|((value&0xff)<<16)|((value&0xff0000)>>16);
1016 #else // NL_LITTLE_ENDIAN
1017 *ptr0 = (value&0x00ff00ff)|((value&0xff00)<<16)|((value&0xff000000)>>16);
1018 #endif // NL_LITTLE_ENDIAN
1019 ptr0 = (uint32*)(((uint8*)ptr0)+_VertexSize);
1021 if (ptr1)
1023 const register uint32 value = *ptr1;
1024 #ifdef NL_LITTLE_ENDIAN
1025 *ptr1 = (value&0xff00ff00)|((value&0xff)<<16)|((value&0xff0000)>>16);
1026 #else // NL_LITTLE_ENDIAN
1027 *ptr1 = (value&0x00ff00ff)|((value&0xff00)<<16)|((value&0xff000000)>>16);
1028 #endif // NL_LITTLE_ENDIAN
1029 ptr1 = (uint32*)(((uint8*)ptr1)+_VertexSize);
1033 _VertexColorFormat = (uint8)format;
1035 // Force non resident
1036 restoreNonResidentMemory();
1038 return true;
1041 // --------------------------------------------------
1043 void CVertexBuffer::setPreferredMemory (TPreferredMemory preferredMemory, bool keepLocalMemory)
1045 if ((_PreferredMemory != preferredMemory) || (_KeepLocalMemory != keepLocalMemory))
1047 _PreferredMemory = preferredMemory;
1048 _KeepLocalMemory = keepLocalMemory;
1050 // Force non resident
1051 restoreNonResidentMemory();
1055 // --------------------------------------------------
1056 void CVertexBuffer::setLocation (TLocation newLocation)
1058 // Upload ?
1059 if (newLocation != NotResident)
1061 // The driver must have setuped the driver info
1062 nlassert (DrvInfos);
1064 // Current size of the buffer
1065 const uint size = ((_PreferredMemory==RAMVolatile)||(_PreferredMemory==AGPVolatile))?_NbVerts*_VertexSize:_Capacity*_VertexSize;
1067 // The buffer must not be resident
1068 if (_Location != NotResident)
1069 setLocation (NotResident);
1071 // Copy the buffer containt
1072 uint8 *dest = DrvInfos->lock (0, size, false);
1073 nlassert (size<=_NonResidentVertices.size()); // Internal buffer must have the good size
1074 memcpy (dest, &(_NonResidentVertices[0]), size);
1075 DrvInfos->unlock(0, 0);
1077 // Reset the non resident container if not a static preferred memory and not put in RAM
1078 if ((_PreferredMemory != StaticPreferred) && (_Location != RAMResident) && !_KeepLocalMemory)
1079 contReset(_NonResidentVertices);
1081 // Clear touched flags
1082 resetTouchFlags ();
1084 _Location = newLocation;
1085 _ResidentSize = size;
1087 else
1089 // Current size of the buffer
1090 const uint size = _Capacity*_VertexSize;
1092 // Resize the non resident buffer
1093 _NonResidentVertices.resize (size);
1095 // If resident in RAM, backup the data in non resident memory
1096 if ((_Location == RAMResident) && (_PreferredMemory != RAMVolatile) && (_PreferredMemory != AGPVolatile) && !_KeepLocalMemory)
1098 // The driver must have setuped the driver info
1099 nlassert (DrvInfos);
1101 // Copy the old buffer data
1102 const uint8 *src = DrvInfos->lock (0, _ResidentSize, true);
1103 if (!_NonResidentVertices.empty())
1104 memcpy (&(_NonResidentVertices[0]), src, std::min (size, (uint)_ResidentSize));
1105 DrvInfos->unlock(0, 0);
1108 _Location = NotResident;
1109 _ResidentSize = 0;
1111 // Touch the buffer
1112 _InternalFlags |= TouchedAll;
1116 // --------------------------------------------------
1117 void CVertexBuffer::restoreNonResidentMemory()
1119 setLocation (NotResident);
1121 if (DrvInfos)
1122 DrvInfos->VertexBufferPtr = NULL; // Tell the driver info to not restore memory when it will die
1124 // Must kill the drv mirror of this VB.
1125 DrvInfos.kill();
1128 // --------------------------------------------------
1130 void CVertexBuffer::fillBuffer ()
1132 if (DrvInfos && _KeepLocalMemory)
1134 // Copy the local memory in local memory
1135 const uint size = _NbVerts*_VertexSize;
1136 nlassert (size<=_NonResidentVertices.size());
1137 uint8 *dest = DrvInfos->lock (0, size, false);
1138 NLMISC::CFastMem::memcpy (dest, &(_NonResidentVertices[0]), size);
1139 DrvInfos->unlock(0, size);
1143 // --------------------------------------------------
1145 // CPaletteSkin serial (no version chek).
1146 void CPaletteSkin::serial(NLMISC::IStream &f)
1148 f.serial(MatrixId[0], MatrixId[1], MatrixId[2], MatrixId[3]);
1151 // --------------------------------------------------
1153 IVBDrvInfos::~IVBDrvInfos()
1155 _Driver->removeVBDrvInfoPtr(_DriverIterator);
1158 // --------------------------------------------------
1159 // CVertexBufferReadWrite
1160 // --------------------------------------------------
1162 NLMISC::CVector* CVertexBufferReadWrite::getVertexCoordPointer(uint idx)
1164 nlassert (_Parent->checkLockedBuffer());
1165 uint8* ptr;
1167 ptr=_Parent->_LockedBuffer;
1168 ptr+=(idx*_Parent->_VertexSize);
1169 return((NLMISC::CVector*)ptr);
1172 // --------------------------------------------------
1174 NLMISC::CVector* CVertexBufferReadWrite::getNormalCoordPointer(uint idx)
1176 nlassert (_Parent->checkLockedBuffer());
1177 uint8* ptr;
1179 if ( !(_Parent->_Flags & CVertexBuffer::NormalFlag) )
1181 return(NULL);
1183 ptr=_Parent->_LockedBuffer;
1184 ptr+=_Parent->_Offset[CVertexBuffer::Normal];
1185 ptr+=idx*_Parent->_VertexSize;
1186 return((NLMISC::CVector*)ptr);
1189 // --------------------------------------------------
1191 void* CVertexBufferReadWrite::getColorPointer(uint idx)
1193 nlassert (_Parent->checkLockedBuffer());
1194 uint8* ptr;
1196 if ( !(_Parent->_Flags & CVertexBuffer::PrimaryColorFlag) )
1198 return(NULL);
1200 ptr=_Parent->_LockedBuffer;
1201 ptr+=_Parent->_Offset[CVertexBuffer::PrimaryColor];
1202 ptr+=idx*_Parent->_VertexSize;
1203 return((void*)ptr);
1206 // --------------------------------------------------
1208 void* CVertexBufferReadWrite::getSpecularPointer(uint idx)
1210 nlassert (_Parent->checkLockedBuffer());
1211 uint8* ptr;
1213 if ( !(_Parent->_Flags & CVertexBuffer::SecondaryColorFlag) )
1215 return(NULL);
1217 ptr=_Parent->_LockedBuffer;
1218 ptr+=_Parent->_Offset[CVertexBuffer::SecondaryColor];
1219 ptr+=idx*_Parent->_VertexSize;
1220 return((void*)ptr);
1223 // --------------------------------------------------
1225 NLMISC::CUV* CVertexBufferReadWrite::getTexCoordPointer(uint idx, uint8 stage)
1227 nlassert (_Parent->checkLockedBuffer());
1228 uint8* ptr;
1230 if ( !(_Parent->_Flags & (CVertexBuffer::TexCoord0Flag<<stage)) )
1232 return(NULL);
1234 ptr=_Parent->_LockedBuffer;
1235 ptr+=_Parent->_Offset[CVertexBuffer::TexCoord0+stage];
1236 ptr+=idx*_Parent->_VertexSize;
1237 return((NLMISC::CUV*)ptr);
1240 // --------------------------------------------------
1242 float* CVertexBufferReadWrite::getWeightPointer(uint idx, uint8 wgt)
1244 nlassert (_Parent->checkLockedBuffer());
1245 uint8* ptr;
1247 nlassert(wgt<CVertexBuffer::MaxWeight);
1248 if( !(_Parent->_Flags & CVertexBuffer::WeightFlag))
1249 return NULL;
1251 ptr=(uint8*)(&_Parent->_LockedBuffer[idx*_Parent->_VertexSize]);
1252 ptr+=_Parent->_Offset[CVertexBuffer::Weight]+wgt*sizeof(float);
1254 return (float*)ptr;
1257 // --------------------------------------------------
1259 CPaletteSkin* CVertexBufferReadWrite::getPaletteSkinPointer(uint idx)
1261 nlassert (_Parent->checkLockedBuffer());
1262 uint8* ptr;
1264 if ( (_Parent->_Flags & CVertexBuffer::PaletteSkinFlag) != CVertexBuffer::PaletteSkinFlag )
1266 return(NULL);
1268 ptr=_Parent->_LockedBuffer;
1269 ptr+=_Parent->_Offset[CVertexBuffer::PaletteSkin];
1270 ptr+=idx*_Parent->_VertexSize;
1271 return((CPaletteSkin*)ptr);
1274 // --------------------------------------------------
1276 void CVertexBufferReadWrite::touchVertices (uint first, uint last)
1278 nlassert (_Parent->checkLockedBuffer());
1279 _First = first;
1280 _Last = last;
1283 // --------------------------------------------------
1284 // CVertexBufferRead
1285 // --------------------------------------------------
1287 const NLMISC::CVector* CVertexBufferRead::getVertexCoordPointer(uint idx) const
1289 nlassert (_Parent->checkLockedBuffer());
1290 const uint8* ptr;
1292 ptr=_Parent->_LockedBuffer;
1293 ptr+=(idx*_Parent->_VertexSize);
1294 return((const NLMISC::CVector*)ptr);
1297 // --------------------------------------------------
1299 const NLMISC::CVector* CVertexBufferRead::getNormalCoordPointer(uint idx) const
1301 nlassert (_Parent->checkLockedBuffer());
1302 const uint8* ptr;
1304 if ( !(_Parent->_Flags & CVertexBuffer::NormalFlag) )
1306 return(NULL);
1308 ptr=_Parent->_LockedBuffer;
1309 ptr+=_Parent->_Offset[CVertexBuffer::Normal];
1310 ptr+=idx*_Parent->_VertexSize;
1311 return((const NLMISC::CVector*)ptr);
1314 // --------------------------------------------------
1316 const void* CVertexBufferRead::getColorPointer(uint idx) const
1318 nlassert (_Parent->checkLockedBuffer());
1319 const uint8* ptr;
1321 if ( !(_Parent->_Flags & CVertexBuffer::PrimaryColorFlag) )
1323 return(NULL);
1325 ptr=_Parent->_LockedBuffer;
1326 ptr+=_Parent->_Offset[CVertexBuffer::PrimaryColor];
1327 ptr+=idx*_Parent->_VertexSize;
1328 return((const void*)ptr);
1331 // --------------------------------------------------
1333 const void* CVertexBufferRead::getSpecularPointer(uint idx) const
1335 nlassert (_Parent->checkLockedBuffer());
1336 const uint8* ptr;
1338 if ( !(_Parent->_Flags & CVertexBuffer::SecondaryColorFlag) )
1340 return(NULL);
1342 ptr=_Parent->_LockedBuffer;
1343 ptr+=_Parent->_Offset[CVertexBuffer::SecondaryColor];
1344 ptr+=idx*_Parent->_VertexSize;
1345 return((const void*)ptr);
1348 // --------------------------------------------------
1350 const NLMISC::CUV* CVertexBufferRead::getTexCoordPointer(uint idx, uint8 stage) const
1352 nlassert (_Parent->checkLockedBuffer());
1353 const uint8* ptr;
1355 if ( !(_Parent->_Flags & (CVertexBuffer::TexCoord0Flag<<stage)) )
1357 return(NULL);
1359 ptr=_Parent->_LockedBuffer;
1360 ptr+=_Parent->_Offset[CVertexBuffer::TexCoord0+stage];
1361 ptr+=idx*_Parent->_VertexSize;
1362 return((const NLMISC::CUV*)ptr);
1365 // --------------------------------------------------
1367 const float* CVertexBufferRead::getWeightPointer(uint idx, uint8 wgt) const
1369 nlassert (_Parent->checkLockedBuffer());
1370 const uint8* ptr;
1372 nlassert(wgt<CVertexBuffer::MaxWeight);
1373 if( !(_Parent->_Flags & CVertexBuffer::WeightFlag))
1374 return NULL;
1376 ptr=(uint8*)(&_Parent->_LockedBuffer[idx*_Parent->_VertexSize]);
1377 ptr+=_Parent->_Offset[CVertexBuffer::Weight]+wgt*sizeof(float);
1379 return (float*)ptr;
1382 // --------------------------------------------------
1384 const CPaletteSkin* CVertexBufferRead::getPaletteSkinPointer(uint idx) const
1386 nlassert (_Parent->checkLockedBuffer());
1387 const uint8* ptr;
1389 if ( (_Parent->_Flags & CVertexBuffer::PaletteSkinFlag) != CVertexBuffer::PaletteSkinFlag )
1391 return(NULL);
1393 ptr=_Parent->_LockedBuffer;
1394 ptr+=_Parent->_Offset[CVertexBuffer::PaletteSkin];
1395 ptr+=idx*_Parent->_VertexSize;
1396 return((const CPaletteSkin*)ptr);
1399 // --------------------------------------------------