00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/misc/common.h"
00027 #include "nel/3d/lod_character_manager.h"
00028 #include "nel/3d/lod_character_shape.h"
00029 #include "nel/3d/lod_character_shape_bank.h"
00030 #include "nel/3d/lod_character_instance.h"
00031 #include "nel/misc/hierarchical_timer.h"
00032 #include "nel/misc/fast_floor.h"
00033 #include "nel/3d/lod_character_texture.h"
00034 #include "nel/3d/ray_mesh.h"
00035 #include "nel/misc/file.h"
00036 #include "nel/misc/algo.h"
00037 #include "nel/misc/fast_mem.h"
00038 #include "nel/misc/system_info.h"
00039
00040
00041 using namespace std;
00042 using namespace NLMISC;
00043
00044 namespace NL3D
00045 {
00046
00047
00048
00049
00050 #define NL3D_CLOD_VERTEX_FORMAT (CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::PrimaryColorFlag)
00051 #define NL3D_CLOD_VERTEX_SIZE 24
00052 #define NL3D_CLOD_UV_OFF 12
00053 #define NL3D_CLOD_COLOR_OFF 20
00054
00055
00056 #define NL3D_CLOD_TEXT_NLOD_WIDTH 16
00057 #define NL3D_CLOD_TEXT_NLOD_HEIGHT 16
00058 #define NL3D_CLOD_TEXT_NUM_IDS NL3D_CLOD_TEXT_NLOD_WIDTH*NL3D_CLOD_TEXT_NLOD_HEIGHT
00059 #define NL3D_CLOD_BIGTEXT_WIDTH NL3D_CLOD_TEXT_NLOD_WIDTH*NL3D_CLOD_TEXT_WIDTH
00060 #define NL3D_CLOD_BIGTEXT_HEIGHT NL3D_CLOD_TEXT_NLOD_HEIGHT*NL3D_CLOD_TEXT_HEIGHT
00061
00062
00063 #define NL3D_CLOD_DEFAULT_TEXCOLOR CRGBA(255,255,255,255)
00064
00065
00066
00067 CLodCharacterManager::CLodCharacterManager()
00068 {
00069 _MaxNumVertices= 3000;
00070 _NumVBHard= 8;
00071 _Rendering= false;
00072 _LockDone= false;
00073
00074
00075 _BigTexture= new CTextureBlank;
00076
00077
00078 _BigTexture->setReleasable(false);
00079
00080 _BigTexture->resize(NL3D_CLOD_BIGTEXT_WIDTH, NL3D_CLOD_BIGTEXT_HEIGHT, CBitmap::RGBA);
00081
00082 _BigTexture->setUploadFormat(ITexture::RGB565);
00083 _BigTexture->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
00084 _BigTexture->setWrapS(ITexture::Clamp);
00085 _BigTexture->setWrapT(ITexture::Clamp);
00086
00087
00088 _FreeIds.resize(NL3D_CLOD_TEXT_NUM_IDS);
00089 for(uint i=0;i<_FreeIds.size();i++)
00090 {
00091 _FreeIds[i]= i;
00092 }
00093
00094
00095 _Material.initUnlit();
00096 _Material.setAlphaTest(true);
00097 _Material.setDoubleSided(true);
00098 _Material.setTexture(0, _BigTexture);
00099
00100
00101 _LightCorrectionMatrix.rotateZ((float)Pi/2);
00102 _LightCorrectionMatrix.invert();
00103 NL_SET_IB_NAME(_Triangles, "CLodCharacterManager::_Triangles");
00104 }
00105
00106
00107
00108 CLodCharacterManager::~CLodCharacterManager()
00109 {
00110 reset();
00111 }
00112
00113
00114 void CLodCharacterManager::reset()
00115 {
00116 nlassert(!isRendering());
00117
00118
00119 for(uint i=0;i<_ShapeBankArray.size();i++)
00120 {
00121 if(_ShapeBankArray[i])
00122 delete _ShapeBankArray[i];
00123 }
00124
00125
00126 contReset(_ShapeBankArray);
00127 contReset(_ShapeMap);
00128
00129
00130 _VertexStream.release();
00131 }
00132
00133
00134 uint32 CLodCharacterManager::createShapeBank()
00135 {
00136
00137 for(uint i=0;i<_ShapeBankArray.size();i++)
00138 {
00139
00140 if(_ShapeBankArray[i]==NULL)
00141 {
00142 _ShapeBankArray[i]= new CLodCharacterShapeBank;
00143 return i;
00144 }
00145 }
00146
00147
00148 _ShapeBankArray.push_back(new CLodCharacterShapeBank);
00149 return _ShapeBankArray.size()-1;
00150 }
00151
00152
00153 const CLodCharacterShapeBank *CLodCharacterManager::getShapeBank(uint32 bankId) const
00154 {
00155 if(bankId>=_ShapeBankArray.size())
00156 return NULL;
00157 else
00158 return _ShapeBankArray[bankId];
00159 }
00160
00161
00162 CLodCharacterShapeBank *CLodCharacterManager::getShapeBank(uint32 bankId)
00163 {
00164 if(bankId>=_ShapeBankArray.size())
00165 return NULL;
00166 else
00167 return _ShapeBankArray[bankId];
00168 }
00169
00170
00171 void CLodCharacterManager::deleteShapeBank(uint32 bankId)
00172 {
00173 if(bankId>=_ShapeBankArray.size())
00174 {
00175 if(_ShapeBankArray[bankId])
00176 {
00177 delete _ShapeBankArray[bankId];
00178 _ShapeBankArray[bankId]= NULL;
00179 }
00180 }
00181 }
00182
00183
00184 sint32 CLodCharacterManager::getShapeIdByName(const std::string &name) const
00185 {
00186 CstItStrIdMap it= _ShapeMap.find(name);
00187 if(it==_ShapeMap.end())
00188 return -1;
00189 else
00190 return it->second;
00191 }
00192
00193
00194 const CLodCharacterShape *CLodCharacterManager::getShape(uint32 shapeId) const
00195 {
00196
00197 uint bankId= shapeId >> 16;
00198 uint shapeInBankId= shapeId &0xFFFF;
00199
00200
00201 const CLodCharacterShapeBank *shapeBank= getShapeBank(bankId);
00202 if(shapeBank)
00203 {
00204
00205 return shapeBank->getShape(shapeInBankId);
00206 }
00207 else
00208 return NULL;
00209 }
00210
00211
00212 bool CLodCharacterManager::compile()
00213 {
00214 bool error= false;
00215
00216
00217 contReset(_ShapeMap);
00218
00219
00220 for(uint i=0; i<_ShapeBankArray.size(); i++)
00221 {
00222 if(_ShapeBankArray[i])
00223 {
00224
00225 for(uint j=0; j<_ShapeBankArray[i]->getNumShapes(); j++)
00226 {
00227
00228 uint shapeId= (i<<16) + j;
00229
00230
00231 const CLodCharacterShape *shape= _ShapeBankArray[i]->getShape(j);
00232 if(shape)
00233 {
00234 const string &name= shape->getName();
00235 ItStrIdMap it= _ShapeMap.find(name);
00236 if(it == _ShapeMap.end())
00237
00238 _ShapeMap.insert(make_pair(name, shapeId));
00239 else
00240 {
00241 error= true;
00242 nlwarning("Found a Character Lod with same name in the manager: %s", name.c_str());
00243 }
00244 }
00245 }
00246 }
00247 }
00248
00249 return error;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 void CLodCharacterManager::setMaxVertex(uint32 maxVertex)
00261 {
00262
00263 nlassert(!isRendering());
00264 _MaxNumVertices= maxVertex;
00265 }
00266
00267
00268 void CLodCharacterManager::setVertexStreamNumVBHard(uint32 numVBHard)
00269 {
00270
00271 nlassert(!isRendering());
00272 _NumVBHard= numVBHard;
00273 }
00274
00275
00276 void CLodCharacterManager::beginRender(IDriver *driver, const CVector &managerPos)
00277 {
00278 H_AUTO( NL3D_CharacterLod_beginRender );
00279
00280
00281 nlassert(!isRendering());
00282
00283
00284
00285 _CurrentVertexId=0;
00286 _CurrentTriId= 0;
00287
00288
00289
00290 nlassert(driver);
00291
00292
00293 bool mustChangeVertexStream= _VertexStream.getDriver() != driver;
00294 if(!mustChangeVertexStream)
00295 {
00296 mustChangeVertexStream= _MaxNumVertices != _VertexStream.getMaxVertices();
00297 mustChangeVertexStream= mustChangeVertexStream || _NumVBHard != _VertexStream.getNumVB();
00298 }
00299
00300 if( mustChangeVertexStream )
00301 {
00302
00303 CVertexBuffer vb;
00304 vb.setVertexFormat(NL3D_CLOD_VERTEX_FORMAT);
00305
00306 nlassert( NL3D_CLOD_UV_OFF == vb.getTexCoordOff());
00307 nlassert( NL3D_CLOD_COLOR_OFF == vb.getColorOff());
00308
00309
00310 _VertexStream.release();
00311 _VertexStream.init(driver, NL3D_CLOD_VERTEX_FORMAT, _MaxNumVertices, _NumVBHard, "CLodManagerVB", false);
00312 }
00313
00314
00315
00316
00317
00318 nlassert(!_LockDone);
00319 _VertexSize= _VertexStream.getVertexSize();
00320
00321 nlassert( _VertexSize == NL3D_CLOD_VERTEX_SIZE );
00322
00323
00324
00325 if(_Triangles.getNumIndexes()<_MaxNumVertices * 2)
00326 {
00327 _Triangles.setFormat(NL_LOD_CHARACTER_INDEX_FORMAT);
00328 _Triangles.setNumIndexes(_MaxNumVertices * 2);
00329 }
00330
00331
00332 _ManagerMatrixPos= managerPos;
00333
00334
00335 _Rendering= true;
00336 }
00337
00338
00339
00340 static inline void computeLodLighting(CRGBA &lightRes, const CVector &lightObjectSpace, const CVector &normalPtr, CRGBA ambient, CRGBA diffuse)
00341 {
00342 float f= lightObjectSpace * normalPtr;
00343 sint f8= NLMISC::OptFastFloor(f);
00344 fastClamp8(f8);
00345 sint r,g,b;
00346 r= (diffuse.R * f8)>>8;
00347 g= (diffuse.G * f8)>>8;
00348 b= (diffuse.B * f8)>>8;
00349 r+= ambient.R;
00350 g+= ambient.G;
00351 b+= ambient.B;
00352 fastClamp8(r);
00353 fastClamp8(g);
00354 fastClamp8(b);
00355 lightRes.R= r;
00356 lightRes.G= g;
00357 lightRes.B= b;
00358 }
00359
00360
00361
00362 bool CLodCharacterManager::addRenderCharacterKey(CLodCharacterInstance &instance, const CMatrix &worldMatrix,
00363 CRGBA paramAmbient, CRGBA paramDiffuse, const CVector &lightDir)
00364 {
00365 H_AUTO ( NL3D_CharacterLod_AddRenderKey )
00366
00367 nlassert(_VertexStream.getDriver());
00368
00369 nlassert(isRendering());
00370
00371
00372
00373 uint numVertices;
00374 const CLodCharacterShape::CVector3s *vertPtr;
00375 const CVector *normalPtr;
00376 const CUV *uvPtr;
00377 const uint8 *alphaPtr;
00378 CVector lightObjectSpace;
00379 CVector matPos;
00380 float a00, a01, a02;
00381 float a10, a11, a12;
00382 float a20, a21, a22;
00383 sint f8;
00384 uint64 blank= 0;
00385 CRGBA ambient= paramAmbient;
00386 CRGBA diffuse= paramDiffuse;
00387
00388 ambient.A= 0;
00389 diffuse.A= 0;
00390
00391
00392
00393
00394
00395
00396 const CLodCharacterShape *clod= getShape(instance.ShapeId);
00397
00398 if(!clod)
00399 return true;
00400
00401
00402 normalPtr= clod->getNormals();
00403
00404 uvPtr= instance.getUVs();
00405
00406 nlassert(normalPtr && uvPtr);
00407
00408
00409 CVector unPackScaleFactor;
00410 vertPtr= clod->getAnimKey(instance.AnimId, instance.AnimTime, instance.WrapMode, unPackScaleFactor);
00411
00412 if(!vertPtr)
00413 return true;
00414
00415 numVertices= clod->getNumVertices();
00416
00417
00418 if(numVertices==0)
00419 return true;
00420
00421
00422 if(_CurrentVertexId+numVertices > _MaxNumVertices)
00423 return false;
00424
00425
00426 static vector<uint8> defaultAlphaArray;
00427
00428 if(instance.VertexAlphas.size() == numVertices)
00429 {
00430 alphaPtr= &instance.VertexAlphas[0];
00431 }
00432
00433 else
00434 {
00435
00436 if(defaultAlphaArray.size()<numVertices)
00437 defaultAlphaArray.resize(numVertices, 255);
00438 alphaPtr= &defaultAlphaArray[0];
00439 }
00440
00441
00442
00443
00444
00445 if(!_LockDone)
00446 {
00447 _VertexData= _VertexStream.lock();
00448 _LockDone= true;
00449 }
00450
00451
00452 if(_VertexStream.isBRGA())
00453 {
00454
00455 ambient.swapBR();
00456 diffuse.swapBR();
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466 matPos= worldMatrix.getPos();
00467
00468 matPos -= _ManagerMatrixPos;
00469
00470 const float *worldM= worldMatrix.get();
00471 a00= worldM[0]; a01= worldM[4]; a02= worldM[8];
00472 a10= worldM[1]; a11= worldM[5]; a12= worldM[9];
00473 a20= worldM[2]; a21= worldM[6]; a22= worldM[10];
00474
00475
00476
00477 lightObjectSpace.x= a00 * lightDir.x + a10 * lightDir.y + a20 * lightDir.z;
00478 lightObjectSpace.y= a01 * lightDir.x + a11 * lightDir.y + a21 * lightDir.z;
00479 lightObjectSpace.z= a02 * lightDir.x + a12 * lightDir.y + a22 * lightDir.z;
00480
00481 lightObjectSpace= _LightCorrectionMatrix.mulVector(lightObjectSpace);
00482
00483 lightObjectSpace.normalize();
00484 lightObjectSpace= -lightObjectSpace;
00485
00486 lightObjectSpace*= 255;
00487
00488
00489 a00*= unPackScaleFactor.x; a01*= unPackScaleFactor.y; a02*= unPackScaleFactor.z;
00490 a10*= unPackScaleFactor.x; a11*= unPackScaleFactor.y; a12*= unPackScaleFactor.z;
00491 a20*= unPackScaleFactor.x; a21*= unPackScaleFactor.y; a22*= unPackScaleFactor.z;
00492
00493
00494 uint8 *dstPtr;
00495 dstPtr= _VertexData + _CurrentVertexId * _VertexSize;
00496
00497
00498
00499
00500
00501
00502
00503
00504 #if defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
00505
00506 if(CSystemInfo::hasMMX())
00507 {
00508 H_AUTO( NL3D_CharacterLod_vertexFill );
00509
00510 if(numVertices)
00511 {
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 __asm
00543 {
00544 mov edi, dstPtr
00545 theLoop:
00546
00547 mov esi,normalPtr
00548
00549 fld dword ptr [esi]
00550 fmul lightObjectSpace.x
00551 fld dword ptr [esi+4]
00552 fmul lightObjectSpace.y
00553 faddp st(1),st
00554 fld dword ptr [esi+8]
00555 fmul lightObjectSpace.z
00556 faddp st(1),st
00557 fistp f8
00558
00559 add esi, 12
00560 mov normalPtr, esi
00561
00562
00563
00564 mov esi, vertPtr
00565 fild word ptr[esi]
00566 fild word ptr[esi+2]
00567 fild word ptr[esi+4]
00568
00569 fld a00
00570 fmul st, st(3)
00571 fld a01
00572 fmul st, st(3)
00573 faddp st(1), st
00574 fld a02
00575 fmul st, st(2)
00576 faddp st(1), st
00577 fld matPos.x
00578 faddp st(1), st
00579 fstp dword ptr[edi]
00580
00581 fld a10
00582 fmul st, st(3)
00583 fld a11
00584 fmul st, st(3)
00585 faddp st(1), st
00586 fld a12
00587 fmul st, st(2)
00588 faddp st(1), st
00589 fld matPos.y
00590 faddp st(1), st
00591 fstp dword ptr[edi+4]
00592
00593 fld a20
00594 fmul st, st(3)
00595 fld a21
00596 fmul st, st(3)
00597 faddp st(1), st
00598 fld a22
00599 fmul st, st(2)
00600 faddp st(1), st
00601 fld matPos.z
00602 faddp st(1), st
00603 fstp dword ptr[edi+8]
00604
00605 fstp st
00606 fstp st
00607 fstp st
00608
00609 add esi, 6
00610 mov vertPtr, esi
00611
00612
00613
00614 mov esi, uvPtr
00615 mov eax, [esi]
00616 mov [edi+NL3D_CLOD_UV_OFF], eax
00617 mov ebx, [esi+4]
00618 mov [edi+NL3D_CLOD_UV_OFF+4], ebx
00619
00620 add esi, 8
00621 mov uvPtr, esi
00622
00623
00624
00625
00626 mov eax, f8
00627 cmp eax, 0x80000000
00628 sbb ebx, ebx
00629 and eax, ebx
00630
00631
00632
00633 movd mm0, eax
00634 packuswb mm0, mm0
00635 packuswb mm0, mm0
00636 movd mm1, diffuse
00637 punpcklbw mm1, blank
00638 pmullw mm0, mm1
00639 psrlw mm0, 8
00640 packuswb mm0, blank
00641 movd mm2, ambient
00642 paddusb mm0, mm2
00643 movd ebx, mm0
00644
00645 emms
00646
00647
00648
00649 mov esi, alphaPtr
00650 movzx eax, byte ptr[esi]
00651 shl eax, 24
00652 add ebx, eax
00653
00654 mov [edi+NL3D_CLOD_COLOR_OFF], ebx
00655
00656 add esi, 1
00657 mov alphaPtr, esi
00658
00659
00660
00661 add edi, NL3D_CLOD_VERTEX_SIZE
00662
00663 mov eax, numVertices
00664 dec eax
00665 mov numVertices, eax
00666
00667 jnz theLoop
00668
00669
00670 mov dstPtr, edi
00671 }
00672 }
00673 }
00674 else
00675 #endif
00676 {
00677 H_AUTO( NL3D_CharacterLod_vertexFill );
00678
00679 CVector fVect;
00680
00681 for(;numVertices>0;)
00682 {
00683
00684
00685 CVector *dstVector= (CVector*)dstPtr;
00686 fVect.x= vertPtr->x; fVect.y= vertPtr->y; fVect.z= vertPtr->z;
00687 ++vertPtr;
00688 dstVector->x= a00 * fVect.x + a01 * fVect.y + a02 * fVect.z + matPos.x;
00689 dstVector->y= a10 * fVect.x + a11 * fVect.y + a12 * fVect.z + matPos.y;
00690 dstVector->z= a20 * fVect.x + a21 * fVect.y + a22 * fVect.z + matPos.z;
00691
00692 *(CUV*)(dstPtr + NL3D_CLOD_UV_OFF)= *uvPtr;
00693 ++uvPtr;
00694
00695
00696 CRGBA lightRes;
00697 computeLodLighting(lightRes, lightObjectSpace, *normalPtr, ambient, diffuse);
00698 ++normalPtr;
00699 lightRes.A= *alphaPtr;
00700 ++alphaPtr;
00701
00702 *((CRGBA*)(dstPtr + NL3D_CLOD_COLOR_OFF))= lightRes;
00703
00704
00705 dstPtr+= NL3D_CLOD_VERTEX_SIZE;
00706 numVertices--;
00707 }
00708 }
00709
00710
00711
00712
00713 {
00714 H_AUTO( NL3D_CharacterLod_primitiveFill )
00715
00716
00717 uint numTriIdxs= clod->getNumTriangles() * 3;
00718
00719
00720 if(numTriIdxs)
00721 {
00722
00723 if(_CurrentTriId+numTriIdxs > _Triangles.getNumIndexes())
00724 {
00725 _Triangles.setFormat(NL_LOD_CHARACTER_INDEX_FORMAT);
00726 _Triangles.setNumIndexes(_CurrentTriId+numTriIdxs);
00727 }
00728
00729
00730 CIndexBufferReadWrite iba;
00731 _Triangles.lock(iba);
00732 const TLodCharacterIndexType *srcIdx= clod->getTriangleArray();
00733 nlassert(sizeof(TLodCharacterIndexType) == _Triangles.getIndexNumBytes());
00734 TLodCharacterIndexType *dstIdx= (TLodCharacterIndexType *) iba.getPtr()+_CurrentTriId;
00735 for(;numTriIdxs>0;numTriIdxs--, srcIdx++, dstIdx++)
00736 {
00737 *dstIdx= *srcIdx + _CurrentVertexId;
00738 }
00739 }
00740 }
00741
00742
00743
00744
00745
00746 _CurrentVertexId+= clod->getNumVertices();
00747
00748 _CurrentTriId+= clod->getNumTriangles() * 3;
00749
00750
00751
00752 return true;
00753 }
00754
00755
00756 void CLodCharacterManager::endRender()
00757 {
00758 H_AUTO ( NL3D_CharacterLod_endRender );
00759
00760 IDriver *driver= _VertexStream.getDriver();
00761 nlassert(driver);
00762
00763 nlassert(isRendering());
00764
00765
00766 if(_LockDone)
00767 {
00768
00769 _VertexStream.unlock(_CurrentVertexId);
00770 _LockDone= false;
00771
00772
00773 if(_CurrentTriId>0)
00774 {
00775
00776 CMatrix managerMatrix;
00777 managerMatrix.setPos(_ManagerMatrixPos);
00778 driver->setupModelMatrix(managerMatrix);
00779
00780
00781 _VertexStream.activate();
00782
00783
00784 driver->activeIndexBuffer(_Triangles);
00785 driver->renderTriangles(_Material, 0, _CurrentTriId/3);
00786 }
00787
00788
00789 _VertexStream.swapVBHard();
00790 }
00791
00792
00793 _Rendering= false;
00794 }
00795
00796
00797 void CLodCharacterManager::setupNormalCorrectionMatrix(const CMatrix &normalMatrix)
00798 {
00799 _LightCorrectionMatrix= normalMatrix;
00800 _LightCorrectionMatrix.setPos(CVector::Null);
00801 _LightCorrectionMatrix.invert();
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 CLodCharacterTmpBitmap::CLodCharacterTmpBitmap()
00814 {
00815 reset();
00816 }
00817
00818
00819 void CLodCharacterTmpBitmap::reset()
00820 {
00821
00822 _Bitmap.resize(1);
00823 _Bitmap[0]= CRGBA::Black;
00824 _WidthPower=0;
00825 _UShift= 8;
00826 _VShift= 8;
00827 }
00828
00829
00830 void CLodCharacterTmpBitmap::build(const NLMISC::CBitmap &bmpIn)
00831 {
00832 uint width= bmpIn.getWidth();
00833 uint height= bmpIn.getHeight();
00834 nlassert(width>0 && width<=256);
00835 nlassert(height>0 && height<=256);
00836
00837
00838 _Bitmap.resize(width*height);
00839 _WidthPower= getPowerOf2(width);
00840
00841 _UShift= 8-getPowerOf2(width);
00842 _VShift= 8-getPowerOf2(height);
00843
00844
00845 CBitmap bmp= bmpIn;
00846 bmp.convertToType(CBitmap::RGBA);
00847 CRGBA *src= (CRGBA*)&bmp.getPixels()[0];
00848 CRGBA *dst= _Bitmap.getPtr();
00849 for(sint nPix= width*height;nPix>0;nPix--, src++, dst++)
00850 {
00851 *dst= *src;
00852 }
00853 }
00854
00855
00856 void CLodCharacterTmpBitmap::build(CRGBA col)
00857 {
00858
00859 reset();
00860 _Bitmap[0]= col;
00861 }
00862
00863
00864
00865 void CLodCharacterManager::initInstance(CLodCharacterInstance &instance)
00866 {
00867
00868 if(instance._Owner)
00869 instance._Owner->releaseInstance(instance);
00870
00871
00872 const CLodCharacterShape *clod= getShape(instance.ShapeId);
00873
00874 if(!clod)
00875 return;
00876
00877 const CUV *uvSrc= clod->getUVs();
00878 nlassert(uvSrc);
00879
00880
00881
00882 instance._Owner= this;
00883 instance._UVs.resize(clod->getNumVertices());
00884
00885
00886 if(_FreeIds.empty())
00887 {
00888
00889 instance._TextureId= NL3D_CLOD_TEXT_NUM_IDS;
00890 CUV uv(0,0);
00891 fill(instance._UVs.begin(), instance._UVs.end(), uv);
00892 }
00893
00894 else
00895 {
00896
00897 instance._TextureId= _FreeIds.back();
00898 _FreeIds.pop_back();
00899
00900 uint xId= instance._TextureId % NL3D_CLOD_TEXT_NLOD_WIDTH;
00901 uint yId= instance._TextureId / NL3D_CLOD_TEXT_NLOD_WIDTH;
00902
00903 float scaleU= 1.0f / NL3D_CLOD_TEXT_NLOD_WIDTH;
00904 float scaleV= 1.0f / NL3D_CLOD_TEXT_NLOD_HEIGHT;
00905 float biasU= (float)xId / NL3D_CLOD_TEXT_NLOD_WIDTH;
00906 float biasV= (float)yId / NL3D_CLOD_TEXT_NLOD_HEIGHT;
00907
00908 CUV *uvDst= &instance._UVs[0];
00909 for(uint i=0; i<instance._UVs.size();i++)
00910 {
00911 uvDst[i].U= biasU + uvSrc[i].U*scaleU;
00912 uvDst[i].V= biasV + uvSrc[i].V*scaleV;
00913 }
00914 }
00915 }
00916
00917
00918 void CLodCharacterManager::releaseInstance(CLodCharacterInstance &instance)
00919 {
00920 if(instance._Owner==NULL)
00921 return;
00922 nlassert(this==instance._Owner);
00923
00924
00925 if(instance._TextureId>=0 && instance._TextureId<NL3D_CLOD_TEXT_NUM_IDS)
00926 _FreeIds.push_back(instance._TextureId);
00927
00928
00929 instance._Owner= NULL;
00930 instance._TextureId= -1;
00931 contReset(instance._UVs);
00932 }
00933
00934
00935
00936 CRGBA *CLodCharacterManager::getTextureInstance(CLodCharacterInstance &instance)
00937 {
00938 nlassert(instance._Owner==this);
00939 nlassert(instance._TextureId!=-1);
00940
00941 if(instance._TextureId==NL3D_CLOD_TEXT_NUM_IDS)
00942 return NULL;
00943
00944
00945 uint xId= instance._TextureId % NL3D_CLOD_TEXT_NLOD_WIDTH;
00946 uint yId= instance._TextureId / NL3D_CLOD_TEXT_NLOD_WIDTH;
00947
00948
00949 CRGBA *pix= (CRGBA*)&_BigTexture->getPixels(0)[0];
00950 return pix + yId*NL3D_CLOD_TEXT_HEIGHT*NL3D_CLOD_BIGTEXT_WIDTH + xId*NL3D_CLOD_TEXT_WIDTH;
00951 }
00952
00953
00954
00955 bool CLodCharacterManager::startTextureCompute(CLodCharacterInstance &instance)
00956 {
00957 CRGBA *dst= getTextureInstance(instance);
00958 if(!dst)
00959 return false;
00960
00961
00962 CRGBA col= NL3D_CLOD_DEFAULT_TEXCOLOR;
00963 for(uint y=0;y<NL3D_CLOD_TEXT_HEIGHT;y++)
00964 {
00965
00966 for(uint x=0;x<NL3D_CLOD_TEXT_WIDTH;x++)
00967 dst[x]= col;
00968
00969 dst+= NL3D_CLOD_BIGTEXT_WIDTH;
00970 }
00971
00972 return true;
00973 }
00974
00975
00976 void CLodCharacterManager::addTextureCompute(CLodCharacterInstance &instance, const CLodCharacterTexture &lodTexture)
00977 {
00978 CRGBA *dst= getTextureInstance(instance);
00979 if(!dst)
00980 return;
00981
00982
00983 nlassert(lodTexture.Texture.size()==NL3D_CLOD_TEXT_SIZE);
00984 const CLodCharacterTexture::CTUVQ *lookUpPtr= &lodTexture.Texture[0];
00985
00986
00987 for(uint y=0;y<NL3D_CLOD_TEXT_HEIGHT;y++)
00988 {
00989
00990 for(uint x=0;x<NL3D_CLOD_TEXT_WIDTH;x++)
00991 {
00992 CLodCharacterTexture::CTUVQ lut= *lookUpPtr;
00993
00994 if(lut.Q<dst[x].A)
00995 {
00996
00997 CRGBA col= _TmpBitmaps[lut.T].getPixel(lut.U, lut.V);
00998
00999 col.A= lut.Q;
01000
01001 dst[x]= col;
01002 }
01003
01004
01005 lookUpPtr++;
01006 }
01007
01008 dst+= NL3D_CLOD_BIGTEXT_WIDTH;
01009 }
01010 }
01011
01012
01013 void CLodCharacterManager::endTextureCompute(CLodCharacterInstance &instance, uint numBmpToReset)
01014 {
01015 CRGBA *dst= getTextureInstance(instance);
01016 if(!dst)
01017 return;
01018
01019
01020 for(uint y=0;y<NL3D_CLOD_TEXT_HEIGHT;y++)
01021 {
01022
01023 for(uint x=0;x<NL3D_CLOD_TEXT_WIDTH;x++)
01024 {
01025 dst[x].A= 255;
01026 }
01027
01028 dst+= NL3D_CLOD_BIGTEXT_WIDTH;
01029 }
01030
01031
01032 if(instance._TextureId==0)
01033 *(CRGBA*)&_BigTexture->getPixels(0)[0]= NL3D_CLOD_DEFAULT_TEXCOLOR;
01034
01035
01036 uint xId= instance._TextureId % NL3D_CLOD_TEXT_NLOD_WIDTH;
01037 uint yId= instance._TextureId / NL3D_CLOD_TEXT_NLOD_WIDTH;
01038
01039 _BigTexture->touchRect(
01040 CRect(xId*NL3D_CLOD_TEXT_WIDTH, yId*NL3D_CLOD_TEXT_HEIGHT, NL3D_CLOD_TEXT_WIDTH, NL3D_CLOD_TEXT_HEIGHT) );
01041
01042
01043 for(uint i=0; i<numBmpToReset; i++)
01044 {
01045 _TmpBitmaps[i].reset();
01046 }
01047
01048
01049
01050
01051 }
01052
01053
01054
01055 bool CLodCharacterManager::fastIntersect(const CLodCharacterInstance &instance, const NLMISC::CMatrix &toRaySpace, float &dist2D, float &distZ, bool computeDist2D)
01056 {
01057 H_AUTO ( NL3D_CharacterLod_fastIntersect )
01058
01059 uint numVertices;
01060 const CLodCharacterShape::CVector3s *vertPtr;
01061 CVector matPos;
01062 float a00, a01, a02;
01063 float a10, a11, a12;
01064 float a20, a21, a22;
01065
01066
01067
01068
01069
01070
01071 const CLodCharacterShape *clod= getShape(instance.ShapeId);
01072
01073 if(!clod)
01074 return false;
01075
01076
01077 CVector unPackScaleFactor;
01078 vertPtr= clod->getAnimKey(instance.AnimId, instance.AnimTime, instance.WrapMode, unPackScaleFactor);
01079
01080 if(!vertPtr)
01081 return false;
01082
01083 numVertices= clod->getNumVertices();
01084
01085
01086 if(numVertices==0)
01087 return false;
01088
01089
01090
01091
01092
01093 matPos= toRaySpace.getPos();
01094
01095 const float *rayM= toRaySpace.get();
01096 a00= rayM[0]; a01= rayM[4]; a02= rayM[8];
01097 a10= rayM[1]; a11= rayM[5]; a12= rayM[9];
01098 a20= rayM[2]; a21= rayM[6]; a22= rayM[10];
01099
01100
01101 a00*= unPackScaleFactor.x; a01*= unPackScaleFactor.y; a02*= unPackScaleFactor.z;
01102 a10*= unPackScaleFactor.x; a11*= unPackScaleFactor.y; a12*= unPackScaleFactor.z;
01103 a20*= unPackScaleFactor.x; a21*= unPackScaleFactor.y; a22*= unPackScaleFactor.z;
01104
01105
01106
01107 static std::vector<CVector> lodInRaySpace;
01108 if(numVertices>lodInRaySpace.size())
01109 lodInRaySpace.resize(numVertices);
01110 CVector *dstPtr= &lodInRaySpace[0];
01111
01112
01113
01114
01115 {
01116 CVector fVect;
01117
01118 for(;numVertices>0;)
01119 {
01120
01121 fVect.x= vertPtr->x; fVect.y= vertPtr->y; fVect.z= vertPtr->z;
01122 ++vertPtr;
01123 dstPtr->x= a00 * fVect.x + a01 * fVect.y + a02 * fVect.z + matPos.x;
01124 dstPtr->y= a10 * fVect.x + a11 * fVect.y + a12 * fVect.z + matPos.y;
01125 dstPtr->z= a20 * fVect.x + a21 * fVect.y + a22 * fVect.z + matPos.z;
01126
01127
01128 dstPtr++;
01129 numVertices--;
01130 }
01131 }
01132
01133
01134
01135
01136 return CRayMesh::getRayIntersection(lodInRaySpace, clod->getTriangleIndices(), dist2D, distZ, computeDist2D);
01137 }
01138
01139
01140 }