Add optional UV2 logic for lightmapping to primitive shapes
This commit is contained in:
parent
c17f17eb98
commit
7658dc6e7e
|
@ -34,6 +34,9 @@
|
|||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="add_uv2" type="bool" setter="set_add_uv2" getter="get_add_uv2" default="false">
|
||||
If set, generates UV2 UV coordinates applying a padding using the [member uv2_padding] setting. UV2 is needed for lightmapping.
|
||||
</member>
|
||||
<member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB(0, 0, 0, 0, 0, 0)">
|
||||
Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
|
||||
</member>
|
||||
|
@ -44,5 +47,8 @@
|
|||
<member name="material" type="Material" setter="set_material" getter="get_material">
|
||||
The current [Material] of the primitive mesh.
|
||||
</member>
|
||||
<member name="uv2_padding" type="float" setter="set_uv2_padding" getter="get_uv2_padding" default="2.0">
|
||||
If [member add_uv2] is set, specifies the padding in pixels applied along seams of the mesh. If at generation the size of the lightmap texture can't be determined, the UVs are calculated assuming a texture size of 1024x1024.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
||||
|
|
|
@ -2016,6 +2016,9 @@
|
|||
<member name="rendering/lightmapping/bake_quality/ultra_quality_ray_count" type="int" setter="" getter="" default="1024">
|
||||
The number of rays to use for baking lightmaps with [LightmapGI] when [member LightmapGI.quality] is [constant LightmapGI.BAKE_QUALITY_ULTRA].
|
||||
</member>
|
||||
<member name="rendering/lightmapping/primitive_meshes/texel_size" type="float" setter="" getter="" default="0.2">
|
||||
The texel_size that is used to calculate the [member Mesh.lightmap_size_hint] on [PrimitiveMesh] resources if [member PrimitiveMesh.add_uv2] is enabled.
|
||||
</member>
|
||||
<member name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
|
||||
The framerate-independent update speed when representing dynamic object lighting from [LightmapProbe]s. Higher values make dynamic object lighting update faster. Higher values can prevent fast-moving objects from having "outdated" indirect lighting displayed on them, at the cost of possible flickering when an object moves from a bright area to a shaded area.
|
||||
</member>
|
||||
|
|
|
@ -57,6 +57,7 @@ void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level) {
|
|||
GLOBAL_DEF("rendering/lightmapping/bake_quality/high_quality_probe_ray_count", 512);
|
||||
GLOBAL_DEF("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count", 2048);
|
||||
GLOBAL_DEF("rendering/lightmapping/bake_performance/max_rays_per_probe_pass", 64);
|
||||
GLOBAL_DEF("rendering/lightmapping/primitive_meshes/texel_size", 0.2);
|
||||
#ifndef _3D_DISABLED
|
||||
GDREGISTER_CLASS(LightmapperRD);
|
||||
Lightmapper::create_gpu = create_lightmapper_rd;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "primitive_meshes.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/core_string_names.h"
|
||||
#include "scene/resources/theme.h"
|
||||
#include "scene/theme/theme_db.h"
|
||||
|
@ -37,6 +38,8 @@
|
|||
#include "thirdparty/misc/clipper.hpp"
|
||||
#include "thirdparty/misc/polypartition.h"
|
||||
|
||||
#define PADDING_REF_SIZE 1024.0
|
||||
|
||||
/**
|
||||
PrimitiveMesh
|
||||
*/
|
||||
|
@ -94,6 +97,26 @@ void PrimitiveMesh::_update() const {
|
|||
}
|
||||
}
|
||||
|
||||
if (add_uv2) {
|
||||
// _create_mesh_array should populate our UV2, this is a fallback in case it doesn't.
|
||||
// As we don't know anything about the geometry we only pad the right and bottom edge
|
||||
// of our texture.
|
||||
Vector<Vector2> uv = arr[RS::ARRAY_TEX_UV];
|
||||
Vector<Vector2> uv2 = arr[RS::ARRAY_TEX_UV2];
|
||||
|
||||
if (uv.size() > 0 && uv2.size() == 0) {
|
||||
Vector2 uv2_scale = get_uv2_scale();
|
||||
uv2.resize(uv.size());
|
||||
|
||||
Vector2 *uv2w = uv2.ptrw();
|
||||
for (int i = 0; i < uv.size(); i++) {
|
||||
uv2w[i] = uv[i] * uv2_scale;
|
||||
}
|
||||
}
|
||||
|
||||
arr[RS::ARRAY_TEX_UV2] = uv2;
|
||||
}
|
||||
|
||||
array_len = pc;
|
||||
index_array_len = indices.size();
|
||||
// in with the new
|
||||
|
@ -160,7 +183,12 @@ TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) c
|
|||
uint32_t PrimitiveMesh::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 | RS::ARRAY_FORMAT_INDEX;
|
||||
uint32_t mesh_format = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
|
||||
if (add_uv2) {
|
||||
mesh_format |= RS::ARRAY_FORMAT_TEX_UV2;
|
||||
}
|
||||
|
||||
return mesh_format;
|
||||
}
|
||||
|
||||
Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
|
||||
|
@ -219,9 +247,17 @@ void PrimitiveMesh::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
|
||||
ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_add_uv2", "add_uv2"), &PrimitiveMesh::set_add_uv2);
|
||||
ClassDB::bind_method(D_METHOD("get_add_uv2"), &PrimitiveMesh::get_add_uv2);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_uv2_padding", "uv2_padding"), &PrimitiveMesh::set_uv2_padding);
|
||||
ClassDB::bind_method(D_METHOD("get_uv2_padding"), &PrimitiveMesh::get_uv2_padding);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "add_uv2"), "set_add_uv2", "get_add_uv2");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_padding"), "set_uv2_padding", "get_uv2_padding");
|
||||
|
||||
GDVIRTUAL_BIND(_create_mesh_array);
|
||||
}
|
||||
|
@ -263,6 +299,42 @@ bool PrimitiveMesh::get_flip_faces() const {
|
|||
return flip_faces;
|
||||
}
|
||||
|
||||
void PrimitiveMesh::set_add_uv2(bool p_enable) {
|
||||
add_uv2 = p_enable;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
void PrimitiveMesh::set_uv2_padding(float p_padding) {
|
||||
uv2_padding = p_padding;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
Vector2 PrimitiveMesh::get_uv2_scale(Vector2 p_margin_scale) const {
|
||||
Vector2 uv2_scale;
|
||||
Vector2 lightmap_size = get_lightmap_size_hint();
|
||||
|
||||
// Calculate it as a margin, if no lightmap size hint is given we assume "PADDING_REF_SIZE" as our texture size.
|
||||
uv2_scale.x = p_margin_scale.x * uv2_padding / (lightmap_size.x == 0.0 ? PADDING_REF_SIZE : lightmap_size.x);
|
||||
uv2_scale.y = p_margin_scale.y * uv2_padding / (lightmap_size.y == 0.0 ? PADDING_REF_SIZE : lightmap_size.y);
|
||||
|
||||
// Inverse it to turn our margin into a scale
|
||||
uv2_scale = Vector2(1.0, 1.0) - uv2_scale;
|
||||
|
||||
return uv2_scale;
|
||||
}
|
||||
|
||||
float PrimitiveMesh::get_lightmap_texel_size() const {
|
||||
float texel_size = GLOBAL_GET("rendering/lightmapping/primitive_meshes/texel_size");
|
||||
|
||||
if (texel_size <= 0.0) {
|
||||
texel_size = 0.2;
|
||||
}
|
||||
|
||||
return texel_size;
|
||||
}
|
||||
|
||||
PrimitiveMesh::PrimitiveMesh() {
|
||||
mesh = RenderingServer::get_singleton()->mesh_create();
|
||||
}
|
||||
|
@ -275,22 +347,52 @@ PrimitiveMesh::~PrimitiveMesh() {
|
|||
CapsuleMesh
|
||||
*/
|
||||
|
||||
void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
|
||||
create_mesh_array(p_arr, radius, height, radial_segments, rings);
|
||||
void CapsuleMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
|
||||
float vertical_length = radial_length * 2 + (height - 2.0 * radius); // total vertical length
|
||||
|
||||
_lightmap_size_hint.x = MAX(1.0, 4.0 * radial_length / texel_size) + padding;
|
||||
_lightmap_size_hint.y = MAX(1.0, vertical_length / texel_size) + padding;
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings) {
|
||||
void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
|
||||
bool _add_uv2 = get_add_uv2();
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float _uv2_padding = get_uv2_padding() * texel_size;
|
||||
|
||||
create_mesh_array(p_arr, radius, height, radial_segments, rings, _add_uv2, _uv2_padding);
|
||||
}
|
||||
|
||||
void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings, bool p_add_uv2, const float p_uv2_padding) {
|
||||
int i, j, prevrow, thisrow, point;
|
||||
float x, y, z, u, v, w;
|
||||
float onethird = 1.0 / 3.0;
|
||||
float twothirds = 2.0 / 3.0;
|
||||
|
||||
// Only used if we calculate UV2
|
||||
float radial_width = 2.0 * radius * Math_PI;
|
||||
float radial_h = radial_width / (radial_width + p_uv2_padding);
|
||||
float radial_length = radius * Math_PI * 0.5; // circumference of 90 degree bend
|
||||
float vertical_length = radial_length * 2 + (height - 2.0 * radius) + p_uv2_padding; // total vertical length
|
||||
float radial_v = radial_length / vertical_length; // v size of top and bottom section
|
||||
float height_v = (height - 2.0 * radius) / vertical_length; // v size of height section
|
||||
|
||||
// note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
|
||||
|
||||
Vector<Vector3> points;
|
||||
Vector<Vector3> normals;
|
||||
Vector<float> tangents;
|
||||
Vector<Vector2> uvs;
|
||||
Vector<Vector2> uv2s;
|
||||
Vector<int> indices;
|
||||
point = 0;
|
||||
|
||||
|
@ -322,6 +424,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
|
|||
normals.push_back(p.normalized());
|
||||
ADD_TANGENT(-z, 0.0, -x, 1.0)
|
||||
uvs.push_back(Vector2(u, v * onethird));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(u * radial_h, v * radial_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -361,6 +466,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
|
|||
normals.push_back(Vector3(x, 0.0, -z));
|
||||
ADD_TANGENT(-z, 0.0, -x, 1.0)
|
||||
uvs.push_back(Vector2(u, onethird + (v * onethird)));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(u * radial_h, radial_v + (v * height_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -390,17 +498,20 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
|
|||
y = radius * cos(0.5 * Math_PI * v);
|
||||
|
||||
for (i = 0; i <= radial_segments; i++) {
|
||||
float u2 = i;
|
||||
u2 /= radial_segments;
|
||||
u = i;
|
||||
u /= radial_segments;
|
||||
|
||||
x = -sin(u2 * Math_TAU);
|
||||
z = cos(u2 * Math_TAU);
|
||||
x = -sin(u * Math_TAU);
|
||||
z = cos(u * Math_TAU);
|
||||
|
||||
Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
|
||||
points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0));
|
||||
normals.push_back(p.normalized());
|
||||
ADD_TANGENT(-z, 0.0, -x, 1.0)
|
||||
uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird)));
|
||||
uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(u * radial_h, radial_v + height_v + ((v - 1.0) * radial_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -422,6 +533,9 @@ void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const floa
|
|||
p_arr[RS::ARRAY_NORMAL] = normals;
|
||||
p_arr[RS::ARRAY_TANGENT] = tangents;
|
||||
p_arr[RS::ARRAY_TEX_UV] = uvs;
|
||||
if (p_add_uv2) {
|
||||
p_arr[RS::ARRAY_TEX_UV2] = uv2s;
|
||||
}
|
||||
p_arr[RS::ARRAY_INDEX] = indices;
|
||||
}
|
||||
|
||||
|
@ -450,6 +564,7 @@ void CapsuleMesh::set_radius(const float p_radius) {
|
|||
if (radius > height * 0.5) {
|
||||
height = radius * 2.0;
|
||||
}
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -462,6 +577,7 @@ void CapsuleMesh::set_height(const float p_height) {
|
|||
if (radius > height * 0.5) {
|
||||
radius = height * 0.5;
|
||||
}
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -493,16 +609,53 @@ CapsuleMesh::CapsuleMesh() {}
|
|||
BoxMesh
|
||||
*/
|
||||
|
||||
void BoxMesh::_create_mesh_array(Array &p_arr) const {
|
||||
BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d);
|
||||
void BoxMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
float width = (size.x + size.z) / texel_size;
|
||||
float length = (size.y + size.y + MAX(size.x, size.z)) / texel_size;
|
||||
|
||||
_lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
|
||||
_lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d) {
|
||||
void BoxMesh::_create_mesh_array(Array &p_arr) const {
|
||||
// Note about padding, with our box each face of the box faces a different direction so we want a seam
|
||||
// around every face. We thus add our padding to the right and bottom of each face.
|
||||
// With 3 faces along the width and 2 along the height of the texture we need to adjust our scale
|
||||
// accordingly.
|
||||
bool _add_uv2 = get_add_uv2();
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float _uv2_padding = get_uv2_padding() * texel_size;
|
||||
|
||||
BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d, _add_uv2, _uv2_padding);
|
||||
}
|
||||
|
||||
void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d, bool p_add_uv2, const float p_uv2_padding) {
|
||||
int i, j, prevrow, thisrow, point;
|
||||
float x, y, z;
|
||||
float onethird = 1.0 / 3.0;
|
||||
float twothirds = 2.0 / 3.0;
|
||||
|
||||
// Only used if we calculate UV2
|
||||
// TODO this could be improved by changing the order depending on which side is the longest (basically the below works best if size.y is the longest)
|
||||
float total_h = (size.x + size.z + (2.0 * p_uv2_padding));
|
||||
float padding_h = p_uv2_padding / total_h;
|
||||
float width_h = size.x / total_h;
|
||||
float depth_h = size.z / total_h;
|
||||
float total_v = (size.y + size.y + MAX(size.x, size.z) + (3.0 * p_uv2_padding));
|
||||
float padding_v = p_uv2_padding / total_v;
|
||||
float width_v = size.x / total_v;
|
||||
float height_v = size.y / total_v;
|
||||
float depth_v = size.z / total_v;
|
||||
|
||||
Vector3 start_pos = size * -0.5;
|
||||
|
||||
// set our bounding box
|
||||
|
@ -511,6 +664,7 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
Vector<Vector3> normals;
|
||||
Vector<float> tangents;
|
||||
Vector<Vector2> uvs;
|
||||
Vector<Vector2> uv2s;
|
||||
Vector<int> indices;
|
||||
point = 0;
|
||||
|
||||
|
@ -525,18 +679,24 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
thisrow = point;
|
||||
prevrow = 0;
|
||||
for (j = 0; j <= subdivide_h + 1; j++) {
|
||||
float v = j;
|
||||
float v2 = v / (subdivide_w + 1.0);
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
x = start_pos.x;
|
||||
for (i = 0; i <= subdivide_w + 1; i++) {
|
||||
float u = i;
|
||||
float v = j;
|
||||
float u2 = u / (subdivide_w + 1.0);
|
||||
u /= (3.0 * (subdivide_w + 1.0));
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
// front
|
||||
points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
|
||||
normals.push_back(Vector3(0.0, 0.0, 1.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(u, v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(u2 * width_h, v2 * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
// back
|
||||
|
@ -544,6 +704,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
normals.push_back(Vector3(0.0, 0.0, -1.0));
|
||||
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(twothirds + u, v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(u2 * width_h, height_v + padding_v + (v2 * height_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -579,18 +742,24 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
thisrow = point;
|
||||
prevrow = 0;
|
||||
for (j = 0; j <= (subdivide_h + 1); j++) {
|
||||
float v = j;
|
||||
float v2 = v / (subdivide_h + 1.0);
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
z = start_pos.z;
|
||||
for (i = 0; i <= (subdivide_d + 1); i++) {
|
||||
float u = i;
|
||||
float v = j;
|
||||
float u2 = u / (subdivide_d + 1.0);
|
||||
u /= (3.0 * (subdivide_d + 1.0));
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
// right
|
||||
points.push_back(Vector3(-start_pos.x, -y, -z));
|
||||
normals.push_back(Vector3(1.0, 0.0, 0.0));
|
||||
ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
|
||||
uvs.push_back(Vector2(onethird + u, v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), v2 * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
// left
|
||||
|
@ -598,6 +767,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
normals.push_back(Vector3(-1.0, 0.0, 0.0));
|
||||
ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
|
||||
uvs.push_back(Vector2(u, 0.5 + v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), height_v + padding_v + (v2 * height_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -633,18 +805,24 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
thisrow = point;
|
||||
prevrow = 0;
|
||||
for (j = 0; j <= (subdivide_d + 1); j++) {
|
||||
float v = j;
|
||||
float v2 = v / (subdivide_d + 1.0);
|
||||
v /= (2.0 * (subdivide_d + 1.0));
|
||||
|
||||
x = start_pos.x;
|
||||
for (i = 0; i <= (subdivide_w + 1); i++) {
|
||||
float u = i;
|
||||
float v = j;
|
||||
float u2 = u / (subdivide_w + 1.0);
|
||||
u /= (3.0 * (subdivide_w + 1.0));
|
||||
v /= (2.0 * (subdivide_d + 1.0));
|
||||
|
||||
// top
|
||||
points.push_back(Vector3(-x, -start_pos.y, -z));
|
||||
normals.push_back(Vector3(0.0, 1.0, 0.0));
|
||||
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(onethird + u, 0.5 + v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(u2 * width_h, ((height_v + padding_v) * 2.0) + (v2 * depth_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
// bottom
|
||||
|
@ -652,6 +830,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
normals.push_back(Vector3(0.0, -1.0, 0.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(width_h + padding_h + (u2 * depth_h), ((height_v + padding_v) * 2.0) + (v2 * width_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -686,6 +867,9 @@ void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int
|
|||
p_arr[RS::ARRAY_NORMAL] = normals;
|
||||
p_arr[RS::ARRAY_TANGENT] = tangents;
|
||||
p_arr[RS::ARRAY_TEX_UV] = uvs;
|
||||
if (p_add_uv2) {
|
||||
p_arr[RS::ARRAY_TEX_UV2] = uv2s;
|
||||
}
|
||||
p_arr[RS::ARRAY_INDEX] = indices;
|
||||
}
|
||||
|
||||
|
@ -708,6 +892,7 @@ void BoxMesh::_bind_methods() {
|
|||
|
||||
void BoxMesh::set_size(const Vector3 &p_size) {
|
||||
size = p_size;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -748,18 +933,58 @@ BoxMesh::BoxMesh() {}
|
|||
CylinderMesh
|
||||
*/
|
||||
|
||||
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
|
||||
create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom);
|
||||
void CylinderMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
float top_circumference = top_radius * Math_PI * 2.0;
|
||||
float bottom_circumference = bottom_radius * Math_PI * 2.0;
|
||||
|
||||
float _width = MAX(top_circumference, bottom_circumference) / texel_size + padding;
|
||||
_width = MAX(_width, (((top_radius + bottom_radius) / texel_size) + padding) * 2.0); // this is extremely unlikely to be larger, will only happen if padding is larger then our diameter.
|
||||
_lightmap_size_hint.x = MAX(1.0, _width);
|
||||
|
||||
float _height = ((height + (MAX(top_radius, bottom_radius) * 2.0)) / texel_size) + (2.0 * padding);
|
||||
|
||||
_lightmap_size_hint.y = MAX(1.0, _height);
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom) {
|
||||
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
|
||||
bool _add_uv2 = get_add_uv2();
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float _uv2_padding = get_uv2_padding() * texel_size;
|
||||
|
||||
create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom, _add_uv2, _uv2_padding);
|
||||
}
|
||||
|
||||
void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom, bool p_add_uv2, const float p_uv2_padding) {
|
||||
int i, j, prevrow, thisrow, point;
|
||||
float x, y, z, u, v, radius;
|
||||
float x, y, z, u, v, radius, radius_h;
|
||||
|
||||
// Only used if we calculate UV2
|
||||
float top_circumference = top_radius * Math_PI * 2.0;
|
||||
float bottom_circumference = bottom_radius * Math_PI * 2.0;
|
||||
float vertical_length = height + MAX(2.0 * top_radius, 2.0 * bottom_radius) + (2.0 * p_uv2_padding);
|
||||
float height_v = height / vertical_length;
|
||||
float padding_v = p_uv2_padding / vertical_length;
|
||||
|
||||
float horizonal_length = MAX(MAX(2.0 * (top_radius + bottom_radius + p_uv2_padding), top_circumference + p_uv2_padding), bottom_circumference + p_uv2_padding);
|
||||
float center_h = 0.5 * (horizonal_length - p_uv2_padding) / horizonal_length;
|
||||
float top_h = top_circumference / horizonal_length;
|
||||
float bottom_h = bottom_circumference / horizonal_length;
|
||||
float padding_h = p_uv2_padding / horizonal_length;
|
||||
|
||||
Vector<Vector3> points;
|
||||
Vector<Vector3> normals;
|
||||
Vector<float> tangents;
|
||||
Vector<Vector2> uvs;
|
||||
Vector<Vector2> uv2s;
|
||||
Vector<int> indices;
|
||||
point = 0;
|
||||
|
||||
|
@ -777,6 +1002,7 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
v /= (rings + 1);
|
||||
|
||||
radius = top_radius + ((bottom_radius - top_radius) * v);
|
||||
radius_h = top_h + ((bottom_h - top_h) * v);
|
||||
|
||||
y = height * v;
|
||||
y = (height * 0.5) - y;
|
||||
|
@ -793,6 +1019,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
normals.push_back(Vector3(x, side_normal_y, z).normalized());
|
||||
ADD_TANGENT(z, 0.0, -x, 1.0)
|
||||
uvs.push_back(Vector2(u, v * 0.5));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(center_h + (u - 0.5) * radius_h, v * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -810,6 +1039,12 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
thisrow = point;
|
||||
};
|
||||
|
||||
// Adjust for buttom section, only used if we calculate UV2s
|
||||
top_h = top_radius / horizonal_length;
|
||||
float top_v = top_radius / vertical_length;
|
||||
bottom_h = bottom_radius / horizonal_length;
|
||||
float bottom_v = bottom_radius / vertical_length;
|
||||
|
||||
// add top
|
||||
if (cap_top && top_radius > 0.0) {
|
||||
y = height * 0.5;
|
||||
|
@ -819,6 +1054,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
normals.push_back(Vector3(0.0, 1.0, 0.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
|
||||
uvs.push_back(Vector2(0.25, 0.75));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(top_h, height_v + padding_v + MAX(top_v, bottom_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
for (i = 0; i <= radial_segments; i++) {
|
||||
|
@ -836,6 +1074,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
normals.push_back(Vector3(0.0, 1.0, 0.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
|
||||
uvs.push_back(Vector2(u, v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(top_h + (x * top_h), height_v + padding_v + MAX(top_v, bottom_v) + (z * top_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0) {
|
||||
|
@ -855,6 +1096,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
normals.push_back(Vector3(0.0, -1.0, 0.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
|
||||
uvs.push_back(Vector2(0.75, 0.75));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h, height_v + padding_v + MAX(top_v, bottom_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
for (i = 0; i <= radial_segments; i++) {
|
||||
|
@ -872,6 +1116,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
normals.push_back(Vector3(0.0, -1.0, 0.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
|
||||
uvs.push_back(Vector2(u, v));
|
||||
if (p_add_uv2) {
|
||||
uv2s.push_back(Vector2(top_h + top_h + padding_h + bottom_h + (x * bottom_h), height_v + padding_v + MAX(top_v, bottom_v) - (z * bottom_v)));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0) {
|
||||
|
@ -886,6 +1133,9 @@ void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float botto
|
|||
p_arr[RS::ARRAY_NORMAL] = normals;
|
||||
p_arr[RS::ARRAY_TANGENT] = tangents;
|
||||
p_arr[RS::ARRAY_TEX_UV] = uvs;
|
||||
if (p_add_uv2) {
|
||||
p_arr[RS::ARRAY_TEX_UV2] = uv2s;
|
||||
}
|
||||
p_arr[RS::ARRAY_INDEX] = indices;
|
||||
}
|
||||
|
||||
|
@ -919,6 +1169,7 @@ void CylinderMesh::_bind_methods() {
|
|||
|
||||
void CylinderMesh::set_top_radius(const float p_radius) {
|
||||
top_radius = p_radius;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -928,6 +1179,7 @@ float CylinderMesh::get_top_radius() const {
|
|||
|
||||
void CylinderMesh::set_bottom_radius(const float p_radius) {
|
||||
bottom_radius = p_radius;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -937,6 +1189,7 @@ float CylinderMesh::get_bottom_radius() const {
|
|||
|
||||
void CylinderMesh::set_height(const float p_height) {
|
||||
height = p_height;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -986,10 +1239,26 @@ CylinderMesh::CylinderMesh() {}
|
|||
PlaneMesh
|
||||
*/
|
||||
|
||||
void PlaneMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
_lightmap_size_hint.x = MAX(1.0, (size.x / texel_size) + padding);
|
||||
_lightmap_size_hint.y = MAX(1.0, (size.y / texel_size) + padding);
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void PlaneMesh::_create_mesh_array(Array &p_arr) const {
|
||||
int i, j, prevrow, thisrow, point;
|
||||
float x, z;
|
||||
|
||||
// Plane mesh can use default UV2 calculation as implemented in Primitive Mesh
|
||||
|
||||
Size2 start_pos = size * -0.5;
|
||||
|
||||
Vector3 normal = Vector3(0.0, 1.0, 0.0);
|
||||
|
@ -1088,6 +1357,7 @@ void PlaneMesh::_bind_methods() {
|
|||
|
||||
void PlaneMesh::set_size(const Size2 &p_size) {
|
||||
size = p_size;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -1137,12 +1407,49 @@ PlaneMesh::PlaneMesh() {}
|
|||
PrismMesh
|
||||
*/
|
||||
|
||||
void PrismMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
// left_to_right does not effect the surface area of the prism so we ignore that.
|
||||
// TODO we could combine the two triangles and save some space but we need to re-align the uv1 and adjust the tangent.
|
||||
|
||||
float width = (size.x + size.z) / texel_size;
|
||||
float length = (size.y + size.y + size.z) / texel_size;
|
||||
|
||||
_lightmap_size_hint.x = MAX(1.0, width) + 2.0 * padding;
|
||||
_lightmap_size_hint.y = MAX(1.0, length) + 3.0 * padding;
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
||||
int i, j, prevrow, thisrow, point;
|
||||
float x, y, z;
|
||||
float onethird = 1.0 / 3.0;
|
||||
float twothirds = 2.0 / 3.0;
|
||||
|
||||
// Only used if we calculate UV2
|
||||
bool _add_uv2 = get_add_uv2();
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float _uv2_padding = get_uv2_padding() * texel_size;
|
||||
|
||||
float horizontal_total = size.x + size.z + 2.0 * _uv2_padding;
|
||||
float width_h = size.x / horizontal_total;
|
||||
float depth_h = size.z / horizontal_total;
|
||||
float padding_h = _uv2_padding / horizontal_total;
|
||||
|
||||
float vertical_total = (size.y + size.y + size.z) + (3.0 * _uv2_padding);
|
||||
float height_v = size.y / vertical_total;
|
||||
float depth_v = size.z / vertical_total;
|
||||
float padding_v = _uv2_padding / vertical_total;
|
||||
|
||||
// and start building
|
||||
|
||||
Vector3 start_pos = size * -0.5;
|
||||
|
||||
// set our bounding box
|
||||
|
@ -1151,6 +1458,7 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
Vector<Vector3> normals;
|
||||
Vector<float> tangents;
|
||||
Vector<Vector2> uvs;
|
||||
Vector<Vector2> uv2s;
|
||||
Vector<int> indices;
|
||||
point = 0;
|
||||
|
||||
|
@ -1171,12 +1479,15 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
float offset_front = (1.0 - scale) * onethird * left_to_right;
|
||||
float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
|
||||
|
||||
float v = j;
|
||||
float v2 = j / (subdivide_h + 1.0);
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
x = 0.0;
|
||||
for (i = 0; i <= (subdivide_w + 1); i++) {
|
||||
float u = i;
|
||||
float v = j;
|
||||
float u2 = i / (subdivide_w + 1.0);
|
||||
u /= (3.0 * (subdivide_w + 1.0));
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
u *= scale;
|
||||
|
||||
|
@ -1185,6 +1496,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
normals.push_back(Vector3(0.0, 0.0, 1.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(offset_front + u, v));
|
||||
if (_add_uv2) {
|
||||
uv2s.push_back(Vector2(u2 * scale * width_h, v2 * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
/* back */
|
||||
|
@ -1192,6 +1506,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
normals.push_back(Vector3(0.0, 0.0, -1.0));
|
||||
ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(twothirds + offset_back + u, v));
|
||||
if (_add_uv2) {
|
||||
uv2s.push_back(Vector2(u2 * scale * width_h, height_v + padding_v + v2 * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j == 1) {
|
||||
|
@ -1246,6 +1563,10 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
thisrow = point;
|
||||
prevrow = 0;
|
||||
for (j = 0; j <= (subdivide_h + 1); j++) {
|
||||
float v = j;
|
||||
float v2 = j / (subdivide_h + 1.0);
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
float left, right;
|
||||
float scale = (y - start_pos.y) / size.y;
|
||||
|
||||
|
@ -1255,15 +1576,17 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
z = start_pos.z;
|
||||
for (i = 0; i <= (subdivide_d + 1); i++) {
|
||||
float u = i;
|
||||
float v = j;
|
||||
float u2 = u / (subdivide_d + 1.0);
|
||||
u /= (3.0 * (subdivide_d + 1.0));
|
||||
v /= (2.0 * (subdivide_h + 1.0));
|
||||
|
||||
/* right */
|
||||
points.push_back(Vector3(right, -y, -z));
|
||||
normals.push_back(normal_right);
|
||||
ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
|
||||
uvs.push_back(Vector2(onethird + u, v));
|
||||
if (_add_uv2) {
|
||||
uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, v2 * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
/* left */
|
||||
|
@ -1271,6 +1594,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
normals.push_back(normal_left);
|
||||
ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
|
||||
uvs.push_back(Vector2(u, 0.5 + v));
|
||||
if (_add_uv2) {
|
||||
uv2s.push_back(Vector2(width_h + padding_h + u2 * depth_h, height_v + padding_v + v2 * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -1306,18 +1632,24 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
thisrow = point;
|
||||
prevrow = 0;
|
||||
for (j = 0; j <= (subdivide_d + 1); j++) {
|
||||
float v = j;
|
||||
float v2 = v / (subdivide_d + 1.0);
|
||||
v /= (2.0 * (subdivide_d + 1.0));
|
||||
|
||||
x = start_pos.x;
|
||||
for (i = 0; i <= (subdivide_w + 1); i++) {
|
||||
float u = i;
|
||||
float v = j;
|
||||
float u2 = u / (subdivide_w + 1.0);
|
||||
u /= (3.0 * (subdivide_w + 1.0));
|
||||
v /= (2.0 * (subdivide_d + 1.0));
|
||||
|
||||
/* bottom */
|
||||
points.push_back(Vector3(x, start_pos.y, -z));
|
||||
normals.push_back(Vector3(0.0, -1.0, 0.0));
|
||||
ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
|
||||
uvs.push_back(Vector2(twothirds + u, 0.5 + v));
|
||||
if (_add_uv2) {
|
||||
uv2s.push_back(Vector2(u2 * width_h, 2.0 * (height_v + padding_v) + v2 * depth_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -1342,6 +1674,9 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const {
|
|||
p_arr[RS::ARRAY_NORMAL] = normals;
|
||||
p_arr[RS::ARRAY_TANGENT] = tangents;
|
||||
p_arr[RS::ARRAY_TEX_UV] = uvs;
|
||||
if (_add_uv2) {
|
||||
p_arr[RS::ARRAY_TEX_UV2] = uv2s;
|
||||
}
|
||||
p_arr[RS::ARRAY_INDEX] = indices;
|
||||
}
|
||||
|
||||
|
@ -1377,6 +1712,7 @@ float PrismMesh::get_left_to_right() const {
|
|||
|
||||
void PrismMesh::set_size(const Vector3 &p_size) {
|
||||
size = p_size;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -1417,22 +1753,50 @@ PrismMesh::PrismMesh() {}
|
|||
SphereMesh
|
||||
*/
|
||||
|
||||
void SphereMesh::_create_mesh_array(Array &p_arr) const {
|
||||
create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere);
|
||||
void SphereMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
float _width = radius * Math_TAU;
|
||||
_lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
|
||||
float _height = (is_hemisphere ? 1.0 : 0.5) * height * Math_PI; // note, with hemisphere height is our radius, while with a full sphere it is the diameter..
|
||||
_lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) {
|
||||
void SphereMesh::_create_mesh_array(Array &p_arr) const {
|
||||
bool _add_uv2 = get_add_uv2();
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float _uv2_padding = get_uv2_padding() * texel_size;
|
||||
|
||||
create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere, _add_uv2, _uv2_padding);
|
||||
}
|
||||
|
||||
void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere, bool p_add_uv2, const float p_uv2_padding) {
|
||||
int i, j, prevrow, thisrow, point;
|
||||
float x, y, z;
|
||||
|
||||
float scale = height * (is_hemisphere ? 1.0 : 0.5);
|
||||
|
||||
// Only used if we calculate UV2
|
||||
float circumference = radius * Math_TAU;
|
||||
float horizontal_length = circumference + p_uv2_padding;
|
||||
float center_h = 0.5 * circumference / horizontal_length;
|
||||
|
||||
float height_v = scale * Math_PI / ((scale * Math_PI) + p_uv2_padding);
|
||||
|
||||
// set our bounding box
|
||||
|
||||
Vector<Vector3> points;
|
||||
Vector<Vector3> normals;
|
||||
Vector<float> tangents;
|
||||
Vector<Vector2> uvs;
|
||||
Vector<Vector2> uv2s;
|
||||
Vector<int> indices;
|
||||
point = 0;
|
||||
|
||||
|
@ -1470,6 +1834,10 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int
|
|||
};
|
||||
ADD_TANGENT(z, 0.0, -x, 1.0)
|
||||
uvs.push_back(Vector2(u, v));
|
||||
if (p_add_uv2) {
|
||||
float w_h = w * 2.0 * center_h;
|
||||
uv2s.push_back(Vector2(center_h + ((u - 0.5) * w_h), v * height_v));
|
||||
}
|
||||
point++;
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
|
@ -1491,6 +1859,9 @@ void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int
|
|||
p_arr[RS::ARRAY_NORMAL] = normals;
|
||||
p_arr[RS::ARRAY_TANGENT] = tangents;
|
||||
p_arr[RS::ARRAY_TEX_UV] = uvs;
|
||||
if (p_add_uv2) {
|
||||
p_arr[RS::ARRAY_TEX_UV2] = uv2s;
|
||||
}
|
||||
p_arr[RS::ARRAY_INDEX] = indices;
|
||||
}
|
||||
|
||||
|
@ -1517,6 +1888,7 @@ void SphereMesh::_bind_methods() {
|
|||
|
||||
void SphereMesh::set_radius(const float p_radius) {
|
||||
radius = p_radius;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -1526,6 +1898,7 @@ float SphereMesh::get_radius() const {
|
|||
|
||||
void SphereMesh::set_height(const float p_height) {
|
||||
height = p_height;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -1553,6 +1926,7 @@ int SphereMesh::get_rings() const {
|
|||
|
||||
void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
|
||||
is_hemisphere = p_is_hemisphere;
|
||||
_update_lightmap_size();
|
||||
_request_update();
|
||||
}
|
||||
|
||||
|
@ -1566,6 +1940,31 @@ SphereMesh::SphereMesh() {}
|
|||
TorusMesh
|
||||
*/
|
||||
|
||||
void TorusMesh::_update_lightmap_size() {
|
||||
if (get_add_uv2()) {
|
||||
// size must have changed, update lightmap size hint
|
||||
Size2i _lightmap_size_hint;
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float padding = get_uv2_padding();
|
||||
|
||||
float min_radius = inner_radius;
|
||||
float max_radius = outer_radius;
|
||||
|
||||
if (min_radius > max_radius) {
|
||||
SWAP(min_radius, max_radius);
|
||||
}
|
||||
|
||||
float radius = (max_radius - min_radius) * 0.5;
|
||||
|
||||
float _width = max_radius * Math_TAU;
|
||||
_lightmap_size_hint.x = MAX(1.0, (_width / texel_size) + padding);
|
||||
float _height = radius * Math_TAU;
|
||||
_lightmap_size_hint.y = MAX(1.0, (_height / texel_size) + padding);
|
||||
|
||||
set_lightmap_size_hint(_lightmap_size_hint);
|
||||
}
|
||||
}
|
||||
|
||||
void TorusMesh::_create_mesh_array(Array &p_arr) const {
|
||||
// set our bounding box
|
||||
|
||||
|
@ -1573,6 +1972,7 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
|
|||
Vector<Vector3> normals;
|
||||
Vector<float> tangents;
|
||||
Vector<Vector2> uvs;
|
||||
Vector<Vector2> uv2s;
|
||||
Vector<int> indices;
|
||||
|
||||
#define ADD_TANGENT(m_x, m_y, m_z, m_d) \
|
||||
|
@ -1592,6 +1992,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
|
|||
|
||||
float radius = (max_radius - min_radius) * 0.5;
|
||||
|
||||
// Only used if we calculate UV2
|
||||
bool _add_uv2 = get_add_uv2();
|
||||
float texel_size = get_lightmap_texel_size();
|
||||
float _uv2_padding = get_uv2_padding() * texel_size;
|
||||
|
||||
float horizontal_total = max_radius * Math_TAU + _uv2_padding;
|
||||
float max_h = max_radius * Math_TAU / horizontal_total;
|
||||
float delta_h = (max_radius - min_radius) * Math_TAU / horizontal_total;
|
||||
|
||||
float height_v = radius * Math_TAU / (radius * Math_TAU + _uv2_padding);
|
||||
|
||||
for (int i = 0; i <= rings; i++) {
|
||||
int prevrow = (i - 1) * (ring_segments + 1);
|
||||
int thisrow = i * (ring_segments + 1);
|
||||
|
@ -1607,10 +2018,17 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
|
|||
Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
|
||||
Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
|
||||
|
||||
float offset_h = 0.5 * (1.0 - normalj.x) * delta_h;
|
||||
float adj_h = max_h - offset_h;
|
||||
offset_h *= 0.5;
|
||||
|
||||
points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x));
|
||||
normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x));
|
||||
ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0);
|
||||
uvs.push_back(Vector2(inci, incj));
|
||||
if (_add_uv2) {
|
||||
uv2s.push_back(Vector2(offset_h + inci * adj_h, incj * height_v));
|
||||
}
|
||||
|
||||
if (i > 0 && j > 0) {
|
||||
indices.push_back(thisrow + j - 1);
|
||||
|
@ -1628,6 +2046,9 @@ void TorusMesh::_create_mesh_array(Array &p_arr) const {
|
|||
p_arr[RS::ARRAY_NORMAL] = normals;
|
||||
p_arr[RS::ARRAY_TANGENT] = tangents;
|
||||
p_arr[RS::ARRAY_TEX_UV] = uvs;
|
||||
if (_add_uv2) {
|
||||
p_arr[RS::ARRAY_TEX_UV2] = uv2s;
|
||||
}
|
||||
p_arr[RS::ARRAY_INDEX] = indices;
|
||||
}
|
||||
|
||||
|
@ -1785,6 +2206,8 @@ Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
|
|||
}
|
||||
|
||||
void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
|
||||
// Seeing use case for TubeTrailMesh, no need to do anything more then default UV2 calculation
|
||||
|
||||
PackedVector3Array points;
|
||||
PackedVector3Array normals;
|
||||
PackedFloat32Array tangents;
|
||||
|
@ -2109,6 +2532,8 @@ Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
|
|||
}
|
||||
|
||||
void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const {
|
||||
// Seeing use case of ribbon trail mesh, no need to implement special UV2 calculation
|
||||
|
||||
PackedVector3Array points;
|
||||
PackedVector3Array normals;
|
||||
PackedFloat32Array tangents;
|
||||
|
|
|
@ -56,6 +56,9 @@ private:
|
|||
Ref<Material> material;
|
||||
bool flip_faces = false;
|
||||
|
||||
bool add_uv2 = false;
|
||||
float uv2_padding = 2.0;
|
||||
|
||||
// make sure we do an update after we've finished constructing our object
|
||||
mutable bool pending_request = true;
|
||||
void _update() const;
|
||||
|
@ -70,6 +73,10 @@ protected:
|
|||
void _request_update();
|
||||
GDVIRTUAL0RC(Array, _create_mesh_array)
|
||||
|
||||
Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const;
|
||||
float get_lightmap_texel_size() const;
|
||||
virtual void _update_lightmap_size(){};
|
||||
|
||||
public:
|
||||
virtual int get_surface_count() const override;
|
||||
virtual int surface_get_array_len(int p_idx) const override;
|
||||
|
@ -98,6 +105,12 @@ public:
|
|||
void set_flip_faces(bool p_enable);
|
||||
bool get_flip_faces() const;
|
||||
|
||||
void set_add_uv2(bool p_enable);
|
||||
bool get_add_uv2() const { return add_uv2; }
|
||||
|
||||
void set_uv2_padding(float p_padding);
|
||||
float get_uv2_padding() const { return uv2_padding; }
|
||||
|
||||
PrimitiveMesh();
|
||||
~PrimitiveMesh();
|
||||
};
|
||||
|
@ -118,8 +131,10 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8);
|
||||
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
|
||||
|
||||
void set_radius(const float p_radius);
|
||||
float get_radius() const;
|
||||
|
@ -152,8 +167,10 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0);
|
||||
static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
|
||||
|
||||
void set_size(const Vector3 &p_size);
|
||||
Vector3 get_size() const;
|
||||
|
@ -190,8 +207,10 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true);
|
||||
static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
|
||||
|
||||
void set_top_radius(const float p_radius);
|
||||
float get_top_radius() const;
|
||||
|
@ -241,6 +260,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
void set_size(const Size2 &p_size);
|
||||
Size2 get_size() const;
|
||||
|
@ -292,6 +313,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
void set_left_to_right(const float p_left_to_right);
|
||||
float get_left_to_right() const;
|
||||
|
@ -328,8 +351,10 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false);
|
||||
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
|
||||
|
||||
void set_radius(const float p_radius);
|
||||
float get_radius() const;
|
||||
|
@ -365,6 +390,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
virtual void _create_mesh_array(Array &p_arr) const override;
|
||||
|
||||
virtual void _update_lightmap_size() override;
|
||||
|
||||
public:
|
||||
void set_inner_radius(const float p_inner_radius);
|
||||
float get_inner_radius() const;
|
||||
|
|
Loading…
Reference in New Issue