Browse Source

Merge pull request #64801 from clayjohn/plane-quad

Remove QuadMesh and add orientation parameter to PlaneMesh
Rémi Verschelde 3 years ago
parent
commit
a0113a98e4

+ 15 - 1
doc/classes/PlaneMesh.xml

@@ -4,7 +4,7 @@
 		Class representing a planar [PrimitiveMesh].
 	</brief_description>
 	<description>
-		Class representing a planar [PrimitiveMesh]. This flat mesh does not have a thickness. By default, this mesh is aligned on the X and Z axes; this default rotation isn't suited for use with billboarded materials. For billboarded materials, use [QuadMesh] instead.
+		Class representing a planar [PrimitiveMesh]. This flat mesh does not have a thickness. By default, this mesh is aligned on the X and Z axes; this default rotation isn't suited for use with billboarded materials. For billboarded materials, change [member orientation] to [constant FACE_Z].
 		[b]Note:[/b] When using a large textured [PlaneMesh] (e.g. as a floor), you may stumble upon UV jittering issues depending on the camera angle. To solve this, increase [member subdivide_depth] and [member subdivide_width] until you no longer notice UV jittering.
 	</description>
 	<tutorials>
@@ -13,6 +13,9 @@
 		<member name="center_offset" type="Vector3" setter="set_center_offset" getter="get_center_offset" default="Vector3(0, 0, 0)">
 			Offset of the generated plane. Useful for particles.
 		</member>
+		<member name="orientation" type="int" setter="set_orientation" getter="get_orientation" enum="PlaneMesh.Orientation" default="1">
+			Direction that the [PlaneMesh] is facing. See [enum Orientation] for options.
+		</member>
 		<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(2, 2)">
 			Size of the generated plane.
 		</member>
@@ -23,4 +26,15 @@
 			Number of subdivision along the X axis.
 		</member>
 	</members>
+	<constants>
+		<constant name="FACE_X" value="0" enum="Orientation">
+			[PlaneMesh] will face the positive X-axis.
+		</constant>
+		<constant name="FACE_Y" value="1" enum="Orientation">
+			[PlaneMesh] will face the positive Y-axis. This matches the behaviour of the [PlaneMesh] in Godot 3.x.
+		</constant>
+		<constant name="FACE_Z" value="2" enum="Orientation">
+			[PlaneMesh] will face the positive Z-axis. This matches the behvaiour of the QuadMesh in Godot 3.x.
+		</constant>
+	</constants>
 </class>

+ 1 - 1
doc/classes/PrimitiveMesh.xml

@@ -4,7 +4,7 @@
 		Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh.
 	</brief_description>
 	<description>
-		Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh. Examples include [BoxMesh], [CapsuleMesh], [CylinderMesh], [PlaneMesh], [PrismMesh], [QuadMesh], and [SphereMesh].
+		Base class for all primitive meshes. Handles applying a [Material] to a primitive mesh. Examples include [BoxMesh], [CapsuleMesh], [CylinderMesh], [PlaneMesh], [PrismMesh], and [SphereMesh].
 	</description>
 	<tutorials>
 	</tutorials>

+ 0 - 21
doc/classes/QuadMesh.xml

@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="QuadMesh" inherits="PrimitiveMesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
-	<brief_description>
-		Class representing a square mesh.
-	</brief_description>
-	<description>
-		Class representing a square [PrimitiveMesh]. This flat mesh does not have a thickness. By default, this mesh is aligned on the X and Y axes; this default rotation is more suited for use with billboarded materials. Unlike [PlaneMesh], this mesh doesn't provide subdivision options.
-	</description>
-	<tutorials>
-		<link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link>
-		<link title="2D in 3D Demo">https://godotengine.org/asset-library/asset/129</link>
-	</tutorials>
-	<members>
-		<member name="center_offset" type="Vector3" setter="set_center_offset" getter="get_center_offset" default="Vector3(0, 0, 0)">
-			Offset of the generated Quad. Useful for particles.
-		</member>
-		<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(1, 1)">
-			Size on the X and Y axes.
-		</member>
-	</members>
-</class>

+ 1 - 1
scene/register_scene_types.cpp

