00001
00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024
00025
00026 #ifndef __RYKOL_PATCH_MESH_H
00027 #define __RYKOL_PATCH_MESH_H
00028
00029 #pragma warning (disable : 4786)
00030 #include <vector>
00031 #include <set>
00032 #include <string>
00033 #include <nel/misc/debug.h>
00034 #include <nel/3d/tile_bank.h>
00035 #include <nel/misc/file.h>
00036 #include <nel/misc/rgba.h>
00037 #include "path_mesh_alloc.h"
00038
00039
00040
00041 namespace NL3D
00042 {
00043 class CZone;
00044 };
00045
00046 typedef unsigned int uint;
00047
00048 #define RYKOLPATCHOBJ_CLASS_ID Class_ID(0x368c679f, 0x711c22ee)
00049
00050 extern TCHAR *GetString(int id);
00051
00052 extern HINSTANCE hInstance;
00053
00054 extern ClassDesc* GetRPODesc();
00055
00056 #define RPATCHMESH_SERIALIZE_VERSION_7 7
00057 #define RPATCHMESH_SERIALIZE_VERSION_6 6
00058 #define RPATCHMESH_SERIALIZE_VERSION_5 5
00059 #define RPATCHMESH_SERIALIZE_VERSION_4 4
00060 #define RPATCHMESH_SERIALIZE_VERSION_3 3
00061 #define RPATCHMESH_SERIALIZE_VERSION_2 2
00062 #define RPATCHMESH_SERIALIZE_VERSION_1 1
00063 #define RPATCHMESH_SERIALIZE_VERSION RPATCHMESH_SERIALIZE_VERSION_7
00064
00065 #define EP_OBJECT 0
00066 #define EP_VERTEX 1
00067 #define EP_EDGE 2
00068 #define EP_PATCH 3
00069 #define EP_TILE 4
00070
00071 #define PO_TILE 4
00072
00073 #define PATCH_HIT_TILE (PATCH_HIT_INTERIOR+1)
00074
00075 #define MAX_TILE_IN_PATCH 16
00076 #define NUM_TILE_SEL (MAX_TILE_IN_PATCH*MAX_TILE_IN_PATCH)
00077
00078 #pragma warning (disable : 4786)
00079
00080
00081
00082 00083 00084 00085 00086 00087 00088
00089
00090 class CVertexNeighborhood;
00091
00092 int CheckBind (int nVert, int nSeg, int& v0, int& v1, int& v2, int& v3, const CVertexNeighborhood& tab, const PatchMesh& patch, bool bAssert, bool bCreate);
00093 std::string GetBankPathName ();
00094 int GetBankTileSetSet ();
00095 void SetBankPathName (const std::string& path);
00096 void SetBankTileSetSet (int);
00097 int WhereIsTheEdge (int nPatch, int nEdge, const PatchMesh& patch);
00098
00099 extern NL3D::CTileBank bank;
00100
00101 #define RPO_DEFAULT_TESSEL 4
00102
00103 enum typeBind { BIND_25=0, BIND_75, BIND_50, BIND_SINGLE, BIND_COUNT, BIND_ALIGN=0xffffffff };
00104
00105 extern float bindWhere[BIND_COUNT];
00106
00107 class bindingDesc
00108 {
00109 public:
00110 uint8 bBinded;
00111 uint8 nType;
00112 uint16 nPatch;
00113 uint16 nEdge;
00114 uint16 nPrimVert;
00115 uint16 nBefore;
00116 uint16 nBefore2;
00117 uint16 nAfter;
00118 uint16 nAfter2;
00119 uint16 nT;
00120 uint16 fnslmq;
00121
00122
00123 };
00124
00125 class tileIndex
00126 {
00127 public:
00128 tileIndex ()
00129 {}
00130 tileIndex ( bool invert, int tile, int rotate)
00131 {
00132 Invert=invert;
00133 Tile=tile;
00134 Rotate=rotate;
00135 }
00136 uint Tile:16;
00137 int Rotate:8;
00138 int Invert:1;
00139 };
00140
00141 class tileDesc
00142 {
00143 #define CASE_MASK 0x7
00144 friend class RPatchMesh;
00145 public:
00146 void setTile (int num, int ncase, tileIndex tile0, tileIndex tile1, tileIndex tile2)
00147 {
00148 _Num=num;
00149 _MatIDTab[0]=tile0;
00150 _MatIDTab[1]=tile1;
00151 _MatIDTab[2]=tile2;
00152 setCase (ncase);
00153 }
00154 tileIndex& getLayer (int num)
00155 {
00156 return _MatIDTab[num];
00157 }
00158 const tileIndex& getLayer (int num) const
00159 {
00160 return _MatIDTab[num];
00161 }
00162 int getNumLayer ()
00163 {
00164 return _Num;
00165 }
00166 void setEmpty ()
00167 {
00168 _Num=0;
00169 _Flags=0;
00170 }
00171 bool isEmpty ()
00172 {
00173 return _Num==0;
00174 }
00175 void rotate (int nRotate)
00176 {
00177 for (int i=0; i<3; i++)
00178 {
00179 _MatIDTab[i].Rotate+=nRotate;
00180 _MatIDTab[i].Rotate&=3;
00181 }
00182 }
00183 int getCase() const
00184 {
00185 return _Flags&CASE_MASK;
00186 }
00187 void setCase(int nCase)
00188 {
00189 nlassert ((nCase>=0)&&(nCase<5));
00190 _Flags&=~CASE_MASK;
00191 _Flags|=nCase;
00192 }
00193 private:
00194 tileIndex _MatIDTab[3];
00195 USHORT _Num;
00196 USHORT _Flags;
00197 };
00198
00199 class UI_VERTEX
00200 {
00201 public:
00202 bindingDesc Binding;
00203 void Init ()
00204 {
00205 Binding.bBinded=false;
00206 }
00207 };
00208
00209
00210 #define UI_EDGE_FLAGS_NO_SMOOTH_MASK 0x1
00211
00212
00213 class CEdgeInfo
00214 {
00215 public:
00216
00217 CEdgeInfo ()
00218 {
00219
00220 Flags=0;
00221 }
00222
00223
00224 uint32 Flags;
00225 };
00226
00227 class UI_PATCH
00228 {
00229 public:
00230 int NbTilesU;
00231 int NbTilesV;
00232
00233 private:
00234
00235 tileDesc Tile[16*16];
00236
00237
00238 uint Colors[17*17];
00239
00240
00241 CEdgeInfo _Edges[4];
00242 public:
00243
00244 tileDesc& getTileDesc (uint iD)
00245 {
00246
00247 nlassert (iD<getTileSize ());
00248
00249
00250 return Tile[iD];
00251 }
00252
00253
00254 const tileDesc& getTileDesc (uint iD) const
00255 {
00256
00257 nlassert (iD<getTileSize ());
00258
00259
00260 return Tile[iD];
00261 }
00262
00263
00264 uint getColor (uint iD) const
00265 {
00266
00267 nlassert (iD<getColorSize ());
00268
00269
00270 return Colors[iD];
00271 }
00272
00273
00274 void setColor (uint iD, uint newColor)
00275 {
00276
00277 nlassert (iD<getColorSize ());
00278
00279
00280 Colors[iD]=newColor;
00281 }
00282
00283
00284 uint getTileSize () const
00285 {
00286 return (1<<NbTilesU)*(1<<NbTilesV);
00287 }
00288
00289
00290 uint getColorSize () const
00291 {
00292 return ((1<<NbTilesU)+1)*((1<<NbTilesV)+1);
00293 }
00294
00295
00296 bool getEdgeFlag (uint edge)
00297 {
00298 nlassert ((edge>=0)&&(edge<4));
00299 return (_Edges[edge].Flags&UI_EDGE_FLAGS_NO_SMOOTH_MASK)!=0;
00300 }
00301
00302
00303 void setEdgeFlag (uint edge, bool flags)
00304 {
00305 nlassert ((edge>=0)&&(edge<4));
00306
00307 _Edges[edge].Flags&=~UI_EDGE_FLAGS_NO_SMOOTH_MASK;
00308 _Edges[edge].Flags|=(uint32)flags;
00309 }
00310
00311
00312 CEdgeInfo& getEdge (uint edge)
00313 {
00314 return _Edges[edge];
00315 }
00316
00317
00318 const CEdgeInfo& getEdge (uint edge) const
00319 {
00320 return _Edges[edge];
00321 }
00322 public:
00323 void Init (int nU=RPO_DEFAULT_TESSEL, int nV=RPO_DEFAULT_TESSEL, bool bKeep=false)
00324 {
00325
00326 UI_PATCH old=*this;
00327
00328
00329 int nOldU=old.NbTilesU;
00330 int nOldV=old.NbTilesV;
00331 int nNewU=1<<nU;
00332 int nNewV=1<<nV;
00333 NbTilesU=nU;
00334 NbTilesV=nV;
00335 int nTileCount=(1<<NbTilesU)*(1<<NbTilesV);
00336 int nVertexCount=((1<<NbTilesU)+1)*((1<<NbTilesV)+1);
00337
00338
00339 if (bKeep)
00340 {
00341
00342 int i,j;
00343 int nMinU=std::min (nOldU, nNewU);
00344 int nMinV=std::min (nOldV, nNewV);
00345 for (j=0; j<nMinV; j++)
00346 {
00347 for (i=0; i<nMinU; i++)
00348 {
00349 Tile[i+j*nNewU]=old.getTileDesc (i+j*nOldU);
00350 }
00351 for (; i<nNewU; i++)
00352 {
00353 Tile[i+j*nNewU].setEmpty ();
00354 }
00355 }
00356 for (; j<nNewV; j++)
00357 {
00358 for (i=0; i<nNewU; i++)
00359 {
00360 Tile[i+j*nNewU].setEmpty ();
00361 }
00362 }
00363 for (j=0; j<nMinV+1; j++)
00364 {
00365 for (i=0; i<nMinU+1; i++)
00366 {
00367 Colors[i+j*(nNewU+1)]=old.getColor (i+j*(nOldU+1));
00368 }
00369 for (; i<nNewU+1; i++)
00370 {
00371 Colors[i+j*nNewU]=0xffffff;
00372 }
00373 }
00374 for (; j<nNewV+1; j++)
00375 {
00376 for (i=0; i<nMinU+1; i++)
00377 {
00378 Colors[i+j*nNewU]=0xffffff;
00379 }
00380 }
00381 }
00382 else
00383 {
00384
00385 int j;
00386 for(j=0; j<nTileCount; j++)
00387 {
00388 Tile[j].setEmpty ();
00389 }
00390 for(j=0; j<nVertexCount; j++)
00391 {
00392 Colors[j]=0xffffff;
00393 }
00394 }
00395 }
00396 };
00397
00398 class CPatchAllocator
00399 {
00400 public:
00401 CPatchAllocator ();
00402 CPathMeshAlloc<UI_PATCH> AllocPatch;
00403 CPathMeshAlloc<UI_VERTEX> AllocVertex;
00404 CPathMeshAlloc<int> AllocInt;
00405 };
00406
00407 struct RPOTess
00408 {
00409 int TileTesselLevel;
00410 bool ModeTile;
00411 bool KeepMapping;
00412 int TransitionType;
00413 };
00414
00415 class CBankManager
00416 {
00417 public:
00418 CBankManager ()
00419 {
00420 _lastPath="";
00421 }
00422 const NL3D::CTileBank& getBank (std::string& path=GetBankPathName ())
00423 {
00424 if (path!=_lastPath)
00425 {
00426 try
00427 {
00428 NLMISC::CIFile file;
00429 if (file.open (path))
00430 {
00431 _bank.clear();
00432 _bank.serial (file);
00433 }
00434 }
00435 catch (NLMISC::EStream& excp)
00436 {
00437 MessageBox (NULL, excp.what(), "Load error", MB_OK|MB_ICONEXCLAMATION);
00438 }
00439 }
00440 return _bank;
00441 }
00442 private:
00443 NL3D::CTileBank _bank;
00444 std::string _lastPath;
00445 };
00446
00447
00448 class CPatchMeshData
00449 {
00450 public:
00451
00452 CPatchMeshData ();
00453
00454
00455 CPatchMeshData (const CPatchMeshData& src);
00456
00457 ~CPatchMeshData ();
00458
00459
00460 CPatchMeshData& operator= (const CPatchMeshData& src);
00461
00462
00463 std::vector<UI_PATCH> *_UIPatch;
00464 std::vector<UI_VERTEX> *_UIVertex;
00465 std::vector<int> *_MapHitToTileIndex;
00466 };
00467
00468 class RPatchMesh
00469 {
00470 friend class RPO;
00471 public:
00472 RPatchMesh ();
00473 ~RPatchMesh ();
00474
00475
00476
00477 private:
00478 CPatchMeshData _Data;
00479 private:
00480
00481 void resizeMapHit (uint size)
00482 {
00483 _Data._MapHitToTileIndex->resize (size);
00484 }
00485
00486
00487 void setRemapEntry (uint iD, uint remap)
00488 {
00489 (*_Data._MapHitToTileIndex)[iD]=remap;
00490 }
00491
00492
00493 void resizeUIPatch (uint size)
00494 {
00495 _Data._UIPatch->resize (size);
00496 }
00497
00498
00499 void resizeUIVertex (uint size)
00500 {
00501 _Data._UIVertex->resize (size);
00502 }
00503 public:
00504
00505 uint getMapHitSize () const
00506 {
00507 return _Data._MapHitToTileIndex->size ();
00508 }
00509
00510
00511 uint remapTriangle (uint iD) const
00512 {
00513 nlassert (iD<getMapHitSize ());
00514 return (*_Data._MapHitToTileIndex)[iD];
00515 }
00516
00517
00518 uint getUIPatchSize () const
00519 {
00520 return _Data._UIPatch->size();
00521 }
00522
00523
00524 UI_PATCH& getUIPatch (uint iD)
00525 {
00526
00527 nlassert (iD<getUIPatchSize ());
00528
00529 return (*_Data._UIPatch)[iD];
00530 }
00531
00532
00533 const UI_PATCH& getUIPatch (uint iD) const
00534 {
00535
00536 nlassert (iD<getUIPatchSize ());
00537
00538 return (*_Data._UIPatch)[iD];
00539 }
00540
00541
00542 uint getUIVertexSize () const
00543 {
00544 return _Data._UIVertex->size();
00545 }
00546
00547
00548 UI_VERTEX& getUIVertex (uint iD)
00549 {
00550
00551 nlassert (iD<getUIVertexSize ());
00552
00553 return (*_Data._UIVertex)[iD];
00554 }
00555
00556
00557 const UI_VERTEX& getUIVertex (uint iD) const
00558 {
00559
00560 nlassert (iD<getUIVertexSize ());
00561
00562 return (*_Data._UIVertex)[iD];
00563 }
00564
00565 public:
00566
00567 Interval ValidGeom;
00568 Interval ValidTopo;
00569 Interval ValidTexmap;
00570 Interval ValidSelect;
00571 Interval ValidDisplay;
00572 Interval ValidBindingPos;
00573 Interval ValidBindingInfo;
00574 BitArray tileSel;
00575 #pragma warning (disable : 4786)
00576
00577
00578 RPOTess rTess;
00579 private:
00580
00581 Mesh mesh;
00582
00583 int selLevel;
00584 int tileSet;
00585 int build;
00586 public:
00587 bool paint;
00588 bool paintHack;
00589 private:
00590 static CBankManager manager;
00591
00592
00593 void BindingVertex (int nVertex, int nPatch, int nEdge, int nPrimary, typeBind nType);
00594
00595
00596 void UnBindingVertex (int nVertex);
00597
00598
00599 void UnbindRelatedPatch (int nPatch, PatchMesh& patch);
00600
00601
00602 void UnbindRelatedVertex (int nPatch, PatchMesh& patch);
00603
00604
00605 void UpdateBindingPos (PatchMesh& patch);
00606
00607
00608 void UpdateBindingInfo (PatchMesh& patch);
00609
00610
00611 void FindPatch (PatchMesh *patch, int nEdge, int &WhichEdge, int &nPatch, int nFirstPatch);
00612 public:
00613
00614 RPatchMesh (PatchMesh *pmesh);
00615
00616
00617 void InvalidateBindingPos () { ValidBindingPos=NEVER; };
00618 void InvalidateBindingInfo () { ValidBindingInfo=NEVER; InvalidateBindingPos (); };
00619
00620
00621 void UpdateBinding (PatchMesh& patch, TimeValue t);
00622
00623
00624 bool Validity (const PatchMesh& patch, bool bAssert);
00625
00626
00627 void SetNumVerts (int nVert);
00628
00629
00630 void SetNumPatches (int nPatch);
00631
00632
00633 void Subdivide (int nPatch, int nV0, int nV1, int nV2, int nV3, int nCenter, int nFirstPatch, PatchMesh& patch);
00634
00635
00636 void SubdivideU (int nPatch, int nV0, int nV1, int nFirstPatch, PatchMesh& patch);
00637
00638
00639 void SubdivideV (int nPatch, int nV0, int nV1, int nFirstPatch, PatchMesh& patch);
00640
00641
00642 void AddHook (int nVert, int nSeg, PatchMesh& patch);
00643
00644
00645 void AddHook (int nVert0, int nVert1, int nVert2, int nSeg, PatchMesh& patch);
00646
00647
00648 void RemoveHook (PatchMesh& patch);
00649
00650
00651 void Attach(RPatchMesh *rattPatch, PatchMesh& patch);
00652
00653
00654 void CreateExtrusion (PatchMesh *rpatch);
00655
00656
00657 void Weld (PatchMesh *patch);
00658
00659
00660 void AddPatch (int nEdge, int nFirstPatch, PatchMesh *patch);
00661
00662
00663 void DeleteAndSweep (const BitArray &remapVerts, const BitArray &remapPatches, PatchMesh& patch);
00664
00665
00666 void InvalidateChannels(ChannelMask channels);
00667
00668
00669 void ResolveTopoChanges(PatchMesh *patch);
00670
00671
00672 void SetSelLevel (int sellevel)
00673 {
00674 selLevel=sellevel;
00675 InvalidateChannels(PART_SELECT);
00676 }
00677
00678
00679 int GetSelLevel ()
00680 {
00681 return selLevel;
00682 }
00683
00684
00685 IOResult Load(ILoad *iload);
00686
00687
00688 IOResult Save(ISave *isave);
00689
00690
00691
00692
00693 Matrix3 GetSelTileTm(PatchMesh& patch, TimeValue t, INode *node, bool& bHasSel) const;
00694
00695
00696 Point3 GetSelTileCenter(PatchMesh& patch, TimeValue t, INode *node, bool& bHasSel) const;
00697
00698
00699 BOOL SubObjectHitTest(GraphicsWindow *gw, Material *ma, HitRegion *hr, DWORD flags, SubPatchHitList& hitList, TimeValue t,
00700 PatchMesh& patch);
00701
00702
00703 int GetTileNumber(int nPatch, int nU, int nV) const
00704 {
00705 nlassert (nU>=0);
00706 nlassert (nU<MAX_TILE_IN_PATCH);
00707 nlassert (nV>=0);
00708 nlassert (nV<MAX_TILE_IN_PATCH);
00709 return nV*MAX_TILE_IN_PATCH+nU+nPatch*NUM_TILE_SEL;
00710 }
00711
00712
00713 void BuildMesh(TimeValue t, PatchMesh& patch, Mesh *pMesh=NULL);
00714
00715
00716 void GetPatchTess (int nPatch, int& nUTess, int& nVTess);
00717
00718
00719 int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags, PatchMesh& patch);
00720
00721
00722 tileDesc& getTileDesc (int nTile);
00723
00724
00725 void setTileDesc (int nTile, const tileDesc& desc);
00726
00727
00728 void TurnPatch(PatchMesh *patch);
00729
00730
00731 void exportZone(INode* pNode, PatchMesh* pPM, NL3D::CZone& zone, int zoneId);
00732
00733
00734
00735
00736 void getVertexColor (int patch, int s, int t, NLMISC::CRGBA& dest)
00737 {
00738
00739 uint encodedColor=getUIPatch (patch).getColor (t*((1<<getUIPatch (patch).NbTilesU)+1)+s);
00740
00741
00742 dest.A=encodedColor>>24;
00743 dest.R=(encodedColor>>16)&0xff;
00744 dest.G=(encodedColor>>8)&0xff;
00745 dest.B=encodedColor&0xff;
00746 }
00747
00748
00749 void setVertexColor (int patch, int s, int t, const NLMISC::CRGBA& newColor)
00750 {
00751
00752 uint encodedColor=(newColor.A<<24)|(newColor.R<<16)|(newColor.G<<8)|newColor.B;
00753
00754
00755 getUIPatch (patch).setColor (t*((1<<getUIPatch (patch).NbTilesU)+1)+s, encodedColor);
00756 }
00757 };
00758
00759
00760
00761 #endif // __RYKOL_PATCH_MESH_H