1
0
forked from 0ad/0ad
0ad/source/tools/rmgen/clumpplacer.cpp

87 lines
2.1 KiB
C++

#include "stdafx.h"
#include "clumpplacer.h"
#include "random.h"
#include "pointmap.h"
using namespace std;
ClumpPlacer::ClumpPlacer(float size, float coherence, float smoothness, float failFraction, int x, int y)
{
this->size = size;
this->coherence = coherence;
this->smoothness = smoothness;
this->x = x;
this->y = y;
this->failFraction = failFraction;
}
ClumpPlacer::~ClumpPlacer()
{
}
bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& retVec) {
if(!m->validT(x, y) || !constr->allows(m, x, y)) {
return false;
}
PointMap<int> gotRet;
float radius = sqrt(size / PI);
float perim = 4 * radius * 2 * PI;
int intPerim = (int)(ceil(perim));
vector<float> noise(intPerim);
int ctrlPts = 1 + (int)(1.0/max(smoothness,1.0f/intPerim));
if(ctrlPts > radius * 2 * PI) ctrlPts = (int) (radius * 2 * PI) + 1;
vector<float> ctrlCoords(ctrlPts+1);
vector<float> ctrlVals(ctrlPts+1);
for(int i=0; i<ctrlPts; i++) {
ctrlCoords[i] = i * perim / ctrlPts;
ctrlVals[i] = 2.0*RandFloat();
}
int c = 0;
int looped = 0;
for(int i=0; i<intPerim; i++) {
if(ctrlCoords[(c+1) % ctrlPts] < i && !looped) {
c = (c+1) % ctrlPts;
if(c==ctrlPts-1) looped = 1;
}
float t = (i - ctrlCoords[c]) / ((looped ? perim : ctrlCoords[(c+1)%ctrlPts]) - ctrlCoords[c]);
float v0 = ctrlVals[(c+ctrlPts-1)%ctrlPts];
float v1 = ctrlVals[c];
float v2 = ctrlVals[(c+1)%ctrlPts];
float v3 = ctrlVals[(c+2)%ctrlPts];
float P = (v3 - v2) - (v0 - v1);
float Q = (v0 - v1) - P;
float R = v2 - v0;
float S = v1;
noise[i] = P*t*t*t + Q*t*t + R*t + S;
}
int failed = 0;
for(int p=0; p<intPerim; p++) {
float th = 2 * PI * p / perim;
float r = radius * (1 + (1-coherence)*noise[p]);
float s = sin(th);
float c = cos(th);
float xx=x, yy=y;
for(float k=0; k<r; k++) {
int i = (int)xx, j = (int)yy;
if(m->validT(i, j) && constr->allows(m, i, j)) {
Point p(i,j);
if(!gotRet[p]) {
gotRet[p] = 1;
retVec.push_back(p);
}
}
else {
failed++;
}
xx += s;
yy += c;
}
}
return (failed > size*failFraction ? false : true);
}