Refactored Mesh internals and formats.

-Changed how mesh data is organized, hoping to make it more efficient on Vulkan and GLES.
-Removed compression, it now always uses the most efficient format.
-Added support for custom arrays (up to 8 custom formats)
-Added support for 8 weights in skeleton data.
-Added a simple optional versioning system for imported assets, to reimport if binary is newer
-Fixes #43979 (I needed to test)

WARNING:

-NOT backwards compatible with previous 4.x-devel, will most likely never be, but it will force reimport scenes due to version change.
-NOT backwards compatible with 3.x scenes, this will be eventually re-added.
-Skeletons not working any longer, will fix in next PR.
This commit is contained in:
reduz 2020-12-01 22:40:47 -03:00
parent 3beab2646f
commit 70f5972905
29 changed files with 1332 additions and 881 deletions

View file

@ -102,6 +102,7 @@ public:
virtual String get_resource_type() const = 0;
virtual float get_priority() const { return 1.0; }
virtual int get_import_order() const { return 0; }
virtual int get_format_version() const { return 0; }
struct ImportOption {
PropertyInfo option;

View file

@ -615,6 +615,7 @@ int RenderingDeviceVulkan::get_format_vertex_size(DataFormat p_format) {
case DATA_FORMAT_B8G8R8A8_SNORM:
case DATA_FORMAT_B8G8R8A8_UINT:
case DATA_FORMAT_B8G8R8A8_SINT:
case DATA_FORMAT_A2B10G10R10_UNORM_PACK32:
return 4;
case DATA_FORMAT_R16_UNORM:
case DATA_FORMAT_R16_SNORM:
@ -3528,7 +3529,7 @@ RenderingDevice::VertexFormatID RenderingDeviceVulkan::vertex_format_create(cons
ERR_FAIL_COND_V(used_locations.has(p_vertex_formats[i].location), INVALID_ID);
ERR_FAIL_COND_V_MSG(get_format_vertex_size(p_vertex_formats[i].format) == 0, INVALID_ID,
"Data format for attachment (" + itos(i) + ") is not valid for a vertex array.");
"Data format for attachment (" + itos(i) + "), '" + named_formats[p_vertex_formats[i].format] + "', is not valid for a vertex array.");
vdcache.bindings[i].binding = i;
vdcache.bindings[i].stride = p_vertex_formats[i].stride;

View file

@ -357,10 +357,12 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
List<String> to_check;
String importer_name;
String source_file = "";
String source_md5 = "";
Vector<String> dest_files;
String dest_md5 = "";
int version = 0;
while (true) {
assign = Variant();
@ -384,6 +386,10 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
for (int i = 0; i < fa.size(); i++) {
to_check.push_back(fa[i]);
}
} else if (assign == "importer_version") {
version = value;
} else if (assign == "importer") {
importer_name = value;
} else if (!p_only_imported_files) {
if (assign == "source_file") {
source_file = value;
@ -399,6 +405,12 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
memdelete(f);
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
if (importer->get_format_version() > version) {
return true; // version changed, reimport
}
// Read the md5's from a separate file (so the import parameters aren't dependent on the file version
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_path);
FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err);
@ -1576,6 +1588,10 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
f->store_line("[remap]");
f->store_line("");
f->store_line("importer=\"" + importer->get_importer_name() + "\"");
int version = importer->get_format_version();
if (version > 0) {
f->store_line("importer_version=" + itos(importer->get_format_version()));
}
if (importer->get_resource_type() != "") {
f->store_line("type=\"" + importer->get_resource_type() + "\"");
}

View file

@ -844,19 +844,19 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
for (int k = 0; k < vertex_array.size(); k++) {
if (normal_src) {
surftool->add_normal(vertex_array[k].normal);
surftool->set_normal(vertex_array[k].normal);
if (binormal_src && tangent_src) {
surftool->add_tangent(vertex_array[k].tangent);
surftool->set_tangent(vertex_array[k].tangent);
}
}
if (uv_src) {
surftool->add_uv(Vector2(vertex_array[k].uv.x, vertex_array[k].uv.y));
surftool->set_uv(Vector2(vertex_array[k].uv.x, vertex_array[k].uv.y));
}
if (uv2_src) {
surftool->add_uv2(Vector2(vertex_array[k].uv2.x, vertex_array[k].uv2.y));
surftool->set_uv2(Vector2(vertex_array[k].uv2.x, vertex_array[k].uv2.y));
}
if (color_src) {
surftool->add_color(vertex_array[k].color);
surftool->set_color(vertex_array[k].color);
}
if (has_weights) {
@ -876,8 +876,8 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
}
}
surftool->add_bones(bones);
surftool->add_weights(weights);
surftool->set_bones(bones);
surftool->set_weights(weights);
}
surftool->add_vertex(vertex_array[k].vertex);
@ -923,7 +923,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me
mr.push_back(a);
}
p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, Dictionary(), p_use_compression ? Mesh::ARRAY_COMPRESS_DEFAULT : 0);
p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, d, mr, Dictionary(), 0);
if (material.is_valid()) {
if (p_use_mesh_material) {

View file

@ -970,8 +970,7 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
return OK;
}
bool compress_vert_data = state.import_flags & IMPORT_USE_COMPRESSION;
uint32_t mesh_flags = compress_vert_data ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
uint32_t mesh_flags = 0;
Array meshes = state.json["meshes"];
for (GLTFMeshIndex i = 0; i < meshes.size(); i++) {

View file

@ -210,7 +210,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
bool generate_tangents = p_generate_tangents;
Vector3 scale_mesh = p_scale_mesh;
Vector3 offset_mesh = p_offset_mesh;
int mesh_flags = p_optimize ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
int mesh_flags = 0;
Vector<Vector3> vertices;
Vector<Vector3> normals;
@ -294,7 +294,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
norm += normals.size() + 1;
}
ERR_FAIL_INDEX_V(norm, normals.size(), ERR_FILE_CORRUPT);
surf_tool->add_normal(normals[norm]);
surf_tool->set_normal(normals[norm]);
}
if (face[idx].size() >= 2 && face[idx][1] != String()) {
@ -303,7 +303,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_
uv += uvs.size() + 1;
}
ERR_FAIL_INDEX_V(uv, uvs.size(), ERR_FILE_CORRUPT);
surf_tool->add_uv(uvs[uv]);
surf_tool->set_uv(uvs[uv]);
}
int vtx = face[idx][0].to_int() - 1;
@ -473,6 +473,10 @@ String ResourceImporterOBJ::get_resource_type() const {
return "Mesh";
}
int ResourceImporterOBJ::get_format_version() const {
return 1;
}
int ResourceImporterOBJ::get_preset_count() const {
return 0;
}

View file

@ -54,6 +54,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual String get_save_extension() const override;
virtual String get_resource_type() const override;
virtual int get_format_version() const override;
virtual int get_preset_count() const override;
virtual String get_preset_name(int p_idx) const override;

View file