@@ -780,7 +780,6 @@ void register_scene_types() {
 	GDREGISTER_CLASS(CylinderMesh);
 	GDREGISTER_CLASS(PlaneMesh);
 	GDREGISTER_CLASS(PrismMesh);
-	GDREGISTER_CLASS(QuadMesh);
 	GDREGISTER_CLASS(SphereMesh);
 	GDREGISTER_CLASS(TextMesh);
 	GDREGISTER_CLASS(TorusMesh);
@@ -943,6 +942,7 @@ void register_scene_types() {
 	ClassDB::add_compatibility_class("Navigation3D", "Node3D");
 	ClassDB::add_compatibility_class("Navigation2D", "Node2D");
 	ClassDB::add_compatibility_class("OpenSimplexNoise", "FastNoiseLite");
+	ClassDB::add_compatibility_class("QuadMesh", "PlaneMesh");
 	ClassDB::add_compatibility_class("ToolButton", "Button");
 	ClassDB::add_compatibility_class("YSort", "Node2D");
 	// Portal and room occlusion was replaced by raster occlusion (OccluderInstance3D node).

+ 33 - 94
scene/resources/primitive_meshes.cpp

@@ -990,6 +990,13 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
 
 	Size2 start_pos = size * -0.5;
 
+	Vector3 normal = Vector3(0.0, 1.0, 0.0);
+	if (orientation == FACE_X) {
+		normal = Vector3(1.0, 0.0, 0.0);
+	} else if (orientation == FACE_Z) {
+		normal = Vector3(0.0, 0.0, 1.0);
+	}
+
 	Vector<Vector3> points;
 	Vector<Vector3> normals;
 	Vector<float> tangents;
@@ -1015,8 +1022,14 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const {
 			u /= (subdivide_w + 1.0);
 			v /= (subdivide_d + 1.0);
 
-			points.push_back(Vector3(-x, 0.0, -z) + center_offset);
-			normals.push_back(Vector3(0.0, 1.0, 0.0));
+			if (orientation == FACE_X) {
+				points.push_back(Vector3(0.0, z, x) + center_offset);
+			} else if (orientation == FACE_Y) {
+				points.push_back(Vector3(-x, 0.0, -z) + center_offset);
+			} else if (orientation == FACE_Z) {
+				points.push_back(Vector3(-x, z, 0.0) + center_offset);
+			}
+			normals.push_back(normal);
 			ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
 			uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
 			point++;
@@ -1053,13 +1066,22 @@ void PlaneMesh::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
 	ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
 	ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
+
 	ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset);
 	ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset);
 
+	ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &PlaneMesh::set_orientation);
+	ClassDB::bind_method(D_METHOD("get_orientation"), &PlaneMesh::get_orientation);
+
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "orientation", PROPERTY_HINT_ENUM, "Face X, Face Y, Face Z"), "set_orientation", "get_orientation");
+
+	BIND_ENUM_CONSTANT(FACE_X)
+	BIND_ENUM_CONSTANT(FACE_Y)
+	BIND_ENUM_CONSTANT(FACE_Z)
 }
 
 void PlaneMesh::set_size(const Size2 &p_size) {
@@ -1098,6 +1120,15 @@ Vector3 PlaneMesh::get_center_offset() const {
 	return center_offset;
 }
 
+void PlaneMesh::set_orientation(const Orientation p_orientation) {
+	orientation = p_orientation;
+	_request_update();
+}
+
+PlaneMesh::Orientation PlaneMesh::get_orientation() const {
+	return orientation;
+}
+
 PlaneMesh::PlaneMesh() {}
 
 /**
@@ -1380,98 +1411,6 @@ int PrismMesh::get_subdivide_depth() const {
 
 PrismMesh::PrismMesh() {}
 
-/**
-  QuadMesh
-*/
-
-void QuadMesh::_create_mesh_array(Array &p_arr) const {
-	Vector<Vector3> faces;
-	Vector<Vector3> normals;
-	Vector<float> tangents;
-	Vector<Vector2> uvs;
-
-	faces.resize(6);
-	normals.resize(6);
-	tangents.resize(6 * 4);
-	uvs.resize(6);
-
-	Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f);
-
-	Vector3 quad_faces[4] = {
-		Vector3(-_size.x, -_size.y, 0) + center_offset,
-		Vector3(-_size.x, _size.y, 0) + center_offset,
-		Vector3(_size.x, _size.y, 0) + center_offset,
-		Vector3(_size.x, -_size.y, 0) + center_offset,
-	};
-
-	static const int indices[6] = {
-		0, 1, 2,
-		0, 2, 3
-	};
-
-	for (int i = 0; i < 6; i++) {
-		int j = indices[i];
-		faces.set(i, quad_faces[j]);
-		normals.set(i, Vector3(0, 0, 1));
-		tangents.set(i * 4 + 0, 1.0);
-		tangents.set(i * 4 + 1, 0.0);
-		tangents.set(i * 4 + 2, 0.0);
-		tangents.set(i * 4 + 3, 1.0);
-
-		static const Vector2 quad_uv[4] = {
-			Vector2(0, 1),
-			Vector2(0, 0),
-			Vector2(1, 0),
-			Vector2(1, 1),
-		};
-
-		uvs.set(i, quad_uv[j]);
-	}
-
-	p_arr[RS::ARRAY_VERTEX] = faces;
-	p_arr[RS::ARRAY_NORMAL] = normals;
-	p_arr[RS::ARRAY_TANGENT] = tangents;
-	p_arr[RS::ARRAY_TEX_UV] = uvs;
-}
-
-void QuadMesh::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size);
-	ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size);
-	ClassDB::bind_method(D_METHOD("set_center_offset", "center_offset"), &QuadMesh::set_center_offset);
-	ClassDB::bind_method(D_METHOD("get_center_offset"), &QuadMesh::get_center_offset);
-
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
-	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset");
-}
-
-uint32_t QuadMesh::surface_get_format(int p_idx) const {
-	ERR_FAIL_INDEX_V(p_idx, 1, 0);
-
-	return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV;
-}
-
-QuadMesh::QuadMesh() {
-	primitive_type = PRIMITIVE_TRIANGLES;
-}
-
-void QuadMesh::set_size(const Size2 &p_size) {
-	size = p_size;
-	_request_update();
-}
-
-Size2 QuadMesh::get_size() const {
-	return size;
-}
-
-void QuadMesh::set_center_offset(Vector3 p_center_offset) {
-	center_offset = p_center_offset;
-	_request_update();
-}
-
-Vector3 QuadMesh::get_center_offset() const {
-	return center_offset;
-}
-
 /**
   SphereMesh
 */

