1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

- Fixed a few bugs related to the terrain view generation - Updated CMakeLists in /test(copy resources if no source files has been changed too)

This commit is contained in:
beegee1 2013-04-25 16:09:48 +00:00
parent 8273f323b1
commit 23f7be2a54
5 changed files with 97 additions and 71 deletions

View File

@ -48,30 +48,33 @@
"id" : "s1",
"data" :
[
"?", "?", "T",
"?", "N", "N",
"T,N-1", "T,N-2", "T,N-3",
"T,N-2", "N", "N",
"T", "N", "N"
],
"maxPoints" : 3,
"mapping" : "0-3, 20-23"
},
{
"id" : "s2",
"data" :
[
"?", "N", "N",
"T", "N", "N",
"?", "N", "N"
"D-1,S-2,N", "N", "N",
"T,D-2", "N", "N",
"D-1,S-2,N", "N", "N"
],
"maxPoints" : 4,
"mapping" : "4-7, 24-27"
},
{
"id" : "s3",
"data" :
[
"?", "T", "?",
"D-1,S-2,N", "T,D-2", "D-1,S-2,N",
"N", "N", "N",
"N", "N", "N"
],
"maxPoints" : 4,
"mapping" : "8-11, 28-31"
},
{
@ -79,18 +82,19 @@
"data" :
[
"N", "N", "N",
"N", "N", "N",
"N", "N", "T"
"N", "N", "s3-1",
"N", "s2-1", "T"
],
"mapping" : "12-15, 32-35"
"mapping" : "12-15, 32-35",
"minPoints" : 2
},
{
"id" : "s5",
"data" :
[
"T", "T", "s5-1,?",
"T", "N", "N",
"s5-1,?", "N", "N"
"T", "T", "?",
"T", "N", "s6-1,m1-1,m2-1,N",
"?", "s6-1,m1-1,m2-1,N", "N"
],
"mapping" : "16-17, 36-37",
"minPoints" : 1
@ -133,7 +137,7 @@
[
"N", "N", "D,N",
"N", "N", "D",
"S", "D", "D,N"
"S", "D,N", "D,N"
],
"mapping" : "43"
},
@ -151,7 +155,7 @@
"id" : "m5",
"data" :
[
"N", "N", "D,N",
"N", "N", "D",
"N", "N", "D",
"N", "N", "S"
],
@ -171,10 +175,11 @@
"id" : "m7",
"data" :
[
"N", "N", "D,S,N",
"N", "N", "?",
"N", "N", "S",
"D", "D", "D,S,N"
"D-1,N", "D-1,N", "?"
],
"minPoints" : 1,
"mapping" : "47"
},
{
@ -183,7 +188,7 @@
[
"N", "N", "D",
"N", "N", "D",
"D,S,N", "S", "D,S,N"
"?", "S", "?"
],
"mapping" : "48"
},
@ -237,8 +242,8 @@
"data" :
[
"D", "D", "D",
"D", "N", "N",
"D", "N", "S"
"D", "N", "?",
"D", "?", "S"
],
"mapping" : "12-15"
},
@ -347,11 +352,12 @@
"id" : "s5",
"data" :
[
"S", "S", "N",
"S", "S", "N,S-1",
"S", "N", "N",
"N", "N", "N"
"N,S-1", "N", "N"
],
"mapping" : "16-17",
"maxPoints" : 1
},
{
"id" : "s6",

View File

@ -301,7 +301,10 @@ CTerrainViewPatternConfig::CTerrainViewPatternConfig()
// Read optional attributes
pattern.id = ptrnNode["id"].String();
assert(!pattern.id.empty());
pattern.minPoints = static_cast<int>(ptrnNode["minPoints"].Float());
pattern.maxPoints = static_cast<int>(ptrnNode["maxPoints"].Float());
if(pattern.maxPoints == 0) pattern.maxPoints = std::numeric_limits<int>::max();
pattern.flipMode = ptrnNode["flipMode"].String();
if(pattern.flipMode.empty())
{
@ -388,65 +391,59 @@ std::string CDrawTerrainOperation::getLabel() const
void CDrawTerrainOperation::updateTerrainViews(const MapRect & rect)
{
for(int i = rect.x; i < rect.x + rect.width; ++i)
for(int x = rect.x; x < rect.x + rect.width; ++x)
{
for(int j = rect.y; j < rect.y + rect.height; ++j)
for(int y = rect.y; y < rect.y + rect.height; ++y)
{
const auto & patterns =
CTerrainViewPatternConfig::get().getPatternsForGroup(getTerrainGroup(map->getTile(int3(i, j, rect.z)).terType));
CTerrainViewPatternConfig::get().getPatternsForGroup(getTerrainGroup(map->getTile(int3(x, y, rect.z)).terType));
// Detect a pattern which fits best
int bestPattern = -1, bestFlip = -1;
std::string transitionReplacement;
int bestPattern = -1;
ValidationResult valRslt(false);
for(int k = 0; k < patterns.size(); ++k)
{
const auto & pattern = patterns[k];
for(int flip = 0; flip < 4; ++flip)
valRslt = validateTerrainView(int3(x, y, rect.z), pattern);
if(valRslt.result)
{
auto valRslt = validateTerrainView(int3(i, j, rect.z), flip > 0 ? getFlippedPattern(pattern, flip) : pattern);
if(valRslt.result)
{
logGlobal->debugStream() << "Pattern detected at pos " << i << "x" << j << "x" << rect.z << ": P-Nr. " << k
<< ", Flip " << flip << ", Repl. " << valRslt.transitionReplacement;
bestPattern = k;
bestFlip = flip;
transitionReplacement = valRslt.transitionReplacement;
break;
}
logGlobal->debugStream() << "Pattern detected at pos " << x << "x" << y << "x" << rect.z << ": P-Nr. " << pattern.id
<< ", Flip " << valRslt.flip << ", Repl. " << valRslt.transitionReplacement;
bestPattern = k;
break;
}
}
//assert(bestPattern != -1);
if(bestPattern == -1)
{
// This shouldn't be the case
logGlobal->warnStream() << "No pattern detected at pos " << i << "x" << j << "x" << rect.z;
logGlobal->warnStream() << "No pattern detected at pos " << x << "x" << y << "x" << rect.z;
continue;
}
// Get mapping
const TerrainViewPattern & pattern = patterns[bestPattern];
std::pair<int, int> mapping;
if(transitionReplacement.empty())
if(valRslt.transitionReplacement.empty())
{
mapping = pattern.mapping[0];
}
else
{
mapping = transitionReplacement == TerrainViewPattern::RULE_DIRT ? pattern.mapping[0] : pattern.mapping[1];
mapping = valRslt.transitionReplacement == TerrainViewPattern::RULE_DIRT ? pattern.mapping[0] : pattern.mapping[1];
}
// Set terrain view
auto & tile = map->getTile(int3(i, j, rect.z));
auto & tile = map->getTile(int3(x, y, rect.z));
if(pattern.flipMode == TerrainViewPattern::FLIP_MODE_SAME_IMAGE)
{
tile.terView = gen->getInteger(mapping.first, mapping.second);
tile.extTileFlags = bestFlip;
tile.extTileFlags = valRslt.flip;
}
else
{
const int framesPerRot = 2;
int firstFrame = mapping.first + bestFlip * framesPerRot;
int firstFrame = mapping.first + valRslt.flip * framesPerRot;
tile.terView = gen->getInteger(firstFrame, firstFrame + framesPerRot - 1);
tile.extTileFlags = 0;
}
@ -472,6 +469,20 @@ ETerrainGroup::ETerrainGroup CDrawTerrainOperation::getTerrainGroup(ETerrainType
}
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
{
for(int flip = 0; flip < 4; ++flip)
{
auto valRslt = validateTerrainViewInner(pos, flip > 0 ? getFlippedPattern(pattern, flip) : pattern, recDepth);
if(valRslt.result)
{
valRslt.flip = flip;
return valRslt;
}
}
return ValidationResult(false);
}
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
{
ETerrainType centerTerType = map->getTile(pos).terType;
int totalPoints = 0;
@ -488,15 +499,16 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
// Get terrain group of the current cell
int cx = pos.x + (i % 3) - 1;
int cy = pos.y + (i / 3) - 1;
int3 currentPos(cx, cy, pos.z);
bool isAlien = false;
ETerrainType terType;
if(cx < 0 || cx >= map->width || cy < 0 || cy >= map->height)
if(!map->isInTheMap(currentPos))
{
terType = centerTerType;
}
else
{
terType = map->getTile(int3(cx, cy, pos.z)).terType;
terType = map->getTile(currentPos).terType;
if(terType != centerTerType)
{
isAlien = true;
@ -512,17 +524,13 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
{
if(recDepth == 0)
{
const auto & patternForRule = CTerrainViewPatternConfig::get().getPatternById(pattern.terGroup, rule.name);
auto rslt = validateTerrainView(int3(cx, cy, pos.z), patternForRule, 1);
if(!rslt.result)
if(map->isInTheMap(currentPos) && terType == centerTerType)
{
return ValidationResult(false);
}
else
{
topPoints = std::max(topPoints, rule.points);
continue;
const auto & patternForRule = CTerrainViewPatternConfig::get().getPatternById(pattern.terGroup, rule.name);
auto rslt = validateTerrainView(currentPos, patternForRule, 1);
if(rslt.result) topPoints = std::max(topPoints, rule.points);
}
continue;
}
else
{
@ -549,14 +557,20 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|| rule.name == TerrainViewPattern::RULE_ANY)
&& isSandType(terType);
if(transitionReplacement.empty() && (rule.name == TerrainViewPattern::RULE_TRANSITION
|| rule.name == TerrainViewPattern::RULE_ANY) && (dirtTestOk || sandTestOk))
if(transitionReplacement.empty() && rule.name == TerrainViewPattern::RULE_TRANSITION
&& (dirtTestOk || sandTestOk))
{
transitionReplacement = dirtTestOk ? TerrainViewPattern::RULE_DIRT : TerrainViewPattern::RULE_SAND;
}
applyValidationRslt((dirtTestOk && transitionReplacement != TerrainViewPattern::RULE_SAND)
|| (sandTestOk && transitionReplacement != TerrainViewPattern::RULE_DIRT)
|| nativeTestOk);
if(rule.name == TerrainViewPattern::RULE_TRANSITION)
{
applyValidationRslt((dirtTestOk && transitionReplacement != TerrainViewPattern::RULE_SAND) ||
(sandTestOk && transitionReplacement != TerrainViewPattern::RULE_DIRT));
}
else
{
applyValidationRslt(dirtTestOk || sandTestOk || nativeTestOk);
}
}
else if(pattern.terGroup == ETerrainGroup::DIRT)
{
@ -593,12 +607,14 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
}
}
if(pattern.minPoints > totalPoints)
if(totalPoints >= pattern.minPoints && totalPoints <= pattern.maxPoints)
{
return ValidationResult(true, transitionReplacement);
}
else
{
return ValidationResult(false);
}
return ValidationResult(true, transitionReplacement);
}
bool CDrawTerrainOperation::isSandType(ETerrainType terType) const

View File

@ -190,8 +190,8 @@ struct DLL_LINKAGE TerrainViewPattern
/// std::pair -> 1st value: lower range, 2nd value: upper range
std::vector<std::pair<int, int> > mapping;
/// The minimum points to reach to to validate the pattern successfully.
int minPoints;
/// The minimum and maximum points to reach to validate the pattern successfully.
int minPoints, maxPoints;
/// Describes if flipping is required and which mapping should be used.
std::string flipMode;
@ -236,12 +236,15 @@ private:
bool result;
/// The replacement of a T rule, either D or S.
std::string transitionReplacement;
int flip;
};
void updateTerrainViews(const MapRect & rect);
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
/// Validates the terrain view of the given position and with the given pattern.
/// Validates the terrain view of the given position and with the given pattern. The first method wraps the
/// second method to validate the terrain view with the given pattern in all four flip directions(horizontal, vertical).
ValidationResult validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const;
ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const;
/// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock
bool isSandType(ETerrainType terType) const;
TerrainViewPattern getFlippedPattern(const TerrainViewPattern & pattern, int flip) const;

View File

@ -14,14 +14,15 @@ add_executable(vcmitest ${test_SRCS})
target_link_libraries(vcmitest vcmi ${Boost_LIBRARIES})
add_test(vcmitest vcmitest)
# Files to copy to the build directory after compilation
# Files to copy to the build directory
add_custom_target(vcmitestFiles ALL)
set(vcmitest_FILES
TerrainViewTest.h3m
terrainViewMappings.json
)
foreach(file ${vcmitest_FILES})
add_custom_command(TARGET vcmitest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${file}" $<TARGET_FILE_DIR:vcmitest>
add_custom_command(TARGET vcmitestFiles POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${file}" ${CMAKE_CURRENT_BINARY_DIR}
)
endforeach()

View File

@ -26,7 +26,7 @@
"pattern" : "normal.s6"
},
{
"pos" : [ [ 21,20,1 ], [ 28,27,1 ] ],
"pos" : [ [ 21,20,1 ], [ 28,27,0 ] ],
"pattern" : "normal.m1"
},
{