Skip to content

Commit ebfef62

Browse files
committed
Add support for custom 0-3 attributes to ImmediateMesh
1 parent 9a5d6d1 commit ebfef62

File tree

3 files changed

+195
-1
lines changed

3 files changed

+195
-1
lines changed

doc/classes/ImmediateMesh.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
[/csharp]
2626
[/codeblocks]
2727
[b]Note:[/b] Generating complex geometries with [ImmediateMesh] is highly inefficient. Instead, it is designed to generate simple geometry that changes often.
28+
[b]Note:[/b] The custom data attributes will use the [constant Mesh.ARRAY_CUSTOM_RGBA_FLOAT] format.
2829
</description>
2930
<tutorials>
3031
<link title="Using ImmediateMesh">$DOCS_URL/tutorials/3d/procedural_geometry/immediatemesh.html</link>
@@ -71,6 +72,34 @@
7172
Set the color attribute that will be pushed with the next vertex.
7273
</description>
7374
</method>
75+
<method name="surface_set_custom0">
76+
<return type="void" />
77+
<param index="0" name="custom0" type="Vector4" />
78+
<description>
79+
Set the CUSTOM0 attribute that will be pushed with the next vertex.
80+
</description>
81+
</method>
82+
<method name="surface_set_custom1">
83+
<return type="void" />
84+
<param index="0" name="custom1" type="Vector4" />
85+
<description>
86+
Set the CUSTOM1 attribute that will be pushed with the next vertex.
87+
</description>
88+
</method>
89+
<method name="surface_set_custom2">
90+
<return type="void" />
91+
<param index="0" name="custom2" type="Vector4" />
92+
<description>
93+
Set the CUSTOM2 attribute that will be pushed with the next vertex.
94+
</description>
95+
</method>
96+
<method name="surface_set_custom3">
97+
<return type="void" />
98+
<param index="0" name="custom3" type="Vector4" />
99+
<description>
100+
Set the CUSTOM3 attribute that will be pushed with the next vertex.
101+
</description>
102+
</method>
74103
<method name="surface_set_normal">
75104
<return type="void" />
76105
<param index="0" name="normal" type="Vector3" />

