NL3D::CZoneSymmetrisation Class Reference

#include <zone_symmetrisation.h>


Detailed Description

Environnement used to symmetrise zones

This class build symmetry specific informations needed to know how transform tiles when a zone is symmetrise.

There is two states for a tile : Regular or Goofy. If the tile is regular, it doesn't need specific transformation when the zone is symmetrise. If the tile is goofy, the tile must be rotate by 180deg more to be correct.

Author:
Cyril 'Hulud' Corvazier

Nevrax France

Date:
2002

Definition at line 54 of file zone_symmetrisation.h.

Public Types

enum  TState { Nothing = 0, Regular = 1, Goofy = 2 }
 Symmetrie state. More...


Public Member Functions

bool build (const std::vector< CPatchInfo > &patchInfo, float snapCell, float weldThreshold, const CTileBank &bank, CError &errorDesc, const NLMISC::CMatrix &toOriginalSpace)
 CZoneSymmetrisation ()
 Constructor.

TState getOrientedTileBorderState (uint patch, uint tile) const
bool getOrientedTileCorner (uint patch, uint tile)
TState getTileBorderState (uint patch, uint tile) const
TState getTileState (uint patch, uint tile, uint layer) const

Private Member Functions

bool propagateTileState (uint i, uint s, uint t, const std::vector< CPatchInfo > &patchInfo, const CTileBank &bank, bool forceRegular)
void setOrientedTileBorderState (uint patch, uint tile, TState state)
void setOrientedTileCorner (uint patch, uint tile, bool corner)
bool setOrientedTileState (const NL3D::CPatchInfo &patch, uint patchId, float snapCell, float weldThreshold, TState &state, const NLMISC::CMatrix &toOriginalSpace, const CTileBank &bank)
void setTileBorderState (uint patch, uint tile, TState state)
bool setTileState (const NL3D::CPatchInfo &patch, uint patchId, float snapCell, float weldThreshold, TState &state, const NLMISC::CMatrix &toOriginalSpace, const CTileBank &bank)
void setTileState (uint patch, uint tile, uint layer, TState state)

Static Private Member Functions

bool snapOnGrid (float &value, float resolution, float snap)

Private Attributes

std::vector< std::vector<
uint16 > > 
_TilesLayerStates


Member Enumeration Documentation

enum NL3D::CZoneSymmetrisation::TState
 

Symmetrie state.

Enumeration values:
Nothing 
Regular 
Goofy 

Definition at line 59 of file zone_symmetrisation.h.

00060         {
00061                 Nothing         =0,
00062                 Regular         =1,
00063                 Goofy           =2,
00064         };


Constructor & Destructor Documentation

NL3D::CZoneSymmetrisation::CZoneSymmetrisation  ) 
 

Constructor.

Definition at line 39 of file zone_symmetrisation.cpp.

00040 {
00041 }


Member Function Documentation

bool NL3D::CZoneSymmetrisation::build const std::vector< CPatchInfo > &  patchInfo,
float  snapCell,
float  weldThreshold,
const CTileBank bank,
CError errorDesc,
const NLMISC::CMatrix toOriginalSpace
 

Build symmetry informations

Parameters:
zone is the zone to build symmetry informations
snapCell is the unit size of the zones
weldThreshold is the threshold used to check vertex over snaped positions
errorDesc is a structure used to return errors
toOriginalSpace is the matrix used to transform back a vertex in its original position before symmetry / rotation
Returns:
false if the patch topology is invalid for this operations

Definition at line 186 of file zone_symmetrisation.cpp.

References _TilesLayerStates, NL3D::CZoneSymmetrisation::CError::Errors, NL3D::CPatchInfo::OrderS, NL3D::CPatchInfo::OrderT, propagateTileState(), s, setOrientedTileState(), setTileState(), t, NLMISC::toString(), and uint.

Referenced by NL3D::CPatchInfo::transform().

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 nb "+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 nb "+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 true; // errorDesc.Errors.size () == 0;
00276 }

CZoneSymmetrisation::TState NL3D::CZoneSymmetrisation::getOrientedTileBorderState uint  patch,
uint  tile
const
 

Get tile symmetry state for oriented tiles Can return Regular, Goofy or Nothing.

Definition at line 72 of file zone_symmetrisation.cpp.

