//Creates a full patch for one frequency. Calculates gradientpoints, and interpolates values for all pixels between them vector<float> PerlinPatchGenerator::createPatch(int frequency, int gradientPoints, float amplitude){ float s,t,u,v,diffX,diffY,a,b,z; int gradientX, gradientY; vector<float> finalGrid; float sVec[2], tVec[2], uVec[2], vVec[2]; vector<vector<float>> gradients; gradients = createGradients(gradientPoints); //Number of pixels included between each gradient point int numberOfPixels = gridSize/frequency; //Loop over all pixels in patch for(int row = 0; row < gridSize; row++) { //Calculate distance from pixel to closest gradient point in Y-axis diffY = (float)(row % numberOfPixels)/(float)numberOfPixels; for(int col = 0; col < gridSize; col++) { //Calculate distance from pixel to closest gradient point in X-axis diffX = (float)(col % numberOfPixels)/(float)numberOfPixels; //Check what gradientpoints we should interpolate values from gradientX = floor(col/numberOfPixels); gradientY = floor(row/numberOfPixels); //Calculate vectors from each gradientpoint to the pixel sVec[0] = diffX; sVec[1] = diffY; tVec[0] = diffX-1; tVec[1] = diffY; uVec[0] = diffX; uVec[1] = diffY-1; vVec[0] = diffX-1; vVec[1] = diffY-1; //Calculate values to interpolate between for each pixel s = dotProduct(gradients.at(gradientY*gradientPoints + gradientX),sVec); t = dotProduct(gradients.at(gradientY*gradientPoints + gradientX+1),tVec); u = dotProduct(gradients.at((gradientY+1)*gradientPoints + gradientX),uVec); v = dotProduct(gradients.at((gradientY+1)*gradientPoints + gradientX+1),vVec); //Interpolate in x-axis and y-axis a = interpolateValues(s,t,diffX); b = interpolateValues(u,v,diffX); z = interpolateValues(a,b,diffY);; finalGrid.push_back(z * amplitude); } } return finalGrid; }
// Private functions void Blender::initCornerWeight(){ // Fill cornerWeight with zeros // There are four corners, hence i < 4 vector<float> tempZeros (overlap*overlap,0.0); for(int i = 0; i<4; i++){ cornerWeight.push_back(tempZeros); } for(int i = 0; i<overlap;i++){ for(int j = 0; j<overlap; j++){ float diffX = ((float)i)/((float)overlap-1); float diffY = ((float)j)/((float)overlap-1); float interpX = interpolateValues(1,0,diffX); cornerWeight.at(0).at(overlap*i + j) = interpolateValues(interpX,0,diffY); interpX = interpolateValues(0,1,diffX); cornerWeight.at(1).at(overlap*i + j) = interpolateValues(interpX,0,diffY); interpX = interpolateValues(1,0,diffX); cornerWeight.at(2).at(overlap*i + j) = interpolateValues(0,interpX,diffY); interpX = interpolateValues(0,1,diffX); cornerWeight.at(3).at(overlap*i + j) = interpolateValues(0,interpX,diffY); } } }
vector<float> PerlinPatchGenerator::createPatch(int gridSize, int frequency, int gradientPoints, float amplitude){ cout << "createPatch begin\n"; vector<vector<float>> gradients; gradients = createGradients(gradientPoints); int numberOfPixels = gridSize/frequency; float s,t,u,v,diffX,diffY,Sx,Sy,a,b,z,ft,f; int gradientX, gradientY; vector<float> finalGrid; for(int row = 0; row < gridSize; row++) { diffY = (float)(row % numberOfPixels)/(float)numberOfPixels; for(int col = 0; col < gridSize; col++) { diffX = (float)(col % numberOfPixels)/(float)numberOfPixels; gradientX = floor(col/numberOfPixels); gradientY = floor(row/numberOfPixels); vector<float> sVec, tVec, uVec, vVec; sVec.push_back(diffX); sVec.push_back(diffY); tVec.push_back(diffX-1); tVec.push_back(diffY); uVec.push_back(diffX); uVec.push_back(diffY-1); vVec.push_back(diffX-1); vVec.push_back(diffY-1); s = dotProduct(gradients.at(gradientY*gradientPoints + gradientX),sVec); t = dotProduct(gradients.at(gradientY*gradientPoints + gradientX+1),tVec); u = dotProduct(gradients.at((gradientY+1)*gradientPoints + gradientX),uVec); v = dotProduct(gradients.at((gradientY+1)*gradientPoints + gradientX+1),vVec); a = interpolateValues(s,t,diffX); b = interpolateValues(u,v,diffX); z = interpolateValues(a,b,diffY);; finalGrid.push_back(z * amplitude); } } cout << "createPatch end\n"; return finalGrid; }
void Blender::blendHors(TerrainPatch* patchWest,TerrainPatch* patchEast){ int patchSize = patchWest->size; int jWest; // jEast is always = j for(int i=overlap; i<patchSize-overlap; i++){ for(int j=0; j<overlap; j++){ jWest = j + patchSize - overlap; float diff = ((float)j)/(overlap-1); float weight = interpolateValues(0,1,diff); float interp = weight*patchEast->rawHeightMap.at(patchSize*i + j) + (1-weight)*patchWest->rawHeightMap.at(patchSize*i + jWest); patchWest->blendedHeightMap.at(patchSize*i + jWest) = interp; patchEast->blendedHeightMap.at(patchSize*i + j) = interp; } } }
void Blender::blendVert(TerrainPatch* patchNorth,TerrainPatch* patchSouth){ int patchSize = patchNorth->size; int iNorth; // iSouth is always = i for(int i=0; i<overlap; i++){ float diff = ((float)i)/(overlap-1); float weight = interpolateValues(0,1,diff); for(int j=overlap; j<patchSize-overlap; j++){ iNorth = i + patchSize - overlap; float interp = weight*patchSouth->rawHeightMap.at(patchSize*i + j) + (1-weight)*patchNorth->rawHeightMap.at(patchSize*iNorth + j); patchNorth->blendedHeightMap.at(patchSize*iNorth + j) = interp; patchSouth->blendedHeightMap.at(patchSize*i + j) = interp; } } }