scene/resources/immediate_mesh.cpp

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,54 @@ void ImmediateMesh::surface_set_uv2(const Vector2 &p_uv2) {
9898

9999
current_uv2 = p_uv2;
100100
}
101+
void ImmediateMesh::surface_set_custom0(const Vector4 &p_custom0) {
102+
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
103+
if (!uses_custom0) {
104+
custom0s.resize(vertices.size());
105+
for (Vector4 &custom0 : custom0s) {
106+
custom0 = p_custom0;
107+
}
108+
uses_custom0 = true;
109+
}
110+
111+
current_custom0 = p_custom0;
112+
}
113+
void ImmediateMesh::surface_set_custom1(const Vector4 &p_custom1) {
114+
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
115+
if (!uses_custom1) {
116+
custom1s.resize(vertices.size());
117+
for (Vector4 &custom1 : custom1s) {
118+
custom1 = p_custom1;
119+
}
120+
uses_custom1 = true;
121+
}
122+
123+
current_custom1 = p_custom1;
124+
}
125+
void ImmediateMesh::surface_set_custom2(const Vector4 &p_custom2) {
126+
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
127+
if (!uses_custom2) {
128+
custom2s.resize(vertices.size());
129+
for (Vector4 &custom2 : custom2s) {
130+
custom2 = p_custom2;
131+
}
132+
uses_custom2 = true;
133+
}
134+
135+
current_custom2 = p_custom2;
136+
}
137+
void ImmediateMesh::surface_set_custom3(const Vector4 &p_custom3) {
138+
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
139+
if (!uses_custom3) {
140+
custom1s.resize(vertices.size());
141+
for (Vector4 &custom3 : custom3s) {
142+
custom3 = p_custom3;
143+
}
144+
uses_custom3 = true;
145+
}
146+
147+
current_custom3 = p_custom3;
148+
}
101149
void ImmediateMesh::surface_add_vertex(const Vector3 &p_vertex) {
102150
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
103151
ERR_FAIL_COND_MSG(vertices.size() && active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
@@ -117,6 +165,18 @@ void ImmediateMesh::surface_add_vertex(const Vector3 &p_vertex) {
117165
if (uses_uv2s) {
118166
uv2s.push_back(current_uv2);
119167
}
168+
if (uses_custom0) {
169+
custom0s.push_back(current_custom0);
170+
}
171+
if (uses_custom1) {
172+
custom1s.push_back(current_custom1);
173+
}
174+
if (uses_custom2) {
175+
custom2s.push_back(current_custom2);
176+
}
177+
if (uses_custom3) {
178+
custom3s.push_back(current_custom3);
179+
}
120180
vertices.push_back(p_vertex);
121181
}
122182

@@ -139,6 +199,18 @@ void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) {
139199
if (uses_uv2s) {
140200
uv2s.push_back(current_uv2);
141201
}
202+
if (uses_custom0) {
203+
custom0s.push_back(current_custom0);
204+
}
205+
if (uses_custom1) {
206+
custom1s.push_back(current_custom1);
207+
}
208+
if (uses_custom2) {
209+
custom2s.push_back(current_custom2);
210+
}
211+
if (uses_custom3) {
212+
custom3s.push_back(current_custom3);
213+
}
142214
Vector3 v(p_vertex.x, p_vertex.y, 0);
143215
vertices.push_back(v);
144216

@@ -245,6 +317,30 @@ void ImmediateMesh::surface_end() {
245317
uv2_offset = attribute_stride;
246318
attribute_stride += sizeof(float) * 2;
247319
}
320+
uint32_t custom0_offset = 0;
321+
if (uses_custom0) {
322+
format |= ARRAY_FORMAT_CUSTOM0 | (ARRAY_CUSTOM_RGBA_FLOAT << ARRAY_FORMAT_CUSTOM0_SHIFT);
323+
custom0_offset = attribute_stride;
324+
attribute_stride += sizeof(float) * 4;
325+
}
326+
uint32_t custom1_offset = 0;
327+
if (uses_custom1) {
328+
format |= ARRAY_FORMAT_CUSTOM1 | (ARRAY_CUSTOM_RGBA_FLOAT << ARRAY_FORMAT_CUSTOM1_SHIFT);
329+
custom1_offset = attribute_stride;
330+
attribute_stride += sizeof(float) * 4;
331+
}
332+
uint32_t custom2_offset = 0;
333+
if (uses_custom2) {
334+
format |= ARRAY_FORMAT_CUSTOM2 | (ARRAY_CUSTOM_RGBA_FLOAT << ARRAY_FORMAT_CUSTOM2_SHIFT);
335+
custom2_offset = attribute_stride;
336+
attribute_stride += sizeof(float) * 4;
337+
}
338+
uint32_t custom3_offset = 0;
339+
if (uses_custom3) {
340+
format |= ARRAY_FORMAT_CUSTOM3 | (ARRAY_CUSTOM_RGBA_FLOAT << ARRAY_FORMAT_CUSTOM3_SHIFT);
341+
custom3_offset = attribute_stride;
342+
attribute_stride += sizeof(float) * 4;
343+
}
248344

249345
surface_attribute_create_cache.resize(vertices.size() * attribute_stride);
250346

@@ -272,6 +368,39 @@ void ImmediateMesh::surface_end() {
272368
uv2[0] = uv2s[i].x;
273369
uv2[1] = uv2s[i].y;
274370
}
371+
372+
if (uses_custom0) {
373+
float *custom0 = (float *)&surface_attribute_ptr[i * attribute_stride + custom0_offset];
374+
375+
custom0[0] = custom0s[i].x;
376+
custom0[1] = custom0s[i].y;
377+
custom0[2] = custom0s[i].z;
378+
custom0[3] = custom0s[i].w;
379+
}
380+
if (uses_custom1) {
381+
float *custom1 = (float *)&surface_attribute_ptr[i * attribute_stride + custom1_offset];
382+
383+
custom1[0] = custom1s[i].x;
384+
custom1[1] = custom1s[i].y;
385+
custom1[2] = custom1s[i].z;
386+
custom1[3] = custom1s[i].w;
387+
}
388+
if (uses_custom2) {
389+
float *custom2 = (float *)&surface_attribute_ptr[i * attribute_stride + custom2_offset];
390+
391+
custom2[0] = custom2s[i].x;
392+
custom2[1] = custom2s[i].y;
393+
custom2[2] = custom2s[i].z;
394+
custom2[3] = custom2s[i].w;
395+
}
396+
if (uses_custom1) {
397+
float *custom3 = (float *)&surface_attribute_ptr[i * attribute_stride + custom3_offset];
398+
399+
custom3[0] = custom3s[i].x;
400+
custom3[1] = custom3s[i].y;
401+
custom3[2] = custom3s[i].z;
402+
custom3[3] = custom3s[i].w;
403+
}
275404
}
276405
}
277406