@ -172,6 +172,10 @@ String ResourceImporterScene::get_resource_type() const {
return "PackedScene";
}
int ResourceImporterScene::get_format_version() const {
return 1;
}
bool ResourceImporterScene::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
if (p_option.begins_with("animation/")) {
if (p_option != "animation/import" && !bool(p_options["animation/import"])) {

View file

@ -133,6 +133,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual String get_save_extension() const override;
virtual String get_resource_type() const override;
virtual int get_format_version() const override;
virtual int get_preset_count() const override;
virtual String get_preset_name(int p_idx) const override;

View file

@ -1625,13 +1625,13 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
int pointidx = 0;
for (int j = 0; j < 3; j++) {
bones.write[0] = parent;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(rootcolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(rootcolor);
surface_tool->add_vertex(v0 - grests[parent].basis[j].normalized() * dist * 0.05);
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(rootcolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(rootcolor);
surface_tool->add_vertex(v0 + grests[parent].basis[j].normalized() * dist * 0.05);
if (j == closest) {
@ -1654,24 +1654,24 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
point += axis * dist * 0.1;
bones.write[0] = parent;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(bonecolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(v0);
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(bonecolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(point);
bones.write[0] = parent;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(bonecolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(point);
bones.write[0] = i;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(bonecolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(v1);
points[pointidx++] = point;
}
@ -1680,13 +1680,13 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
SWAP(points[1], points[2]);
for (int j = 0; j < 4; j++) {
bones.write[0] = parent;
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(bonecolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(points[j]);
surface_tool->add_bones(bones);
surface_tool->add_weights(weights);
surface_tool->add_color(bonecolor);
surface_tool->set_bones(bones);
surface_tool->set_weights(weights);
surface_tool->set_color(bonecolor);
surface_tool->add_vertex(points[(j + 1) % 4]);
}

View file

@ -5345,7 +5345,7 @@ void Node3DEditor::_init_indicators() {
Vector2 ofs = Vector2(Math::cos((Math_PI * 2.0 * k) / m), Math::sin((Math_PI * 2.0 * k) / m));
Vector3 normal = ivec * ofs.x + ivec2 * ofs.y;
surftool->add_normal(basis.xform(normal));
surftool->set_normal(basis.xform(normal));
surftool->add_vertex(vertex);
}
}

View file

@ -712,8 +712,8 @@ void ARKitInterface::_add_or_update_anchor(GodotARAnchor *p_anchor) {
int16_t index = planeAnchor.geometry.triangleIndices[j];
simd_float3 vrtx = planeAnchor.geometry.vertices[index];
simd_float2 textcoord = planeAnchor.geometry.textureCoordinates[index];
surftool->add_uv(Vector2(textcoord[0], textcoord[1]));
surftool->add_color(Color(0.8, 0.8, 0.8));
surftool->set_uv(Vector2(textcoord[0], textcoord[1]));
surftool->set_color(Color(0.8, 0.8, 0.8));
surftool->add_vertex(Vector3(vrtx[0], vrtx[1], vrtx[2]));
}

View file

@ -827,8 +827,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat
Ref<ArrayMesh> mesh;
mesh.instance();
bool has_uvs = false;
bool compress_vert_data = state.import_flags & IMPORT_USE_COMPRESSION;
uint32_t mesh_flags = compress_vert_data ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
uint32_t mesh_flags = 0;
Map<String, uint32_t> morph_mesh_string_lookup;
@ -904,33 +903,33 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat
// Get the texture coordinates if they exist
if (ai_mesh->HasTextureCoords(0)) {
has_uvs = true;
st->add_uv(Vector2(ai_mesh->mTextureCoords[0][j].x, 1.0f - ai_mesh->mTextureCoords[0][j].y));
st->set_uv(Vector2(ai_mesh->mTextureCoords[0][j].x, 1.0f - ai_mesh->mTextureCoords[0][j].y));
}
if (ai_mesh->HasTextureCoords(1)) {
has_uvs = true;
st->add_uv2(Vector2(ai_mesh->mTextureCoords[1][j].x, 1.0f - ai_mesh->mTextureCoords[1][j].y));
st->set_uv2(Vector2(ai_mesh->mTextureCoords[1][j].x, 1.0f - ai_mesh->mTextureCoords[1][j].y));
}
// Assign vertex colors
if (ai_mesh->HasVertexColors(0)) {
Color color = Color(ai_mesh->mColors[0]->r, ai_mesh->mColors[0]->g, ai_mesh->mColors[0]->b,
ai_mesh->mColors[0]->a);
st->add_color(color);
st->set_color(color);
}
// Work out normal calculations? - this needs work it doesn't work properly on huestos
if (ai_mesh->mNormals != nullptr) {
const aiVector3D normals = ai_mesh->mNormals[j];
const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z);
st->add_normal(godot_normal);
st->set_normal(godot_normal);
if (ai_mesh->HasTangentsAndBitangents()) {
const aiVector3D tangents = ai_mesh->mTangents[j];
const Vector3 godot_tangent = Vector3(tangents.x, tangents.y, tangents.z);
const aiVector3D bitangent = ai_mesh->mBitangents[j];
const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z);
float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f;
st->add_tangent(Plane(tangents.x, tangents.y, tangents.z, d));
st->set_tangent(Plane(tangents.x, tangents.y, tangents.z, d));
}
}
@ -948,8 +947,8 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat
weights.write[k] = bone_info[k].weight;
}
st->add_bones(bones);
st->add_weights(weights);
st->set_bones(bones);
st->set_weights(weights);
}
// Assign vertex

View file

@ -480,7 +480,6 @@ void SoftBody3D::become_mesh_owner() {
Dictionary surface_lods = mesh->surface_get_lods(0);
uint32_t surface_format = mesh->surface_get_format(0);
surface_format &= ~(Mesh::ARRAY_COMPRESS_NORMAL);
surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
Ref<ArrayMesh> soft_mesh;

View file

@ -157,7 +157,7 @@ void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) {
bool Mesh::surface_is_softbody_friendly(int p_idx) const {
const uint32_t surface_format = surface_get_format(p_idx);
return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL)));
return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE);
}
Vector<Face3> Mesh::get_faces() const {
@ -483,37 +483,59 @@ void Mesh::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT);
BIND_ENUM_CONSTANT(ARRAY_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_COLOR);
BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM0);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM1);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM2);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_BONES);
BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_INDEX);
BIND_ENUM_CONSTANT(ARRAY_MAX);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_MASK);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_FLAGS_BASE);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
}
void Mesh::clear_cache() const {
@ -559,12 +581,50 @@ Vector<Ref<Shape3D>> Mesh::convex_decompose() const {
Mesh::Mesh() {
}
#if 0
static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) {
bool vertex_16bit = p_format & ((1 << (Mesh::ARRAY_VERTEX + Mesh::ARRAY_COMPRESS_BASE)));
bool has_bones = (p_format & Mesh::ARRAY_FORMAT_BONES);
bool bone_8 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_INDEX << 2));
bool weight_32 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_TEX_UV2 << 2));
enum ArrayType {
OLD_ARRAY_VERTEX = 0,
OLD_ARRAY_NORMAL = 1,
OLD_ARRAY_TANGENT = 2,
OLD_ARRAY_COLOR = 3,
OLD_ARRAY_TEX_UV = 4,
OLD_ARRAY_TEX_UV2 = 5,
OLD_ARRAY_BONES = 6,
OLD_ARRAY_WEIGHTS = 7,
OLD_ARRAY_INDEX = 8,
OLD_ARRAY_MAX = 9
};
enum ArrayFormat {
/* OLD_ARRAY FORMAT FLAGS */
OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory
OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL,
OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT,
OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR,
OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV,
OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2,
OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES,
OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS,
OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX,
OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1),
OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE),
OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE),
OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE),
OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE),
OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE),
OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE),
OLD_ARRAY_COMPRESS_DEFAULT = OLD_ARRAY_COMPRESS_NORMAL | OLD_ARRAY_COMPRESS_TANGENT | OLD_ARRAY_COMPRESS_COLOR | OLD_ARRAY_COMPRESS_TEX_UV | OLD_ARRAY_COMPRESS_TEX_UV2,
OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1,
OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3,
};
bool vertex_16bit = p_format & ((1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE)));
bool has_bones = (p_format & OLD_ARRAY_FORMAT_BONES);
bool bone_8 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_INDEX << 2));
bool weight_32 = has_bones && !(p_format & (OLD_ARRAY_COMPRESS_TEX_UV2 << 2));
print_line("convert vertex16: " + itos(vertex_16bit) + " convert bone 8 " + itos(bone_8) + " convert weight 32 " + itos(weight_32));
@ -572,7 +632,7 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui
return p_src;
}
bool vertex_2d = (p_format & (Mesh::ARRAY_COMPRESS_INDEX << 1));
bool vertex_2d = (p_format & (OLD_ARRAY_COMPRESS_INDEX << 1));
uint32_t src_stride = p_src.size() / p_elements;
uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) + (bone_8 ? 4 : 0) - (weight_32 ? 8 : 0);
@ -671,7 +731,7 @@ static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, ui
return ret;
}
#endif
bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
String sname = p_name;
@ -727,6 +787,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]);
} else if (d.has("array_data")) {
#if 0
//print_line("array data (old style");
//older format (3.x)
Vector<uint8_t> array_data = d["array_data"];
@ -793,6 +854,7 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) {
}
add_surface(format, PrimitiveType(primitive), array_data, vertex_count, array_index_data, index_count, aabb, blend_shapes, bone_aabb);
#endif
} else {
ERR_FAIL_V(false);
}
@ -824,6 +886,12 @@ Array ArrayMesh::_get_surfaces() const {
data["primitive"] = surface.primitive;
data["vertex_data"] = surface.vertex_data;
data["vertex_count"] = surface.vertex_count;
if (surface.skin_data.size()) {
data["skin_data"] = surface.skin_data;
}
if (surface.attribute_data.size()) {
data["attribute_data"] = surface.attribute_data;
}
data["aabb"] = surface.aabb;
if (surface.index_count) {
data["index_data"] = surface.index_data;
@ -848,9 +916,9 @@ Array ArrayMesh::_get_surfaces() const {
data["bone_aabbs"] = bone_aabbs;
}
Array blend_shapes;
for (int j = 0; j < surface.blend_shapes.size(); j++) {
blend_shapes.push_back(surface.blend_shapes[j]);
if (surface.blend_shape_data.size()) {
data["blend_shapes"] = surface.blend_shape_data;
data["blend_shapes_count"] = surface.blend_shape_count;
}
if (surfaces[i].material.is_valid()) {
@ -896,6 +964,12 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
surface.primitive = RS::PrimitiveType(int(d["primitive"]));
surface.vertex_data = d["vertex_data"];
surface.vertex_count = d["vertex_count"];
if (d.has("attribute_data")) {
surface.attribute_data = d["attribute_data"];
}
if (d.has("skin_data")) {
surface.skin_data = d["skin_data"];
}
surface.aabb = d["aabb"];
if (d.has("index_data")) {
@ -922,11 +996,9 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
}
}
if (d.has("blend_shapes")) {
Array blend_shapes;
for (int j = 0; j < blend_shapes.size(); j++) {
surface.blend_shapes.push_back(blend_shapes[j]);
}
if (d.has("blend_shapes") && d.has("blend_shape_count")) {
surface.blend_shape_data = d["blend_shapes"];
surface.blend_shape_count = d["blend_shape_count"];
}
Ref<Material> material;
@ -982,7 +1054,7 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) {
s.aabb = surface_data[i].aabb;
if (i == 0) {
aabb = s.aabb;
blend_shapes.resize(surface_data[i].blend_shapes.size());
blend_shapes.resize(surface_data[i].blend_shape_count);
} else {
aabb.merge_with(s.aabb);
}
@ -1070,7 +1142,7 @@ void ArrayMesh::_recompute_aabb() {
#ifndef _MSC_VER
#warning need to add binding to add_surface using future MeshSurfaceData object
#endif
void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes, const Vector<AABB> &p_bone_aabb, const Vector<RS::SurfaceData::LOD> &p_lods) {
void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data, uint32_t p_blend_shape_count, const Vector<AABB> &p_bone_aabbs, const Vector<RS::SurfaceData::LOD> &p_lods) {
_create_if_empty();
Surface s;
@ -1090,10 +1162,13 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const
sd.aabb = p_aabb;
sd.vertex_count = p_vertex_count;
sd.vertex_data = p_array;
sd.attribute_data = p_attribute_array;
sd.skin_data = p_skin_array;
sd.index_count = p_index_count;
sd.index_data = p_index_array;
sd.blend_shapes = p_blend_shapes;
sd.bone_aabbs = p_bone_aabb;
sd.blend_shape_data = p_blend_shape_data;
sd.blend_shape_count = p_blend_shape_count;
sd.bone_aabbs = p_bone_aabbs;
sd.lods = p_lods;
RenderingServer::get_singleton()->mesh_add_surface(mesh, sd);
@ -1119,7 +1194,7 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &
print_line("index count: " + itos(surface.index_count));
print_line("primitive: " + itos(surface.primitive));
*/
add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shapes, surface.bone_aabbs, surface.lods);
add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.attribute_data, surface.skin_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shape_data, surface.blend_shape_count, surface.bone_aabbs, surface.lods);
}
Array ArrayMesh::surface_get_arrays(int p_surface) const {
@ -1452,29 +1527,29 @@ Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cach
SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second];
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) {
surfaces_tools.write[surface]->add_color(v.color);
surfaces_tools.write[surface]->set_color(v.color);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) {
surfaces_tools.write[surface]->add_uv(v.uv);
surfaces_tools.write[surface]->set_uv(v.uv);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) {
surfaces_tools.write[surface]->add_normal(v.normal);
surfaces_tools.write[surface]->set_normal(v.normal);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) {
Plane t;
t.normal = v.tangent;
t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1;
surfaces_tools.write[surface]->add_tangent(t);
surfaces_tools.write[surface]->set_tangent(t);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) {
surfaces_tools.write[surface]->add_bones(v.bones);
surfaces_tools.write[surface]->set_bones(v.bones);
}
if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) {
surfaces_tools.write[surface]->add_weights(v.weights);
surfaces_tools.write[surface]->set_weights(v.weights);
}
Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]);
surfaces_tools.write[surface]->add_uv2(uv2);
surfaces_tools.write[surface]->set_uv2(uv2);
surfaces_tools.write[surface]->add_vertex(v.vertex);
}
@ -1507,7 +1582,7 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode);
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode);
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(ARRAY_COMPRESS_DEFAULT));
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_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len);
@ -1546,20 +1621,53 @@ void ArrayMesh::_bind_methods() {
BIND_ENUM_CONSTANT(ARRAY_COLOR);
BIND_ENUM_CONSTANT(ARRAY_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_TEX_UV2);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM0);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM1);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM2);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_BONES);
BIND_ENUM_CONSTANT(ARRAY_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_INDEX);
BIND_ENUM_CONSTANT(ARRAY_MAX);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT);
BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM3_SHIFT);
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_MASK);
BIND_ENUM_CONSTANT(ARRAY_COMPRESS_FLAGS_BASE);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
}
void ArrayMesh::reload_from_file() {

View file

@ -61,6 +61,10 @@ public:
ARRAY_COLOR = RenderingServer::ARRAY_COLOR,
ARRAY_TEX_UV = RenderingServer::ARRAY_TEX_UV,
ARRAY_TEX_UV2 = RenderingServer::ARRAY_TEX_UV2,
ARRAY_CUSTOM0 = RenderingServer::ARRAY_CUSTOM0,
ARRAY_CUSTOM1 = RenderingServer::ARRAY_CUSTOM1,
ARRAY_CUSTOM2 = RenderingServer::ARRAY_CUSTOM2,
ARRAY_CUSTOM3 = RenderingServer::ARRAY_CUSTOM3,
ARRAY_BONES = RenderingServer::ARRAY_BONES,
ARRAY_WEIGHTS = RenderingServer::ARRAY_WEIGHTS,
ARRAY_INDEX = RenderingServer::ARRAY_INDEX,
@ -68,30 +72,47 @@ public:
};
enum ArrayCustomFormat {
ARRAY_CUSTOM_RGBA8_UNORM,
ARRAY_CUSTOM_RGBA8_SNORM,
ARRAY_CUSTOM_RG_HALF,
ARRAY_CUSTOM_RGBA_HALF,
ARRAY_CUSTOM_R_FLOAT,
ARRAY_CUSTOM_RG_FLOAT,
ARRAY_CUSTOM_RGB_FLOAT,
ARRAY_CUSTOM_RGBA_FLOAT,
ARRAY_CUSTOM_MAX
};
enum ArrayFormat {
/* ARRAY FORMAT FLAGS */
ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory
ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL,
ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT,
ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
ARRAY_FORMAT_TEX_UV = 1 << ARRAY_TEX_UV,
ARRAY_FORMAT_TEX_UV2 = 1 << ARRAY_TEX_UV2,
ARRAY_FORMAT_BONES = 1 << ARRAY_BONES,
ARRAY_FORMAT_WEIGHTS = 1 << ARRAY_WEIGHTS,
ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX,
ARRAY_FORMAT_VERTEX = RS::ARRAY_FORMAT_VERTEX,
ARRAY_FORMAT_NORMAL = RS::ARRAY_FORMAT_NORMAL,
ARRAY_FORMAT_TANGENT = RS::ARRAY_FORMAT_TANGENT,
ARRAY_FORMAT_COLOR = RS::ARRAY_FORMAT_COLOR,
ARRAY_FORMAT_TEX_UV = RS::ARRAY_FORMAT_TEX_UV,
ARRAY_FORMAT_TEX_UV2 = RS::ARRAY_FORMAT_TEX_UV2,
ARRAY_FORMAT_CUSTOM0 = RS::ARRAY_FORMAT_CUSTOM0,
ARRAY_FORMAT_CUSTOM1 = RS::ARRAY_FORMAT_CUSTOM1,
ARRAY_FORMAT_CUSTOM2 = RS::ARRAY_FORMAT_CUSTOM2,
ARRAY_FORMAT_CUSTOM3 = RS::ARRAY_FORMAT_CUSTOM3,
ARRAY_FORMAT_BONES = RS::ARRAY_FORMAT_BONES,
ARRAY_FORMAT_WEIGHTS = RS::ARRAY_FORMAT_WEIGHTS,
ARRAY_FORMAT_INDEX = RS::ARRAY_FORMAT_INDEX,
ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1),
ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE),
ARRAY_FORMAT_BLEND_SHAPE_MASK = RS::ARRAY_FORMAT_BLEND_SHAPE_MASK,
ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
ARRAY_FORMAT_CUSTOM_BASE = RS::ARRAY_FORMAT_CUSTOM_BASE,
ARRAY_FORMAT_CUSTOM0_SHIFT = RS::ARRAY_FORMAT_CUSTOM0_SHIFT,
ARRAY_FORMAT_CUSTOM1_SHIFT = RS::ARRAY_FORMAT_CUSTOM1_SHIFT,
ARRAY_FORMAT_CUSTOM2_SHIFT = RS::ARRAY_FORMAT_CUSTOM2_SHIFT,
ARRAY_FORMAT_CUSTOM3_SHIFT = RS::ARRAY_FORMAT_CUSTOM3_SHIFT,
ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2
ARRAY_FORMAT_CUSTOM_MASK = RS::ARRAY_FORMAT_CUSTOM_MASK,
ARRAY_COMPRESS_FLAGS_BASE = RS::ARRAY_COMPRESS_FLAGS_BASE,
ARRAY_FLAG_USE_2D_VERTICES = RS::ARRAY_FLAG_USE_2D_VERTICES,
ARRAY_FLAG_USE_DYNAMIC_UPDATE = RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE,
ARRAY_FLAG_USE_8_BONE_WEIGHTS = RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS,
};
@ -187,9 +208,9 @@ protected:
static void _bind_methods();
public:
void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT);
void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = 0);
void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes = Vector<Vector<uint8_t>>(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>(), const Vector<RS::SurfaceData::LOD> &p_lods = Vector<RS::SurfaceData::LOD>());
void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data = Vector<uint8_t>(), uint32_t p_blend_shape_count = 0, const Vector<AABB> &p_bone_aabbs = Vector<AABB>(), const Vector<RS::SurfaceData::LOD> &p_lods = Vector<RS::SurfaceData::LOD>());
Array surface_get_arrays(int p_surface) const override;
Array surface_get_blend_shape_arrays(int p_surface) const override;
@ -244,6 +265,7 @@ public:
VARIANT_ENUM_CAST(Mesh::ArrayType);
VARIANT_ENUM_CAST(Mesh::ArrayFormat);
VARIANT_ENUM_CAST(Mesh::ArrayCustomFormat);
VARIANT_ENUM_CAST(Mesh::PrimitiveType);
VARIANT_ENUM_CAST(Mesh::BlendShapeMode);