References getTileState(), and uint.

00073 {
00074         return getTileState (patch, tile, 4);
00075 }

bool NL3D::CZoneSymmetrisation::getOrientedTileCorner uint  patch,
uint  tile
 

Set oriented tile corner state

Definition at line 79 of file zone_symmetrisation.cpp.

References _TilesLayerStates, and uint.

Referenced by propagateTileState().

00080 {
00081         return ( ( _TilesLayerStates[patch][tile] >> 10 ) & 1 ) != 0;
00082 }

CZoneSymmetrisation::TState NL3D::CZoneSymmetrisation::getTileBorderState uint  patch,
uint  tile
const
 

Get tile symmetry state Can return Regular, Goofy or Nothing.

Definition at line 65 of file zone_symmetrisation.cpp.

References getTileState(), and uint.

00066 {
00067         return getTileState (patch, tile, 3);
00068 }

CZoneSymmetrisation::TState NL3D::CZoneSymmetrisation::getTileState uint  patch,
uint  tile,
uint  layer
const
 

Get tile symmetry state Can return Regular, Goofy or Nothing.

Definition at line 57 of file zone_symmetrisation.cpp.

References _TilesLayerStates, nlassert, and uint.

Referenced by getOrientedTileBorderState(), getTileBorderState(), propagateTileState(), and NL3D::CPatchInfo::transform().

00058 {
00059         nlassert (layer<5);
00060         return (TState)((_TilesLayerStates[patch][tile]>>(layer*2))&0x3);
00061 }

bool NL3D::CZoneSymmetrisation::propagateTileState uint  i,
uint  s,
uint  t,
const std::vector< CPatchInfo > &  patchInfo,
const CTileBank bank,
bool  forceRegular
[private]
 

Propagate tile state information for a given tile.

Parameters:
i is the patch number in the zone that contain the tile to propagate
u is the tile u coordinate in the patch
v is the tile v coordinate in the patch
patchInfo is a vector of patch information
bank is the tile bank used by the landscape
forceRegular must be true to force the first propagated tile to Regular if Nothing
Returns:
false if the patch topology is invalid for this operations true if succesful

Definition at line 670 of file zone_symmetrisation.cpp.

References NL3D::CPatchInfo::CBindInfo::Edge, NL3D::CFillStackNode::Edge, NL3D::CTileSet::getOriented(), getOrientedTileCorner(), NL3D::CTileBank::getTileCount(), NL3D::CTileBank::getTileSet(), NL3D::CTileBank::getTileSetCount(), getTileState(), NL3D::CTileBank::getTileXRef(), Goofy, NL3D::CPatchInfo::CBindInfo::Next, NL_TILE_ELM_LAYER_EMPTY, nlassert, nlwarning, Nothing, NL3D::CPatchInfo::CBindInfo::NPatchs, NL3D::CPatchInfo::OrderS, NL3D::CFillStackNode::Patch, Regular, NL3D::CFillStackNode::Rotate, NL3D::CFillStackNode::S, s, setTileState(), sint, NL3D::CFillStackNode::State, NL3D::CFillStackNode::T, t, NL3D::CPatchInfo::Tiles, type, and uint.

Referenced by build().

