Detailed Desert Toolkit

(Work In Progress)

()

Updated Progress

Dune solver with stable wind field input

Dune solver with chaotic wind field input

Wind erosion mask by path tracing principle

Wind erosion with high detail level

Introduction

Wind erosion with the lowest detail level

Focusing on developing a procedural desert toolkit that emphasizes editability is thesis’s goal.The tool will be able to generate specified shapes based on user’s input, such as lattices, curves, and wind field information. The toolkit will have procedural control over slope, shape, dispersion, and displacement of the desert surface. Sub-tools such as Dune Tool, Mass Desert Tool, Dune Terrain Fusion Detail Tool, and Desert Ruin Tool make up a procedural desert toolkit. This toolkit will combine the large-scale random generation capabilities of the previous desert tool, and provide users with additional detailed control to ensure that the generated desert can be edited and applied to other subsequent pipelines.

Designed for: In case the user wants to add custom-shaped dunes in certain areas based on the existing terrain

Node’s Input: User’s curve polyline

Node’s Output: height field after adding dunes

Key parameters: change of dune height, shape of front slope of dune, shape of back slope of dune

Node Example: Single Dune From Curve

Control Panel Design

The user can control the shape of the dune boundary using the ramp parameter curve

The user can add random deformation to the boundary shape using the noise parameter

Input Curve (User’s Input)

STEP1: Smooth curve resample it and calculate the tangentv of each point

STEP2: Set height, dune boundary coefficient info to each point


// STEP 2
float numpt = @numpt-1;
float ptnum = @ptnum;
float max_height = ch("max_height");

float curve = ptnum/numpt;
f@outer_fall_off = chramp("outer_slope_fall_off_along_curve",curve);
f@inner_fall_off = chramp("inner_slope_fall_off_along_curve",curve);
f@height = max_height*chramp("main_curve_shape",curve);
setpointgroup(0,"main_slope",@ptnum,1,"set");

STEP3: Set the Width of Boundary and use boundary coefficient info to get the Real boundary of the dune

STEP4: Use boundary line to generate boundary primitive


// STEP 3
vector dir = v@tangentv;
float influence_distance = ch("slop_width");
float outer_mult = ch("outer_slope_mult");

float rand_length = @rand_length;
float outer_fall_off = @outer_fall_off;

setprimgroup(0,"main_slope",0,1,"set");

vector new_pos = @P + (influence_distance*dir+rand_length*dir)*outer_fall_off*outer_mult;
f@outer_bound_dist = length((influence_distance*dir+rand_length*dir)*outer_fall_off*outer_mult);
int p = addpoint(0,new_pos);
int prim = addprim(0,"polyline",@ptnum,p);
setprimgroup(0,"outer_slope",prim,1,"set");
addvertex(0,prim,@ptnum);
addvertex(0,prim,p);

vector dir = v@tangentv;
float influence_distance = ch("slop_width");
float inner_mult = ch("inner_slope_mult");

float rand_length = @rand_length;
float inner_fall_off = @inner_fall_off;

vector new_pos2 = @P + (influence_distance*-dir+rand_length*-dir)*inner_fall_off*inner_mult;
f@inner_bound_dist = length((influence_distance*-dir+rand_length*-dir)*inner_fall_off*inner_mult);
int p2 = addpoint(0,new_pos2);
int prim2 = addprim(0,"polyline",@ptnum,p2);
setprimgroup(0,"inner_slope",prim2,1,"set");
addvertex(0,prim2,@ptnum);
addvertex(0,prim2,p2);

STEP5: Use Boundary primitive to mask the volume that needed to be processed

STEP6: For every masked volume voxel, Calculate the vector pointing to the point on the curve that is closest to you(sample direction)


// STEP 5
@if_in_prim = xyzdist(2,@P);
if(@if_in_prim < 0.1)
{
    int belong_point = nearpoint(1,@P);
    vector pos = point(1,"P",belong_point);
    vector dir = normalize(pos - @P);
    @sample_dirx = dir.x;
    @sample_dirz = dir.z;
    
    @mask = 1;
    float dist = distance(pos,@P);
    float max_dist = ch("max_dist");
    float index =  fit(dist,0,max_dist,0,1);
    float mask = chramp("mask_fall_off",index);
    @mask = mask;

}
else
{
    @sample_dirx = 0;
    @sample_dirz = 0;
}

STEP7: Smooth the sample direction vector,To ensure that the volume has smooth sampling when obtaining height information from the curve

STEP8: Each voxel uses the sample direction to find the corresponding 2 points on the curve.

obtains the height information from these two points, and makes a weighted average according to the distance of each point to calculate the final height


// STEP 8
@if_in_prim = xyzdist(1,@P);
if(@if_in_prim < 0.1)
{
    @dist = xyzdist(2,@P);
    int belong_point = nearpoint(2,@P);
    int sample_point[];// = nearpoints(2,@P,@dist + ch("search_tolerance"),chi("search_accuracy"));
    for(int n = 0;n < chi("search_accuracy");n++)
    {   
        int additional_p = belong_point + floor(n - 0.5*chi("search_accuracy"));
        append(sample_point,additional_p);
    }
    
    vector standard_tanv = point(2,"tangentv",sample_point[0]);
    vector belong_pos = point(2,"P",sample_point[0]);
    vector current_v = @P - belong_pos;
    
    float outer_bound_dist = point(3,"outer_bound_dist",sample_point[0]);
    float inner_bound_dist = point(2,"inner_bound_dist",sample_point[0]);
    
    float diff = degrees(acos(dot(normalize(standard_tanv),normalize(current_v))));
    
    float sample_dist_list[];
    for(int i = 0; i < len(sample_point);i++){
        vector sample_point_pos = point(2,"P",sample_point[i]);
        append(sample_dist_list,distance(@P,sample_point_pos));
    }
    
    float dist_sum = sum(sample_dist_list);
    float sum_prop = 0;
    for(int m = 0; m < len(sample_point);m++)
    {
        sum_prop += dist_sum/sample_dist_list[m];
    }
   
    for(int k = 0; k < len(sample_point);k++){
        float height_sample = point(2,"height",sample_point[k]);
        if(diff < 90)
            {
            @outer_group = 1;
            float index = fit(sample_dist_list[k],0,outer_bound_dist,0,1);
            float dist_prop = dist_sum/sample_dist_list[k]/sum_prop;
            @height += height_sample*chramp("outer_slope_shape",index)*dist_prop;
            }
        else
            {
            @inner_group = 1; 
            float index = fit(sample_dist_list[k],0,inner_bound_dist,0,1);
            float dist_prop = dist_sum/sample_dist_list[k]/sum_prop;
            @height += height_sample*chramp("inner_slope_shape",index)*dist_prop;
            }
        }
}