-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTerrainHeightmapGen.gd
165 lines (135 loc) · 3.73 KB
/
TerrainHeightmapGen.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
tool
extends Spatial
export (NodePath) var block_map = null setget set_block_map
func set_block_map(val):
_clear()
block_map = val
_initialize()
export (int) var view_distance = 12 setget set_view_distance
func set_view_distance(val):
_clear()
view_distance = val
view_distance = clamp(view_distance, 1, 256)
_initialize()
export (int) var height = 4 setget set_height
func set_height(val):
_clear()
height = val
_initialize()
export (int) var seed_val = 20 setget set_seed_val
func set_seed_val(val):
_clear()
seed_val = val
_initialize()
export (int) var octaves = 2 setget set_octaves
func set_octaves(val):
_clear()
octaves = val
_initialize()
export (float) var period = 20.0 setget set_period
func set_period(val):
_clear()
period = val
_initialize()
export (float) var lacunarity = 2 setget set_lacunarity
func set_lacunarity(val):
_clear()
lacunarity = val
_initialize()
export (float) var persistence = 0.5 setget set_persistence
func set_persistence(val):
_clear()
persistence = val
_initialize()
var mesh_node : MeshInstance = null
var noise : OpenSimplexNoise = null
var vertices : PoolVector3Array
var UVs : PoolVector2Array
var normals : PoolVector3Array
#var tangent : PoolVector3Array
#var bitangent : PoolVector3Array
var indices : PoolIntArray
var is_initialized = false
func _generate_vertices():
vertices = PoolVector3Array()
var centre_offset = floor(view_distance / 2)
for x in range(view_distance+1):
for y in range(view_distance+1):
var h = noise.get_noise_2d(x, y) * height
vertices.append(Vector3(x-centre_offset,h,y-centre_offset))
func _generate_UVs():
UVs = PoolVector2Array()
var offset = 1.0 / (view_distance)
for x in range(view_distance+1):
for y in range(view_distance+1):
UVs.append(Vector2(offset*x, offset*y))
func _generate_indices():
indices = PoolIntArray()
for index in range((view_distance+1)*view_distance):
indices.append(index)
indices.append(index+(view_distance+1))
if index != 0 and (index+1) % (view_distance+1) == 0:
indices.append(index+(view_distance+1))
indices.append(index+1)
func _generate_normals():
normals = PoolVector3Array()
normals.resize(vertices.size())
for f in range(normals.size()):
normals[f] = Vector3(0,1,0)
for i in range(0, indices.size()-2, 2):
var ia = indices[i]
var ib = indices[i+1]
var ic = indices[i+2]
if ia==ib or ib==ic or ia==ic:
continue
var a :Vector3 = vertices[ia]
var b :Vector3 = vertices[ib]
var c :Vector3 = vertices[ic]
var tangent = c-a
var bitangent = b-a
var normal_a = tangent.cross(bitangent)
normals[ia] += normal_a
normals[ib] += normal_a
normals[ic] += normal_a
_normalize_normals()
func _normalize_normals():
for i in range(normals.size()):
normals[i] = normals[i].normalized()
func _generate_mesh():
_generate_vertices()
_generate_UVs()
_generate_indices()
_generate_normals()
var mesh = ArrayMesh.new()
var data = []
data.resize(ArrayMesh.ARRAY_MAX)
data[ArrayMesh.ARRAY_VERTEX] = vertices
data[ArrayMesh.ARRAY_TEX_UV] = UVs
data[ArrayMesh.ARRAY_INDEX] = indices
data[ArrayMesh.ARRAY_NORMAL] = normals
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLE_STRIP, data)
return mesh
func _generate_noise():
noise = OpenSimplexNoise.new()
noise.seed = seed_val
noise.octaves = octaves
noise.period = period
noise.lacunarity = lacunarity
noise.persistence = persistence
func _initialize():
if is_initialized:
return
if block_map == null:
return
mesh_node = get_node_or_null(block_map)
if mesh_node == null:
return
_generate_noise()
mesh_node.mesh = _generate_mesh()
is_initialized = true
func _clear():
if mesh_node != null and is_initialized:
is_initialized = false
mesh_node.mesh = null
func _ready():
_initialize()