/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
/*
* Determine which alpha blend map fits a given shape.
*/
#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