View file

@ -148,7 +148,7 @@ Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, 1, 0);
return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX | RS::ARRAY_COMPRESS_DEFAULT;
return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
}
Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {

View file

@ -74,6 +74,12 @@ bool SurfaceTool::Vertex::operator==(const Vertex &p_vertex) const {
}
}
for (int i = 0; i < RS::ARRAY_CUSTOM_MAX; i++) {
if (custom[i] != p_vertex.custom[i]) {
return false;
}
}
return true;
}
@ -87,6 +93,7 @@ uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) {
h = hash_djb2_buffer((const uint8_t *)&p_vtx.color, sizeof(real_t) * 4, h);
h = hash_djb2_buffer((const uint8_t *)p_vtx.bones.ptr(), p_vtx.bones.size() * sizeof(int), h);
h = hash_djb2_buffer((const uint8_t *)p_vtx.weights.ptr(), p_vtx.weights.size() * sizeof(float), h);
h = hash_djb2_buffer((const uint8_t *)&p_vtx.custom[0], sizeof(Color) * RS::ARRAY_CUSTOM_COUNT, h);
return h;
}
@ -111,8 +118,11 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
vtx.bones = last_bones;
vtx.tangent = last_tangent.normal;
vtx.binormal = last_normal.cross(last_tangent.normal).normalized() * last_tangent.d;
for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
vtx.custom[i] = last_custom[i];
}
const int expected_vertices = 4;
const int expected_vertices = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
if ((format & Mesh::ARRAY_FORMAT_WEIGHTS || format & Mesh::ARRAY_FORMAT_BONES) && (vtx.weights.size() != expected_vertices || vtx.bones.size() != expected_vertices)) {
//ensure vertices are the expected amount
@ -163,7 +173,7 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
format |= Mesh::ARRAY_FORMAT_VERTEX;
}
void SurfaceTool::add_color(Color p_color) {
void SurfaceTool::set_color(Color p_color) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_COLOR));
@ -172,7 +182,7 @@ void SurfaceTool::add_color(Color p_color) {
last_color = p_color;
}
void SurfaceTool::add_normal(const Vector3 &p_normal) {
void SurfaceTool::set_normal(const Vector3 &p_normal) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_NORMAL));
@ -181,7 +191,7 @@ void SurfaceTool::add_normal(const Vector3 &p_normal) {
last_normal = p_normal;
}
void SurfaceTool::add_tangent(const Plane &p_tangent) {
void SurfaceTool::set_tangent(const Plane &p_tangent) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TANGENT));
@ -189,7 +199,7 @@ void SurfaceTool::add_tangent(const Plane &p_tangent) {
last_tangent = p_tangent;
}
void SurfaceTool::add_uv(const Vector2 &p_uv) {
void SurfaceTool::set_uv(const Vector2 &p_uv) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV));
@ -197,7 +207,7 @@ void SurfaceTool::add_uv(const Vector2 &p_uv) {
last_uv = p_uv;
}
void SurfaceTool::add_uv2(const Vector2 &p_uv2) {
void SurfaceTool::set_uv2(const Vector2 &p_uv2) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV2));
@ -205,19 +215,40 @@ void SurfaceTool::add_uv2(const Vector2 &p_uv2) {
last_uv2 = p_uv2;
}
void SurfaceTool::add_bones(const Vector<int> &p_bones) {
void SurfaceTool::set_custom(int p_index, const Color &p_custom) {
ERR_FAIL_INDEX(p_index, RS::ARRAY_CUSTOM_COUNT);
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(last_custom_format[p_index] == CUSTOM_MAX);
static const uint32_t mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 };
static const uint32_t shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT };
ERR_FAIL_COND(!first && !(format & mask[p_index]));
if (first) {
format |= mask[p_index];
format |= last_custom_format[p_index] << shift[p_index];
}
last_custom[p_index] = p_custom;
}
void SurfaceTool::set_bones(const Vector<int> &p_bones) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_BONES));
format |= Mesh::ARRAY_FORMAT_BONES;
if (skin_weights == SKIN_8_WEIGHTS) {
format |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
}
last_bones = p_bones;
}
void SurfaceTool::add_weights(const Vector<float> &p_weights) {
void SurfaceTool::set_weights(const Vector<float> &p_weights) {
ERR_FAIL_COND(!begun);
ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_WEIGHTS));
format |= Mesh::ARRAY_FORMAT_WEIGHTS;
if (skin_weights == SKIN_8_WEIGHTS) {
format |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
}
last_weights = p_weights;
}
@ -238,15 +269,15 @@ void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertices, const Vect
#define ADD_POINT(n) \
{ \
if (p_colors.size() > n) \
add_color(p_colors[n]); \
set_color(p_colors[n]); \
if (p_uvs.size() > n) \
add_uv(p_uvs[n]); \
set_uv(p_uvs[n]); \
if (p_uv2s.size() > n) \
add_uv2(p_uv2s[n]); \
set_uv2(p_uv2s[n]); \
if (p_normals.size() > n) \
add_normal(p_normals[n]); \
set_normal(p_normals[n]); \
if (p_tangents.size() > n) \
add_tangent(p_tangents[n]); \
set_tangent(p_tangents[n]); \
add_vertex(p_vertices[n]); \
}
@ -358,18 +389,157 @@ Array SurfaceTool::commit_to_arrays() {
a[i] = array;
} break;
case Mesh::ARRAY_CUSTOM0:
case Mesh::ARRAY_CUSTOM1:
case Mesh::ARRAY_CUSTOM2:
case Mesh::ARRAY_CUSTOM3: {
int fmt = i - Mesh::ARRAY_CUSTOM0;
switch (last_custom_format[fmt]) {
case CUSTOM_RGBA8_UNORM: {
Vector<uint8_t> array;
array.resize(varr_len * 4);
uint8_t *w = array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 4 + 0] = CLAMP(int32_t(c.r * 255.0), 0, 255);
w[idx * 4 + 1] = CLAMP(int32_t(c.g * 255.0), 0, 255);
w[idx * 4 + 2] = CLAMP(int32_t(c.b * 255.0), 0, 255);
w[idx * 4 + 3] = CLAMP(int32_t(c.a * 255.0), 0, 255);
}
a[i] = array;
} break;
case CUSTOM_RGBA8_SNORM: {
Vector<uint8_t> array;
array.resize(varr_len * 4);
uint8_t *w = array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 4 + 0] = uint8_t(int8_t(CLAMP(int32_t(c.r * 127.0), -128, 127)));
w[idx * 4 + 1] = uint8_t(int8_t(CLAMP(int32_t(c.g * 127.0), -128, 127)));
w[idx * 4 + 2] = uint8_t(int8_t(CLAMP(int32_t(c.b * 127.0), -128, 127)));
w[idx * 4 + 3] = uint8_t(int8_t(CLAMP(int32_t(c.a * 127.0), -128, 127)));
}
a[i] = array;
} break;
case CUSTOM_RG_HALF: {
Vector<uint8_t> array;
array.resize(varr_len * 4);
uint16_t *w = (uint16_t *)array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 2 + 0] = Math::make_half_float(c.r);
w[idx * 2 + 1] = Math::make_half_float(c.g);
}
a[i] = array;
} break;
case CUSTOM_RGBA_HALF: {
Vector<uint8_t> array;
array.resize(varr_len * 8);
uint16_t *w = (uint16_t *)array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 4 + 0] = Math::make_half_float(c.r);
w[idx * 4 + 1] = Math::make_half_float(c.g);
w[idx * 4 + 2] = Math::make_half_float(c.b);
w[idx * 4 + 3] = Math::make_half_float(c.a);
}
a[i] = array;
} break;
case CUSTOM_R_FLOAT: {
Vector<float> array;
array.resize(varr_len);
float *w = (float *)array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx] = c.r;
}
a[i] = array;
} break;
case CUSTOM_RG_FLOAT: {
Vector<float> array;
array.resize(varr_len * 2);
float *w = (float *)array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 2 + 0] = c.r;
w[idx * 2 + 1] = c.g;
}
a[i] = array;
} break;
case CUSTOM_RGB_FLOAT: {
Vector<float> array;
array.resize(varr_len * 3);
float *w = (float *)array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 3 + 0] = c.r;
w[idx * 3 + 1] = c.g;
w[idx * 3 + 2] = c.b;
}
a[i] = array;
} break;
case CUSTOM_RGBA_FLOAT: {
Vector<float> array;
array.resize(varr_len * 4);
float *w = (float *)array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) {
const Vertex &v = E->get();
const Color &c = v.custom[idx];
w[idx * 4 + 0] = c.r;
w[idx * 4 + 1] = c.g;
w[idx * 4 + 2] = c.b;
w[idx * 4 + 3] = c.a;
}
a[i] = array;
} break;
default: {
} //unreachable but compiler warning anyway
}
} break;
case Mesh::ARRAY_BONES: {
int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
Vector<int> array;
array.resize(varr_len * 4);
array.resize(varr_len * count);
int *w = array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) {
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += count) {
const Vertex &v = E->get();
ERR_CONTINUE(v.bones.size() != 4);
ERR_CONTINUE(v.bones.size() != count);
for (int j = 0; j < 4; j++) {
for (int j = 0; j < count; j++) {
w[idx + j] = v.bones[j];
}
}
@ -379,15 +549,17 @@ Array SurfaceTool::commit_to_arrays() {
} break;
case Mesh::ARRAY_WEIGHTS: {
Vector<float> array;
array.resize(varr_len * 4);
int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
array.resize(varr_len * count);
float *w = array.ptrw();
int idx = 0;
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) {
for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += count) {
const Vertex &v = E->get();
ERR_CONTINUE(v.weights.size() != 4);
ERR_CONTINUE(v.weights.size() != count);
for (int j = 0; j < 4; j++) {
for (int j = 0; j < count; j++) {
w[idx + j] = v.weights[j];
}
}
@ -492,13 +664,13 @@ void SurfaceTool::deindex() {
index_array.clear();
}
void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {
void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat) {
Array arr = p_existing->surface_get_arrays(p_surface);
ERR_FAIL_COND(arr.size() != RS::ARRAY_MAX);
_create_list_from_arrays(arr, r_vertex, r_index, lformat);
}
Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) {
Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, uint32_t *r_format) {
Vector<SurfaceTool::Vertex> ret;
Vector<Vector3> varr = p_arrays[RS::ARRAY_VERTEX];
@ -509,9 +681,13 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array
Vector<Vector2> uv2arr = p_arrays[RS::ARRAY_TEX_UV2];
Vector<int> barr = p_arrays[RS::ARRAY_BONES];
Vector<float> warr = p_arrays[RS::ARRAY_WEIGHTS];
Vector<float> custom_float[RS::ARRAY_CUSTOM_COUNT];
int vc = varr.size();
if (vc == 0) {
if (r_format) {
*r_format = 0;
}
return ret;
}
@ -534,12 +710,40 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array
if (uv2arr.size()) {
lformat |= RS::ARRAY_FORMAT_TEX_UV2;
}
if (barr.size()) {
int wcount = 0;
if (barr.size() && warr.size()) {
lformat |= RS::ARRAY_FORMAT_BONES;
lformat |= RS::ARRAY_FORMAT_WEIGHTS;
wcount = barr.size() / varr.size();
if (wcount == 8) {
lformat |= RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
}
}
if (warr.size()) {
lformat |= RS::ARRAY_FORMAT_WEIGHTS;
}
static const uint32_t custom_mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 };
static const uint32_t custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT };
for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
ERR_CONTINUE_MSG(p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_BYTE_ARRAY, "Extracting Byte/Half formats is not supported");
if (p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_FLOAT32_ARRAY) {
lformat |= custom_mask[i];
custom_float[i] = p_arrays[RS::ARRAY_CUSTOM0 + i];
int fmt = custom_float[i].size() / varr.size();
if (fmt == 1) {
lformat |= CUSTOM_R_FLOAT << custom_shift[i];
} else if (fmt == 2) {
lformat |= CUSTOM_RG_FLOAT << custom_shift[i];
} else if (fmt == 3) {
lformat |= CUSTOM_RGB_FLOAT << custom_shift[i];
} else if (fmt == 4) {
lformat |= CUSTOM_RGBA_FLOAT << custom_shift[i];
}
}
}
for (int i = 0; i < vc; i++) {
Vertex v;
@ -565,112 +769,46 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array
}
if (lformat & RS::ARRAY_FORMAT_BONES) {
Vector<int> b;
b.resize(4);
b.write[0] = barr[i * 4 + 0];
b.write[1] = barr[i * 4 + 1];
b.write[2] = barr[i * 4 + 2];
b.write[3] = barr[i * 4 + 3];
b.resize(wcount);
for (int j = 0; j < wcount; j++) {
b.write[j] = barr[i * wcount + j];
}
v.bones = b;
}
if (lformat & RS::ARRAY_FORMAT_WEIGHTS) {
Vector<float> w;
w.resize(4);
w.write[0] = warr[i * 4 + 0];
w.write[1] = warr[i * 4 + 1];
w.write[2] = warr[i * 4 + 2];
w.write[3] = warr[i * 4 + 3];
w.resize(wcount);
for (int j = 0; j < wcount; j++) {
w.write[j] = warr[i * wcount + j];
}
v.weights = w;
}
for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
if (lformat & custom_mask[j]) {
int cc = custom_float[j].size() / varr.size();
for (int k = 0; k < cc; k++) {
v.custom[j][k] = custom_float[j][i * cc + k];
}
}
}
ret.push_back(v);
}
if (r_format) {
*r_format = lformat;
}
return ret;
}
void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) {
Vector<Vector3> varr = arr[RS::ARRAY_VERTEX];
Vector<Vector3> narr = arr[RS::ARRAY_NORMAL];
Vector<float> tarr = arr[RS::ARRAY_TANGENT];
Vector<Color> carr = arr[RS::ARRAY_COLOR];
Vector<Vector2> uvarr = arr[RS::ARRAY_TEX_UV];
Vector<Vector2> uv2arr = arr[RS::ARRAY_TEX_UV2];
Vector<int> barr = arr[RS::ARRAY_BONES];
Vector<float> warr = arr[RS::ARRAY_WEIGHTS];
void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat) {
Vector<Vertex> arrays = create_vertex_array_from_triangle_arrays(arr, &lformat);
ERR_FAIL_COND(arrays.size() == 0);
int vc = varr.size();
if (vc == 0) {
return;
}
lformat = 0;
if (varr.size()) {
lformat |= RS::ARRAY_FORMAT_VERTEX;
}
if (narr.size()) {
lformat |= RS::ARRAY_FORMAT_NORMAL;
}
if (tarr.size()) {
lformat |= RS::ARRAY_FORMAT_TANGENT;
}
if (carr.size()) {
lformat |= RS::ARRAY_FORMAT_COLOR;
}
if (uvarr.size()) {
lformat |= RS::ARRAY_FORMAT_TEX_UV;
}
if (uv2arr.size()) {
lformat |= RS::ARRAY_FORMAT_TEX_UV2;
}
if (barr.size()) {
lformat |= RS::ARRAY_FORMAT_BONES;
}
if (warr.size()) {
lformat |= RS::ARRAY_FORMAT_WEIGHTS;
}
for (int i = 0; i < vc; i++) {
Vertex v;
if (lformat & RS::ARRAY_FORMAT_VERTEX) {
v.vertex = varr[i];
}
if (lformat & RS::ARRAY_FORMAT_NORMAL) {
v.normal = narr[i];
}
if (lformat & RS::ARRAY_FORMAT_TANGENT) {
Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
v.tangent = p.normal;
v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
}
if (lformat & RS::ARRAY_FORMAT_COLOR) {
v.color = carr[i];
}
if (lformat & RS::ARRAY_FORMAT_TEX_UV) {
v.uv = uvarr[i];
}
if (lformat & RS::ARRAY_FORMAT_TEX_UV2) {
v.uv2 = uv2arr[i];
}
if (lformat & RS::ARRAY_FORMAT_BONES) {
Vector<int> b;
b.resize(4);
b.write[0] = barr[i * 4 + 0];
b.write[1] = barr[i * 4 + 1];
b.write[2] = barr[i * 4 + 2];
b.write[3] = barr[i * 4 + 3];
v.bones = b;
}
if (lformat & RS::ARRAY_FORMAT_WEIGHTS) {
Vector<float> w;
w.resize(4);
w.write[0] = warr[i * 4 + 0];
w.write[1] = warr[i * 4 + 1];
w.write[2] = warr[i * 4 + 2];
w.write[3] = warr[i * 4 + 3];
v.weights = w;
}
r_vertex->push_back(v);
for (int i = 0; i < arrays.size(); i++) {
r_vertex->push_back(arrays[i]);
}
//indices
@ -725,7 +863,7 @@ void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const
format = 0;
}
int nformat;
uint32_t nformat;
List<Vertex> nvertices;
List<int> nindices;
_create_list(p_existing, p_surface, &nvertices, &nindices, nformat);
@ -975,19 +1113,48 @@ void SurfaceTool::clear() {
vertex_array.clear();
smooth_groups.clear();
material.unref();
for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
last_custom_format[i] = CUSTOM_MAX;
}
skin_weights = SKIN_4_WEIGHTS;
}
void SurfaceTool::set_skin_weight_count(SkinWeightCount p_weights) {
ERR_FAIL_COND(begun);
skin_weights = p_weights;
}
SurfaceTool::SkinWeightCount SurfaceTool::get_skin_weight_count() const {
return skin_weights;
}
void SurfaceTool::set_custom_format(int p_index, CustomFormat p_format) {
ERR_FAIL_INDEX(p_index, RS::ARRAY_CUSTOM_COUNT);
ERR_FAIL_COND(begun);
last_custom_format[p_index] = p_format;
}
SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_index) const {
ERR_FAIL_INDEX_V(p_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX);
return last_custom_format[p_index];
}
void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_skin_weight_count", "count"), &SurfaceTool::set_skin_weight_count);
ClassDB::bind_method(D_METHOD("get_skin_weight_count"), &SurfaceTool::get_skin_weight_count);
ClassDB::bind_method(D_METHOD("set_custom_format", "index", "format"), &SurfaceTool::set_custom_format);
ClassDB::bind_method(D_METHOD("get_custom_format", "index"), &SurfaceTool::get_custom_format);
ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin);
ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex);
ClassDB::bind_method(D_METHOD("add_color", "color"), &SurfaceTool::add_color);
ClassDB::bind_method(D_METHOD("add_normal", "normal"), &SurfaceTool::add_normal);
ClassDB::bind_method(D_METHOD("add_tangent", "tangent"), &SurfaceTool::add_tangent);
ClassDB::bind_method(D_METHOD("add_uv", "uv"), &SurfaceTool::add_uv);
ClassDB::bind_method(D_METHOD("add_uv2", "uv2"), &SurfaceTool::add_uv2);
ClassDB::bind_method(D_METHOD("add_bones", "bones"), &SurfaceTool::add_bones);
ClassDB::bind_method(D_METHOD("add_weights", "weights"), &SurfaceTool::add_weights);
ClassDB::bind_method(D_METHOD("set_color", "color"), &SurfaceTool::set_color);
ClassDB::bind_method(D_METHOD("set_normal", "normal"), &SurfaceTool::set_normal);
ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &SurfaceTool::set_tangent);
ClassDB::bind_method(D_METHOD("set_uv", "uv"), &SurfaceTool::set_uv);
ClassDB::bind_method(D_METHOD("set_uv2", "uv2"), &SurfaceTool::set_uv2);
ClassDB::bind_method(D_METHOD("set_bones", "bones"), &SurfaceTool::set_bones);
ClassDB::bind_method(D_METHOD("set_weights", "weights"), &SurfaceTool::set_weights);
ClassDB::bind_method(D_METHOD("set_custom", "index", "custom"), &SurfaceTool::set_custom);
ClassDB::bind_method(D_METHOD("add_smooth_group", "smooth"), &SurfaceTool::add_smooth_group);
ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertices", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>()));
@ -1006,13 +1173,29 @@ void SurfaceTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from);
ClassDB::bind_method(D_METHOD("create_from_blend_shape", "existing", "surface", "blend_shape"), &SurfaceTool::create_from_blend_shape);
ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from);
ClassDB::bind_method(D_METHOD("commit", "existing", "flags"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(Mesh::ARRAY_COMPRESS_DEFAULT));
ClassDB::bind_method(D_METHOD("commit", "existing", "flags"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(0));
ClassDB::bind_method(D_METHOD("commit_to_arrays"), &SurfaceTool::commit_to_arrays);
BIND_ENUM_CONSTANT(CUSTOM_RGBA8_UNORM);
BIND_ENUM_CONSTANT(CUSTOM_RGBA8_SNORM);
BIND_ENUM_CONSTANT(CUSTOM_RG_HALF);
BIND_ENUM_CONSTANT(CUSTOM_RGBA_HALF);
BIND_ENUM_CONSTANT(CUSTOM_R_FLOAT);
BIND_ENUM_CONSTANT(CUSTOM_RG_FLOAT);
BIND_ENUM_CONSTANT(CUSTOM_RGB_FLOAT);
BIND_ENUM_CONSTANT(CUSTOM_RGBA_FLOAT);
BIND_ENUM_CONSTANT(CUSTOM_MAX);
BIND_ENUM_CONSTANT(SKIN_4_WEIGHTS);
BIND_ENUM_CONSTANT(SKIN_8_WEIGHTS);
}
SurfaceTool::SurfaceTool() {
first = false;
begun = false;
for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
last_custom_format[i] = CUSTOM_MAX;
}
primitive = Mesh::PRIMITIVE_LINES;
skin_weights = SKIN_4_WEIGHTS;
format = 0;
}

