1/**************************************************************************/
2/* immediate_mesh.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "immediate_mesh.h"
32
33void ImmediateMesh::surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material) {
34 ERR_FAIL_COND_MSG(surface_active, "Already creating a new surface.");
35 active_surface_data.primitive = p_primitive;
36 active_surface_data.material = p_material;
37 surface_active = true;
38}
39void ImmediateMesh::surface_set_color(const Color &p_color) {
40 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
41
42 if (!uses_colors) {
43 colors.resize(vertices.size());
44 for (Color &color : colors) {
45 color = p_color;
46 }
47 uses_colors = true;
48 }
49
50 current_color = p_color;
51}
52void ImmediateMesh::surface_set_normal(const Vector3 &p_normal) {
53 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
54
55 if (!uses_normals) {
56 normals.resize(vertices.size());
57 for (Vector3 &normal : normals) {
58 normal = p_normal;
59 }
60 uses_normals = true;
61 }
62
63 current_normal = p_normal;
64}
65void ImmediateMesh::surface_set_tangent(const Plane &p_tangent) {
66 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
67 if (!uses_tangents) {
68 tangents.resize(vertices.size());
69 for (Plane &tangent : tangents) {
70 tangent = p_tangent;
71 }
72 uses_tangents = true;
73 }
74
75 current_tangent = p_tangent;
76}
77void ImmediateMesh::surface_set_uv(const Vector2 &p_uv) {
78 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
79 if (!uses_uvs) {
80 uvs.resize(vertices.size());
81 for (Vector2 &uv : uvs) {
82 uv = p_uv;
83 }
84 uses_uvs = true;
85 }
86
87 current_uv = p_uv;
88}
89void ImmediateMesh::surface_set_uv2(const Vector2 &p_uv2) {
90 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
91 if (!uses_uv2s) {
92 uv2s.resize(vertices.size());
93 for (Vector2 &uv : uv2s) {
94 uv = p_uv2;
95 }
96 uses_uv2s = true;
97 }
98
99 current_uv2 = p_uv2;
100}
101void ImmediateMesh::surface_add_vertex(const Vector3 &p_vertex) {
102 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
103 ERR_FAIL_COND_MSG(vertices.size() && active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
104
105 if (uses_colors) {
106 colors.push_back(current_color);
107 }
108 if (uses_normals) {
109 normals.push_back(current_normal);
110 }
111 if (uses_tangents) {
112 tangents.push_back(current_tangent);
113 }
114 if (uses_uvs) {
115 uvs.push_back(current_uv);
116 }
117 if (uses_uv2s) {
118 uv2s.push_back(current_uv2);
119 }
120 vertices.push_back(p_vertex);
121}
122
123void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) {
124 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
125 ERR_FAIL_COND_MSG(vertices.size() && !active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
126
127 if (uses_colors) {
128 colors.push_back(current_color);
129 }
130 if (uses_normals) {
131 normals.push_back(current_normal);
132 }
133 if (uses_tangents) {
134 tangents.push_back(current_tangent);
135 }
136 if (uses_uvs) {
137 uvs.push_back(current_uv);
138 }
139 if (uses_uv2s) {
140 uv2s.push_back(current_uv2);
141 }
142 Vector3 v(p_vertex.x, p_vertex.y, 0);
143 vertices.push_back(v);
144
145 active_surface_data.vertex_2d = true;
146}
147
148void ImmediateMesh::surface_end() {
149 ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
150 ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface can't be created.");
151
152 uint32_t format = ARRAY_FORMAT_VERTEX;
153
154 uint32_t vertex_stride = 0;
155 if (active_surface_data.vertex_2d) {
156 format |= ARRAY_FLAG_USE_2D_VERTICES;
157 vertex_stride = sizeof(float) * 2;
158 } else {
159 vertex_stride = sizeof(float) * 3;
160 }
161
162 uint32_t normal_offset = 0;
163 if (uses_normals) {
164 format |= ARRAY_FORMAT_NORMAL;
165 normal_offset = vertex_stride;
166 vertex_stride += sizeof(uint32_t);
167 }
168 uint32_t tangent_offset = 0;
169 if (uses_tangents) {
170 format |= ARRAY_FORMAT_TANGENT;
171 tangent_offset += vertex_stride;
172 vertex_stride += sizeof(uint32_t);
173 }
174
175 AABB aabb;
176
177 {
178 surface_vertex_create_cache.resize(vertex_stride * vertices.size());
179 uint8_t *surface_vertex_ptr = surface_vertex_create_cache.ptrw();
180 for (uint32_t i = 0; i < vertices.size(); i++) {
181 {
182 float *vtx = (float *)&surface_vertex_ptr[i * vertex_stride];
183 vtx[0] = vertices[i].x;
184 vtx[1] = vertices[i].y;
185 if (!active_surface_data.vertex_2d) {
186 vtx[2] = vertices[i].z;
187 }
188 if (i == 0) {
189 aabb = AABB(vertices[i], SMALL_VEC3); // Must have a bit of size.
190 } else {
191 aabb.expand_to(vertices[i]);
192 }
193 }
194 if (uses_normals) {
195 uint32_t *normal = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + normal_offset];
196
197 Vector2 n = normals[i].octahedron_encode();
198
199 uint32_t value = 0;
200 value |= (uint16_t)CLAMP(n.x * 65535, 0, 65535);
201 value |= (uint16_t)CLAMP(n.y * 65535, 0, 65535) << 16;
202
203 *normal = value;
204 }
205 if (uses_tangents) {
206 uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + tangent_offset];
207 Vector2 t = tangents[i].normal.octahedron_tangent_encode(tangents[i].d);
208 uint32_t value = 0;
209 value |= (uint16_t)CLAMP(t.x * 65535, 0, 65535);
210 value |= (uint16_t)CLAMP(t.y * 65535, 0, 65535) << 16;
211
212 *tangent = value;
213 }
214 }
215 }
216
217 if (uses_colors || uses_uvs || uses_uv2s) {
218 uint32_t attribute_stride = 0;
219
220 if (uses_colors) {
221 format |= ARRAY_FORMAT_COLOR;
222 attribute_stride += sizeof(uint8_t) * 4;
223 }
224 uint32_t uv_offset = 0;
225 if (uses_uvs) {
226 format |= ARRAY_FORMAT_TEX_UV;
227 uv_offset = attribute_stride;
228 attribute_stride += sizeof(float) * 2;
229 }
230 uint32_t uv2_offset = 0;
231 if (uses_uv2s) {
232 format |= ARRAY_FORMAT_TEX_UV2;
233 uv2_offset = attribute_stride;
234 attribute_stride += sizeof(float) * 2;
235 }
236
237 surface_attribute_create_cache.resize(vertices.size() * attribute_stride);
238
239 uint8_t *surface_attribute_ptr = surface_attribute_create_cache.ptrw();
240
241 for (uint32_t i = 0; i < vertices.size(); i++) {
242 if (uses_colors) {
243 uint8_t *color8 = (uint8_t *)&surface_attribute_ptr[i * attribute_stride];
244
245 color8[0] = uint8_t(CLAMP(colors[i].r * 255.0, 0.0, 255.0));
246 color8[1] = uint8_t(CLAMP(colors[i].g * 255.0, 0.0, 255.0));
247 color8[2] = uint8_t(CLAMP(colors[i].b * 255.0, 0.0, 255.0));
248 color8[3] = uint8_t(CLAMP(colors[i].a * 255.0, 0.0, 255.0));
249 }
250 if (uses_uvs) {
251 float *uv = (float *)&surface_attribute_ptr[i * attribute_stride + uv_offset];
252
253 uv[0] = uvs[i].x;
254 uv[1] = uvs[i].y;
255 }
256
257 if (uses_uv2s) {
258 float *uv2 = (float *)&surface_attribute_ptr[i * attribute_stride + uv2_offset];
259
260 uv2[0] = uv2s[i].x;
261 uv2[1] = uv2s[i].y;
262 }
263 }
264 }
265
266 RS::SurfaceData sd;
267
268 sd.primitive = RS::PrimitiveType(active_surface_data.primitive);
269 sd.format = format;
270 sd.vertex_data = surface_vertex_create_cache;
271 if (uses_colors || uses_uvs || uses_uv2s) {
272 sd.attribute_data = surface_attribute_create_cache;
273 }
274 sd.vertex_count = vertices.size();
275 sd.aabb = aabb;
276 if (active_surface_data.material.is_valid()) {
277 sd.material = active_surface_data.material->get_rid();
278 }
279
280 RS::get_singleton()->mesh_add_surface(mesh, sd);
281
282 active_surface_data.aabb = aabb;
283
284 active_surface_data.format = format;
285 active_surface_data.array_len = vertices.size();
286
287 surfaces.push_back(active_surface_data);
288
289 colors.clear();
290 normals.clear();
291 tangents.clear();
292 uvs.clear();
293 uv2s.clear();
294 vertices.clear();
295
296 uses_colors = false;
297 uses_normals = false;
298 uses_tangents = false;
299 uses_uvs = false;
300 uses_uv2s = false;
301
302 surface_active = false;
303}
304
305void ImmediateMesh::clear_surfaces() {
306 RS::get_singleton()->mesh_clear(mesh);
307 surfaces.clear();
308 surface_active = false;
309
310 colors.clear();
311 normals.clear();
312 tangents.clear();
313 uvs.clear();
314 uv2s.clear();
315 vertices.clear();
316
317 uses_colors = false;
318 uses_normals = false;
319 uses_tangents = false;
320 uses_uvs = false;
321 uses_uv2s = false;
322}
323
324int ImmediateMesh::get_surface_count() const {
325 return surfaces.size();
326}
327int ImmediateMesh::surface_get_array_len(int p_idx) const {
328 ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), -1);
329 return surfaces[p_idx].array_len;
330}
331int ImmediateMesh::surface_get_array_index_len(int p_idx) const {
332 return 0;
333}
334Array ImmediateMesh::surface_get_arrays(int p_surface) const {
335 ERR_FAIL_INDEX_V(p_surface, int(surfaces.size()), Array());
336 return RS::get_singleton()->mesh_surface_get_arrays(mesh, p_surface);
337}
338TypedArray<Array> ImmediateMesh::surface_get_blend_shape_arrays(int p_surface) const {
339 return TypedArray<Array>();
340}
341Dictionary ImmediateMesh::surface_get_lods(int p_surface) const {
342 return Dictionary();
343}
344BitField<Mesh::ArrayFormat> ImmediateMesh::surface_get_format(int p_idx) const {
345 ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), 0);
346 return surfaces[p_idx].format;
347}
348Mesh::PrimitiveType ImmediateMesh::surface_get_primitive_type(int p_idx) const {
349 ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), PRIMITIVE_MAX);
350 return surfaces[p_idx].primitive;
351}
352void ImmediateMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
353 ERR_FAIL_INDEX(p_idx, int(surfaces.size()));
354 surfaces[p_idx].material = p_material;
355 RID mat;
356 if (p_material.is_valid()) {
357 mat = p_material->get_rid();
358 }
359 RS::get_singleton()->mesh_surface_set_material(mesh, p_idx, mat);
360}
361Ref<Material> ImmediateMesh::surface_get_material(int p_idx) const {
362 ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), Ref<Material>());
363 return surfaces[p_idx].material;
364}
365int ImmediateMesh::get_blend_shape_count() const {
366 return 0;
367}
368StringName ImmediateMesh::get_blend_shape_name(int p_index) const {
369 return StringName();
370}
371void ImmediateMesh::set_blend_shape_name(int p_index, const StringName &p_name) {
372}
373
374AABB ImmediateMesh::get_aabb() const {
375 AABB aabb;
376 for (uint32_t i = 0; i < surfaces.size(); i++) {
377 if (i == 0) {
378 aabb = surfaces[i].aabb;
379 } else {
380 aabb = aabb.merge(surfaces[i].aabb);
381 }
382 }
383 return aabb;
384}
385
386void ImmediateMesh::_bind_methods() {
387 ClassDB::bind_method(D_METHOD("surface_begin", "primitive", "material"), &ImmediateMesh::surface_begin, DEFVAL(Ref<Material>()));
388 ClassDB::bind_method(D_METHOD("surface_set_color", "color"), &ImmediateMesh::surface_set_color);
389 ClassDB::bind_method(D_METHOD("surface_set_normal", "normal"), &ImmediateMesh::surface_set_normal);
390 ClassDB::bind_method(D_METHOD("surface_set_tangent", "tangent"), &ImmediateMesh::surface_set_tangent);
391 ClassDB::bind_method(D_METHOD("surface_set_uv", "uv"), &ImmediateMesh::surface_set_uv);
392 ClassDB::bind_method(D_METHOD("surface_set_uv2", "uv2"), &ImmediateMesh::surface_set_uv2);
393 ClassDB::bind_method(D_METHOD("surface_add_vertex", "vertex"), &ImmediateMesh::surface_add_vertex);
394 ClassDB::bind_method(D_METHOD("surface_add_vertex_2d", "vertex"), &ImmediateMesh::surface_add_vertex_2d);
395 ClassDB::bind_method(D_METHOD("surface_end"), &ImmediateMesh::surface_end);
396
397 ClassDB::bind_method(D_METHOD("clear_surfaces"), &ImmediateMesh::clear_surfaces);
398}
399
400RID ImmediateMesh::get_rid() const {
401 return mesh;
402}
403
404ImmediateMesh::ImmediateMesh() {
405 mesh = RS::get_singleton()->mesh_create();
406}
407ImmediateMesh::~ImmediateMesh() {
408 ERR_FAIL_NULL(RenderingServer::get_singleton());
409 RS::get_singleton()->free(mesh);
410}
411