00671 {
00672         // For each layer
00673         uint layer;
00674         for (layer=0; layer<3; layer++)
00675         {
00676                 // Get the patch ptr
00677                 const CPatchInfo *currentPatchPtr = &(patchInfo[patch]);
00678 
00679                 // Get the tile index
00680                 uint tile = s+t*currentPatchPtr->OrderS;
00681 
00682                 // Get the tiles set used here
00683                 uint tileIndex = currentPatchPtr->Tiles[tile].Tile[layer];
00684                 if (tileIndex != NL_TILE_ELM_LAYER_EMPTY)
00685                 {
00686                         // Valid tile number ?
00687                         if (tileIndex >= (uint)bank.getTileCount ())
00688                         {
00689                                 nlwarning ("CZoneSymmetrisation::propagateTileState: Invalid tile index");
00690                                 return false;
00691                         }
00692 
00693                         // Get the tile set used by this layer
00694                         int tileSetToPropagate;
00695                         int number;
00696                         CTileBank::TTileType type;
00697                         bank.getTileXRef (tileIndex, tileSetToPropagate, number, type);
00698 
00699                         if ((tileSetToPropagate < 0) || (tileSetToPropagate >= bank.getTileSetCount()))
00700                         {
00701                                 nlwarning("CZoneSymmetrisation::propagateTileState: tile %d has an unknown tileSet (%d)", tileIndex, tileSetToPropagate);
00702                         }
00703                         else
00704                         {
00705                                 // Oriented ?
00706                                 bool oriented = bank.getTileSet (tileSetToPropagate)->getOriented ();
00707 
00708                                 // If oriented, must not be a corner
00709                                 if (!(oriented && getOrientedTileCorner (patch, tile)))
00710                                 {
00711                                         // Current node
00712                                         CFillStackNode currentNode (patch, s, t, currentPatchPtr->Tiles[tile].getTileOrient(layer), getTileState (patch, tile, layer));
00713 
00714                                         // Propagate non-Nothing tiles
00715                                         if ( (!forceRegular && (currentNode.State != Nothing)) || (forceRegular && (currentNode.State == Nothing)) )
00716                                         {
00717                                                 // Force to Regular ?
00718                                                 if (forceRegular)
00719                                                 {
00720                                                         setTileState (patch, tile, layer, Regular);
00721                                                         currentNode.State = Regular;
00722                                                 }
00723 
00724                                                 // Fill stack
00725                                                 vector<CFillStackNode>  stack;
00726                                                 stack.push_back (currentNode);
00727 
00728                                                 // While people in the stack
00729                                                 while (!stack.empty ())
00730                                                 {               
00731                                                         // Pop last element
00732                                                         currentNode = stack.back ();
00733                                                         stack.pop_back ();
00734 
00735                                                         do
00736                                                         {
00737                                                                 // Set current patch pointer
00738                                                                 currentPatchPtr = &(patchInfo[currentNode.Patch]);
00739 
00740                                                                 // Get neighbor
00741                                                                 CFillStackNode neighborNode (currentNode.Patch, currentNode.S, currentNode.T, currentNode.Rotate, currentNode.State);
00742                                                                 switch (currentNode.Edge)
00743                                                                 {
00744                                                                 case 0:
00745                                                                         neighborNode.S--;
00746                                                                         break;
00747                                                                 case 1:
00748                                                                         neighborNode.T++;
00749                                                                         break;
00750                                                                 case 2:
00751                                                                         neighborNode.S++;
00752                                                                         break;
00753                                                                 case 3:
00754                                                                         neighborNode.T--;
00755                                                                         break;
00756                                                                 }
00757 
00758                                                                 // Is still in patch ?
00759                                                                 if ( (neighborNode.S>=patchInfo[currentNode.Patch].OrderS) || (neighborNode.T>=patchInfo[currentNode.Patch].OrderT) )
00760                                                                 {
00761                                                                         // No, found new patch
00762                                                                         uint position;
00763                                                                         switch (currentNode.Edge)
00764                                                                         {
00765                                                                         case 0:
00766                                                                                 position = neighborNode.T;
00767                                                                                 break;
00768                                                                         case 1:
00769                                                                                 position = neighborNode.S;
00770                                                                                 break;
00771                                                                         case 2:
00772                                                                                 position = patchInfo[currentNode.Patch].OrderT - neighborNode.T - 1;
00773                                                                                 break;
00774                                                                         case 3:
00775                                                                                 position = patchInfo[currentNode.Patch].OrderS - neighborNode.S - 1;
00776                                                                                 break;
00777                                                                         }
00778 
00779                                                                         // Get next patch
00780                                                                         uint patchOut;
00781                                                                         sint sOut;
00782                                                                         sint tOut;
00783                                                                         if (patchInfo[currentNode.Patch].getNeighborTile (currentNode.Patch, currentNode.Edge, position, 
00784                                                                                 patchOut, sOut, tOut, patchInfo))
00785                                                                         {
00786                                                                                 // Should be another patch
00787                                                                                 nlassert (patchOut != currentNode.Patch);
00788 
00789                                                                                 // Get patch id
00790                                                                                 neighborNode.Patch = patchOut;
00791 
00792                                                                                 // Coordinate must be IN the patch
00793                                                                                 nlassert (sOut >= 0);
00794                                                                                 nlassert (tOut >= 0);
00795                                                                                 nlassert (sOut < patchInfo[neighborNode.Patch].OrderS);
00796                                                                                 nlassert (tOut < patchInfo[neighborNode.Patch].OrderT);
00797 
00798                                                                                 // Copy it
00799                                                                                 neighborNode.S = sOut;
00800                                                                                 neighborNode.T = tOut;
00801 
00802                                                                                 // Find neighbor
00803                                                                                 const CPatchInfo::CBindInfo &neighborBindInfo = patchInfo[currentNode.Patch].BindEdges[currentNode.Edge];
00804                                                                                 uint edgePatch;
00805                                                                                 for (edgePatch=0; edgePatch<(uint)neighborBindInfo.NPatchs; edgePatch++)
00806                                                                                 {
00807                                                                                         if (neighborBindInfo.Next[edgePatch] == neighborNode.Patch)
00808                                                                                                 break;
00809                                                                                 }
00810 
00811                                                                                 // Must find one patch
00812                                                                                 nlassert (edgePatch<(uint)neighborBindInfo.NPatchs);
00813 
00814                                                                                 // Rotation
00815                                                                                 neighborNode.Rotate = (currentNode.Rotate + 2 + neighborBindInfo.Edge[edgePatch] - currentNode.Edge) & 3;
00816 
00817                                                                                 // Toggle the state ?
00818                                                                                 if ((neighborNode.Rotate ^ currentNode.Rotate) & 1)
00819                                                                                 {
00820                                                                                         // Yes
00821                                                                                         neighborNode.State = (neighborNode.State == Regular) ? Goofy : Regular;
00822                                                                                 }
00823                                                                         }
00824                                                                         else
00825                                                                         {
00826                                                                                 // No propagation, continue
00827                                                                                 currentNode.Edge++;
00828                                                                                 continue;
00829                                                                         }
00830                                                                 }
00831 
00832                                                                 // Neighbor patch
00833                                                                 const CPatchInfo *neighborPatchPtr = &(patchInfo[neighborNode.Patch]);
00834 
00835                                                                 // Get the tile index
00836                                                                 uint neighborTile = neighborNode.S+neighborNode.T*neighborPatchPtr->OrderS;
00837                                                                 
00838                                                                 // Look for the same tile set in the new tile
00839                                                                 uint neighborLayer;
00840                                                                 for (neighborLayer=0; neighborLayer<3; neighborLayer++)
00841                                                                 {
00842                                                                         // Get the tile index
00843                                                                         uint neighborTileIndex = neighborPatchPtr->Tiles[neighborTile].Tile[neighborLayer];
00844 
00845                                                                         if (neighborTileIndex != NL_TILE_ELM_LAYER_EMPTY)
00846                                                                         {
00847                                                                                 // Valid tile number ?
00848                                                                                 if (neighborTileIndex >= (uint)bank.getTileCount ())
00849                                                                                 {
00850                                                                                         nlwarning ("CZoneSymmetrisation::propagateTileState: Invalid tile index");
00851                                                                                         return false;
00852                                                                                 }
00853 
00854                                                                                 // Get tileset
00855                                                                                 int neighborTileSet;
00856                                                                                 int neighborNumber;
00857                                                                                 CTileBank::TTileType neighborType;
00858                                                                                 bank.getTileXRef (neighborTileIndex, neighborTileSet, neighborNumber, neighborType);
00859 
00860                                                                                 // Same tileset ? Stop!
00861                                                                                 if (    (neighborTileSet == tileSetToPropagate) && 
00862                                                                                                 (neighborNode.Rotate == neighborPatchPtr->Tiles[neighborTile].getTileOrient(neighborLayer)) )
00863                                                                                         break;
00864                                                                         }
00865                                                                 }
00866 
00867                                                                 // Found ?
00868                                                                 if (neighborLayer<3)
00869                                                                 {
00870                                                                         // If oriented, must not be a corner
00871                                                                         if (!(oriented && getOrientedTileCorner (neighborNode.Patch, neighborTile)))
00872                                                                         {
00873                                                                                 // Propagate in the new node ?
00874                                                                                 TState neighborState = getTileState (neighborNode.Patch, neighborTile, neighborLayer);
00875                                                                                 if (neighborState == Nothing)
00876                                                                                 {
00877                                                                                         // Set the state
00878                                                                                         setTileState (neighborNode.Patch, neighborTile, neighborLayer, neighborNode.State);
00879 
00880                                                                                         // Stack current node if some neighbor left to visit
00881                                                                                         if (currentNode.Edge < 3)
00882                                                                                         {
00883                                                                                                 currentNode.Edge++;
00884                                                                                                 stack.push_back (currentNode);
00885                                                                                         }
00886 
00887                                                                                         // Continue with the new node
00888                                                                                         currentNode = neighborNode;
00889                                                                                 }
00890                                                                                 else if (neighborState != neighborNode.State)
00891                                                                                 {
00892                                                                                         // Error, same tile but not same state
00893                                                                                         // nlwarning ("CZoneSymmetrisation::propagateTileState: error, find same iso surfaces with different state.");
00894 
00895                                                                                         // No propagation, continue
00896                                                                                         currentNode.Edge++;
00897                                                                                 }
00898                                                                                 else
00899                                                                                 {
00900                                                                                         // No propagation, continue
00901                                                                                         currentNode.Edge++;
00902                                                                                 }
00903                                                                         }
00904                                                                         else
00905                                                                         {
00906                                                                                 // No propagation, continue
00907                                                                                 currentNode.Edge++;
00908                                                                         }
00909                                                                 }
00910                                                                 else
00911                                                                         // No propagation, continue
00912                                                                         currentNode.Edge++;
00913                                                         }
00914                                                         while (currentNode.Edge<4);
00915                                                 }
00916                                         }
00917                                 }
00918                         }
00919                 }
00920         }
00921 
00922         return true;
00923 }

