Ver código fonte

Some more fixes for compressed meshes

This cleans up a few more cases of uint32_t->uint64_t

Importantly this fixes an edge case in the axis-angle compression by
using the pre-existing Basis methods instead
clayjohn 1 ano atrás
pai
commit
8f9cd4e1e3

+ 4 - 6
drivers/gles3/storage/mesh_storage.cpp

@@ -202,12 +202,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
 	if (surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION)) {
 		RS::get_singleton()->fix_surface_compatibility(new_surface);
 		surface_version = new_surface.format & (uint64_t(RS::ARRAY_FLAG_FORMAT_VERSION_MASK) << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
-		ERR_FAIL_COND_MSG(surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION),
-				"Surface version provided (" +
-						itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
-						") does not match current version (" +
-						itos((uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION) >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
-						")");
+		ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION,
+				vformat("Surface version provided (%d) does not match current version (%d).",
+						(surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK,
+						(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK));
 	}
 #endif
 

+ 6 - 6
editor/import/resource_importer_obj.cpp

@@ -226,11 +226,6 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
 	bool generate_tangents = p_generate_tangents;
 	Vector3 scale_mesh = p_scale_mesh;
 	Vector3 offset_mesh = p_offset_mesh;
-	uint64_t mesh_flags = RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
-
-	if (p_disable_compression) {
-		mesh_flags = 0;
-	}
 
 	Vector<Vector3> vertices;
 	Vector<Vector3> normals;
@@ -374,6 +369,11 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
 				}
 			}
 		} else if (/*l.begins_with("g ") ||*/ l.begins_with("usemtl ") || (l.begins_with("o ") || f->eof_reached())) { //commit group to mesh
+			uint64_t mesh_flags = RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
+
+			if (p_disable_compression) {
+				mesh_flags = 0;
+			}
 			//groups are too annoying
 			if (surf_tool->get_vertex_array().size()) {
 				//another group going on, commit it
@@ -385,7 +385,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
 					surf_tool->generate_tangents();
 				} else {
 					// We need tangents in order to compress vertex data. So disable if tangents aren't generated.
-					mesh_flags &= ~RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES;
+					mesh_flags = 0;
 				}
 
 				surf_tool->index();

+ 1 - 1
editor/import/resource_importer_scene.cpp

@@ -2371,7 +2371,7 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashM
 	Error err = OK;
 	HashMap<StringName, Variant> options_dupe = p_options;
 
-	Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, options_dupe, nullptr, &err);
+	Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS | EditorSceneFormatImporter::IMPORT_FORCE_DISABLE_MESH_COMPRESSION, options_dupe, nullptr, &err);
 	if (!scene || err != OK) {
 		return nullptr;
 	}

+ 2 - 4
scene/resources/importer_mesh.cpp

@@ -868,7 +868,7 @@ void ImporterMesh::_set_data(const Dictionary &p_data) {
 			if (s.has("material")) {
 				material = s["material"];
 			}
-			uint32_t flags = 0;
+			uint64_t flags = 0;
 			if (s.has("flags")) {
 				flags = s["flags"];
 			}
@@ -909,9 +909,7 @@ Dictionary ImporterMesh::_get_data() const {
 			d["name"] = surfaces[i].name;
 		}
 
-		if (surfaces[i].flags != 0) {
-			d["flags"] = surfaces[i].flags;
-		}
+		d["flags"] = surfaces[i].flags;
 
 		surface_arr.push_back(d);
 	}

+ 8 - 1
scene/resources/mesh.cpp

