|
@@ -31,6 +31,7 @@
|
|
|
#ifdef GLES3_ENABLED
|
|
|
|
|
|
#include "mesh_storage.h"
|
|
|
+#include "config.h"
|
|
|
#include "material_storage.h"
|
|
|
#include "utilities.h"
|
|
|
|
|
@@ -285,6 +286,69 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
|
|
|
|
|
ERR_FAIL_COND_MSG(!new_surface.index_count && !new_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
|
|
|
|
|
|
+ if (GLES3::Config::get_singleton()->generate_wireframes && s->primitive == RS::PRIMITIVE_TRIANGLES) {
|
|
|
+ // Generate wireframes. This is mostly used by the editor.
|
|
|
+ s->wireframe = memnew(Mesh::Surface::Wireframe);
|
|
|
+ Vector<uint32_t> wf_indices;
|
|
|
+ uint32_t &wf_index_count = s->wireframe->index_count;
|
|
|
+ uint32_t *wr = nullptr;
|
|
|
+
|
|
|
+ if (new_surface.format & RS::ARRAY_FORMAT_INDEX) {
|
|
|
+ wf_index_count = s->index_count * 2;
|
|
|
+ wf_indices.resize(wf_index_count);
|
|
|
+
|
|
|
+ Vector<uint8_t> ir = new_surface.index_data;
|
|
|
+ wr = wf_indices.ptrw();
|
|
|
+
|
|
|
+ if (new_surface.vertex_count < (1 << 16)) {
|
|
|
+ // Read 16 bit indices.
|
|
|
+ const uint16_t *src_idx = (const uint16_t *)ir.ptr();
|
|
|
+ for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
|
|
|
+ // We use GL_LINES instead of GL_TRIANGLES for drawing these primitives later,
|
|
|
+ // so we need double the indices for each triangle.
|
|
|
+ wr[i + 0] = src_idx[i / 2];
|
|
|
+ wr[i + 1] = src_idx[i / 2 + 1];
|
|
|
+ wr[i + 2] = src_idx[i / 2 + 1];
|
|
|
+ wr[i + 3] = src_idx[i / 2 + 2];
|
|
|
+ wr[i + 4] = src_idx[i / 2 + 2];
|
|
|
+ wr[i + 5] = src_idx[i / 2];
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // Read 32 bit indices.
|
|
|
+ const uint32_t *src_idx = (const uint32_t *)ir.ptr();
|
|
|
+ for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
|
|
|
+ wr[i + 0] = src_idx[i / 2];
|
|
|
+ wr[i + 1] = src_idx[i / 2 + 1];
|
|
|
+ wr[i + 2] = src_idx[i / 2 + 1];
|
|
|
+ wr[i + 3] = src_idx[i / 2 + 2];
|
|
|
+ wr[i + 4] = src_idx[i / 2 + 2];
|
|
|
+ wr[i + 5] = src_idx[i / 2];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // Not using indices.
|
|
|
+ wf_index_count = s->vertex_count * 2;
|
|
|
+ wf_indices.resize(wf_index_count);
|
|
|
+ wr = wf_indices.ptrw();
|
|
|
+
|
|
|
+ for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
|
|
|
+ wr[i + 0] = i / 2;
|
|
|
+ wr[i + 1] = i / 2 + 1;
|
|
|
+ wr[i + 2] = i / 2 + 1;
|
|
|
+ wr[i + 3] = i / 2 + 2;
|
|
|
+ wr[i + 4] = i / 2 + 2;
|
|
|
+ wr[i + 5] = i / 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ s->wireframe->index_buffer_size = wf_index_count * sizeof(uint32_t);
|
|
|
+ glGenBuffers(1, &s->wireframe->index_buffer);
|
|
|
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->wireframe->index_buffer);
|
|
|
+ GLES3::Utilities::get_singleton()->buffer_allocate_data(GL_ELEMENT_ARRAY_BUFFER, s->wireframe->index_buffer, s->wireframe->index_buffer_size, wr, GL_STATIC_DRAW, "Mesh wireframe index buffer");
|
|
|
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // unbind
|
|
|
+ }
|
|
|
+
|
|
|
s->aabb = new_surface.aabb;
|
|
|
s->bone_aabbs = new_surface.bone_aabbs; //only really useful for returning them.
|
|
|
|
|
@@ -712,6 +776,11 @@ void MeshStorage::mesh_clear(RID p_mesh) {
|
|
|
memfree(s.versions); //reallocs, so free with memfree.
|
|
|
}
|
|
|
|
|
|
+ if (s.wireframe) {
|
|
|
+ GLES3::Utilities::get_singleton()->buffer_free_data(s.wireframe->index_buffer);
|
|
|
+ memdelete(s.wireframe);
|
|
|
+ }
|
|
|
+
|
|
|
if (s.lod_count) {
|
|
|
for (uint32_t j = 0; j < s.lod_count; j++) {
|
|
|
if (s.lods[j].index_buffer != 0) {
|