void NL3D::CZoneSymmetrisation::setOrientedTileBorderState uint  patch,
uint  tile,
TState  state
[private]
 

Set border oriented tile symmetry state

Definition at line 102 of file zone_symmetrisation.cpp.

References setTileState(), and uint.

Referenced by setOrientedTileState().

00103 {
00104         setTileState (patch, tile, 4, state);
00105 }

void NL3D::CZoneSymmetrisation::setOrientedTileCorner uint  patch,
uint  tile,
bool  corner
[private]
 

Set oriented tile corner state

Definition at line 109 of file zone_symmetrisation.cpp.

References _TilesLayerStates, uint, and uint16.

Referenced by setOrientedTileState().

00110 {
00111         uint16 &ref = _TilesLayerStates[patch][tile];
00112         ref &= ~(1<<10);
00113         ref |= ((uint16)corner)<<(10);
00114 }

bool NL3D::CZoneSymmetrisation::setOrientedTileState const NL3D::CPatchInfo patch,
uint  patchId,
float  snapCell,
float  weldThreshold,
TState state,
const NLMISC::CMatrix toOriginalSpace,
const CTileBank bank
[private]
 

Definition at line 472 of file zone_symmetrisation.cpp.

References NL3D::CTileSet::getOriented(), NL3D::CTileBank::getTileSet(), NL3D::CTileBank::getTileSetCount(), NL3D::CTileBank::getTileXRef(), Goofy, NL_TILE_ELM_LAYER_EMPTY, nlwarning, Nothing, NL3D::CPatchInfo::OrderS, NL3D::CPatchInfo::OrderT, NL3D::CPatchInfo::Patch, Regular, setOrientedTileBorderState(), setOrientedTileCorner(), setTileState(), sint, sint32, snapOnGrid(), NL3D::CPatchInfo::Tiles, type, uint, NL3D::CBezierPatch::Vertices, NLMISC::CVector::x, and NLMISC::CVector::y.