View file

@ -49,12 +49,30 @@ public:
Vector2 uv2;
Vector<int> bones;
Vector<float> weights;
Color custom[RS::ARRAY_CUSTOM_COUNT];
bool operator==(const Vertex &p_vertex) const;
Vertex() {}
};
enum CustomFormat {
CUSTOM_RGBA8_UNORM = RS::ARRAY_CUSTOM_RGBA8_UNORM,
CUSTOM_RGBA8_SNORM = RS::ARRAY_CUSTOM_RGBA8_SNORM,
CUSTOM_RG_HALF = RS::ARRAY_CUSTOM_RG_HALF,
CUSTOM_RGBA_HALF = RS::ARRAY_CUSTOM_RGBA_HALF,
CUSTOM_R_FLOAT = RS::ARRAY_CUSTOM_R_FLOAT,
CUSTOM_RG_FLOAT = RS::ARRAY_CUSTOM_RG_FLOAT,
CUSTOM_RGB_FLOAT = RS::ARRAY_CUSTOM_RGB_FLOAT,
CUSTOM_RGBA_FLOAT = RS::ARRAY_CUSTOM_RGBA_FLOAT,
CUSTOM_MAX = RS::ARRAY_CUSTOM_MAX
};
enum SkinWeightCount {
SKIN_4_WEIGHTS,
SKIN_8_WEIGHTS
};
private:
struct VertexHasher {
static _FORCE_INLINE_ uint32_t hash(const Vertex &p_vtx);
@ -71,7 +89,7 @@ private:
bool begun;
bool first;
Mesh::PrimitiveType primitive;
int format;
uint32_t format;
Ref<Material> material;
//arrays
List<Vertex> vertex_array;
@ -87,8 +105,14 @@ private:
Vector<float> last_weights;
Plane last_tangent;
void _create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat);
void _create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat);
SkinWeightCount skin_weights;
Color last_custom[RS::ARRAY_CUSTOM_COUNT];
CustomFormat last_custom_format[RS::ARRAY_CUSTOM_COUNT];
void _create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat);
void _create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, uint32_t &lformat);
//mikktspace callbacks
static int mikktGetNumFaces(const SMikkTSpaceContext *pContext);
@ -103,18 +127,26 @@ protected:
static void _bind_methods();
public:
void set_skin_weight_count(SkinWeightCount p_weights);
SkinWeightCount get_skin_weight_count() const;
void set_custom_format(int p_index, CustomFormat p_format);
CustomFormat get_custom_format(int p_index) const;
void begin(Mesh::PrimitiveType p_primitive);
void add_vertex(const Vector3 &p_vertex);
void add_color(Color p_color);
void add_normal(const Vector3 &p_normal);
void add_tangent(const Plane &p_tangent);
void add_uv(const Vector2 &p_uv);
void add_uv2(const Vector2 &p_uv2);
void add_bones(const Vector<int> &p_bones);
void add_weights(const Vector<float> &p_weights);
void add_smooth_group(bool p_smooth);
void set_color(Color p_color);
void set_normal(const Vector3 &p_normal);
void set_tangent(const Plane &p_tangent);
void set_uv(const Vector2 &p_uv);
void set_uv2(const Vector2 &p_uv2);
void set_custom(int p_index, const Color &p_custom);
void set_bones(const Vector<int> &p_bones);
void set_weights(const Vector<float> &p_weights);
void add_vertex(const Vector3 &p_vertex);
void add_smooth_group(bool p_smooth);
void add_triangle_fan(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs = Vector<Vector2>(), const Vector<Color> &p_colors = Vector<Color>(), const Vector<Vector2> &p_uv2s = Vector<Vector2>(), const Vector<Vector3> &p_normals = Vector<Vector3>(), const Vector<Plane> &p_tangents = Vector<Plane>());
void add_index(int p_index);
@ -131,14 +163,17 @@ public:
List<Vertex> &get_vertex_array() { return vertex_array; }
void create_from_triangle_arrays(const Array &p_arrays);
static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays);
static Vector<Vertex> create_vertex_array_from_triangle_arrays(const Array &p_arrays, uint32_t *r_format = nullptr);
Array commit_to_arrays();
void create_from(const Ref<Mesh> &p_existing, int p_surface);
void create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name);
void append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform);
Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = Mesh::ARRAY_COMPRESS_DEFAULT);
Ref<ArrayMesh> commit(const Ref<ArrayMesh> &p_existing = Ref<ArrayMesh>(), uint32_t p_flags = 0);
SurfaceTool();
};
VARIANT_ENUM_CAST(SurfaceTool::CustomFormat)
VARIANT_ENUM_CAST(SurfaceTool::SkinWeightCount)
#endif

