create static method
A terrain object for use with the js library.
Usage: Terrain terrainScene = Terrain();
TerrainOptions options An optional map of settings that control how the terrain is constructed and displayed. Options include:
after: A function to run after other transformations on the terrain produce the highest-detail heightmap, but before optimizations and visual properties are applied. Takes two parameters, which are the same as those for {@link Terrain.DiamondSquare}: an array ofVector3objects representing the vertices of the terrain, and a map of options with the same available properties as theoptionsparameter for theTerrainfunction.easing: A function that affects the distribution of slopes by interpolating the height of each vertex along a curve. Valid values includeTerrain.Linear(the default),Terrain.EaseIn,Terrain.EaseOut,Terrain.EaseInOut,Terrain.InEaseOut, and any custom function that accepts a float between 0 and 1 and returns a float between 0 and 1.frequency: For terrain generation methods that support it (Perlin, Simplex, and Worley) the octave of randomness. This basically controls how big features of the terrain will be (higher frequencies result in smaller features). Often running multiple generation functions with different frequencies and heights results in nice detail, as the PerlinLayers and SimplexLayers methods demonstrate. (The counterpart to frequency, amplitude, is represented by the difference between themaxHeightandminHeightparameters.) Defaults to 2.5.heightmap: Either a canvas or pre-loaded image (from the same domain as the webpage or served with a CORS-friendly header) representing terrain height data (lighter pixels are higher); or a function used to generate random height data for the terrain. Valid random functions are specified ingenerators.js(or custom functions with the same signature). Ideally heightmap images have the same number of pixels as the terrain has vertices, as determined by thexSegmentsandySegmentsoptions, but this is not required. If the heightmap is a different size, vertex height values will be interpolated.) Defaults toTerrain.DiamondSquare.material: a Material instance used to display the terrain. Defaults tonew MeshBasicMaterial({color: 0xee6633}).maxHeight: the highest point, in js units, that a peak should reach. Defaults to 100. Setting toundefined,null, orInfinityremoves the cap, but this is generally not recommended because many generators and filters require a vertical range. Instead, consider setting thestretchoption tofalse.minHeight: the lowest point, in js units, that a valley should reach. Defaults to -100. Setting toundefined,null, or-Infinityremoves the cap, but this is generally not recommended because many generators and filters require a vertical range. Instead, consider setting thestretchoption tofalse.steps: If this is a number above 1, the terrain will be paritioned into that many flat "steps," resulting in a blocky appearance. Defaults to 1.stretch: Determines whether to stretch the heightmap across the maximum and minimum height range if the height range produced by theheightmapproperty is smaller. Defaults to true.turbulent: Whether to perform a turbulence transformation. Defaults to false.xSegments: The number of segments (rows) to divide the terrain plane into. (This basically determines how detailed the terrain is.) Defaults to 63.xSize: The width of the terrain in js units. Defaults to 1024. Rendering might be slightly faster if this is a multiple ofoptions.xSegments + 1.ySegments: The number of segments (columns) to divide the terrain plane into. (This basically determines how detailed the terrain is.) Defaults to 63.ySize: The length of the terrain in js units. Defaults to 1024. Rendering might be slightly faster if this is a multiple ofoptions.ySegments + 1.
Implementation
static Object3D create(TerrainOptions? options) {
options = options ?? TerrainOptions(
maxHeight: 100,
minHeight: -100
);
options.material = options.material ?? MeshBasicMaterial.fromMap({ 'color': 0xee6633 });
// Encapsulating the terrain in a parent object allows us the flexibility
// to more easily have multiple meshes for optimization purposes.
final scene = Object3D();
// Planes are initialized on the XY plane, so rotate the plane to make it lie flat.
scene.rotation.x = -0.5*math.pi;
// Create the terrain mesh.
final mesh = Mesh(
PlaneGeometry(options.xSize, options.ySize, options.xSegments, options.ySegments),
options.material
);
// Assign elevation data to the terrain plane from a heightmap or function.
final zs = toArray1D(mesh.geometry!.attributes['position'].array.toDartList());
if (options.heightmap is Uint8List) {
fromHeightmap(zs, options);
}
else if (options.heightmap is Function) {
options.heightmap(zs, options);
}
else {
console.warning('An invalid value was passed for `options.heightmap`: ${options.heightmap.runtimeType}');
}
fromArray1D(mesh.geometry!.attributes['position'].array.toDartList(), zs);
normalize(mesh, options);
// lod.addLevel(mesh, options.unit*10*Math.pow(2, lodLevel));
scene.add(mesh);
return scene;
}