/////////////////////////////////////////////////////////////////////////////// // // Name: AlphaMapCalculator.cpp // Author: Rich Cross // Contact: rich@wildfiregames.com // /////////////////////////////////////////////////////////////////////////////// #include "precompiled.h" #include "AlphaMapCalculator.h" #include #include /////////////////////////////////////////////////////////////////////////////// // CAlphaMapCalculator: functionality for calculating which alpha blend map // fits a given shape namespace CAlphaMapCalculator { /////////////////////////////////////////////////////////////////////////////// // Blend4: structure mapping a blend shape for N,E,S,W to a particular map struct Blend4 { Blend4(BlendShape4 shape,int alphamap) : m_Shape(shape), m_AlphaMap(alphamap) {} BlendShape4 m_Shape; int m_AlphaMap; }; /////////////////////////////////////////////////////////////////////////////// // Blend8: structure mapping a blend shape for N,NE,E,SE,S,SW,W,NW to a // particular map struct Blend8 { Blend8(BlendShape8 shape,int alphamap) : m_Shape(shape), m_AlphaMap(alphamap) {} BlendShape8 m_Shape; int m_AlphaMap; }; /////////////////////////////////////////////////////////////////////////////// // Data tables for mapping between shapes and blend maps /////////////////////////////////////////////////////////////////////////////// const Blend4 Blends1Neighbour[] = { Blend4(BlendShape4(1,0,0,0), 12) }; const Blend4 Blends2Neighbour[] = { Blend4(BlendShape4(0,1,1,0), 7), Blend4(BlendShape4(1,0,1,0), 10) }; const Blend8 Blends2Neighbour8[] = { Blend8(BlendShape8(1,1,0,0,0,0,0,0), 12), Blend8(BlendShape8(1,0,0,0,0,1,0,0), 12), Blend8(BlendShape8(0,1,0,1,0,0,0,0), 0) , Blend8(BlendShape8(0,1,0,0,0,1,0,0), 0) }; const Blend4 Blends3Neighbour[] = { Blend4(BlendShape4(1,1,1,0), 4) }; const Blend8 Blends3Neighbour8[] = { Blend8(BlendShape8(1,1,0,0,1,0,0,0), 10), Blend8(BlendShape8(1,1,0,0,0,0,0,1), 12), Blend8(BlendShape8(1,1,1,0,0,0,0,0), 1), Blend8(BlendShape8(0,1,1,0,1,0,0,0), 7), Blend8(BlendShape8(0,0,1,0,1,0,1,0), 4), Blend8(BlendShape8(1,1,0,0,0,1,0,0), 12), Blend8(BlendShape8(1,1,0,1,0,0,0,0), 12), Blend8(BlendShape8(0,0,1,0,1,0,0,1), 7), Blend8(BlendShape8(1,0,0,1,0,1,0,0), 12), Blend8(BlendShape8(0,1,0,1,0,1,0,0), 0) }; const Blend8 Blends4Neighbour8[] = { Blend8(BlendShape8(1,1,0,0,1,0,0,1), 10), Blend8(BlendShape8(1,1,0,1,1,0,0,0), 10), Blend8(BlendShape8(1,1,0,0,1,1,0,0), 10), Blend8(BlendShape8(1,1,0,1,0,0,0,1), 12), Blend8(BlendShape8(0,1,1,0,1,1,0,0), 7), Blend8(BlendShape8(1,1,1,1,0,0,0,0), 1), Blend8(BlendShape8(1,1,1,0,1,0,0,0), 3), Blend8(BlendShape8(0,0,1,0,1,1,0,1), 7), Blend8(BlendShape8(1,0,1,0,1,1,0,0), 4), Blend8(BlendShape8(1,1,1,0,0,1,0,0), 1), Blend8(BlendShape8(1,1,0,1,0,1,0,0), 12), Blend8(BlendShape8(0,1,0,1,0,1,0,1), 0) }; const Blend8 Blends5Neighbour8[] = { Blend8(BlendShape8(1,1,1,1,1,0,0,0), 2), Blend8(BlendShape8(1,1,1,1,0,0,0,1), 1), Blend8(BlendShape8(1,1,1,0,1,0,0,1), 3), Blend8(BlendShape8(1,1,1,0,1,0,1,0), 11), Blend8(BlendShape8(1,1,1,0,0,1,0,1), 1), Blend8(BlendShape8(1,1,0,1,1,1,0,0), 10), Blend8(BlendShape8(1,1,1,0,1,1,0,0), 3), Blend8(BlendShape8(1,0,1,0,1,1,0,1), 4), Blend8(BlendShape8(1,1,0,1,0,1,0,1), 12), Blend8(BlendShape8(0,1,1,0,1,1,0,1), 7) }; const Blend8 Blends6Neighbour8[] = { Blend8(BlendShape8(1,1,1,1,1,1,0,0), 2), Blend8(BlendShape8(1,1,1,1,1,0,1,0), 8), Blend8(BlendShape8(1,1,1,1,0,1,0,1), 1), Blend8(BlendShape8(1,1,1,0,1,1,1,0), 6), Blend8(BlendShape8(1,1,1,0,1,1,0,1), 3), Blend8(BlendShape8(1,1,0,1,1,1,0,1), 10) }; const Blend8 Blends7Neighbour8[] = { Blend8(BlendShape8(1,1,1,1,1,1,0,1), 2), Blend8(BlendShape8(1,1,1,1,1,1,1,0), 9) }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // MatchBlendShapeFlipped: test if the given shape can be made to fit the // template in either unflipped state, or by flipping the shape in U or V template bool MatchBlendShapeFlipped(const T& templateshape,const T& shape,unsigned int& flags) { // test unrotated shape if (shape==templateshape) { return true; } // test against shape flipped in U T tstShape; templateshape.FlipU(tstShape); if (shape==tstShape) { flags|=BLENDMAP_FLIPU; return true; } // test against shape flipped in V templateshape.FlipV(tstShape); if (shape==tstShape) { flags|=BLENDMAP_FLIPV; return true; } // no joy; no match by flipping return false; } /////////////////////////////////////////////////////////////////////////////// // MatchBlendShape: try and find a matching blendmap, and the required flip/ // rotation flags, to fit the given shape to the template template int MatchBlendShape(const T& templateshape,const T& shape,unsigned int& flags) { // try matching unrotated shape first using just flipping if (MatchBlendShapeFlipped(templateshape,shape,flags)) { return true; } // now try iterating through rotations of 90,180,270 degrees T tstShape; templateshape.Rotate90(tstShape); if (MatchBlendShapeFlipped(tstShape,shape,flags)) { // update flags - note if we've flipped in u or v, we need to rotate in // the opposite direction flags|=flags ? BLENDMAP_ROTATE270 : BLENDMAP_ROTATE90; return true; } templateshape.Rotate180(tstShape); if (MatchBlendShapeFlipped(tstShape,shape,flags)) { flags|=BLENDMAP_ROTATE180; return true; } templateshape.Rotate270(tstShape); if (MatchBlendShapeFlipped(tstShape,shape,flags)) { // update flags - note if we've flipped in u or v, we need to rotate in // the opposite direction flags|=flags ? BLENDMAP_ROTATE90 : BLENDMAP_ROTATE270; return true; } return false; } /////////////////////////////////////////////////////////////////////////////// // LookupBlend: find and return the blendmap fitting the given shape by // iterating through the given data table and testing each shape in flipped and // rotated forms until a match is found template int LookupBlend(int tableSize,const S* table,const T& shape,unsigned int& flags) { // iterate through known blend shapes for (int b=0;b