@@ -1639,6 +1639,11 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
 		uint64_t surface_version = surface.format & (ARRAY_FLAG_FORMAT_VERSION_MASK << ARRAY_FLAG_FORMAT_VERSION_SHIFT);
 		if (surface_version != ARRAY_FLAG_FORMAT_CURRENT_VERSION) {
 			RS::get_singleton()->fix_surface_compatibility(surface, get_path());
+			surface_version = surface.format & (RS::ARRAY_FLAG_FORMAT_VERSION_MASK << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
+			ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION,
+					vformat("Surface version provided (%d) does not match current version (%d).",
+							(surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK,
+							(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK));
 		}
 #endif
 
@@ -2008,17 +2013,19 @@ void ArrayMesh::regen_normal_maps() {
 		return;
 	}
 	Vector<Ref<SurfaceTool>> surfs;
+	Vector<uint64_t> formats;
 	for (int i = 0; i < get_surface_count(); i++) {
 		Ref<SurfaceTool> st = memnew(SurfaceTool);
 		st->create_from(Ref<ArrayMesh>(this), i);
 		surfs.push_back(st);
+		formats.push_back(surface_get_format(i));
 	}
 
 	clear_surfaces();
 
 	for (int i = 0; i < surfs.size(); i++) {
 		surfs.write[i]->generate_tangents();
-		surfs.write[i]->commit(Ref<ArrayMesh>(this));
+		surfs.write[i]->commit(Ref<ArrayMesh>(this), formats[i]);
 	}
 }
 

+ 1 - 1
servers/rendering/renderer_rd/pipeline_cache_rd.h

@@ -38,7 +38,7 @@ class PipelineCacheRD {
 	SpinLock spin_lock;
 
 	RID shader;
-	uint32_t input_mask;
+	uint64_t input_mask;
 
 	RD::RenderPrimitive render_primitive;
 	RD::PipelineRasterizationState rasterization_state;

+ 3 - 5
servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp

@@ -359,11 +359,9 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
 		RS::get_singleton()->fix_surface_compatibility(new_surface);
 		surface_version = new_surface.format & (RS::ARRAY_FLAG_FORMAT_VERSION_MASK << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
 		ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION,
-				"Surface version provided (" +
-						itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
-						") does not match current version (" +
-						itos((RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
-						")");
+				vformat("Surface version provided (%d) does not match current version (%d).",
+						(surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK,
+						(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK));
 	}
 #endif
 

+ 2 - 2
servers/rendering/renderer_rd/storage_rd/mesh_storage.h

@@ -469,7 +469,7 @@ public:
 		}
 	}
 
-	_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+	_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
 		Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
 
 		s->version_lock.lock();
@@ -501,7 +501,7 @@ public:
 		s->version_lock.unlock();
 	}
 
-	_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+	_FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
 		MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
 		ERR_FAIL_NULL(mi);
 		Mesh *mesh = mi->mesh;

+ 16 - 16
servers/rendering_server.cpp

@@ -323,16 +323,18 @@ RID RenderingServer::get_white_texture() {
 }
 
 void _get_axis_angle(const Vector3 &p_normal, const Vector4 &p_tangent, float &r_angle, Vector3 &r_axis) {
-	Vector3 tangent = Vector3(p_tangent.x, p_tangent.y, p_tangent.z);
+	Vector3 normal = p_normal.normalized();
+	Vector3 tangent = Vector3(p_tangent.x, p_tangent.y, p_tangent.z).normalized();
 	float d = p_tangent.w;
-	Vector3 binormal = p_normal.cross(tangent);
+	Vector3 binormal = normal.cross(tangent).normalized();
+	real_t angle;
 
-	r_angle = Math::acos((tangent.x + binormal.y + p_normal.z - 1.0) / 2.0);
-	float denom = 2.0 * Math::sin(r_angle);
-	r_axis.x = (p_normal.y - binormal.z) / denom;
-	r_axis.y = (tangent.z - p_normal.x) / denom;
-	r_axis.z = (binormal.x - tangent.y) / denom;
-	r_axis.normalize();
+	Basis tbn = Basis();
+	tbn.rows[0] = tangent;
+	tbn.rows[1] = binormal;
+	tbn.rows[2] = normal;
+	tbn.get_axis_angle(r_axis, angle);
+	r_angle = float(angle);
 
 	if (d < 0.0) {
 		r_angle = CLAMP((1.0 - r_angle / Math_PI) * 0.5, 0.0, 0.49999);
@@ -346,13 +348,11 @@ void _get_axis_angle(const Vector3 &p_normal, const Vector4 &p_tangent, float &r
 void _get_tbn_from_axis_angle(const Vector3 &p_axis, float p_angle, Vector3 &r_normal, Vector4 &r_tangent) {
 	float binormal_sign = p_angle > 0.5 ? 1.0 : -1.0;
 	float angle = Math::abs(p_angle * 2.0 - 1.0) * Math_PI;
-	float c = cos(angle);
-	float s = sin(angle);
-	Vector3 omc_axis = (1.0 - c) * p_axis;
-	Vector3 s_axis = s * p_axis;
-	Vector3 tan = omc_axis.x * p_axis + Vector3(c, -s_axis.z, s_axis.y);
+
+	Basis tbn = Basis(p_axis, angle);
+	Vector3 tan = tbn.rows[0];
 	r_tangent = Vector4(tan.x, tan.y, tan.z, binormal_sign);
-	r_normal = omc_axis.z * p_axis + Vector3(-s_axis.y, s_axis.x, c);
+	r_normal = tbn.rows[2];
 }
 
 Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_normal_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb, Vector4 &r_uv_scale) {
@@ -1194,7 +1194,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
 		format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY;
 	}
 
-	if (format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES && ((format & RS::ARRAY_FORMAT_NORMAL) || (format & RS::ARRAY_FORMAT_TANGENT))) {
+	if ((format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && ((format & RS::ARRAY_FORMAT_NORMAL) || (format & RS::ARRAY_FORMAT_TANGENT))) {
 		// If using normals or tangents, then we need all three.
 		ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_VERTEX), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using normals or tangents without vertex array.");
 		ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_NORMAL), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using tangents without normal array.");
@@ -1399,7 +1399,7 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
 								tangentsw[j * 4 + 3] = tan.w;
 							}
 							ret[RS::ARRAY_NORMAL] = normals;
-							ret[RS::ARRAY_FORMAT_TANGENT] = tangents;
+							ret[RS::ARRAY_TANGENT] = tangents;
 
 						} else {
 							for (int j = 0; j < p_vertex_len; j++) {

+ 2 - 0
servers/rendering_server.h

@@ -298,6 +298,8 @@ public:
 		ARRAY_FLAG_FORMAT_VERSION_MASK = 0xFF, // 8 bits version
 	};
 
+	static_assert(sizeof(ArrayFormat) == 8, "ArrayFormat should be 64 bits long.");
+
 	enum PrimitiveType {
 		PRIMITIVE_POINTS,
 		PRIMITIVE_LINES,