@@ -280,7 +409,7 @@ void ImmediateMesh::surface_end() {
280409
sd.primitive = RS::PrimitiveType(active_surface_data.primitive);
281410
sd.format = format;
282411
sd.vertex_data = surface_vertex_create_cache;
283-
if (uses_colors || uses_uvs || uses_uv2s) {
412+
if (uses_colors || uses_uvs || uses_uv2s || uses_custom0 || uses_custom1) {
284413
sd.attribute_data = surface_attribute_create_cache;
285414
}
286415
sd.vertex_count = vertices.size();
@@ -303,13 +432,21 @@ void ImmediateMesh::surface_end() {
303432
tangents.clear();
304433
uvs.clear();
305434
uv2s.clear();
435+
custom0s.clear();
436+
custom1s.clear();
437+
custom2s.clear();
438+
custom3s.clear();
306439
vertices.clear();
307440

308441
uses_colors = false;
309442
uses_normals = false;
310443
uses_tangents = false;
311444
uses_uvs = false;
312445
uses_uv2s = false;
446+
uses_custom0 = false;
447+
uses_custom1 = false;
448+
uses_custom2 = false;
449+
uses_custom3 = false;
313450

314451
surface_active = false;
315452

@@ -326,13 +463,21 @@ void ImmediateMesh::clear_surfaces() {
326463
tangents.clear();
327464
uvs.clear();
328465
uv2s.clear();
466+
custom0s.clear();
467+
custom1s.clear();
468+
custom2s.clear();
469+
custom3s.clear();
329470
vertices.clear();
330471

331472
uses_colors = false;
332473
uses_normals = false;
333474
uses_tangents = false;
334475
uses_uvs = false;
335476
uses_uv2s = false;
477+
uses_custom0 = false;
478+
uses_custom1 = false;
479+
uses_custom2 = false;
480+
uses_custom3 = false;
336481
}
337482

338483
int ImmediateMesh::get_surface_count() const {
@@ -404,6 +549,10 @@ void ImmediateMesh::_bind_methods() {
404549
ClassDB::bind_method(D_METHOD("surface_set_tangent", "tangent"), &ImmediateMesh::surface_set_tangent);
405550
ClassDB::bind_method(D_METHOD("surface_set_uv", "uv"), &ImmediateMesh::surface_set_uv);
406551
ClassDB::bind_method(D_METHOD("surface_set_uv2", "uv2"), &ImmediateMesh::surface_set_uv2);
552+
ClassDB::bind_method(D_METHOD("surface_set_custom0", "custom0"), &ImmediateMesh::surface_set_custom0);
553+
ClassDB::bind_method(D_METHOD("surface_set_custom1", "custom1"), &ImmediateMesh::surface_set_custom1);
554+
ClassDB::bind_method(D_METHOD("surface_set_custom2", "custom2"), &ImmediateMesh::surface_set_custom2);
555+
ClassDB::bind_method(D_METHOD("surface_set_custom3", "custom3"), &ImmediateMesh::surface_set_custom3);
407556
ClassDB::bind_method(D_METHOD("surface_add_vertex", "vertex"), &ImmediateMesh::surface_add_vertex);
408557
ClassDB::bind_method(D_METHOD("surface_add_vertex_2d", "vertex"), &ImmediateMesh::surface_add_vertex_2d);
409558
ClassDB::bind_method(D_METHOD("surface_end"), &ImmediateMesh::surface_end);

scene/resources/immediate_mesh.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,30 @@ class ImmediateMesh : public Mesh {
4343
bool uses_tangents = false;
4444
bool uses_uvs = false;
4545
bool uses_uv2s = false;
46+
bool uses_custom0 = false;
47+
bool uses_custom1 = false;
48+
bool uses_custom2 = false;
49+
bool uses_custom3 = false;
4650

4751
Color current_color;
4852
Vector3 current_normal;
4953
Plane current_tangent;
5054
Vector2 current_uv;
5155
Vector2 current_uv2;
56+
Vector4 current_custom0;
57+
Vector4 current_custom1;
58+
Vector4 current_custom2;
59+
Vector4 current_custom3;
5260

5361
LocalVector<Color> colors;
5462
LocalVector<Vector3> normals;
5563
LocalVector<Plane> tangents;
5664
LocalVector<Vector2> uvs;
5765
LocalVector<Vector2> uv2s;
66+
LocalVector<Vector4> custom0s;
67+
LocalVector<Vector4> custom1s;
68+
LocalVector<Vector4> custom2s;
69+
LocalVector<Vector4> custom3s;
5870
LocalVector<Vector3> vertices;
5971

6072
struct Surface {
@@ -86,6 +98,10 @@ class ImmediateMesh : public Mesh {
8698
void surface_set_tangent(const Plane &p_tangent);
8799
void surface_set_uv(const Vector2 &p_uv);
88100
void surface_set_uv2(const Vector2 &p_uv2);
101+
void surface_set_custom0(const Vector4 &p_custom0);
102+
void surface_set_custom1(const Vector4 &p_custom1);
103+
void surface_set_custom2(const Vector4 &p_custom2);
104+
void surface_set_custom3(const Vector4 &p_custom3);
89105
void surface_add_vertex(const Vector3 &p_vertex);
90106
void surface_add_vertex_2d(const Vector2 &p_vertex);
91107
void surface_end();

0 commit comments

Comments
 (0)