Merge pull request #50014 from reduz/remove-immediate
Deprecate ImmediateGeometry
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user