87 lines
2.1 KiB
C++
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);
|
|
} |