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/landscapevb_allocator.h"
00029 #include "3d/driver.h"
00030
00031
00032 using namespace std;
00033
00034 namespace NL3D
00035 {
00036
00037
00038
00039
00040
00041 #define NL3D_LANDSCAPE_VERTEX_ALLOCATE_SECURITY 1024
00042
00043
00044
00045 #define NL3D_LANDSCAPE_VERTEX_ALLOCATE_START 4048
00046
00047
00048 #define NL3D_VERTEX_FREE_MEMORY_RESERVE 1024
00049
00050 #define NL3D_VERTEX_MAX_VERTEX_VBHARD 40000
00051
00052
00053
00054 CLandscapeVBAllocator::CLandscapeVBAllocator(TType type)
00055 {
00056 _Type= type;
00057 _VertexFreeMemory.reserve(NL3D_VERTEX_FREE_MEMORY_RESERVE);
00058
00059 _ReallocationOccur= false;
00060 _NumVerticesAllocated= 0;
00061 _VBHardOk= false;
00062 _BufferLocked= false;
00063
00064 for(uint i=0;i<MaxVertexProgram;i++)
00065 _VertexProgram[i]= NULL;
00066 }
00067
00068
00069 CLandscapeVBAllocator::~CLandscapeVBAllocator()
00070 {
00071 clear();
00072 }
00073
00074
00075
00076 void CLandscapeVBAllocator::updateDriver(IDriver *driver)
00077 {
00078
00079 nlassert(driver);
00080 if( _Driver==NULL || driver!=_Driver )
00081 {
00082 deleteVertexBuffer();
00083 _Driver= driver;
00084 _VBHardOk= _Driver->supportVertexBufferHard();
00085
00086
00087 deleteVertexProgram();
00088
00089
00090 setupVBFormatAndVertexProgram(_Driver->isVertexProgramSupported() && !_Driver->isVertexProgramEmulated());
00091
00092
00093 if( _NumVerticesAllocated>0 )
00094 allocateVertexBuffer(_NumVerticesAllocated);
00095 }
00096 else
00097 {
00098
00099 if( _VBHardOk && _VBHard==NULL && _NumVerticesAllocated>0 )
00100 allocateVertexBuffer(_NumVerticesAllocated);
00101 }
00102
00103 }
00104
00105
00106
00107 void CLandscapeVBAllocator::clear()
00108 {
00109
00110 _VertexFreeMemory.clear();
00111 _NumVerticesAllocated= 0;
00112
00113
00114 deleteVertexBuffer();
00115
00116
00117 deleteVertexProgram();
00118
00119
00120 _ReallocationOccur= false;
00121 _Driver= NULL;
00122 _VBHardOk= false;
00123 }
00124
00125
00126
00127
00128 void CLandscapeVBAllocator::resetReallocation()
00129 {
00130 _ReallocationOccur= false;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 uint CLandscapeVBAllocator::allocateVertex()
00145 {
00146
00147 if( _VertexFreeMemory.size()==0 )
00148 {
00149
00150 uint newResize;
00151 if(_NumVerticesAllocated==0)
00152 newResize= NL3D_LANDSCAPE_VERTEX_ALLOCATE_START;
00153 else
00154 newResize= NL3D_LANDSCAPE_VERTEX_ALLOCATE_SECURITY;
00155 _NumVerticesAllocated+= newResize;
00156
00157 allocateVertexBuffer(_NumVerticesAllocated);
00158
00159 _VertexInfos.resize(_NumVerticesAllocated);
00160
00161
00162 for(uint i=0;i<newResize;i++)
00163 {
00164
00165
00166 _VertexFreeMemory.push_back( _NumVerticesAllocated - (i+1) );
00167
00168
00169 _VertexInfos[_NumVerticesAllocated - (i+1)].Free= true;
00170 }
00171 }
00172
00173
00174 uint id= _VertexFreeMemory.back();
00175
00176 _VertexFreeMemory.pop_back();
00177
00178
00179 nlassert(id<_NumVerticesAllocated);
00180 nlassert(_VertexInfos[id].Free);
00181 _VertexInfos[id].Free= false;
00182
00183 return id;
00184 }
00185
00186
00187 void CLandscapeVBAllocator::deleteVertex(uint vid)
00188 {
00189
00190 nlassert(vid<_NumVerticesAllocated);
00191 nlassert(!_VertexInfos[vid].Free);
00192 _VertexInfos[vid].Free= true;
00193
00194
00195
00196 _VertexFreeMemory.push_back( vid );
00197 }
00198
00199
00200
00201 void CLandscapeVBAllocator::lockBuffer(CFarVertexBufferInfo &farVB)
00202 {
00203 nlassert( _Type==Far0 || _Type==Far1 );
00204
00205 unlockBuffer();
00206
00207 if(_VBHard)
00208 {
00209 void *data= _VBHard->lock();
00210 farVB.setupVertexBufferHard(*_VBHard, data, _VertexProgram[0]!=NULL );
00211 }
00212 else
00213 {
00214 farVB.setupVertexBuffer(_VB, _VertexProgram[0]!=NULL );
00215 }
00216
00217 _BufferLocked= true;
00218 }
00219
00220 void CLandscapeVBAllocator::lockBuffer(CNearVertexBufferInfo &tileVB)
00221 {
00222 nlassert(_Type==Tile);
00223
00224 unlockBuffer();
00225
00226 if(_VBHard)
00227 {
00228 void *data= _VBHard->lock();
00229 tileVB.setupVertexBufferHard(*_VBHard, data, _VertexProgram[0]!=NULL );
00230 }
00231 else
00232 {
00233 tileVB.setupVertexBuffer(_VB, _VertexProgram[0]!=NULL );
00234 }
00235
00236 _BufferLocked= true;
00237 }
00238
00239 void CLandscapeVBAllocator::unlockBuffer()
00240 {
00241 if(_BufferLocked)
00242 {
00243 if(_VBHard)
00244 _VBHard->unlock();
00245 _BufferLocked= false;
00246 }
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 void CLandscapeVBAllocator::activate(uint vpId)
00259 {
00260 nlassert(_Driver);
00261 nlassert(!_BufferLocked);
00262
00263
00264 if(_VertexProgram[vpId])
00265 {
00266
00267 nlverify(_Driver->activeVertexProgram(_VertexProgram[vpId]));
00268 }
00269
00270
00271 if(_VBHard)
00272 _Driver->activeVertexBufferHard(_VBHard);
00273 else
00274 _Driver->activeVertexBuffer(_VB);
00275 }
00276
00277
00278
00279 void CLandscapeVBAllocator::deleteVertexBuffer()
00280 {
00281
00282 unlockBuffer();
00283
00284
00285 if(_VBHard!=NULL)
00286 {
00287
00288 nlassert(_Driver!=NULL);
00289
00290
00291 _Driver->deleteVertexBufferHard(_VBHard);
00292 _VBHard= NULL;
00293 }
00294
00295
00296 _VB.deleteAllVertices();
00297 }
00298
00299
00300
00301 void CLandscapeVBAllocator::allocateVertexBuffer(uint32 numVertices)
00302 {
00303
00304 nlassert(_Driver);
00305
00306
00307 _ReallocationOccur= true;
00308
00309 unlockBuffer();
00310
00311
00312 if( _VBHardOk )
00313 {
00314
00315 if(_VBHard!=NULL)
00316 {
00317
00318 nlassert(_Driver!=NULL);
00319 _Driver->deleteVertexBufferHard(_VBHard);
00320 }
00321
00322
00323
00324 if(numVertices <= NL3D_VERTEX_MAX_VERTEX_VBHARD)
00325 _VBHard= _Driver->createVertexBufferHard(_VB.getVertexFormat(), _VB.getValueTypePointer(), numVertices, IDriver::VBHardAGP);
00326 else
00327 _VBHard= NULL;
00328
00329
00330 if(_VBHard==NULL)
00331 _VBHardOk= false;
00332 }
00333
00334
00335 if(!_VBHardOk)
00336 {
00337
00338 _VB.setNumVertices(numVertices);
00339 }
00340
00341
00342
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 const char* NL3D_LandscapeCommonStartProgram=
00440 "!!VP1.0 \n\
00441 # compute Basic geomorph into R0.x \n\
00442 ADD R0, v[0], -c[5]; # R0 = startPos - RefineCenter \n\
00443 DP3 R2.x, R0, R0; # R2.x= sqrDist= (startPos - RefineCenter).sqrnorm()\n\
00444 RCP R0.x, R2.x; # R0.x= 1 / sqrDist \n\
00445 MUL R0.x, v[10].x, R0.x; # R0.x= ErrorMetric= GeomFactor / sqrDist \n\
00446 \n\
00447 # compute Transition Factor To TileNear Geomorph, into R0.z \n\
00448 ADD R0.z, c[6].x, -R2.x; # R0.z= TileDistFarSqr - sqrDist \n\
00449 MUL R0.z, R0.z, c[6].y; # R0.z= f= (TileDistFarSqr - sqrDist ) * OOTileDistDeltaSqr \n\
00450 MAX R0.z, R0.z, c[4].x; \n\
00451 MIN R0.z, R0.z, c[4].y; # R0.z= f= clamp(f, 0, 1); \n\
00452 MUL R0.z, R0.z, R0.z; \n\
00453 MUL R0.z, R0.z, R0.z; # R0.z= finalFactor= f^4 \n\
00454 \n\
00455 # Apply the transition factor to the ErrorMetric => R0.w= ErrorMetricModified. \n\
00456 ADD R0.w, v[10].y, -R0.x; # R0.w= maxNearLimit - ErrorMetric \n\
00457 MAD R0.w, R0.z, R0.w, R0.x; # R0.w= finalFactor * (maxNearLimit - ErrorMetric) + ErrorMetric \n\
00458 \n\
00459 # R0.w may be < R0.x; (when the point is very near). Must take the bigger errorMetric. \n\
00460 MAX R0.x, R0.x, R0.w; # R0.x= ErrorMetric Max \n\
00461 \n\
00462 # apply geomorph into R1 \n\
00463 ADD R0.x, R0.x, -c[4].y; # R0.x= ErrorMetric Max - 1 \n\
00464 MAX R0.x, R0.x, c[4].x; \n\
00465 MIN R0.x, R0.x, c[4].y; # R0.x= geomBlend= clamp(R0.x, 0, 1); \n\
00466 \n\
00467 # NB: Can't use MAD R1.xyz, v[11], R0.x, v[0], because can't acces 2 inputs in one op. \n\
00468 # Hence, can use a MAD to Sub the Landscape Center _PZBModelPosition \n\
00469 MAD R1.xyz, v[11], R0.x, -c[12]; \n\
00470 # trick here: since R1.w= 0, and v[0].w= 1, final R1.w==1. \n\
00471 ADD R1, R1, v[0]; # R1= geomBlend * (EndPos-StartPos) + StartPos \n\
00472 ";
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 const string NL3D_LandscapeTestSpeedProgram=
00485 " MOV R1, R1; \n MOV R1, R1; \n MOV R1, R1; \n MOV R1, R1; \n MOV R1, R1; \n\
00486 MOV R1, R1; \n MOV R1, R1; \n MOV R1, R1; \n MOV R1, R1; \n MOV R1, R1; \n\
00487 ";
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 const char* NL3D_LandscapeFar0EndProgram=
00498 " # compute in Projection space \n\
00499 DP4 o[HPOS].x, c[0], R1; \n\
00500 DP4 o[HPOS].y, c[1], R1; \n\
00501 DP4 o[HPOS].z, c[2], R1; \n\
00502 DP4 o[HPOS].w, c[3], R1; \n\
00503 MOV o[TEX0].xy, v[8]; \n\
00504 MOV o[TEX1].xy, v[9]; \n\
00505 DP4 o[FOGC].x, c[10], -R1; # fogc>0 => fogc= - (ModelView*R1).z \n\
00506 END \n\
00507 ";
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 const char* NL3D_LandscapeFar1EndProgram=
00519 " # compute Alpha Transition \n\
00520 ADD R0.x, R2.x, -v[12].x; # R0.x= sqrDist-TransitionSqrMin \n\
00521 MUL R0.x, R0.x, v[12].y; # R0.x= (sqrDist-TransitionSqrMin) * OOTransitionSqrDelta \n\
00522 MAX R0.x, R0.x, c[4].x; \n\
00523 MIN o[COL0].w, R0.x, c[4].y; # col.A= clamp(R0.x, 0, 1); \n\
00524 \n\
00525 # compute in Projection space \n\
00526 DP4 o[HPOS].x, c[0], R1; \n\
00527 DP4 o[HPOS].y, c[1], R1; \n\
00528 DP4 o[HPOS].z, c[2], R1; \n\
00529 DP4 o[HPOS].w, c[3], R1; \n\
00530 MOV o[TEX0].xy, v[8]; \n\
00531 MOV o[TEX1].xy, v[9]; \n\
00532 DP4 o[FOGC].x, c[10], -R1; # fogc>0 => fogc= - (ModelView*R1).z \n\
00533 END \n\
00534 ";
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 const char* NL3D_LandscapeTileEndProgram=
00545 " # compute in Projection space \n\
00546 DP4 o[HPOS].x, c[0], R1; \n\
00547 DP4 o[HPOS].y, c[1], R1; \n\
00548 DP4 o[HPOS].z, c[2], R1; \n\
00549 DP4 o[HPOS].w, c[3], R1; \n\
00550 MOV o[TEX0].xy, v[8]; \n\
00551 MOV o[TEX1].xy, v[9]; \n\
00552 DP4 o[FOGC].x, c[10], -R1; # fogc>0 => fogc= - (ModelView*R1).z \n\
00553 END \n\
00554 ";
00555
00557 const char* NL3D_LandscapeTileLightMapEndProgram=
00558 " # compute in Projection space \n\
00559 DP4 o[HPOS].x, c[0], R1; \n\
00560 DP4 o[HPOS].y, c[1], R1; \n\
00561 DP4 o[HPOS].z, c[2], R1; \n\
00562 DP4 o[HPOS].w, c[3], R1; \n\
00563 MOV o[TEX0].xy, v[13]; \n\
00564 MOV o[TEX1].xy, v[9]; \n\
00565 DP4 o[FOGC].x, c[10], -R1; # fogc>0 => fogc= - (ModelView*R1).z \n\
00566 END \n\
00567 ";
00568
00569
00570
00571 void CLandscapeVBAllocator::deleteVertexProgram()
00572 {
00573 for(uint i=0;i<MaxVertexProgram;i++)
00574 {
00575 if(_VertexProgram[i])
00576 {
00577 delete _VertexProgram[i];
00578 _VertexProgram[i]= NULL;
00579 }
00580 }
00581 }
00582
00583
00584
00585 void CLandscapeVBAllocator::setupVBFormatAndVertexProgram(bool withVertexProgram)
00586 {
00587
00588 if(!withVertexProgram)
00589 {
00590
00591 if(_Type==Far0)
00592
00593 _VB.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag);
00594 else if(_Type==Far1)
00595
00596 _VB.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag | CVertexBuffer::PrimaryColorFlag );
00597 else
00598
00599 _VB.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag | CVertexBuffer::TexCoord2Flag);
00600 }
00601 else
00602 {
00603
00604
00605 if(_Type==Far0)
00606 {
00607
00608 _VB.clearValueEx();
00609 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_STARTPOS, CVertexBuffer::Float3);
00610 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX0, CVertexBuffer::Float2);
00611 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX1, CVertexBuffer::Float2);
00612 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_GEOMINFO, CVertexBuffer::Float2);
00613 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_DELTAPOS, CVertexBuffer::Float3);
00614 _VB.initEx();
00615
00616
00617 string vpgram= string(NL3D_LandscapeCommonStartProgram) +
00618 string(NL3D_LandscapeFar0EndProgram);
00619 _VertexProgram[0]= new CVertexProgram(vpgram.c_str());
00620 }
00621 else if(_Type==Far1)
00622 {
00623
00624 _VB.clearValueEx();
00625 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_STARTPOS, CVertexBuffer::Float3);
00626 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX0, CVertexBuffer::Float2);
00627 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX1, CVertexBuffer::Float2);
00628 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_GEOMINFO, CVertexBuffer::Float2);
00629 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_DELTAPOS, CVertexBuffer::Float3);
00630 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_ALPHAINFO, CVertexBuffer::Float2);
00631 _VB.initEx();
00632
00633
00634 string vpgram= string(NL3D_LandscapeCommonStartProgram) +
00635 string(NL3D_LandscapeFar1EndProgram);
00636 _VertexProgram[0]= new CVertexProgram(vpgram.c_str());
00637 }
00638 else
00639 {
00640
00641 _VB.clearValueEx();
00642 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_STARTPOS, CVertexBuffer::Float3);
00643 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX0, CVertexBuffer::Float2);
00644 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX1, CVertexBuffer::Float2);
00645 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_TEX2, CVertexBuffer::Float2);
00646 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_GEOMINFO, CVertexBuffer::Float2);
00647 _VB.addValueEx(NL3D_LANDSCAPE_VPPOS_DELTAPOS, CVertexBuffer::Float3);
00648 _VB.initEx();
00649
00650
00651 string vpgram= string(NL3D_LandscapeCommonStartProgram) +
00652 string(NL3D_LandscapeTileEndProgram);
00653 _VertexProgram[0]= new CVertexProgram(vpgram.c_str());
00654
00655
00656 vpgram= string(NL3D_LandscapeCommonStartProgram) +
00657 string(NL3D_LandscapeTileLightMapEndProgram);
00658 _VertexProgram[1]= new CVertexProgram(vpgram.c_str());
00659 }
00660 }
00661
00662 }
00663
00664
00665
00666
00667 }