Referenced by build().

00473 {
00474         // Edges state
00475         TState edgesState[4] = { Nothing, Nothing, Nothing, Nothing };
00476 
00477         // Vertices position
00478         sint32 vertPosU[4];
00479         sint32 vertPosV[4];
00480         
00481         // For each vertices
00482         uint i;
00483         for (i=0; i<4; i++)
00484         {
00485                 // Snap the vertex
00486                 CVector original = toOriginalSpace * patch.Patch.Vertices[i];
00487                 float valueU = original.x;
00488                 float valueV = original.y;
00489 
00490                 // Snap on U
00491                 if (snapOnGrid (valueU, snapCell, weldThreshold))
00492                         vertPosU[i] = (sint32)((valueU+0.5f) / snapCell);
00493                 else
00494                         vertPosU[i] = 0x80000000;
00495 
00496                 // Snap on V
00497                 if (snapOnGrid (valueV, snapCell, weldThreshold))
00498                         vertPosV[i] = (sint32)((valueV+0.5f) / snapCell);
00499                 else
00500                         vertPosV[i] = 0x80000000;
00501         }
00502 
00503         // Patch flags
00504         bool regular = false;
00505         bool goofy = false;
00506         bool EdgeSnaped[4] = { false, false, false, false };
00507 
00508         // For each edges
00509         for (i=0; i<4; i++)
00510         {
00511                 // Vertex snapped and align on a common axis ?
00512                 if ( (vertPosU[i] != 0x80000000) || (vertPosV[i] != 0x80000000) )
00513                 {
00514                         // Snapped on U or V ?
00515                         bool snapU = (vertPosU[i] == vertPosU[(i+1)&3]) && (vertPosU[i] != 0x80000000);
00516                         bool snapV = (vertPosV[i] == vertPosV[(i+1)&3]) && (vertPosV[i] != 0x80000000);
00517                         
00518                         // If snapped on one, continue
00519                         if (snapU || snapV)
00520                         {
00521                                 // If snap on the both, error
00522                                 if (snapU && snapV)
00523                                         return false;
00524 
00525                                 // Is this edge Regular or Goofy ?
00526                                 edgesState[i] = (i&1)?Goofy:Regular;
00527 
00528                                 // Flag the patch
00529                                 if (edgesState[i] == Regular)
00530                                         regular = true;
00531                                 else
00532                                         goofy = true;
00533 
00534                                 // Edge snaped
00535                                 EdgeSnaped[i] = true;
00536                         }
00537                 }
00538         }
00539 
00540         // * Set the tiles
00541 
00542         // For each edges
00543         for (i=0; i<4; i++)
00544         {
00545                 // Edge snapped ?
00546                 if (EdgeSnaped[i])
00547                 {
00548                         // For each tiles
00549                         uint tileCount = ((i&1)!=0)?patch.OrderS:patch.OrderT;
00550                         sint currentTile;
00551                         sint delta;
00552                         switch (i)
00553                         {
00554                         case 0:
00555                                 currentTile = 0;
00556                                 delta = patch.OrderS;
00557                                 break;
00558                         case 1:
00559                                 currentTile = patch.OrderS*(patch.OrderT-1);
00560                                 delta = 1;
00561                                 break;
00562                         case 2:
00563                                 currentTile = patch.OrderS-1;
00564                                 delta = patch.OrderS;
00565                                 break;
00566                         case 3:
00567                                 currentTile = 0;
00568                                 delta = 1;
00569                                 break;
00570                         }
00571                         uint j;
00572                         for (j=0; j<tileCount; j++)
00573                         {
00574                                 // Set the border state
00575                                 setOrientedTileBorderState (patchId, currentTile, edgesState[i]);
00576 
00577                                 // For each layer
00578                                 uint layer;
00579                                 for (layer=0; layer<3; layer++)
00580                                 {
00581                                         // Get the tiles set used here
00582                                         uint tile = patch.Tiles[currentTile].Tile[layer];
00583                                         if (tile != NL_TILE_ELM_LAYER_EMPTY)
00584                                         {
00585                                                 int tileSet;
00586                                                 int number;
00587                                                 CTileBank::TTileType type;
00588 
00589                                                 bank.getTileXRef (tile, tileSet, number, type);
00590                                                 if ((tileSet < 0) || (tileSet >= bank.getTileSetCount()))
00591                                                 {
00592                                                         nlwarning("CZoneSymmetrisation::setOrientedTileState : tile %d has an unknown tileSet (%d)", tile, tileSet);
00593                                                         return false;
00594                                                 }
00595 
00596                                                 // Set it only if oriented
00597                                                 if (bank.getTileSet (tileSet)->getOriented ())
00598                                                 {
00599                                                         setTileState (patchId, currentTile, layer, edgesState[i]);
00600                                                 }
00601                                         }
00602                                 }
00603 
00604                                 // Next tile
00605                                 currentTile += delta;
00606                         }
00607                 }
00608         }
00609         
00610         // For each corners
00611         for (i=0; i<4; i++)
00612         {
00613                 // Corner snapped ?
00614                 uint next = (i+1)&3;
00615                 if (EdgeSnaped[i] && EdgeSnaped[next])
00616                 {
00617                         // Flag tile as corner
00618                         switch (i)
00619                         {
00620                         case 0:
00621                                 setOrientedTileCorner (patchId, patch.OrderS*(patch.OrderT-1), true);
00622                                 break;
00623                         case 1:
00624                                 setOrientedTileCorner (patchId, patch.OrderS*patch.OrderT-1, true);
00625                                 break;
00626                         case 2:
00627                                 setOrientedTileCorner (patchId, patch.OrderS-1, true);
00628                                 break;
00629                         case 3:
00630                                 setOrientedTileCorner (patchId, 0, true);
00631                                 break;
00632                         }
00633                 }
00634         }
00635         
00636         return true;
00637 }