+ 15 - 29
scene/resources/primitive_meshes.h

@@ -217,17 +217,25 @@ public:
 	CylinderMesh();
 };
 
-/**
-	Similar to quadmesh but with tessellation support
+/*
+	A flat rectangle, can be used as quad or heightmap.
 */
 class PlaneMesh : public PrimitiveMesh {
 	GDCLASS(PlaneMesh, PrimitiveMesh);
 
+public:
+	enum Orientation {
+		FACE_X,
+		FACE_Y,
+		FACE_Z,
+	};
+
 private:
 	Size2 size = Size2(2.0, 2.0);
 	int subdivide_w = 0;
 	int subdivide_d = 0;
 	Vector3 center_offset;
+	Orientation orientation = FACE_Y;
 
 protected:
 	static void _bind_methods();
@@ -246,9 +254,14 @@ public:
 	void set_center_offset(const Vector3 p_offset);
 	Vector3 get_center_offset() const;
 
+	void set_orientation(const Orientation p_orientation);
+	Orientation get_orientation() const;
+
 	PlaneMesh();
 };
 
+VARIANT_ENUM_CAST(PlaneMesh::Orientation)
+
 /**
 	A prism shapen, handy for ramps, triangles, etc.
 */
@@ -285,33 +298,6 @@ public:
 	PrismMesh();
 };
 
-/**
-	Our original quadmesh...
-*/
-
-class QuadMesh : public PrimitiveMesh {
-	GDCLASS(QuadMesh, PrimitiveMesh);
-
-private:
-	Size2 size = Size2(1.0, 1.0);
-	Vector3 center_offset;
-
-protected:
-	static void _bind_methods();
-	virtual void _create_mesh_array(Array &p_arr) const override;
-
-public:
-	virtual uint32_t surface_get_format(int p_idx) const override;
-
-	QuadMesh();
-
-	void set_size(const Size2 &p_size);
-	Size2 get_size() const;
-
-	void set_center_offset(const Vector3 p_offset);
-	Vector3 get_center_offset() const;
-};
-
 /**
 	A sphere..
 */