View file

@ -119,9 +119,9 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
Vector<uint8_t> polygon_buffer;
polygon_buffer.resize(buffer_size * sizeof(float));
Vector<RD::VertexAttribute> descriptions;
descriptions.resize(4);
descriptions.resize(5);
Vector<RID> buffers;
buffers.resize(4);
buffers.resize(5);
{
const uint8_t *r = polygon_buffer.ptr();
@ -218,7 +218,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
//bones
if ((uint32_t)p_indices.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) {
RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_BONES;
vd.stride = stride * sizeof(float);
@ -226,24 +226,17 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
descriptions.write[3] = vd;
const int *bone_ptr = p_bones.ptr();
const float *weight_ptr = p_weights.ptr();
for (uint32_t i = 0; i < vertex_count; i++) {
uint16_t *bone16w = (uint16_t *)&uptr[base_offset + i * stride];
uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride + 2];
bone16w[0] = bone_ptr[i * 4 + 0];
bone16w[1] = bone_ptr[i * 4 + 1];
bone16w[2] = bone_ptr[i * 4 + 2];
bone16w[3] = bone_ptr[i * 4 + 3];
weight16w[0] = CLAMP(weight_ptr[i * 4 + 0] * 65535, 0, 65535);
weight16w[1] = CLAMP(weight_ptr[i * 4 + 1] * 65535, 0, 65535);
weight16w[2] = CLAMP(weight_ptr[i * 4 + 2] * 65535, 0, 65535);
weight16w[3] = CLAMP(weight_ptr[i * 4 + 3] * 65535, 0, 65535);
}
base_offset += 4;
base_offset += 2;
} else {
RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
@ -255,6 +248,39 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int
buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES);
}
//weights
if ((uint32_t)p_weights.size() == vertex_count * 4) {
RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
vd.offset = base_offset * sizeof(float);
vd.location = RS::ARRAY_WEIGHTS;
vd.stride = stride * sizeof(float);
descriptions.write[4] = vd;
const float *weight_ptr = p_weights.ptr();
for (uint32_t i = 0; i < vertex_count; i++) {
uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride];
weight16w[0] = CLAMP(weight_ptr[i * 4 + 0] * 65535, 0, 65535);
weight16w[1] = CLAMP(weight_ptr[i * 4 + 1] * 65535, 0, 65535);
weight16w[2] = CLAMP(weight_ptr[i * 4 + 2] * 65535, 0, 65535);
weight16w[3] = CLAMP(weight_ptr[i * 4 + 3] * 65535, 0, 65535);
}
base_offset += 2;
} else {
RD::VertexAttribute vd;
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
vd.offset = 0;
vd.location = RS::ARRAY_WEIGHTS;
vd.stride = 0;
descriptions.write[4] = vd;
buffers.write[4] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES);
}
//check that everything is as it should be
ERR_FAIL_COND_V(base_offset != stride, 0); //bug
}
@ -1796,22 +1822,25 @@ void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector
ERR_FAIL_COND(!oc);
Vector<Vector2> lines;
int lc = p_points.size() * 2;
lines.resize(lc - (p_closed ? 0 : 2));
{
Vector2 *w = lines.ptrw();
const Vector2 *r = p_points.ptr();
if (p_points.size()) {
int lc = p_points.size() * 2;
int max = lc / 2;
if (!p_closed) {
max--;
}
for (int i = 0; i < max; i++) {
Vector2 a = r[i];
Vector2 b = r[(i + 1) % (lc / 2)];
w[i * 2 + 0] = a;
w[i * 2 + 1] = b;
lines.resize(lc - (p_closed ? 0 : 2));
{
Vector2 *w = lines.ptrw();
const Vector2 *r = p_points.ptr();
int max = lc / 2;
if (!p_closed) {
max--;
}
for (int i = 0; i < max; i++) {
Vector2 a = r[i];
Vector2 b = r[(i + 1) % (lc / 2)];
w[i * 2 + 0] = a;
w[i * 2 + 1] = b;
}
}
}
@ -1832,7 +1861,7 @@ void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector
if (lines.size()) {
Vector<uint8_t> geometry;
Vector<uint8_t> indices;
lc = lines.size();
int lc = lines.size();
geometry.resize(lc * 6 * sizeof(float));
indices.resize(lc * 3 * sizeof(uint16_t));
@ -1902,19 +1931,21 @@ void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector
Vector<int> sdf_indices;
if (p_closed) {
sdf_indices = Geometry2D::triangulate_polygon(p_points);
oc->sdf_is_lines = false;
} else {
int max = p_points.size();
sdf_indices.resize(max * 2);
if (p_points.size()) {
if (p_closed) {
sdf_indices = Geometry2D::triangulate_polygon(p_points);
oc->sdf_is_lines = false;
} else {
int max = p_points.size();
sdf_indices.resize(max * 2);
int *iw = sdf_indices.ptrw();
for (int i = 0; i < max; i++) {
iw[i * 2 + 0] = i;
iw[i * 2 + 1] = (i + 1) % max;
int *iw = sdf_indices.ptrw();
for (int i = 0; i < max; i++) {
iw[i * 2 + 0] = i;
iw[i * 2 + 1] = (i + 1) % max;
}
oc->sdf_is_lines = true;
}
oc->sdf_is_lines = true;
}
if (oc->sdf_index_count != sdf_indices.size() && oc->sdf_point_count != p_points.size() && oc->sdf_vertex_array.is_valid()) {

View file

@ -2795,6 +2795,12 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.renames["FOG"] = "custom_fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
actions.renames["BONE_WEIGHTS"] = "weight_attrib";
actions.renames["CUSTOM0"] = "custom0_attrib";
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
//for light
actions.renames["VIEW"] = "view";
@ -2817,6 +2823,12 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag
actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n";
actions.usage_defines["UV"] = "#define UV_USED\n";
actions.usage_defines["UV2"] = "#define UV2_USED\n";
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";
actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n";
actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n";
actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n";
actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n";
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n";
actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";

View file

@ -5336,18 +5336,19 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
tonemap.exposure = env->exposure;
}
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
if (can_use_effects && env) {
tonemap.use_bcs = env->adjustments_enabled;
tonemap.brightness = env->adjustments_brightness;
tonemap.contrast = env->adjustments_contrast;
tonemap.saturation = env->adjustments_saturation;
tonemap.use_1d_color_correction = env->use_1d_color_correction;
if (env->adjustments_enabled && env->color_correction.is_valid()) {
tonemap.use_color_correction = true;
tonemap.use_1d_color_correction = env->use_1d_color_correction;
tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction);
} else {
tonemap.use_color_correction = false;
tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE);
}
}

View file

@ -2398,13 +2398,15 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
ERR_FAIL_COND(!mesh);
//ensure blend shape consistency
ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shapes.size() != (int)mesh->blend_shape_count);
ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shape_count != mesh->blend_shape_count);
ERR_FAIL_COND(mesh->blend_shape_count && p_surface.bone_aabbs.size() != mesh->bone_aabbs.size());
#ifdef DEBUG_ENABLED
//do a validation, to catch errors first
{
uint32_t stride = 0;
uint32_t attrib_stride = 0;
uint32_t skin_stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
if ((p_surface.format & (1 << i))) {
@ -2418,59 +2420,54 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
} break;
case RS::ARRAY_NORMAL: {
if (p_surface.format & RS::ARRAY_COMPRESS_NORMAL) {
stride += sizeof(int8_t) * 4;
} else {
stride += sizeof(float) * 4;
}
stride += sizeof(int32_t);
} break;
case RS::ARRAY_TANGENT: {
if (p_surface.format & RS::ARRAY_COMPRESS_TANGENT) {
stride += sizeof(int8_t) * 4;
} else {
stride += sizeof(float) * 4;
}
stride += sizeof(int32_t);
} break;
case RS::ARRAY_COLOR: {
if (p_surface.format & RS::ARRAY_COMPRESS_COLOR) {
stride += sizeof(int8_t) * 4;
} else {
stride += sizeof(float) * 4;
}
attrib_stride += sizeof(int16_t) * 4;
} break;
case RS::ARRAY_TEX_UV: {
if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV) {
stride += sizeof(int16_t) * 2;
} else {
stride += sizeof(float) * 2;
}
attrib_stride += sizeof(float) * 2;
} break;
case RS::ARRAY_TEX_UV2: {
if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV2) {
stride += sizeof(int16_t) * 2;
} else {
stride += sizeof(float) * 2;
}
attrib_stride += sizeof(float) * 2;
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
case RS::ARRAY_CUSTOM2:
case RS::ARRAY_CUSTOM3: {
int idx = i - RS::ARRAY_CUSTOM0;
uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
attrib_stride += fmtsize[fmt];
} break;
case RS::ARRAY_WEIGHTS:
case RS::ARRAY_BONES: {
//assumed weights too
//unique format, internally 16 bits, exposed as single array for 32
stride += sizeof(int32_t) * 4;
//uses a separate array
bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
skin_stride += sizeof(int16_t) * (use_8 ? 8 : 4);
} break;
}
}
}
int expected_size = stride * p_surface.vertex_count;
ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
int expected_attrib_size = attrib_stride * p_surface.vertex_count;
ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")");
if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) {
expected_size = skin_stride * p_surface.vertex_count;
ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
}
}
#endif
@ -2481,6 +2478,12 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
s->primitive = p_surface.primitive;
s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data);
if (p_surface.attribute_data.size()) {
s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
}
if (p_surface.skin_data.size()) {
s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data);
}
s->vertex_count = p_surface.vertex_count;
if (p_surface.index_count) {
@ -2504,7 +2507,7 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
#if 0
for (int i = 0; i < p_surface.blend_shapes.size(); i++) {
if (p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()) {
memdelete(s);
@ -2513,8 +2516,8 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_
RID vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.blend_shapes[i].size(), p_surface.blend_shapes[i]);
s->blend_shapes.push_back(vertex_buffer);
}
mesh->blend_shape_count = p_surface.blend_shapes.size();
#endif
mesh->blend_shape_count = p_surface.blend_shape_count;
if (mesh->surface_count == 0) {
mesh->bone_aabbs = p_surface.bone_aabbs;
@ -2596,6 +2599,12 @@ RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface)
RS::SurfaceData sd;
sd.format = s.format;
sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
if (s.attribute_buffer.is_valid()) {
sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
}
if (s.skin_buffer.is_valid()) {
sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer);
}
sd.vertex_count = s.vertex_count;
sd.index_count = s.index_count;
sd.primitive = s.primitive;
@ -2613,9 +2622,8 @@ RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface)
sd.bone_aabbs = s.bone_aabbs;
for (int i = 0; i < s.blend_shapes.size(); i++) {
Vector<uint8_t> bs = RD::get_singleton()->buffer_get_data(s.blend_shapes[i]);
sd.blend_shapes.push_back(bs);
if (s.blend_shape_buffer.is_valid()) {
sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
}
return sd;
@ -2750,6 +2758,12 @@ void RasterizerStorageRD::mesh_clear(RID p_mesh) {
for (uint32_t i = 0; i < mesh->surface_count; i++) {
Mesh::Surface &s = *mesh->surfaces[i];
RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
if (s.attribute_buffer.is_valid()) {
RD::get_singleton()->free(s.attribute_buffer);
}
if (s.skin_buffer.is_valid()) {
RD::get_singleton()->free(s.skin_buffer);
}
if (s.versions) {
memfree(s.versions); //reallocs, so free with memfree.
}
@ -2765,12 +2779,8 @@ void RasterizerStorageRD::mesh_clear(RID p_mesh) {
memdelete_arr(s.lods);
}
for (int32_t j = 0; j < s.blend_shapes.size(); j++) {
RD::get_singleton()->free(s.blend_shapes[j]);
}
if (s.blend_shape_base_buffer.is_valid()) {
RD::get_singleton()->free(s.blend_shape_base_buffer);
if (s.blend_shape_buffer.is_valid()) {
RD::get_singleton()->free(s.blend_shape_buffer);
}
memdelete(mesh->surfaces[i]);
@ -2796,8 +2806,10 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
Vector<RID> buffers;
uint32_t stride = 0;
uint32_t attribute_stride = 0;
uint32_t skin_stride = 0;
for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
for (int i = 0; i < RS::ARRAY_INDEX; i++) {
RD::VertexAttribute vd;
RID buffer;
vd.location = i;
@ -2805,6 +2817,7 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
if (!(s->format & (1 << i))) {
// Not supplied by surface, use default value
buffer = mesh_default_rd_buffers[i];
vd.stride = 0;
switch (i) {
case RS::ARRAY_VERTEX: {
vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
@ -2827,20 +2840,31 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
case RS::ARRAY_TEX_UV2: {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
case RS::ARRAY_CUSTOM2:
case RS::ARRAY_CUSTOM3: {
//assumed weights too
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
} break;
case RS::ARRAY_BONES: {
//assumed weights too
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
} break;
case RS::ARRAY_WEIGHTS: {
//assumed weights too
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
} break;
}
} else {
//Supplied, use it
vd.offset = stride;
vd.stride = 1; //mark that it needs a stride set
buffer = s->vertex_buffer;
vd.stride = 1; //mark that it needs a stride set (default uses 0)
switch (i) {
case RS::ARRAY_VERTEX: {
vd.offset = stride;
if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
stride += sizeof(float) * 2;
@ -2849,71 +2873,80 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
stride += sizeof(float) * 3;
}
buffer = s->vertex_buffer;
} break;
case RS::ARRAY_NORMAL: {
if (s->format & RS::ARRAY_COMPRESS_NORMAL) {
vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
stride += sizeof(int8_t) * 4;
} else {
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
stride += sizeof(float) * 4;
}
vd.offset = stride;
vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
stride += sizeof(uint32_t);
buffer = s->vertex_buffer;
} break;
case RS::ARRAY_TANGENT: {
if (s->format & RS::ARRAY_COMPRESS_TANGENT) {
vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM;
stride += sizeof(int8_t) * 4;
} else {
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
stride += sizeof(float) * 4;
}
vd.offset = stride;
vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
stride += sizeof(uint32_t);
buffer = s->vertex_buffer;
} break;
case RS::ARRAY_COLOR: {
if (s->format & RS::ARRAY_COMPRESS_COLOR) {
vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
stride += sizeof(int8_t) * 4;
} else {
vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
stride += sizeof(float) * 4;
}
vd.offset = attribute_stride;
vd.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
attribute_stride += sizeof(int16_t) * 4;
buffer = s->attribute_buffer;
} break;
case RS::ARRAY_TEX_UV: {
if (s->format & RS::ARRAY_COMPRESS_TEX_UV) {
vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
stride += sizeof(int16_t) * 2;
} else {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
stride += sizeof(float) * 2;
}
vd.offset = attribute_stride;
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
attribute_stride += sizeof(float) * 2;
buffer = s->attribute_buffer;
} break;
case RS::ARRAY_TEX_UV2: {
if (s->format & RS::ARRAY_COMPRESS_TEX_UV2) {
vd.format = RD::DATA_FORMAT_R16G16_SFLOAT;
stride += sizeof(int16_t) * 2;
} else {
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
stride += sizeof(float) * 2;
}
vd.offset = attribute_stride;
vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
attribute_stride += sizeof(float) * 2;
buffer = s->attribute_buffer;
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
case RS::ARRAY_CUSTOM2:
case RS::ARRAY_CUSTOM3: {
vd.offset = attribute_stride;
int idx = i - RS::ARRAY_CUSTOM0;
uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT };
vd.format = fmtrd[fmt];
attribute_stride += fmtsize[fmt];
buffer = s->attribute_buffer;
} break;
case RS::ARRAY_BONES: {
//assumed weights too
vd.offset = skin_stride;
//unique format, internally 16 bits, exposed as single array for 32
vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
stride += sizeof(int32_t) * 4;
vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
skin_stride += sizeof(int16_t) * 4;
buffer = s->skin_buffer;
} break;
case RS::ARRAY_WEIGHTS: {
vd.offset = skin_stride;
vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
skin_stride += sizeof(int16_t) * 4;
buffer = s->skin_buffer;
} break;
}
}
if (!(p_input_mask & (1 << i))) {
continue; // Shader does not need this, skip it
continue; // Shader does not need this, skip it (but computing stride was important anyway)
}
attributes.push_back(vd);
@ -2922,8 +2955,17 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
//update final stride
for (int i = 0; i < attributes.size(); i++) {
if (attributes[i].stride == 1) {
if (attributes[i].stride == 0) {
continue; //default location
}
int loc = attributes[i].location;
if (loc < RS::ARRAY_COLOR) {
attributes.write[i].stride = stride;
} else if (loc < RS::ARRAY_BONES) {
attributes.write[i].stride = attribute_stride;
} else {
attributes.write[i].stride = skin_stride;
}
}
@ -8263,6 +8305,19 @@ RasterizerStorageRD::RasterizerStorageRD() {
mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
}
for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
buffer.resize(sizeof(float) * 4);
{
uint8_t *w = buffer.ptrw();
float *fptr = (float *)w;
fptr[0] = 0.0;
fptr[1] = 0.0;
fptr[2] = 0.0;
fptr[3] = 0.0;
}
mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
}
{ //bones
buffer.resize(sizeof(uint32_t) * 4);
{

View file

@ -170,6 +170,10 @@ public:
DEFAULT_RD_BUFFER_COLOR,
DEFAULT_RD_BUFFER_TEX_UV,
DEFAULT_RD_BUFFER_TEX_UV2,
DEFAULT_RD_BUFFER_CUSTOM0,
DEFAULT_RD_BUFFER_CUSTOM1,
DEFAULT_RD_BUFFER_CUSTOM2,
DEFAULT_RD_BUFFER_CUSTOM3,
DEFAULT_RD_BUFFER_BONES,
DEFAULT_RD_BUFFER_WEIGHTS,
DEFAULT_RD_BUFFER_MAX,
@ -378,6 +382,8 @@ private:
uint32_t format = 0;
RID vertex_buffer;
RID attribute_buffer;
RID skin_buffer;
uint32_t vertex_count = 0;
// A different pipeline needs to be allocated
@ -414,8 +420,7 @@ private:
Vector<AABB> bone_aabbs;
Vector<RID> blend_shapes;
RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed
RID blend_shape_buffer;
RID material;

View file

@ -9,7 +9,8 @@ layout(location = 0) in vec2 vertex_attrib;
layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
layout(location = 6) in uvec4 bones_attrib;
layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
@ -61,6 +62,7 @@ void main() {
color = vec4(unpackHalf2x16(draw_data.colors[4]), unpackHalf2x16(draw_data.colors[5]));
}
uvec4 bones = uvec4(0, 0, 0, 0);
vec4 bone_weights = vec4(0.0);
#elif defined(USE_ATTRIBUTES)
@ -68,7 +70,8 @@ void main() {
vec4 color = color_attrib;
vec2 uv = uv_attrib;
uvec4 bones = bones_attrib;
uvec4 bones = bone_attrib;
vec4 bone_weights = weight_attrib;
#else
vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));

View file

@ -24,7 +24,29 @@ layout(location = 4) in vec2 uv_attrib;
layout(location = 5) in vec2 uv2_attrib;
#endif
layout(location = 6) in uvec4 bone_attrib; // always bound, even if unused
#if defined(CUSTOM0_USED)
layout(location = 6) in vec4 custom0_attrib;
#endif
#if defined(CUSTOM1_USED)
layout(location = 7) in vec4 custom1_attrib;
#endif
#if defined(CUSTOM2_USED)
layout(location = 8) in vec4 custom2_attrib;
#endif
#if defined(CUSTOM3_USED)
layout(location = 9) in vec4 custom3_attrib;
#endif
#if defined(BONES_USED)
layout(location = 10) in uvec4 bone_attrib;
#endif
#if defined(WEIGHTS_USED)
layout(location = 11) in vec4 weight_attrib;
#endif
/* Varyings */
@ -116,14 +138,15 @@ void main() {
}
vec3 vertex = vertex_attrib;
vec3 normal = normal_attrib;
vec3 normal = normal_attrib * 2.0 - 1.0;
#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 tangent = tangent_attrib.xyz;
float binormalf = tangent_attrib.a;
vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
float binormalf = tangent_attrib.a * 2.0 - 1.0;
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
#if 0
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) {
//multimesh, instances are for it
@ -147,7 +170,7 @@ void main() {
binormal = (vec4(binormal, 0.0) * m).xyz;
#endif
}
#endif
uv_interp = uv_attrib;
#if defined(UV2_USED) || defined(USE_LIGHTMAP)

View file

@ -67,6 +67,12 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_INDICES"] = ShaderLanguage::TYPE_UVEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_WEIGHTS"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM0"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM1"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM2"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM3"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].can_discard = false;
//builtins

File diff suppressed because it is too large Load diff

View file

@ -52,7 +52,7 @@ class RenderingServer : public Object {
void _camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
void _canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate = Color(1, 1, 1));
Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const;
Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const;
protected:
RID _make_test_cube();
@ -61,7 +61,7 @@ protected:
RID white_texture;
RID test_material;
Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, Vector<uint8_t> &r_vertex_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb);
Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb);
static RenderingServer *(*create_func)();
static void _bind_methods();
@ -199,16 +199,36 @@ public:
/* MESH API */
enum ArrayType {
ARRAY_VERTEX = 0,
ARRAY_NORMAL = 1,
ARRAY_TANGENT = 2,
ARRAY_COLOR = 3,
ARRAY_TEX_UV = 4,
ARRAY_TEX_UV2 = 5,
ARRAY_BONES = 6,
ARRAY_WEIGHTS = 7,
ARRAY_INDEX = 8,
ARRAY_MAX = 9
ARRAY_VERTEX = 0, // RG32F or RGB32F (depending on 2D bit)
ARRAY_NORMAL = 1, // A2B10G10R10
ARRAY_TANGENT = 2, // A2B10G10R10, A flips sign of binormal
ARRAY_COLOR = 3, // RGBA16F
ARRAY_TEX_UV = 4, // RG32F
ARRAY_TEX_UV2 = 5, // RG32F
ARRAY_CUSTOM0 = 6, // depends on ArrayCustomFormat
ARRAY_CUSTOM1 = 7,
ARRAY_CUSTOM2 = 8,
ARRAY_CUSTOM3 = 9,
ARRAY_BONES = 10, // RGBA16UI (x2 if 8 weights)
ARRAY_WEIGHTS = 11, // RGBA16UNORM (x2 if 8 weights)
ARRAY_INDEX = 12, // 16 or 32 bits depending on length > 0xFFFF
ARRAY_MAX = 13
};
enum {
ARRAY_CUSTOM_COUNT = ARRAY_BONES - ARRAY_CUSTOM0
};
enum ArrayCustomFormat {
ARRAY_CUSTOM_RGBA8_UNORM,
ARRAY_CUSTOM_RGBA8_SNORM,
ARRAY_CUSTOM_RG_HALF,
ARRAY_CUSTOM_RGBA_HALF,
ARRAY_CUSTOM_R_FLOAT,
ARRAY_CUSTOM_RG_FLOAT,
ARRAY_CUSTOM_RGB_FLOAT,
ARRAY_CUSTOM_RGBA_FLOAT,
ARRAY_CUSTOM_MAX
};
enum ArrayFormat {
@ -219,21 +239,29 @@ public:
ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
ARRAY_FORMAT_TEX_UV = 1 << ARRAY_TEX_UV,
ARRAY_FORMAT_TEX_UV2 = 1 << ARRAY_TEX_UV2,
ARRAY_FORMAT_CUSTOM0 = 1 << ARRAY_CUSTOM0,
ARRAY_FORMAT_CUSTOM1 = 1 << ARRAY_CUSTOM1,
ARRAY_FORMAT_CUSTOM2 = 1 << ARRAY_CUSTOM2,
ARRAY_FORMAT_CUSTOM3 = 1 << ARRAY_CUSTOM3,
ARRAY_FORMAT_BONES = 1 << ARRAY_BONES,
ARRAY_FORMAT_WEIGHTS = 1 << ARRAY_WEIGHTS,
ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX,
ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1),
ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE),
ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2,
ARRAY_FORMAT_BLEND_SHAPE_MASK = ~(ARRAY_FORMAT_COLOR | ARRAY_FORMAT_TEX_UV | ARRAY_FORMAT_TEX_UV2 | ARRAY_FORMAT_BONES | ARRAY_FORMAT_WEIGHTS | ARRAY_FORMAT_CUSTOM0 | ARRAY_FORMAT_CUSTOM1 | ARRAY_FORMAT_CUSTOM2 | ARRAY_FORMAT_CUSTOM3 | ARRAY_FORMAT_INDEX),
ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1,
ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3,
ARRAY_FORMAT_CUSTOM_BASE = (ARRAY_INDEX + 1),
ARRAY_FORMAT_CUSTOM_BITS = 3,
ARRAY_FORMAT_CUSTOM0_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + 0),
ARRAY_FORMAT_CUSTOM1_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS),
ARRAY_FORMAT_CUSTOM2_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 2),
ARRAY_FORMAT_CUSTOM3_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 3),
ARRAY_FORMAT_CUSTOM_MASK = 0x7,
ARRAY_COMPRESS_FLAGS_BASE = (ARRAY_INDEX + 1 + 12),
ARRAY_FLAG_USE_2D_VERTICES = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 0),
ARRAY_FLAG_USE_DYNAMIC_UPDATE = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 1),
ARRAY_FLAG_USE_8_BONE_WEIGHTS = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 2),
};
enum PrimitiveType {
@ -249,11 +277,15 @@ public:
PrimitiveType primitive = PRIMITIVE_MAX;
uint32_t format = 0;
Vector<uint8_t> vertex_data;
Vector<uint8_t> vertex_data; // vertex, normal, tangent (change with skinning, blendshape)
Vector<uint8_t> attribute_data; // color,uv, uv2, custom0-3
Vector<uint8_t> skin_data; // bone index, bone weight
uint32_t vertex_count = 0;
Vector<uint8_t> index_data;
uint32_t index_count = 0;
uint32_t blend_shape_count = 0;
AABB aabb;
struct LOD {
float edge_length;
@ -262,7 +294,7 @@ public:
Vector<LOD> lods;
Vector<AABB> bone_aabbs;
Vector<Vector<uint8_t>> blend_shapes;
Vector<uint8_t> blend_shape_data;
RID material;
};
@ -270,17 +302,20 @@ public:
virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) = 0;
virtual RID mesh_create() = 0;
virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const;
virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const;
virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_array_index) const;
virtual uint32_t mesh_surface_get_format_vertex_stride(uint32_t p_format, int p_vertex_len) const;
virtual uint32_t mesh_surface_get_format_attribute_stride(uint32_t p_format, int p_vertex_len) const;
virtual uint32_t mesh_surface_get_format_skin_stride(uint32_t p_format, int p_vertex_len) const;
/// Returns stride
virtual uint32_t mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const;
virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
virtual void mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets, uint32_t &r_vertex_element_size, uint32_t &r_attrib_element_size, uint32_t &r_skin_element_size) const;
virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0);
Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const;
Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const;
Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const;
virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT);
virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0);
virtual void mesh_add_surface(RID p_mesh, const SurfaceData &p_surface) = 0;
virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;