void NL3D::CZoneSymmetrisation::setTileBorderState uint  patch,
uint  tile,
TState  state
[private]
 

Set border tile symmetry state

Definition at line 95 of file zone_symmetrisation.cpp.

References setTileState(), and uint.

Referenced by setTileState().

00096 {
00097         setTileState (patch, tile, 3, state);
00098 }

bool NL3D::CZoneSymmetrisation::setTileState const NL3D::CPatchInfo patch,
uint  patchId,
float  snapCell,
float  weldThreshold,
TState state,
const NLMISC::CMatrix toOriginalSpace,
const CTileBank bank
[private]
 

Set tile state of a patch

Definition at line 312 of file zone_symmetrisation.cpp.

References NL3D::CTileSet::getOriented(), NL3D::CTileBank::getTileSet(), NL3D::CTileBank::getTileSetCount(), NL3D::CTileBank::getTileXRef(), Goofy, NL_TILE_ELM_LAYER_EMPTY, nlwarning, Nothing, NL3D::CPatchInfo::OrderS, NL3D::CPatchInfo::OrderT, NL3D::CPatchInfo::Patch, Regular, setTileBorderState(), setTileState(), sint, sint32, snapOnGrid(), NL3D::CPatchInfo::Tiles, type, uint, NL3D::CBezierPatch::Vertices, NLMISC::CVector::x, and NLMISC::CVector::y.

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                                                         if ((tileSet < 0) || (tileSet >= bank.getTileSetCount()))
00446                                                         {
00447                                                                 nlwarning("CZoneSymmetrisation::setTileState : tile %d has an unknown tileSet (%d)", tile, tileSet);
00448                                                                 return false;
00449                                                         }
00450 
00451                                                         // Set it only if not oriented
00452                                                         if (!bank.getTileSet (tileSet)->getOriented ())
00453                                                         {
00454                                                                 // Set the tile state
00455                                                                 setTileState (patchId, currentTile, layer, state);
00456                                                         }
00457                                                 }
00458                                         }
00459 
00460                                         // Next tile
00461                                         currentTile += delta;
00462                                 }
00463                         }
00464                 }
00465         }
00466 
00467         return true;
00468 }

void NL3D::CZoneSymmetrisation::setTileState uint  patch,
uint  tile,
uint  layer,
TState  state
[private]
 

Set orientedtile symmetry state

Definition at line 86 of file zone_symmetrisation.cpp.

References _TilesLayerStates, uint, and uint16.

Referenced by build(), propagateTileState(), setOrientedTileBorderState(), setOrientedTileState(), setTileBorderState(), and setTileState().

00087 {
00088         uint16 &ref = _TilesLayerStates[patch][tile];
00089         ref &= ~(3<<(layer*2));
00090         ref |= ((uint16)state)<<(layer*2);
00091 }

bool NL3D::CZoneSymmetrisation::snapOnGrid float &  value,
float  resolution,
float  snap
[static, private]
 

Definition at line 280 of file zone_symmetrisation.cpp.

References nlassert, and value.

Referenced by setOrientedTileState(), and setTileState().

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 }


Field Documentation

std::vector<std::vector<uint16> > NL3D::CZoneSymmetrisation::_TilesLayerStates [private]
 

Definition at line 158 of file zone_symmetrisation.h.

Referenced by build(), getOrientedTileCorner(), getTileState(), setOrientedTileCorner(), and setTileState().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 08:36:36 2004 for NeL by doxygen 1.3.6