From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- .../nel/zone__symmetrisation_8cpp-source.html | 977 +++++++++++++++++++++ 1 file changed, 977 insertions(+) create mode 100644 docs/doxygen/nel/zone__symmetrisation_8cpp-source.html (limited to 'docs/doxygen/nel/zone__symmetrisation_8cpp-source.html') diff --git a/docs/doxygen/nel/zone__symmetrisation_8cpp-source.html b/docs/doxygen/nel/zone__symmetrisation_8cpp-source.html new file mode 100644 index 00000000..f5b1ccd0 --- /dev/null +++ b/docs/doxygen/nel/zone__symmetrisation_8cpp-source.html @@ -0,0 +1,977 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

zone_symmetrisation.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000-2002 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "std3d.h"
+00027 #include "3d/zone_symmetrisation.h"
+00028 #include "3d/zone.h"
+00029 #include "3d/tile_bank.h"
+00030 
+00031 using namespace std;
+00032 using namespace NLMISC;
+00033 
+00034 namespace NL3D 
+00035 {
+00036 
+00037 // ***************************************************************************
+00038 
+00039 CZoneSymmetrisation::CZoneSymmetrisation()
+00040 {
+00041 }
+00042 
+00043 // ***************************************************************************
+00044 
+00045 /*
+00046 Bit field
+00047         1-0 : state layer 0
+00048         3-2 : state layer 1
+00049         5-4 : state layer 2
+00050         7-6 : border state
+00051         9-8 : oriented border state
+00052         10  : corner flag
+00053 */
+00054 
+00055 // ***************************************************************************
+00056 
+00057 CZoneSymmetrisation::TState CZoneSymmetrisation::getTileState (uint patch, uint tile, uint layer) const
+00058 {
+00059         nlassert (layer<5);
+00060         return (TState)((_TilesLayerStates[patch][tile]>>(layer*2))&0x3);
+00061 }
+00062 
+00063 // ***************************************************************************
+00064 
+00065 CZoneSymmetrisation::TState CZoneSymmetrisation::getTileBorderState (uint patch, uint tile) const
+00066 {
+00067         return getTileState (patch, tile, 3);
+00068 }
+00069 
+00070 // ***************************************************************************
+00071 
+00072 CZoneSymmetrisation::TState CZoneSymmetrisation::getOrientedTileBorderState (uint patch, uint tile) const
+00073 {
+00074         return getTileState (patch, tile, 4);
+00075 }
+00076 
+00077 // ***************************************************************************
+00078 
+00079 bool CZoneSymmetrisation::getOrientedTileCorner (uint patch, uint tile)
+00080 {
+00081         return ( ( _TilesLayerStates[patch][tile] >> 10 ) & 1 ) != 0;
+00082 }
+00083 
+00084 // ***************************************************************************
+00085 
+00086 void CZoneSymmetrisation::setTileState (uint patch, uint tile, uint layer, TState state)
+00087 {
+00088         uint16 &ref = _TilesLayerStates[patch][tile];
+00089         ref &= ~(3<<(layer*2));
+00090         ref |= ((uint16)state)<<(layer*2);
+00091 }
+00092 
+00093 // ***************************************************************************
+00094 
+00095 void CZoneSymmetrisation::setTileBorderState (uint patch, uint tile, TState state)
+00096 {
+00097         setTileState (patch, tile, 3, state);
+00098 }
+00099 
+00100 // ***************************************************************************
+00101 
+00102 void CZoneSymmetrisation::setOrientedTileBorderState (uint patch, uint tile, TState state)
+00103 {
+00104         setTileState (patch, tile, 4, state);
+00105 }
+00106 
+00107 // ***************************************************************************
+00108 
+00109 void CZoneSymmetrisation::setOrientedTileCorner (uint patch, uint tile, bool corner)
+00110 {
+00111         uint16 &ref = _TilesLayerStates[patch][tile];
+00112         ref &= ~(1<<10);
+00113         ref |= ((uint16)corner)<<(10);
+00114 }
+00115 
+00116 // ***************************************************************************
+00117 
+00118 /*
+00119 
+00120 REMARKS:
+00121 - I call "isotile" the set of connected tiles in the zone using the same tileset and a continus rotation value.
+00122 
+00123 This method determines the state of each tile in the zone. This state will be used to transform
+00124 the tile during symmetrisation of the zone.
+00125 
+00126 The state can be Regular, Goofy or Nothing.
+00127 
+00128 If the state is Nothing, this tile is in an "isotile" that is not connected to a zone border. No matter the method
+00129 you use to tranform it, it will not influence the neighbor zones.
+00130 
+00131 If the state is Regular, the rotation of this tile after symmetrisation will by given by this formula : tilerot = (4-tilerot)&3
+00132 If the state is Goofy, the rotation of this tile after symmetrisation will by given by this formula : tilerot = (4-tilerot+2)&3
+00133 
+00134 - Getting the state of the tile:
+00135         - A) We flag all the zone patches as Nothing.
+00136         - B) We need to select patches having an open edge on the zone border. To do so, we use the snapCell and weldThreshold
+00137         parameters.
+00138         - C) Then, for each patches on the zone border, we need to know if they are Goofy or Regular.
+00139 
+00140                 Y
+00141   
+00142                 /\
+00143                 | 
+00144                 |  0     3
+00145                 |   *****
+00146                 |   *   *   This patch is regular
+00147                 |   *   *
+00148                 |   *****
+00149                 |  1     2
+00150                 | 
+00151                 |  2     1
+00152                 |   *****
+00153                 |   *   *   This patch is regular
+00154                 |   *   *
+00155                 |   *****
+00156                 |  3     0
+00157                 | 
+00158                 |  3     2
+00159                 |   *****
+00160                 |   *   *   This patch is goofy
+00161                 |   *   *
+00162                 |   *****
+00163                 |  0     1
+00164                 | 
+00165                 |  1     4
+00166                 |   *****
+00167                 |   *   *   This patch is goofy
+00168                 |   *   *
+00169                 |   *****
+00170                 |  2     3
+00171                 -----------------------------------------> X
+00172 
+00173         - D) We flag each tiles as Nothing
+00174         - E) We flag each tile on an opened edge using this formula:
+00175                 - If the patch is not Nothing do
+00176                         - tileIsGoofy = (patchIsGoofy) XOR ((tileRotation&1) != 0)
+00177         - F) Then, we propagate the tile A flag across the tiles in the zone following this rules:
+00178                 - If A is not Nothing do
+00179                         - For each neighbor B of A do
+00180                                 - If B is different from A do
+00181                                         - If A is Regular (res Goofy), and B is Nothing, B will be Regular (res Goofy)
+00182                                         - If A is Regular (res Goofy), and B is Goofy (res Regular), -> Error
+00183                                         - Propagate B
+00184 */
+00185 
+00186 bool CZoneSymmetrisation::build (const std::vector<CPatchInfo> &patchInfo, float snapCell, float weldThreshold, const CTileBank &bank, CError &errorDesc, const NLMISC::CMatrix &toOriginalSpace)
+00187 {
+00188         // * Clear errors
+00189         errorDesc.Errors.clear ();
+00190 
+00191         // * Build the patches state
+00192         
+00193         // A) Resize arrays
+00194         _TilesLayerStates.resize (patchInfo.size ());
+00195 
+00196         // D) Resize the tile array
+00197         uint i;
+00198         for (i=0; i<patchInfo.size (); i++)
+00199         {
+00200                 // Ref on the patch
+00201                 const CPatchInfo &patch = patchInfo[i];
+00202                 _TilesLayerStates[i].resize (0);
+00203                 _TilesLayerStates[i].resize (patch.OrderS * patch.OrderT, 0);
+00204         }
+00205 
+00206         // B), C) and E) We need to select patches having an open edge on the zone border. To do so, we use the snapCell and weldThreshold parameters
+00207         for (i=0; i<patchInfo.size (); i++)
+00208         {
+00209                 // Ref on the patch
+00210                 const CPatchInfo &patch = patchInfo[i];
+00211 
+00212                 // Does this patch is over a border ?
+00213                 TState patchState;
+00214                 if (!setTileState (patch, i, snapCell, weldThreshold, patchState, toOriginalSpace, bank))
+00215                 {
+00216                         // Push an error
+00217                         errorDesc.Errors.push_back ("Patch n°"+toString (i)+" is invalid");
+00218                 }
+00219 
+00220                 // Set the oriented patch state
+00221                 if (!setOrientedTileState (patch, i, snapCell, weldThreshold, patchState, toOriginalSpace, bank))
+00222                 {
+00223                         // Push an error
+00224                         errorDesc.Errors.push_back ("Patch n°"+toString (i)+" is invalid");
+00225                 }
+00226         }
+00227 
+00228         // F) We flag each tile on an opened edge using this formula
+00229         //      - If the patch is not Nothing do
+00230         //              - tileIsGoofy = (patchIsGoofy) XOR ((tileRotation&1) != 0)
+00231         for (i=0; i<patchInfo.size (); i++)
+00232         {
+00233                 // Ref on the patch
+00234                 const CPatchInfo &patch = patchInfo[i];
+00235 
+00236                 // For each tile
+00237                 uint s,t;
+00238                 for (t=0; t<patch.OrderT; t++)
+00239                 {
+00240                         for (s=0; s<patch.OrderS; s++)
+00241                         {
+00242                                 if (!propagateTileState (i, s, t, patchInfo, bank, false))
+00243                                 {
+00244                                         // Push an error
+00245                                         errorDesc.Errors.push_back ("Error during propagation. Topology invalid.");
+00246                                         return false;
+00247                                 }
+00248                         }
+00249                 }
+00250         }
+00251 
+00252         // G) Force all remaining Nothing tiles to Regular
+00253         for (i=0; i<patchInfo.size (); i++)
+00254         {
+00255                 // Ref on the patch
+00256                 const CPatchInfo &patch = patchInfo[i];
+00257 
+00258                 // For each tile
+00259                 uint s,t;
+00260                 for (t=0; t<patch.OrderT; t++)
+00261                 {
+00262                         for (s=0; s<patch.OrderS; s++)
+00263                         {
+00264                                 if (!propagateTileState (i, s, t, patchInfo, bank, true))
+00265                                 {
+00266                                         // Push an error
+00267                                         errorDesc.Errors.push_back ("Error during propagation. Topology invalid.");
+00268                                         return false;
+00269                                 }
+00270                         }
+00271                 }
+00272         }
+00273 
+00274         // Returns true if no error
+00275         return errorDesc.Errors.size () == 0;
+00276 }
+00277 
+00278 // ***************************************************************************
+00279 
+00280 bool CZoneSymmetrisation::snapOnGrid (float& value, float resolution, float snap)
+00281 {
+00282         // Calc the floor
+00283         float _floor = (float) ( resolution * floor (value / resolution) );
+00284         nlassert (_floor<=value);
+00285 
+00286         // Calc the remainder
+00287         float remainder = value - _floor;
+00288         //nlassert ( (remainder>=0) && (remainder<resolution) );
+00289 
+00290         // Check the snape
+00291         if ( remainder <= snap )
+00292         {
+00293                 // Flag it
+00294                 value = _floor;
+00295 
+00296                 // Floor is good
+00297                 return true;
+00298         }
+00299         else if ( (resolution - remainder) <= snap )
+00300         {
+00301                 // Flag it
+00302                 value = _floor + resolution;
+00303 
+00304                 // Floor + resolution is good
+00305                 return true;
+00306         }
+00307         return false;
+00308 }
+00309 
+00310 // ***************************************************************************
+00311 
+00312 bool CZoneSymmetrisation::setTileState (const NL3D::CPatchInfo &patch, uint patchId, float snapCell, float weldThreshold, TState &state, const NLMISC::CMatrix &toOriginalSpace, const CTileBank &bank)
+00313 {
+00314         // Edges state
+00315         TState edgesState[4] = { Nothing, Nothing, Nothing, Nothing };
+00316 
+00317         // Vertices position
+00318         sint32 vertPosU[4];
+00319         sint32 vertPosV[4];
+00320         
+00321         // For each vertices
+00322         uint i;
+00323         for (i=0; i<4; i++)
+00324         {
+00325                 // Snap the vertex
+00326                 CVector original = toOriginalSpace * patch.Patch.Vertices[i];
+00327                 float valueU = original.x;
+00328                 float valueV = original.y;
+00329 
+00330                 // Snap on U
+00331                 if (snapOnGrid (valueU, snapCell, weldThreshold))
+00332                         vertPosU[i] = (sint32)((valueU+0.5f) / snapCell);
+00333                 else
+00334                         vertPosU[i] = 0x80000000;
+00335 
+00336                 // Snap on V
+00337                 if (snapOnGrid (valueV, snapCell, weldThreshold))
+00338                         vertPosV[i] = (sint32)((valueV+0.5f) / snapCell);
+00339                 else
+00340                         vertPosV[i] = 0x80000000;
+00341         }
+00342 
+00343         // Patch flags
+00344         bool regular = false;
+00345         bool goofy = false;
+00346         bool EdgeSnaped[4] = { false, false, false, false };
+00347 
+00348         // For each edges
+00349         for (i=0; i<4; i++)
+00350         {
+00351                 // Vertex snapped and align on a common axis ?
+00352                 if ( (vertPosU[i] != 0x80000000) || (vertPosV[i] != 0x80000000) )
+00353                 {
+00354                         // Snapped on U or V ?
+00355                         bool snapU = (vertPosU[i] == vertPosU[(i+1)&3]) && (vertPosU[i] != 0x80000000);
+00356                         bool snapV = (vertPosV[i] == vertPosV[(i+1)&3]) && (vertPosV[i] != 0x80000000);
+00357                         
+00358                         // If snapped on one, continue
+00359                         if (snapU || snapV)
+00360                         {
+00361                                 // If snap on the both, error
+00362                                 if (snapU && snapV)
+00363                                         return false;
+00364 
+00365                                 // Is this edge Regular or Goofy ?
+00366                                 if (snapU)
+00367                                         edgesState[i] = (i&1)?Goofy:Regular;
+00368                                 else // (snapV)
+00369                                         edgesState[i] = (i&1)?Regular:Goofy;
+00370 
+00371                                 // Flag the patch
+00372                                 if (edgesState[i] == Regular)
+00373                                         regular = true;
+00374                                 else
+00375                                         goofy = true;
+00376 
+00377                                 // Edge snaped
+00378                                 EdgeSnaped[i] = true;
+00379                         }
+00380                 }
+00381         }
+00382 
+00383         // Goofy and regular ? Error
+00384         if (goofy && regular)
+00385                 return false;
+00386 
+00387         // Nothing ?
+00388         if ((!goofy) && (!regular))
+00389                 state = Nothing;
+00390         else
+00391         {
+00392                 // Not nothing ?
+00393                 state = regular?Regular:Goofy;
+00394 
+00395                 // * Set the tiles
+00396 
+00397                 // For each edges
+00398                 for (i=0; i<4; i++)
+00399                 {
+00400                         // Edge snapped ?
+00401                         if (EdgeSnaped[i])
+00402                         {
+00403                                 // For each tiles
+00404                                 uint tileCount = ((i&1)!=0)?patch.OrderS:patch.OrderT;
+00405                                 sint currentTile;
+00406                                 sint delta;
+00407                                 switch (i)
+00408                                 {
+00409                                 case 0:
+00410                                         currentTile = 0;
+00411                                         delta = patch.OrderS;
+00412                                         break;
+00413                                 case 1:
+00414                                         currentTile = patch.OrderS*(patch.OrderT-1);
+00415                                         delta = 1;
+00416                                         break;
+00417                                 case 2:
+00418                                         currentTile = patch.OrderS-1;
+00419                                         delta = patch.OrderS;
+00420                                         break;
+00421                                 case 3:
+00422                                         currentTile = 0;
+00423                                         delta = 1;
+00424                                         break;
+00425                                 }
+00426                                 uint j;
+00427                                 for (j=0; j<tileCount; j++)
+00428                                 {
+00429                                         // Set the border state
+00430                                         setTileBorderState (patchId, currentTile, state);
+00431 
+00432                                         // For each layer
+00433                                         uint layer;
+00434                                         for (layer=0; layer<3; layer++)
+00435                                         {
+00436                                                 // Get the tiles set used here
+00437                                                 uint tile = patch.Tiles[currentTile].Tile[layer];
+00438                                                 if (tile != NL_TILE_ELM_LAYER_EMPTY)
+00439                                                 {
+00440                                                         int tileSet;
+00441                                                         int number;
+00442                                                         CTileBank::TTileType type;
+00443                                                         bank.getTileXRef (tile, tileSet, number, type);
+00444 
+00445                                                         // Set it only if not oriented
+00446                                                         if (!bank.getTileSet (tileSet)->getOriented ())
+00447                                                         {
+00448                                                                 // Set the tile state
+00449                                                                 setTileState (patchId, currentTile, layer, state);
+00450                                                         }
+00451                                                 }
+00452                                         }
+00453 
+00454                                         // Next tile
+00455                                         currentTile += delta;
+00456                                 }
+00457                         }
+00458                 }
+00459         }
+00460 
+00461         return true;
+00462 }
+00463 
+00464 // ***************************************************************************
+00465 
+00466 bool CZoneSymmetrisation::setOrientedTileState (const NL3D::CPatchInfo &patch, uint patchId, float snapCell, float weldThreshold, TState &state, const NLMISC::CMatrix &toOriginalSpace, const CTileBank &bank)
+00467 {
+00468         // Edges state
+00469         TState edgesState[4] = { Nothing, Nothing, Nothing, Nothing };
+00470 
+00471         // Vertices position
+00472         sint32 vertPosU[4];
+00473         sint32 vertPosV[4];
+00474         
+00475         // For each vertices
+00476         uint i;
+00477         for (i=0; i<4; i++)
+00478         {
+00479                 // Snap the vertex
+00480                 CVector original = toOriginalSpace * patch.Patch.Vertices[i];
+00481                 float valueU = original.x;
+00482                 float valueV = original.y;
+00483 
+00484                 // Snap on U
+00485                 if (snapOnGrid (valueU, snapCell, weldThreshold))
+00486                         vertPosU[i] = (sint32)((valueU+0.5f) / snapCell);
+00487                 else
+00488                         vertPosU[i] = 0x80000000;
+00489 
+00490                 // Snap on V
+00491                 if (snapOnGrid (valueV, snapCell, weldThreshold))
+00492                         vertPosV[i] = (sint32)((valueV+0.5f) / snapCell);
+00493                 else
+00494                         vertPosV[i] = 0x80000000;
+00495         }
+00496 
+00497         // Patch flags
+00498         bool regular = false;
+00499         bool goofy = false;
+00500         bool EdgeSnaped[4] = { false, false, false, false };
+00501 
+00502         // For each edges
+00503         for (i=0; i<4; i++)
+00504         {
+00505                 // Vertex snapped and align on a common axis ?
+00506                 if ( (vertPosU[i] != 0x80000000) || (vertPosV[i] != 0x80000000) )
+00507                 {
+00508                         // Snapped on U or V ?
+00509                         bool snapU = (vertPosU[i] == vertPosU[(i+1)&3]) && (vertPosU[i] != 0x80000000);
+00510                         bool snapV = (vertPosV[i] == vertPosV[(i+1)&3]) && (vertPosV[i] != 0x80000000);
+00511                         
+00512                         // If snapped on one, continue
+00513                         if (snapU || snapV)
+00514                         {
+00515                                 // If snap on the both, error
+00516                                 if (snapU && snapV)
+00517                                         return false;
+00518 
+00519                                 // Is this edge Regular or Goofy ?
+00520                                 edgesState[i] = (i&1)?Goofy:Regular;
+00521 
+00522                                 // Flag the patch
+00523                                 if (edgesState[i] == Regular)
+00524                                         regular = true;
+00525                                 else
+00526                                         goofy = true;
+00527 
+00528                                 // Edge snaped
+00529                                 EdgeSnaped[i] = true;
+00530                         }
+00531                 }
+00532         }
+00533 
+00534         // * Set the tiles
+00535 
+00536         // For each edges
+00537         for (i=0; i<4; i++)
+00538         {
+00539                 // Edge snapped ?
+00540                 if (EdgeSnaped[i])
+00541                 {
+00542                         // For each tiles
+00543                         uint tileCount = ((i&1)!=0)?patch.OrderS:patch.OrderT;
+00544                         sint currentTile;
+00545                         sint delta;
+00546                         switch (i)
+00547                         {
+00548                         case 0:
+00549                                 currentTile = 0;
+00550                                 delta = patch.OrderS;
+00551                                 break;
+00552                         case 1:
+00553                                 currentTile = patch.OrderS*(patch.OrderT-1);
+00554                                 delta = 1;
+00555                                 break;
+00556                         case 2:
+00557                                 currentTile = patch.OrderS-1;
+00558                                 delta = patch.OrderS;
+00559                                 break;
+00560                         case 3:
+00561                                 currentTile = 0;
+00562                                 delta = 1;
+00563                                 break;
+00564                         }
+00565                         uint j;
+00566                         for (j=0; j<tileCount; j++)
+00567                         {
+00568                                 // Set the border state
+00569                                 setOrientedTileBorderState (patchId, currentTile, edgesState[i]);
+00570 
+00571                                 // For each layer
+00572                                 uint layer;
+00573                                 for (layer=0; layer<3; layer++)
+00574                                 {
+00575                                         // Get the tiles set used here
+00576                                         uint tile = patch.Tiles[currentTile].Tile[layer];
+00577                                         if (tile != NL_TILE_ELM_LAYER_EMPTY)
+00578                                         {
+00579                                                 int tileSet;
+00580                                                 int number;
+00581                                                 CTileBank::TTileType type;
+00582                                                 bank.getTileXRef (tile, tileSet, number, type);
+00583 
+00584                                                 // Set it only if oriented
+00585                                                 if (bank.getTileSet (tileSet)->getOriented ())
+00586                                                 {
+00587                                                         setTileState (patchId, currentTile, layer, edgesState[i]);
+00588                                                 }
+00589                                         }
+00590                                 }
+00591 
+00592                                 // Next tile
+00593                                 currentTile += delta;
+00594                         }
+00595                 }
+00596         }
+00597         
+00598         // For each corners
+00599         for (i=0; i<4; i++)
+00600         {
+00601                 // Corner snapped ?
+00602                 uint next = (i+1)&3;
+00603                 if (EdgeSnaped[i] && EdgeSnaped[next])
+00604                 {
+00605                         // Flag tile as corner
+00606                         switch (i)
+00607                         {
+00608                         case 0:
+00609                                 setOrientedTileCorner (patchId, patch.OrderS*(patch.OrderT-1), true);
+00610                                 break;
+00611                         case 1:
+00612                                 setOrientedTileCorner (patchId, patch.OrderS*patch.OrderT-1, true);
+00613                                 break;
+00614                         case 2:
+00615                                 setOrientedTileCorner (patchId, patch.OrderS-1, true);
+00616                                 break;
+00617                         case 3:
+00618                                 setOrientedTileCorner (patchId, 0, true);
+00619                                 break;
+00620                         }
+00621                 }
+00622         }
+00623         
+00624         return true;
+00625 }
+00626 
+00627 // ***************************************************************************
+00628 
+00629 CVector2f st2uv (sint s, sint t, const CPatchInfo &patch)
+00630 {
+00631         return CVector2f ((((float)s)+0.5f)/(float)patch.OrderS, (((float)t)+0.5f)/(float)patch.OrderT);
+00632 }
+00633 
+00634 // ***************************************************************************
+00635 
+00636 void uv2st (const CVector2f &in, sint &s, sint &t, const CPatchInfo &patch)
+00637 {
+00638         s = (sint)(in.x*(float)patch.OrderS);
+00639         t = (sint)(in.y*(float)patch.OrderT);
+00640 }
+00641 
+00642 // ***************************************************************************
+00643 
+00644 class CFillStackNode
+00645 {
+00646 public:
+00647         CFillStackNode (uint16 patch, uint16 s, uint16 t, uint8 rotate, CZoneSymmetrisation::TState     state) { Patch = patch; S = s; T = t; Edge = 0; Rotate = rotate; State = state; };
+00648         uint16  S;
+00649         uint16  T;
+00650         uint16  Patch;
+00651         uint8   Edge;
+00652         uint8   Rotate;
+00653         CZoneSymmetrisation::TState     State;
+00654 };
+00655 
+00656 // ***************************************************************************
+00657 
+00658 bool CZoneSymmetrisation::propagateTileState (uint patch, uint s, uint t, const std::vector<CPatchInfo> &patchInfo, const CTileBank &bank, bool forceRegular)
+00659 {
+00660         // For each layer
+00661         uint layer;
+00662         for (layer=0; layer<3; layer++)
+00663         {
+00664                 // Get the patch ptr
+00665                 const CPatchInfo *currentPatchPtr = &(patchInfo[patch]);
+00666 
+00667                 // Get the tile index
+00668                 uint tile = s+t*currentPatchPtr->OrderS;
+00669 
+00670                 // Get the tiles set used here
+00671                 uint tileIndex = currentPatchPtr->Tiles[tile].Tile[layer];
+00672                 if (tileIndex != NL_TILE_ELM_LAYER_EMPTY)
+00673                 {
+00674                         // Valid tile number ?
+00675                         if (tileIndex >= (uint)bank.getTileCount ())
+00676                         {
+00677                                 nlwarning ("CZoneSymmetrisation::propagateTileState: Invalid tile index");
+00678                                 return false;
+00679                         }
+00680 
+00681                         // Get the tile set used by this layer
+00682                         int tileSetToPropagate;
+00683                         int number;
+00684                         CTileBank::TTileType type;
+00685                         bank.getTileXRef (tileIndex, tileSetToPropagate, number, type);
+00686 
+00687                         // Oriented ?
+00688                         bool oriented = bank.getTileSet (tileSetToPropagate)->getOriented ();
+00689 
+00690                         // If oriented, must not be a corner
+00691                         if (!(oriented && getOrientedTileCorner (patch, tile)))
+00692                         {
+00693                                 // Current node
+00694                                 CFillStackNode currentNode (patch, s, t, currentPatchPtr->Tiles[tile].getTileOrient(layer), getTileState (patch, tile, layer));
+00695 
+00696                                 // Propagate non-Nothing tiles
+00697                                 if ( (!forceRegular && (currentNode.State != Nothing)) || (forceRegular && (currentNode.State == Nothing)) )
+00698                                 {
+00699                                         // Force to Regular ?
+00700                                         if (forceRegular)
+00701                                         {
+00702                                                 setTileState (patch, tile, layer, Regular);
+00703                                                 currentNode.State = Regular;
+00704                                         }
+00705 
+00706                                         // Fill stack
+00707                                         vector<CFillStackNode>  stack;
+00708                                         stack.push_back (currentNode);
+00709 
+00710                                         // While people in the stack
+00711                                         while (!stack.empty ())
+00712                                         {               
+00713                                                 // Pop last element
+00714                                                 currentNode = stack.back ();
+00715                                                 stack.pop_back ();
+00716 
+00717                                                 do
+00718                                                 {
+00719                                                         // Set current patch pointer
+00720                                                         currentPatchPtr = &(patchInfo[currentNode.Patch]);
+00721 
+00722                                                         // Get neighbor
+00723                                                         CFillStackNode neighborNode (currentNode.Patch, currentNode.S, currentNode.T, currentNode.Rotate, currentNode.State);
+00724                                                         switch (currentNode.Edge)
+00725                                                         {
+00726                                                         case 0:
+00727                                                                 neighborNode.S--;
+00728                                                                 break;
+00729                                                         case 1:
+00730                                                                 neighborNode.T++;
+00731                                                                 break;
+00732                                                         case 2:
+00733                                                                 neighborNode.S++;
+00734                                                                 break;
+00735                                                         case 3:
+00736                                                                 neighborNode.T--;
+00737                                                                 break;
+00738                                                         }
+00739 
+00740                                                         // Is still in patch ?
+00741                                                         if ( (neighborNode.S<0) || (neighborNode.S>=patchInfo[currentNode.Patch].OrderS) || (neighborNode.T<0) || (neighborNode.T>=patchInfo[currentNode.Patch].OrderT) )
+00742                                                         {
+00743                                                                 // No, found new patch
+00744                                                                 uint position;
+00745                                                                 switch (currentNode.Edge)
+00746                                                                 {
+00747                                                                 case 0:
+00748                                                                         position = neighborNode.T;
+00749                                                                         break;
+00750                                                                 case 1:
+00751                                                                         position = neighborNode.S;
+00752                                                                         break;
+00753                                                                 case 2:
+00754                                                                         position = patchInfo[currentNode.Patch].OrderT - neighborNode.T - 1;
+00755                                                                         break;
+00756                                                                 case 3:
+00757                                                                         position = patchInfo[currentNode.Patch].OrderS - neighborNode.S - 1;
+00758                                                                         break;
+00759                                                                 }
+00760 
+00761                                                                 // Get next patch
+00762                                                                 uint patchOut;
+00763                                                                 sint sOut;
+00764                                                                 sint tOut;
+00765                                                                 if (patchInfo[currentNode.Patch].getNeighborTile (currentNode.Patch, currentNode.Edge, position, 
+00766                                                                         patchOut, sOut, tOut, patchInfo))
+00767                                                                 {
+00768                                                                         // Should be another patch
+00769                                                                         nlassert (patchOut != currentNode.Patch);
+00770 
+00771                                                                         // Get patch id
+00772                                                                         neighborNode.Patch = patchOut;
+00773 
+00774                                                                         // Coordinate must be IN the patch
+00775                                                                         nlassert (sOut >= 0);
+00776                                                                         nlassert (tOut >= 0);
+00777                                                                         nlassert (sOut < patchInfo[neighborNode.Patch].OrderS);
+00778                                                                         nlassert (tOut < patchInfo[neighborNode.Patch].OrderT);
+00779 
+00780                                                                         // Copy it
+00781                                                                         neighborNode.S = sOut;
+00782                                                                         neighborNode.T = tOut;
+00783 
+00784                                                                         // Find neighbor
+00785                                                                         const CPatchInfo::CBindInfo &neighborBindInfo = patchInfo[currentNode.Patch].BindEdges[currentNode.Edge];
+00786                                                                         uint edgePatch;
+00787                                                                         for (edgePatch=0; edgePatch<(uint)neighborBindInfo.NPatchs; edgePatch++)
+00788                                                                         {
+00789                                                                                 if (neighborBindInfo.Next[edgePatch] == neighborNode.Patch)
+00790                                                                                         break;
+00791                                                                         }
+00792 
+00793                                                                         // Must find one patch
+00794                                                                         nlassert (edgePatch<(uint)neighborBindInfo.NPatchs);
+00795 
+00796                                                                         // Rotation
+00797                                                                         neighborNode.Rotate = (currentNode.Rotate + 2 + neighborBindInfo.Edge[edgePatch] - currentNode.Edge) & 3;
+00798 
+00799                                                                         // Toggle the state ?
+00800                                                                         if ((neighborNode.Rotate ^ currentNode.Rotate) & 1)
+00801                                                                         {
+00802                                                                                 // Yes
+00803                                                                                 neighborNode.State = (neighborNode.State == Regular) ? Goofy : Regular;
+00804                                                                         }
+00805                                                                 }
+00806                                                                 else
+00807                                                                 {
+00808                                                                         // No propagation, continue
+00809                                                                         currentNode.Edge++;
+00810                                                                         continue;
+00811                                                                 }
+00812                                                         }
+00813 
+00814                                                         // Neighbor patch
+00815                                                         const CPatchInfo *neighborPatchPtr = &(patchInfo[neighborNode.Patch]);
+00816 
+00817                                                         // Get the tile index
+00818                                                         uint neighborTile = neighborNode.S+neighborNode.T*neighborPatchPtr->OrderS;
+00819                                                         
+00820                                                         // Look for the same tile set in the new tile
+00821                                                         uint neighborLayer;
+00822                                                         for (neighborLayer=0; neighborLayer<3; neighborLayer++)
+00823                                                         {
+00824                                                                 // Get the tile index
+00825                                                                 uint neighborTileIndex = neighborPatchPtr->Tiles[neighborTile].Tile[neighborLayer];
+00826 
+00827                                                                 if (neighborTileIndex != NL_TILE_ELM_LAYER_EMPTY)
+00828                                                                 {
+00829                                                                         // Valid tile number ?
+00830                                                                         if (neighborTileIndex >= (uint)bank.getTileCount ())
+00831                                                                         {
+00832                                                                                 nlwarning ("CZoneSymmetrisation::propagateTileState: Invalid tile index");
+00833                                                                                 return false;
+00834                                                                         }
+00835 
+00836                                                                         // Get tileset
+00837                                                                         int neighborTileSet;
+00838                                                                         int neighborNumber;
+00839                                                                         CTileBank::TTileType neighborType;
+00840                                                                         bank.getTileXRef (neighborTileIndex, neighborTileSet, neighborNumber, neighborType);
+00841 
+00842                                                                         // Same tileset ? Stop!
+00843                                                                         if (    (neighborTileSet == tileSetToPropagate) && 
+00844                                                                                         (neighborNode.Rotate == neighborPatchPtr->Tiles[neighborTile].getTileOrient(neighborLayer)) )
+00845                                                                                 break;
+00846                                                                 }
+00847                                                         }
+00848 
+00849                                                         // Found ?
+00850                                                         if (neighborLayer<3)
+00851                                                         {
+00852                                                                 // If oriented, must not be a corner
+00853                                                                 if (!(oriented && getOrientedTileCorner (neighborNode.Patch, neighborTile)))
+00854                                                                 {
+00855                                                                         // Propagate in the new node ?
+00856                                                                         TState neighborState = getTileState (neighborNode.Patch, neighborTile, neighborLayer);
+00857                                                                         if (neighborState == Nothing)
+00858                                                                         {
+00859                                                                                 // Set the state
+00860                                                                                 setTileState (neighborNode.Patch, neighborTile, neighborLayer, neighborNode.State);
+00861 
+00862                                                                                 // Stack current node if some neighbor left to visit
+00863                                                                                 if (currentNode.Edge < 3)
+00864                                                                                 {
+00865                                                                                         currentNode.Edge++;
+00866                                                                                         stack.push_back (currentNode);
+00867                                                                                 }
+00868 
+00869                                                                                 // Continue with the new node
+00870                                                                                 currentNode = neighborNode;
+00871                                                                         }
+00872                                                                         else if (neighborState != neighborNode.State)
+00873                                                                         {
+00874                                                                                 // Error, same tile but not same state
+00875                                                                                 nlwarning ("CZoneSymmetrisation::propagateTileState: error, find same iso surfaces with different state.");
+00876 
+00877                                                                                 // No propagation, continue
+00878                                                                                 currentNode.Edge++;
+00879                                                                         }
+00880                                                                         else
+00881                                                                         {
+00882                                                                                 // No propagation, continue
+00883                                                                                 currentNode.Edge++;
+00884                                                                         }
+00885                                                                 }
+00886                                                                 else
+00887                                                                 {
+00888                                                                         // No propagation, continue
+00889                                                                         currentNode.Edge++;
+00890                                                                 }
+00891                                                         }
+00892                                                         else
+00893                                                                 // No propagation, continue
+00894                                                                 currentNode.Edge++;
+00895                                                 }
+00896                                                 while (currentNode.Edge<4);
+00897                                         }
+00898                                 }
+00899                         }
+00900                 }
+00901         }
+00902 
+00903         return true;
+00904 }
+00905 
+00906 // ***************************************************************************
+00907 
+00908 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1