Merge pull request #50014 from reduz/remove-immediate

Deprecate ImmediateGeometry
This commit is contained in:
Rémi Verschelde
2021-06-30 20:18:59 +02:00
committed by GitHub
32 changed files with 1082 additions and 834 deletions
-157
View File
@@ -1,157 +0,0 @@
/*************************************************************************/
/* immediate_geometry_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "immediate_geometry_3d.h"
void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture) {
RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID());
if (p_texture.is_valid()) {
cached_textures.push_back(p_texture);
}
}
void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) {
RS::get_singleton()->immediate_normal(im, p_normal);
}
void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) {
RS::get_singleton()->immediate_tangent(im, p_tangent);
}
void ImmediateGeometry3D::set_color(const Color &p_color) {
RS::get_singleton()->immediate_color(im, p_color);
}
void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) {
RS::get_singleton()->immediate_uv(im, p_uv);
}
void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) {
RS::get_singleton()->immediate_uv2(im, p_uv2);
}
void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) {
RS::get_singleton()->immediate_vertex(im, p_vertex);
if (empty) {
aabb.position = p_vertex;
aabb.size = Vector3();
empty = false;
} else {
aabb.expand_to(p_vertex);
}
}
void ImmediateGeometry3D::end() {
RS::get_singleton()->immediate_end(im);
}
void ImmediateGeometry3D::clear() {
RS::get_singleton()->immediate_clear(im);
empty = true;
cached_textures.clear();
}
AABB ImmediateGeometry3D::get_aabb() const {
return aabb;
}
Vector<Face3> ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) {
const double lat_step = Math_TAU / p_lats;
const double lon_step = Math_TAU / p_lons;
for (int i = 1; i <= p_lats; i++) {
double lat0 = lat_step * (i - 1) - Math_TAU / 4;
double z0 = Math::sin(lat0);
double zr0 = Math::cos(lat0);
double lat1 = lat_step * i - Math_TAU / 4;
double z1 = Math::sin(lat1);
double zr1 = Math::cos(lat1);
for (int j = p_lons; j >= 1; j--) {
double lng0 = lon_step * (j - 1);
double x0 = Math::cos(lng0);
double y0 = Math::sin(lng0);
double lng1 = lon_step * j;
double x1 = Math::cos(lng1);
double y1 = Math::sin(lng1);
Vector3 v[4] = {
Vector3(x1 * zr0, z0, y1 * zr0),
Vector3(x1 * zr1, z1, y1 * zr1),
Vector3(x0 * zr1, z1, y0 * zr1),
Vector3(x0 * zr0, z0, y0 * zr0)
};
#define ADD_POINT(m_idx) \
if (p_add_uv) { \
set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \
set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \
} \
set_normal(v[m_idx]); \
add_vertex(v[m_idx] * p_radius);
ADD_POINT(0);
ADD_POINT(1);
ADD_POINT(2);
ADD_POINT(2);
ADD_POINT(3);
ADD_POINT(0);
}
}
}
void ImmediateGeometry3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry3D::begin, DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry3D::set_normal);
ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry3D::set_tangent);
ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry3D::set_color);
ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry3D::set_uv);
ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry3D::set_uv2);
ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry3D::add_vertex);
ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry3D::add_sphere, DEFVAL(true));
ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry3D::end);
ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry3D::clear);
}
ImmediateGeometry3D::ImmediateGeometry3D() {
im = RenderingServer::get_singleton()->immediate_create();
set_base(im);
}
ImmediateGeometry3D::~ImmediateGeometry3D() {
RenderingServer::get_singleton()->free(im);
}
-72
View File
@@ -1,72 +0,0 @@
/*************************************************************************/
/* immediate_geometry_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IMMEDIATE_GEOMETRY_3D_H
#define IMMEDIATE_GEOMETRY_3D_H
#include "scene/3d/visual_instance_3d.h"
#include "scene/resources/mesh.h"
class ImmediateGeometry3D : public GeometryInstance3D {
GDCLASS(ImmediateGeometry3D, GeometryInstance3D);
RID im;
//a list of textures drawn need to be kept, to avoid references
// in RenderingServer from becoming invalid if the texture is no longer used
List<Ref<Texture2D>> cached_textures;
bool empty = true;
AABB aabb;
protected:
static void _bind_methods();
public:
void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture = Ref<Texture2D>());
void set_normal(const Vector3 &p_normal);
void set_tangent(const Plane &p_tangent);
void set_color(const Color &p_color);
void set_uv(const Vector2 &p_uv);
void set_uv2(const Vector2 &p_uv2);
void add_vertex(const Vector3 &p_vertex);
void end();
void clear();
void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true);
virtual AABB get_aabb() const override;
virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
ImmediateGeometry3D();
~ImmediateGeometry3D();
};
#endif // IMMEDIATE_GEOMETRY_H
+1 -1
View File
@@ -81,7 +81,7 @@ void SoftBodyRenderingServerHandler::close() {
}
void SoftBodyRenderingServerHandler::commit_changes() {
RS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer);
RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer);
}
void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) {
+232 -78
View File
@@ -164,6 +164,8 @@ void SpriteBase3D::_im_update() {
_draw();
pending_update = false;
//texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
}
void SpriteBase3D::_queue_update() {
@@ -204,6 +206,7 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -313,6 +316,9 @@ void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect);
ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh);
ClassDB::bind_method(D_METHOD("_queue_update"), &SpriteBase3D::_queue_update);
ClassDB::bind_method(D_METHOD("_im_update"), &SpriteBase3D::_im_update);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
@@ -343,21 +349,89 @@ SpriteBase3D::SpriteBase3D() {
flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
}
immediate = RenderingServer::get_singleton()->immediate_create();
set_base(immediate);
material = RenderingServer::get_singleton()->material_create();
// Set defaults for material, names need to match up those in StandardMaterial3D
RS::get_singleton()->material_set_param(material, "albedo", Color(1, 1, 1, 1));
RS::get_singleton()->material_set_param(material, "specular", 0.5);
RS::get_singleton()->material_set_param(material, "metallic", 0.0);
RS::get_singleton()->material_set_param(material, "roughness", 1.0);
RS::get_singleton()->material_set_param(material, "uv1_offset", Vector3(0, 0, 0));
RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1));
RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0));
RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1));
RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98);
mesh = RenderingServer::get_singleton()->mesh_create();
PackedVector3Array mesh_vertices;
PackedVector3Array mesh_normals;
PackedFloat32Array mesh_tangents;
PackedColorArray mesh_colors;
PackedVector2Array mesh_uvs;
PackedInt32Array indices;
mesh_vertices.resize(4);
mesh_normals.resize(4);
mesh_tangents.resize(16);
mesh_colors.resize(4);
mesh_uvs.resize(4);
// create basic mesh and store format information
for (int i = 0; i < 4; i++) {
mesh_normals.write[i] = Vector3(0.0, 0.0, 0.0);
mesh_tangents.write[i * 4 + 0] = 0.0;
mesh_tangents.write[i * 4 + 1] = 0.0;
mesh_tangents.write[i * 4 + 2] = 0.0;
mesh_tangents.write[i * 4 + 3] = 0.0;
mesh_colors.write[i] = Color(1.0, 1.0, 1.0, 1.0);
mesh_uvs.write[i] = Vector2(0.0, 0.0);
mesh_vertices.write[i] = Vector3(0.0, 0.0, 0.0);
}
indices.resize(6);
indices.write[0] = 0;
indices.write[1] = 1;
indices.write[2] = 2;
indices.write[3] = 0;
indices.write[4] = 2;
indices.write[5] = 3;
Array mesh_array;
mesh_array.resize(RS::ARRAY_MAX);
mesh_array[RS::ARRAY_VERTEX] = mesh_vertices;
mesh_array[RS::ARRAY_NORMAL] = mesh_normals;
mesh_array[RS::ARRAY_TANGENT] = mesh_tangents;
mesh_array[RS::ARRAY_COLOR] = mesh_colors;
mesh_array[RS::ARRAY_TEX_UV] = mesh_uvs;
mesh_array[RS::ARRAY_INDEX] = indices;
RS::SurfaceData sd;
RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array);
mesh_surface_format = sd.format;
vertex_buffer = sd.vertex_data;
attribute_buffer = sd.attribute_data;
sd.material = material;
RS::get_singleton()->mesh_surface_make_offsets_from_format(sd.format, sd.vertex_count, sd.index_count, mesh_surface_offsets, vertex_stride, attrib_stride, skin_stride);
RS::get_singleton()->mesh_add_surface(mesh, sd);
set_base(mesh);
}
SpriteBase3D::~SpriteBase3D() {
RenderingServer::get_singleton()->free(immediate);
RenderingServer::get_singleton()->free(mesh);
RenderingServer::get_singleton()->free(material);
}
///////////////////////////////////////////
void Sprite3D::_draw() {
RID immediate = get_immediate();
RS::get_singleton()->immediate_clear(immediate);
if (get_base() != get_mesh()) {
set_base(get_mesh());
}
if (!texture.is_valid()) {
set_base(RID());
return;
}
Vector2 tsize = texture->get_size();
@@ -366,7 +440,7 @@ void Sprite3D::_draw() {
}
Rect2 base_rect;
if (region_enabled) {
if (region) {
base_rect = region_rect;
} else {
base_rect = Rect2(0, 0, texture->get_width(), texture->get_height());
@@ -399,6 +473,7 @@ void Sprite3D::_draw() {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -426,6 +501,7 @@ void Sprite3D::_draw() {
SWAP(uvs[0], uvs[1]);
SWAP(uvs[2], uvs[3]);
}
if (is_flipped_v()) {
SWAP(uvs[0], uvs[3]);
SWAP(uvs[1], uvs[2]);
@@ -442,11 +518,6 @@ void Sprite3D::_draw() {
tangent = Plane(1, 0, 0, 1);
}
RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y);
RS::get_singleton()->immediate_set_material(immediate, mat);
RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid());
int x_axis = ((axis + 1) % 3);
int y_axis = ((axis + 2) % 3);
@@ -466,31 +537,80 @@ void Sprite3D::_draw() {
AABB aabb;
for (int i = 0; i < 6; i++) {
static const int index[6] = { 0, 1, 2, 0, 2, 3 };
// Everything except position and UV is compressed
uint8_t *vertex_write_buffer = vertex_buffer.ptrw();
uint8_t *attribute_write_buffer = attribute_buffer.ptrw();
RS::get_singleton()->immediate_normal(immediate, normal);
RS::get_singleton()->immediate_tangent(immediate, tangent);
RS::get_singleton()->immediate_color(immediate, color);
RS::get_singleton()->immediate_uv(immediate, uvs[index[i]]);
uint32_t v_normal;
{
Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
uint32_t value = 0;
value |= CLAMP(int(n.x * 1023.0), 0, 1023);
value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
v_normal = value;
}
uint32_t v_tangent;
{
Plane t = tangent;
uint32_t value = 0;
value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
if (t.d > 0) {
value |= 3 << 30;
}
v_tangent = value;
}
uint16_t v_color[4] = {
Math::make_half_float(color.r),
Math::make_half_float(color.g),
Math::make_half_float(color.b),
Math::make_half_float(color.a),
};
for (int i = 0; i < 4; i++) {
Vector3 vtx;
vtx[x_axis] = vertices[index[i]][0];
vtx[y_axis] = vertices[index[i]][1];
RS::get_singleton()->immediate_vertex(immediate, vtx);
vtx[x_axis] = vertices[i][0];
vtx[y_axis] = vertices[i][1];
if (i == 0) {
aabb.position = vtx;
aabb.size = Vector3();
} else {
aabb.expand_to(vtx);
}
}
set_aabb(aabb);
RS::get_singleton()->immediate_end(immediate);
}
void Sprite3D::_texture_changed() {
_queue_update();
float v_uv[2] = { uvs[i].x, uvs[i].y };
memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8);
float v_vertex[3] = { vtx.x, vtx.y, vtx.z };
memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4);
memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4);
memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 8);
}
RID mesh = get_mesh();
RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer);
RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer);
RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb);
set_aabb(aabb);
RID shader_rid;
StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid);
if (last_shader != shader_rid) {
RS::get_singleton()->material_set_shader(get_material(), shader_rid);
last_shader = shader_rid;
}
if (last_texture != texture->get_rid()) {
RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
last_texture = texture->get_rid();
}
}
void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
@@ -498,38 +618,36 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) {
return;
}
if (texture.is_valid()) {
texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
texture->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update"));
}
texture = p_texture;
if (texture.is_valid()) {
texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed));
texture->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update"));
}
_queue_update();
emit_signal(SceneStringNames::get_singleton()->texture_changed);
}
Ref<Texture2D> Sprite3D::get_texture() const {
return texture;
}
void Sprite3D::set_region_enabled(bool p_region_enabled) {
if (p_region_enabled == region_enabled) {
void Sprite3D::set_region_enabled(bool p_region) {
if (p_region == region) {
return;
}
region_enabled = p_region_enabled;
region = p_region;
_queue_update();
notify_property_list_changed();
}
bool Sprite3D::is_region_enabled() const {
return region_enabled;
return region;
}
void Sprite3D::set_region_rect(const Rect2 &p_region_rect) {
bool changed = region_rect != p_region_rect;
region_rect = p_region_rect;
if (region_enabled && changed) {
if (region && changed) {
_queue_update();
}
}
@@ -596,7 +714,7 @@ Rect2 Sprite3D::get_item_rect() const {
Size2i s;
if (region_enabled) {
if (region) {
s = region_rect.size;
} else {
s = texture->get_size();
@@ -625,10 +743,6 @@ void Sprite3D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame_coords") {
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
if (!region_enabled && property.name == "region_rect") {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
void Sprite3D::_bind_methods() {
@@ -653,32 +767,28 @@ void Sprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite3D::set_hframes);
ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite3D::get_hframes);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_GROUP("Animation", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("texture_changed"));
}
Sprite3D::Sprite3D() {
region_enabled = false;
frame = 0;
vframes = 1;
hframes = 1;
}
////////////////////////////////////////
void AnimatedSprite3D::_draw() {
RID immediate = get_immediate();
RS::get_singleton()->immediate_clear(immediate);
if (get_base() != get_mesh()) {
set_base(get_mesh());
}
if (frames.is_null()) {
return;
@@ -694,7 +804,8 @@ void AnimatedSprite3D::_draw() {
Ref<Texture2D> texture = frames->get_frame(animation, frame);
if (!texture.is_valid()) {
return; //no texture no life
set_base(RID());
return; //no texuture no life
}
Vector2 tsize = texture->get_size();
if (tsize.x == 0 || tsize.y == 0) {
@@ -729,6 +840,7 @@ void AnimatedSprite3D::_draw() {
float pixel_size = get_pixel_size();
Vector2 vertices[4] = {
(final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size,
(final_rect.position + final_rect.size) * pixel_size,
(final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
@@ -772,12 +884,6 @@ void AnimatedSprite3D::_draw() {
tangent = Plane(1, 0, 0, -1);
}
RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y);
RS::get_singleton()->immediate_set_material(immediate, mat);
RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid());
int x_axis = ((axis + 1) % 3);
int y_axis = ((axis + 2) % 3);
@@ -797,30 +903,79 @@ void AnimatedSprite3D::_draw() {
AABB aabb;
for (int i = 0; i < 6; i++) {
static const int indices[6] = {
0, 1, 2,
0, 2, 3
};
// Everything except position and UV is compressed
uint8_t *vertex_write_buffer = vertex_buffer.ptrw();
uint8_t *attribute_write_buffer = attribute_buffer.ptrw();
RS::get_singleton()->immediate_normal(immediate, normal);
RS::get_singleton()->immediate_tangent(immediate, tangent);
RS::get_singleton()->immediate_color(immediate, color);
RS::get_singleton()->immediate_uv(immediate, uvs[indices[i]]);
uint32_t v_normal;
{
Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
uint32_t value = 0;
value |= CLAMP(int(n.x * 1023.0), 0, 1023);
value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
v_normal = value;
}
uint32_t v_tangent;
{
Plane t = tangent;
uint32_t value = 0;
value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
if (t.d > 0) {
value |= 3 << 30;
}
v_tangent = value;
}
uint16_t v_color[4] = {
Math::make_half_float(color.r),
Math::make_half_float(color.g),
Math::make_half_float(color.b),
Math::make_half_float(color.a),
};
for (int i = 0; i < 4; i++) {
Vector3 vtx;
vtx[x_axis] = vertices[indices[i]][0];
vtx[y_axis] = vertices[indices[i]][1];
RS::get_singleton()->immediate_vertex(immediate, vtx);
vtx[x_axis] = vertices[i][0];
vtx[y_axis] = vertices[i][1];
if (i == 0) {
aabb.position = vtx;
aabb.size = Vector3();
} else {
aabb.expand_to(vtx);
}
float v_uv[2] = { uvs[i].x, uvs[i].y };
memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8);
float v_vertex[3] = { vtx.x, vtx.y, vtx.z };
memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3);
memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4);
memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4);
memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 8);
}
RID mesh = get_mesh();
RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer);
RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer);
RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb);
set_aabb(aabb);
RS::get_singleton()->immediate_end(immediate);
RID shader_rid;
StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid);
if (last_shader != shader_rid) {
RS::get_singleton()->material_set_shader(get_material(), shader_rid);
last_shader = shader_rid;
}
if (last_texture != texture->get_rid()) {
RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
last_texture = texture->get_rid();
}
}
void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
@@ -914,11 +1069,11 @@ void AnimatedSprite3D::_notification(int p_what) {
void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
if (frames.is_valid()) {
frames->disconnect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
frames->disconnect("changed", Callable(this, "_res_changed"));
}
frames = p_frames;
if (frames.is_valid()) {
frames->connect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed));
frames->connect("changed", Callable(this, "_res_changed"));
}
if (!frames.is_valid()) {
@@ -944,9 +1099,8 @@ void AnimatedSprite3D::set_frame(int p_frame) {
if (frames->has_animation(animation)) {
int limit = frames->get_frame_count(animation);
if (p_frame >= limit) {
if (p_frame >= limit)
p_frame = limit - 1;
}
}
if (p_frame < 0) {
@@ -960,7 +1114,6 @@ void AnimatedSprite3D::set_frame(int p_frame) {
frame = p_frame;
_reset_timeout();
_queue_update();
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
@@ -1061,8 +1214,7 @@ StringName AnimatedSprite3D::get_animation() const {
}
TypedArray<String> AnimatedSprite3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
TypedArray<String> warnings = SpriteBase3D::get_configuration_warnings();
if (frames.is_null()) {
warnings.push_back(TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames."));
}
@@ -1087,11 +1239,13 @@ void AnimatedSprite3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame);
ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame);
ClassDB::bind_method(D_METHOD("_res_changed"), &AnimatedSprite3D::_res_changed);
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("animation_finished"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing");
}
+30 -19
View File
@@ -31,8 +31,8 @@
#ifndef SPRITE_3D_H
#define SPRITE_3D_H
#include "scene/2d/animated_sprite_2d.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/resources/sprite_frames.h"
class SpriteBase3D : public GeometryInstance3D {
GDCLASS(SpriteBase3D, GeometryInstance3D);
@@ -75,9 +75,10 @@ private:
float pixel_size = 0.01;
AABB aabb;
RID immediate;
RID mesh;
RID material;
bool flags[FLAG_MAX];
bool flags[FLAG_MAX] = {};
AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
bool pending_update = false;
@@ -91,7 +92,17 @@ protected:
static void _bind_methods();
virtual void _draw() = 0;
_FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; }
_FORCE_INLINE_ RID &get_immediate() { return immediate; }
_FORCE_INLINE_ RID &get_mesh() { return mesh; }
_FORCE_INLINE_ RID &get_material() { return material; }
uint32_t mesh_surface_offsets[RS::ARRAY_MAX];
PackedByteArray vertex_buffer;
PackedByteArray attribute_buffer;
uint32_t vertex_stride;
uint32_t attrib_stride;
uint32_t skin_stride;
uint32_t mesh_surface_format;
void _queue_update();
public:
@@ -107,7 +118,7 @@ public:
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
void set_region_enabled(bool p_region_enabled);
void set_region_enabled(bool p_region);
bool is_region_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
@@ -147,15 +158,16 @@ class Sprite3D : public SpriteBase3D {
GDCLASS(Sprite3D, SpriteBase3D);
Ref<Texture2D> texture;
bool region_enabled;
bool region = false;
Rect2 region_rect;
int frame;
int frame = 0;
int vframes;
int hframes;
int vframes = 1;
int hframes = 1;
void _texture_changed();
RID last_shader;
RID last_texture;
protected:
virtual void _draw() override;
@@ -167,7 +179,7 @@ public:
void set_texture(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture() const;
void set_region_enabled(bool p_region_enabled);
void set_region_enabled(bool p_region);
bool is_region_enabled() const;
void set_region_rect(const Rect2 &p_region_rect);
@@ -199,14 +211,9 @@ class AnimatedSprite3D : public SpriteBase3D {
StringName animation = "default";
int frame = 0;
bool centered = true;
bool centered = false;
float timeout = 0.0;
bool hflip = true;
bool vflip = true;
Color modulate;
float timeout = 0;
void _res_changed();
@@ -214,6 +221,9 @@ class AnimatedSprite3D : public SpriteBase3D {
void _set_playing(bool p_playing);
bool _is_playing() const;
RID last_shader;
RID last_texture;
protected:
virtual void _draw() override;
static void _bind_methods();
@@ -236,10 +246,11 @@ public:
virtual Rect2 get_item_rect() const override;
TypedArray<String> get_configuration_warnings() const override;
virtual TypedArray<String> get_configuration_warnings() const override;
AnimatedSprite3D();
};
VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags);
VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode);
#endif // SPRITE_3D_H
+18 -16
View File
@@ -77,7 +77,7 @@ bool RootMotionView::get_zero_y() const {
void RootMotionView::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
RS::get_singleton()->immediate_set_material(immediate, StandardMaterial3D::get_material_rid_for_2d(false, true, false, false, false));
immediate_material = StandardMaterial3D::get_material_for_2d(false, true, false, false, false);
first = true;
}
@@ -119,11 +119,12 @@ void RootMotionView::_notification(int p_what) {
}
accumulated.origin.z = Math::fposmod(accumulated.origin.z, cell_size);
RS::get_singleton()->immediate_clear(immediate);
immediate->clear_surfaces();
int cells_in_radius = int((radius / cell_size) + 1.0);
RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_LINES);
immediate->surface_begin(Mesh::PRIMITIVE_LINES, immediate_material);
for (int i = -cells_in_radius; i < cells_in_radius; i++) {
for (int j = -cells_in_radius; j < cells_in_radius; j++) {
Vector3 from(i * cell_size, 0, j * cell_size);
@@ -138,21 +139,21 @@ void RootMotionView::_notification(int p_what) {
c_i.a *= MAX(0, 1.0 - from_i.length() / radius);
c_j.a *= MAX(0, 1.0 - from_j.length() / radius);
RS::get_singleton()->immediate_color(immediate, c);
RS::get_singleton()->immediate_vertex(immediate, from);
immediate->surface_set_color(c);
immediate->surface_add_vertex(from);
RS::get_singleton()->immediate_color(immediate, c_i);
RS::get_singleton()->immediate_vertex(immediate, from_i);
immediate->surface_set_color(c_i);
immediate->surface_add_vertex(from_i);
RS::get_singleton()->immediate_color(immediate, c);
RS::get_singleton()->immediate_vertex(immediate, from);
immediate->surface_set_color(c);
immediate->surface_add_vertex(from);
RS::get_singleton()->immediate_color(immediate, c_j);
RS::get_singleton()->immediate_vertex(immediate, from_j);
immediate->surface_set_color(c_j);
immediate->surface_add_vertex(from_j);
}
}
RS::get_singleton()->immediate_end(immediate);
immediate->surface_end();
}
}
@@ -188,12 +189,13 @@ void RootMotionView::_bind_methods() {
}
RootMotionView::RootMotionView() {
set_process_internal(true);
immediate = RenderingServer::get_singleton()->immediate_create();
set_base(immediate);
if (Engine::get_singleton()->is_editor_hint()) {
set_process_internal(true);
}
immediate.instantiate();
set_base(immediate->get_rid());
}
RootMotionView::~RootMotionView() {
set_base(RID());
RenderingServer::get_singleton()->free(immediate);
}
+4 -2
View File
@@ -32,12 +32,12 @@
#define ROOT_MOTION_VIEW_H
#include "scene/3d/visual_instance_3d.h"
#include "scene/resources/immediate_mesh.h"
class RootMotionView : public VisualInstance3D {
GDCLASS(RootMotionView, VisualInstance3D);
public:
RID immediate;
Ref<ImmediateMesh> immediate;
NodePath path;
float cell_size = 1.0;
float radius = 10.0;
@@ -46,6 +46,8 @@ public:
bool first = true;
bool zero_y = true;
Ref<Material> immediate_material;
Transform3D accumulated;
private:
+2 -2
View File
@@ -147,6 +147,7 @@
#include "scene/resources/font.h"
#include "scene/resources/gradient.h"
#include "scene/resources/height_map_shape_3d.h"
#include "scene/resources/immediate_mesh.h"
#include "scene/resources/line_shape_2d.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
@@ -204,7 +205,6 @@
#include "scene/3d/decal.h"
#include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/immediate_geometry_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
@@ -459,7 +459,6 @@ void register_scene_types() {
ClassDB::register_class<MeshInstance3D>();
ClassDB::register_class<OccluderInstance3D>();
ClassDB::register_class<Occluder3D>();
ClassDB::register_class<ImmediateGeometry3D>();
ClassDB::register_virtual_class<SpriteBase3D>();
ClassDB::register_class<Sprite3D>();
ClassDB::register_class<AnimatedSprite3D>();
@@ -718,6 +717,7 @@ void register_scene_types() {
ClassDB::register_virtual_class<Mesh>();
ClassDB::register_class<ArrayMesh>();
ClassDB::register_class<ImmediateMesh>();
ClassDB::register_class<MultiMesh>();
ClassDB::register_class<SurfaceTool>();
ClassDB::register_class<MeshDataTool>();
+416
View File
@@ -0,0 +1,416 @@
/*************************************************************************/
/* immediate_mesh.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "immediate_mesh.h"
void ImmediateMesh::surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material) {
ERR_FAIL_COND_MSG(surface_active, "Already creating a new surface.");
active_surface_data.primitive = p_primitive;
active_surface_data.material = p_material;
surface_active = true;
}
void ImmediateMesh::surface_set_color(const Color &p_color) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
if (!uses_colors) {
colors.resize(vertices.size());
for (uint32_t i = 0; i < colors.size(); i++) {
colors[i] = p_color;
}
uses_colors = true;
}
current_color = p_color;
}
void ImmediateMesh::surface_set_normal(const Vector3 &p_normal) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
if (!uses_normals) {
normals.resize(vertices.size());
for (uint32_t i = 0; i < normals.size(); i++) {
normals[i] = p_normal;
}
uses_normals = true;
}
current_normal = p_normal;
}
void ImmediateMesh::surface_set_tangent(const Plane &p_tangent) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
if (!uses_tangents) {
tangents.resize(vertices.size());
for (uint32_t i = 0; i < tangents.size(); i++) {
tangents[i] = p_tangent;
}
uses_tangents = true;
}
current_tangent = p_tangent;
}
void ImmediateMesh::surface_set_uv(const Vector2 &p_uv) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
if (!uses_uvs) {
uvs.resize(vertices.size());
for (uint32_t i = 0; i < uvs.size(); i++) {
uvs[i] = p_uv;
}
uses_uvs = true;
}
current_uv = p_uv;
}
void ImmediateMesh::surface_set_uv2(const Vector2 &p_uv2) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
if (!uses_uv2s) {
uv2s.resize(vertices.size());
for (uint32_t i = 0; i < uv2s.size(); i++) {
uv2s[i] = p_uv2;
}
uses_uv2s = true;
}
current_uv2 = p_uv2;
}
void ImmediateMesh::surface_add_vertex(const Vector3 &p_vertex) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
ERR_FAIL_COND_MSG(vertices.size() && active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
if (uses_colors) {
colors.push_back(current_color);
}
if (uses_normals) {
normals.push_back(current_normal);
}
if (uses_tangents) {
tangents.push_back(current_tangent);
}
if (uses_uvs) {
uvs.push_back(current_uv);
}
if (uses_uv2s) {
uv2s.push_back(current_uv2);
}
vertices.push_back(p_vertex);
}
void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
ERR_FAIL_COND_MSG(vertices.size() && !active_surface_data.vertex_2d, "Can't mix 2D and 3D vertices in a surface.");
if (uses_colors) {
colors.push_back(current_color);
}
if (uses_normals) {
normals.push_back(current_normal);
}
if (uses_tangents) {
tangents.push_back(current_tangent);
}
if (uses_uvs) {
uvs.push_back(current_uv);
}
if (uses_uv2s) {
uv2s.push_back(current_uv2);
}
Vector3 v(p_vertex.x, p_vertex.y, 0);
vertices.push_back(v);
active_surface_data.vertex_2d = true;
}
void ImmediateMesh::surface_end() {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface cant be created.");
uint32_t format = ARRAY_FORMAT_VERTEX;
uint32_t vertex_stride = 0;
if (active_surface_data.vertex_2d) {
format |= ARRAY_FLAG_USE_2D_VERTICES;
vertex_stride = sizeof(float) * 2;
} else {
vertex_stride = sizeof(float) * 3;
}
uint32_t normal_offset = 0;
if (uses_normals) {
format |= ARRAY_FORMAT_NORMAL;
normal_offset = vertex_stride;
vertex_stride += sizeof(uint32_t);
}
uint32_t tangent_offset = 0;
if (uses_tangents) {
format |= ARRAY_FORMAT_TANGENT;
tangent_offset += vertex_stride;
vertex_stride += sizeof(uint32_t);
}
AABB aabb;
{
surface_vertex_create_cache.resize(vertex_stride * vertices.size());
uint8_t *surface_vertex_ptr = surface_vertex_create_cache.ptrw();
for (uint32_t i = 0; i < vertices.size(); i++) {
{
float *vtx = (float *)&surface_vertex_ptr[i * vertex_stride];
vtx[0] = vertices[i].x;
vtx[1] = vertices[i].y;
if (!active_surface_data.vertex_2d) {
vtx[2] = vertices[i].z;
}
if (i == 0) {
aabb.position = vertices[i];
} else {
aabb.expand_to(vertices[i]);
}
}
if (uses_normals) {
uint32_t *normal = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + normal_offset];
Vector3 n = normals[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
uint32_t value = 0;
value |= CLAMP(int(n.x * 1023.0), 0, 1023);
value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
*normal = value;
}
if (uses_tangents) {
uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * vertex_stride + tangent_offset];
Plane t = tangents[i];
uint32_t value = 0;
value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023);
value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
if (t.d > 0) {
value |= 3 << 30;
}
*tangent = value;
}
}
}
if (uses_colors || uses_uvs || uses_uv2s) {
uint32_t attribute_stride = 0;
if (uses_colors) {
format |= ARRAY_FORMAT_COLOR;
attribute_stride += sizeof(uint16_t) * 4;
}
uint32_t uv_offset = 0;
if (uses_uvs) {
format |= ARRAY_FORMAT_TEX_UV;
uv_offset = attribute_stride;
attribute_stride += sizeof(float) * 2;
}
uint32_t uv2_offset = 0;
if (uses_uv2s) {
format |= ARRAY_FORMAT_TEX_UV2;
uv2_offset = attribute_stride;
attribute_stride += sizeof(float) * 2;
}
surface_attribute_create_cache.resize(vertices.size() * attribute_stride);
uint8_t *surface_attribute_ptr = surface_attribute_create_cache.ptrw();
for (uint32_t i = 0; i < vertices.size(); i++) {
if (uses_colors) {
uint16_t *color16 = (uint16_t *)&surface_attribute_ptr[i * attribute_stride];
color16[0] = Math::make_half_float(colors[i].r);
color16[1] = Math::make_half_float(colors[i].g);
color16[2] = Math::make_half_float(colors[i].b);
color16[3] = Math::make_half_float(colors[i].a);
}
if (uses_uvs) {
float *uv = (float *)&surface_attribute_ptr[i * attribute_stride + uv_offset];
uv[0] = uvs[i].x;
uv[0] = uvs[i].y;
}
if (uses_uv2s) {
float *uv2 = (float *)&surface_attribute_ptr[i * attribute_stride + uv2_offset];
uv2[0] = uv2s[i].x;
uv2[0] = uv2s[i].y;
}
}
}
RS::SurfaceData sd;
sd.primitive = RS::PrimitiveType(active_surface_data.primitive);
sd.format = format;
sd.vertex_data = surface_vertex_create_cache;
if (uses_colors || uses_uvs || uses_uv2s) {
sd.attribute_data = surface_attribute_create_cache;
}
sd.vertex_count = vertices.size();
sd.aabb = aabb;
if (active_surface_data.material.is_valid()) {
sd.material = active_surface_data.material->get_rid();
}
RS::get_singleton()->mesh_add_surface(mesh, sd);
active_surface_data.aabb = aabb;
active_surface_data.format = format;
active_surface_data.array_len = vertices.size();
surfaces.push_back(active_surface_data);
colors.clear();
normals.clear();
tangents.clear();
uvs.clear();
uv2s.clear();
vertices.clear();
uses_colors = false;
uses_normals = false;
uses_tangents = false;
uses_uvs = false;
uses_uv2s = false;
surface_active = false;
}
void ImmediateMesh::clear_surfaces() {
RS::get_singleton()->mesh_clear(mesh);
surfaces.clear();
surface_active = false;
colors.clear();
normals.clear();
tangents.clear();
uvs.clear();
uv2s.clear();
vertices.clear();
uses_colors = false;
uses_normals = false;
uses_tangents = false;
uses_uvs = false;
uses_uv2s = false;
}
int ImmediateMesh::get_surface_count() const {
return surfaces.size();
}
int ImmediateMesh::surface_get_array_len(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), -1);
return surfaces[p_idx].array_len;
}
int ImmediateMesh::surface_get_array_index_len(int p_idx) const {
return 0;
}
bool ImmediateMesh::surface_is_softbody_friendly(int p_idx) const {
return false;
}
Array ImmediateMesh::surface_get_arrays(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface, int(surfaces.size()), Array());
return RS::get_singleton()->mesh_surface_get_arrays(mesh, p_surface);
}
Array ImmediateMesh::surface_get_blend_shape_arrays(int p_surface) const {
return Array();
}
Dictionary ImmediateMesh::surface_get_lods(int p_surface) const {
return Dictionary();
}
uint32_t ImmediateMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), 0);
return surfaces[p_idx].format;
}
Mesh::PrimitiveType ImmediateMesh::surface_get_primitive_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), PRIMITIVE_MAX);
return surfaces[p_idx].primitive;
}
void ImmediateMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
ERR_FAIL_INDEX(p_idx, int(surfaces.size()));
surfaces[p_idx].material = p_material;
RID mat;
if (p_material.is_valid()) {
mat = p_material->get_rid();
}
RS::get_singleton()->mesh_surface_set_material(mesh, p_idx, mat);
}
Ref<Material> ImmediateMesh::surface_get_material(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, int(surfaces.size()), Ref<Material>());
return surfaces[p_idx].material;
}
int ImmediateMesh::get_blend_shape_count() const {
return 0;
}
StringName ImmediateMesh::get_blend_shape_name(int p_index) const {
return StringName();
}
void ImmediateMesh::set_blend_shape_name(int p_index, const StringName &p_name) {
}
AABB ImmediateMesh::get_aabb() const {
AABB aabb;
for (uint32_t i = 0; i < surfaces.size(); i++) {
if (i == 0) {
aabb = surfaces[i].aabb;
} else {
aabb.merge(surfaces[i].aabb);
}
}
return aabb;
}
void ImmediateMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("surface_begin", "primitive", "material"), &ImmediateMesh::surface_begin, DEFVAL(Ref<Material>()));
ClassDB::bind_method(D_METHOD("surface_set_color", "color"), &ImmediateMesh::surface_set_color);
ClassDB::bind_method(D_METHOD("surface_set_normal", "normal"), &ImmediateMesh::surface_set_normal);
ClassDB::bind_method(D_METHOD("surface_set_tangent", "tangent"), &ImmediateMesh::surface_set_tangent);
ClassDB::bind_method(D_METHOD("surface_set_uv", "uv"), &ImmediateMesh::surface_set_uv);
ClassDB::bind_method(D_METHOD("surface_set_uv2", "uv2"), &ImmediateMesh::surface_set_uv2);
ClassDB::bind_method(D_METHOD("surface_add_vertex", "vertex"), &ImmediateMesh::surface_add_vertex);
ClassDB::bind_method(D_METHOD("surface_add_vertex_2d", "vertex"), &ImmediateMesh::surface_add_vertex_2d);
ClassDB::bind_method(D_METHOD("surface_end"), &ImmediateMesh::surface_end);
ClassDB::bind_method(D_METHOD("clear_surfaces"), &ImmediateMesh::clear_surfaces);
}
RID ImmediateMesh::get_rid() const {
return mesh;
}
ImmediateMesh::ImmediateMesh() {
mesh = RS::get_singleton()->mesh_create();
}
ImmediateMesh::~ImmediateMesh() {
RS::get_singleton()->free(mesh);
}
+117
View File
@@ -0,0 +1,117 @@
/*************************************************************************/
/* immediate_mesh.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IMMEDIATE_MESH_H
#define IMMEDIATE_MESH_H
#include "core/templates/local_vector.h"
#include "scene/resources/mesh.h"
class ImmediateMesh : public Mesh {
GDCLASS(ImmediateMesh, Mesh)
RID mesh;
bool uses_colors = false;
bool uses_normals = false;
bool uses_tangents = false;
bool uses_uvs = false;
bool uses_uv2s = false;
Color current_color;
Vector3 current_normal;
Plane current_tangent;
Vector2 current_uv;
Vector2 current_uv2;
LocalVector<Color> colors;
LocalVector<Vector3> normals;
LocalVector<Plane> tangents;
LocalVector<Vector2> uvs;
LocalVector<Vector2> uv2s;
LocalVector<Vector3> vertices;
struct Surface {
PrimitiveType primitive;
Ref<Material> material;
bool vertex_2d = false;
int array_len = 0;
uint32_t format = 0;
AABB aabb;
};
LocalVector<Surface> surfaces;
bool surface_active = false;
Surface active_surface_data;
Vector<uint8_t> surface_vertex_create_cache;
Vector<uint8_t> surface_attribute_create_cache;
protected:
static void _bind_methods();
public:
void surface_begin(PrimitiveType p_primitive, const Ref<Material> &p_material = Ref<Material>());
void surface_set_color(const Color &p_color);
void surface_set_normal(const Vector3 &p_normal);
void surface_set_tangent(const Plane &p_tangent);
void surface_set_uv(const Vector2 &p_uv);
void surface_set_uv2(const Vector2 &p_uv2);
void surface_add_vertex(const Vector3 &p_vertex);
void surface_add_vertex_2d(const Vector2 &p_vertex);
void surface_end();
void clear_surfaces();
virtual int get_surface_count() const override;
virtual int surface_get_array_len(int p_idx) const override;
virtual int surface_get_array_index_len(int p_idx) const override;
virtual bool surface_is_softbody_friendly(int p_idx) const override;
virtual Array surface_get_arrays(int p_surface) const override;
virtual Array surface_get_blend_shape_arrays(int p_surface) const override;
virtual Dictionary surface_get_lods(int p_surface) const override;
virtual uint32_t surface_get_format(int p_idx) const override;
virtual PrimitiveType surface_get_primitive_type(int p_idx) const override;
virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override;
virtual Ref<Material> surface_get_material(int p_idx) const override;
virtual int get_blend_shape_count() const override;
virtual StringName get_blend_shape_name(int p_index) const override;
virtual void set_blend_shape_name(int p_index, const StringName &p_name) override;
virtual AABB get_aabb() const override;
virtual RID get_rid() const override;
ImmediateMesh();
~ImmediateMesh();
};
#endif // IMMEDIATEMESH_H
+12 -3
View File
@@ -2077,7 +2077,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel()
return refraction_texture_channel;
}
RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y) {
Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, RID *r_shader_rid) {
int version = 0;
if (p_shaded) {
version = 1;
@@ -2102,7 +2102,10 @@ RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, b
}
if (materials_for_2d[version].is_valid()) {
return materials_for_2d[version]->get_rid();
if (r_shader_rid) {
*r_shader_rid = materials_for_2d[version]->get_shader_rid();
}
return materials_for_2d[version];
}
Ref<StandardMaterial3D> material;
@@ -2120,7 +2123,11 @@ RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, b
materials_for_2d[version] = material;
return materials_for_2d[version]->get_rid();
if (r_shader_rid) {
*r_shader_rid = materials_for_2d[version]->get_shader_rid();
}
return materials_for_2d[version];
}
void BaseMaterial3D::set_on_top_of_alpha() {
@@ -2189,6 +2196,8 @@ BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const {
}
RID BaseMaterial3D::get_shader_rid() const {
MutexLock lock(material_mutex);
((BaseMaterial3D *)this)->_update_shader();
ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
return shader_map[current_key].shader;
}
+1 -1
View File
@@ -738,7 +738,7 @@ public:
static void finish_shaders();
static void flush_changes();
static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false);
static Ref<Material> get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, RID *r_shader_rid = nullptr);
virtual RID get_shader_rid() const override;
+17 -3
View File
@@ -1335,9 +1335,21 @@ String ArrayMesh::surface_get_name(int p_idx) const {
return surfaces[p_idx].name;
}
void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
void ArrayMesh::surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
ERR_FAIL_INDEX(p_surface, surfaces.size());
RS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data);
RS::get_singleton()->mesh_surface_update_vertex_region(mesh, p_surface, p_offset, p_data);
emit_changed();
}
void ArrayMesh::surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
ERR_FAIL_INDEX(p_surface, surfaces.size());
RS::get_singleton()->mesh_surface_update_attribute_region(mesh, p_surface, p_offset, p_data);
emit_changed();
}
void ArrayMesh::surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
ERR_FAIL_INDEX(p_surface, surfaces.size());
RS::get_singleton()->mesh_surface_update_skin_region(mesh, p_surface, p_offset, p_data);
emit_changed();
}
@@ -1635,7 +1647,9 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces);
ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region);
ClassDB::bind_method(D_METHOD("surface_update_vertex_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_vertex_region);
ClassDB::bind_method(D_METHOD("surface_update_attribute_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_attribute_region);
ClassDB::bind_method(D_METHOD("surface_update_skin_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_skin_region);
ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len);
ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len);
ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format);
+3 -1
View File
@@ -233,7 +233,9 @@ public:
void set_blend_shape_mode(BlendShapeMode p_mode);
BlendShapeMode get_blend_shape_mode() const;
void surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
void surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
void surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
void surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data);
int get_surface_count() const override;