mirror of
https://github.com/godotengine/godot.git
synced 2024-12-03 09:52:18 +08:00
Merge pull request #52504 from V-Sekai/gltf_8_uv
8 uvs for glTF2, URI decode and Vertex Custom api
This commit is contained in:
commit
8aedcfced7
@ -27,6 +27,7 @@
|
||||
}" />
|
||||
<argument index="4" name="material" type="Material" default="null" />
|
||||
<argument index="5" name="name" type="String" default="""" />
|
||||
<argument index="6" name="flags" type="int" default="0" />
|
||||
<description>
|
||||
Creates a new surface, analogous to [method ArrayMesh.add_surface_from_arrays].
|
||||
Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
|
||||
@ -94,6 +95,13 @@
|
||||
Returns the amount of surfaces that the mesh holds.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_surface_format" qualifiers="const">
|
||||
<return type="int" />
|
||||
<argument index="0" name="surface_idx" type="int" />
|
||||
<description>
|
||||
Returns the format of the surface that the mesh holds.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_surface_lod_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<argument index="0" name="surface_idx" type="int" />
|
||||
|
@ -210,6 +210,8 @@
|
||||
</constant>
|
||||
<constant name="ARRAY_FORMAT_CUSTOM_BASE" value="13" enum="ArrayFormat">
|
||||
</constant>
|
||||
<constant name="ARRAY_FORMAT_CUSTOM_BITS" value="3" enum="ArrayFormat">
|
||||
</constant>
|
||||
<constant name="ARRAY_FORMAT_CUSTOM0_SHIFT" value="13" enum="ArrayFormat">
|
||||
</constant>
|
||||
<constant name="ARRAY_FORMAT_CUSTOM1_SHIFT" value="16" enum="ArrayFormat">
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "core/math/math_defs.h"
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void EditorSceneImporterMesh::add_blend_shape(const String &p_name) {
|
||||
ERR_FAIL_COND(surfaces.size() > 0);
|
||||
blend_shapes.push_back(p_name);
|
||||
@ -55,13 +57,14 @@ Mesh::BlendShapeMode EditorSceneImporterMesh::get_blend_shape_mode() const {
|
||||
return blend_shape_mode;
|
||||
}
|
||||
|
||||
void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name) {
|
||||
void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, const Ref<Material> &p_material, const String &p_name, const uint32_t p_flags) {
|
||||
ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size());
|
||||
ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX);
|
||||
Surface s;
|
||||
s.primitive = p_primitive;
|
||||
s.arrays = p_arrays;
|
||||
s.name = p_name;
|
||||
s.flags = p_flags;
|
||||
|
||||
Vector<Vector3> vertex_array = p_arrays[Mesh::ARRAY_VERTEX];
|
||||
int vertex_count = vertex_array.size();
|
||||
@ -138,6 +141,11 @@ float EditorSceneImporterMesh::get_surface_lod_size(int p_surface, int p_lod) co
|
||||
return surfaces[p_surface].lods[p_lod].distance;
|
||||
}
|
||||
|
||||
uint32_t EditorSceneImporterMesh::get_surface_format(int p_surface) const {
|
||||
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), 0);
|
||||
return surfaces[p_surface].flags;
|
||||
}
|
||||
|
||||
Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const {
|
||||
ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Ref<Material>());
|
||||
return surfaces[p_surface].material;
|
||||
@ -283,7 +291,7 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<ArrayMesh> &p_base) {
|
||||
}
|
||||
}
|
||||
|
||||
mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods);
|
||||
mesh->add_surface_from_arrays(surfaces[i].primitive, surfaces[i].arrays, bs_data, lods, surfaces[i].flags);
|
||||
if (surfaces[i].material.is_valid()) {
|
||||
mesh->surface_set_material(mesh->get_surface_count() - 1, surfaces[i].material);
|
||||
}
|
||||
@ -398,7 +406,7 @@ void EditorSceneImporterMesh::create_shadow_mesh() {
|
||||
}
|
||||
}
|
||||
|
||||
shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name);
|
||||
shadow_mesh->add_surface(surfaces[i].primitive, new_surface, Array(), lods, Ref<Material>(), surfaces[i].name, surfaces[i].flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +444,11 @@ void EditorSceneImporterMesh::_set_data(const Dictionary &p_data) {
|
||||
if (s.has("material")) {
|
||||
material = s["material"];
|
||||
}
|
||||
add_surface(prim, arr, blend_shapes, lods, material, name);
|
||||
uint32_t flags = 0;
|
||||
if (s.has("flags")) {
|
||||
flags = s["flags"];
|
||||
}
|
||||
add_surface(prim, arr, blend_shapes, lods, material, name, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -473,6 +485,10 @@ Dictionary EditorSceneImporterMesh::_get_data() const {
|
||||
d["name"] = surfaces[i].name;
|
||||
}
|
||||
|
||||
if (surfaces[i].flags != 0) {
|
||||
d["flags"] = surfaces[i].flags;
|
||||
}
|
||||
|
||||
surface_arr.push_back(d);
|
||||
}
|
||||
data["surfaces"] = surface_arr;
|
||||
@ -833,7 +849,7 @@ void EditorSceneImporterMesh::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &EditorSceneImporterMesh::set_blend_shape_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &EditorSceneImporterMesh::get_blend_shape_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()));
|
||||
ClassDB::bind_method(D_METHOD("add_surface", "primitive", "arrays", "blend_shapes", "lods", "material", "name", "flags"), &EditorSceneImporterMesh::add_surface, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(Ref<Material>()), DEFVAL(String()), DEFVAL(0));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_surface_count"), &EditorSceneImporterMesh::get_surface_count);
|
||||
ClassDB::bind_method(D_METHOD("get_surface_primitive_type", "surface_idx"), &EditorSceneImporterMesh::get_surface_primitive_type);
|
||||
@ -844,6 +860,7 @@ void EditorSceneImporterMesh::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_surface_lod_size", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_size);
|
||||
ClassDB::bind_method(D_METHOD("get_surface_lod_indices", "surface_idx", "lod_idx"), &EditorSceneImporterMesh::get_surface_lod_indices);
|
||||
ClassDB::bind_method(D_METHOD("get_surface_material", "surface_idx"), &EditorSceneImporterMesh::get_surface_material);
|
||||
ClassDB::bind_method(D_METHOD("get_surface_format", "surface_idx"), &EditorSceneImporterMesh::get_surface_format);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &EditorSceneImporterMesh::set_surface_name);
|
||||
ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &EditorSceneImporterMesh::set_surface_material);
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "scene/resources/convex_polygon_shape_3d.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
#include "scene/resources/navigation_mesh.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// The following classes are used by importers instead of ArrayMesh and MeshInstance3D
|
||||
// so the data is not registered (hence, quality loss), importing happens faster and
|
||||
// its easier to modify before saving
|
||||
@ -57,6 +60,7 @@ class EditorSceneImporterMesh : public Resource {
|
||||
Vector<LOD> lods;
|
||||
Ref<Material> material;
|
||||
String name;
|
||||
uint32_t flags = 0;
|
||||
};
|
||||
Vector<Surface> surfaces;
|
||||
Vector<String> blend_shapes;
|
||||
@ -80,7 +84,7 @@ public:
|
||||
int get_blend_shape_count() const;
|
||||
String get_blend_shape_name(int p_blend_shape) const;
|
||||
|
||||
void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String());
|
||||
void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref<Material> &p_material = Ref<Material>(), const String &p_name = String(), const uint32_t p_flags = 0);
|
||||
int get_surface_count() const;
|
||||
|
||||
void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode);
|
||||
@ -95,6 +99,7 @@ public:
|
||||
Vector<int> get_surface_lod_indices(int p_surface, int p_lod) const;
|
||||
float get_surface_lod_size(int p_surface, int p_lod) const;
|
||||
Ref<Material> get_surface_material(int p_surface) const;
|
||||
uint32_t get_surface_format(int p_surface) const;
|
||||
|
||||
void set_surface_material(int p_surface, const Ref<Material> &p_material);
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/math/disjoint_set.h"
|
||||
#include "core/math/vector2.h"
|
||||
#include "core/variant/typed_array.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "core/version.h"
|
||||
@ -61,7 +62,7 @@
|
||||
#include "scene/resources/surface_tool.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef MODULE_CSG_ENABLED
|
||||
#include "modules/csg/csg_shape.h"
|
||||
#endif // MODULE_CSG_ENABLED
|
||||
@ -71,6 +72,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &p_path) {
|
||||
@ -2171,11 +2173,14 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
|
||||
}
|
||||
|
||||
Array array = import_mesh->get_surface_arrays(surface_i);
|
||||
uint32_t format = import_mesh->get_surface_format(surface_i);
|
||||
int32_t vertex_num = 0;
|
||||
Dictionary attributes;
|
||||
{
|
||||
Vector<Vector3> a = array[Mesh::ARRAY_VERTEX];
|
||||
ERR_FAIL_COND_V(!a.size(), ERR_INVALID_DATA);
|
||||
attributes["POSITION"] = _encode_accessor_as_vec3(state, a, true);
|
||||
vertex_num = a.size();
|
||||
}
|
||||
{
|
||||
Vector<real_t> a = array[Mesh::ARRAY_TANGENT];
|
||||
@ -2218,6 +2223,58 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
|
||||
attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true);
|
||||
}
|
||||
}
|
||||
for (int custom_i = 0; custom_i < 3; custom_i++) {
|
||||
Vector<float> a = array[Mesh::ARRAY_CUSTOM0 + custom_i];
|
||||
if (a.size()) {
|
||||
int num_channels = 4;
|
||||
int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS;
|
||||
switch ((format >> custom_shift) & Mesh::ARRAY_FORMAT_CUSTOM_MASK) {
|
||||
case Mesh::ARRAY_CUSTOM_R_FLOAT:
|
||||
num_channels = 1;
|
||||
break;
|
||||
case Mesh::ARRAY_CUSTOM_RG_FLOAT:
|
||||
num_channels = 2;
|
||||
break;
|
||||
case Mesh::ARRAY_CUSTOM_RGB_FLOAT:
|
||||
num_channels = 3;
|
||||
break;
|
||||
case Mesh::ARRAY_CUSTOM_RGBA_FLOAT:
|
||||
num_channels = 4;
|
||||
break;
|
||||
}
|
||||
int texcoord_i = 2 + 2 * custom_i;
|
||||
String gltf_texcoord_key;
|
||||
for (int prev_texcoord_i = 0; prev_texcoord_i < texcoord_i; prev_texcoord_i++) {
|
||||
gltf_texcoord_key = vformat("TEXCOORD_%d", prev_texcoord_i);
|
||||
if (!attributes.has(gltf_texcoord_key)) {
|
||||
Vector<Vector2> empty;
|
||||
empty.resize(vertex_num);
|
||||
attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, empty, true);
|
||||
}
|
||||
}
|
||||
|
||||
LocalVector<Vector2> first_channel;
|
||||
first_channel.resize(vertex_num);
|
||||
LocalVector<Vector2> second_channel;
|
||||
second_channel.resize(vertex_num);
|
||||
for (int32_t vert_i = 0; vert_i < vertex_num; vert_i++) {
|
||||
float u = a[vert_i * num_channels + 0];
|
||||
float v = (num_channels == 1 ? 0.0f : a[vert_i * num_channels + 1]);
|
||||
first_channel[vert_i] = Vector2(u, v);
|
||||
u = 0;
|
||||
v = 0;
|
||||
if (num_channels >= 3) {
|
||||
u = a[vert_i * num_channels + 2];
|
||||
v = (num_channels == 3 ? 0.0f : a[vert_i * num_channels + 3]);
|
||||
second_channel[vert_i] = Vector2(u, v);
|
||||
}
|
||||
}
|
||||
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
|
||||
attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, first_channel, true);
|
||||
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
|
||||
attributes[gltf_texcoord_key] = _encode_accessor_as_vec2(state, second_channel, true);
|
||||
}
|
||||
}
|
||||
{
|
||||
Vector<Color> a = array[Mesh::ARRAY_COLOR];
|
||||
if (a.size()) {
|
||||
@ -2253,13 +2310,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
|
||||
}
|
||||
attributes["JOINTS_0"] = _encode_accessor_as_joints(state, attribs, true);
|
||||
} else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) {
|
||||
int32_t vertex_count = vertex_array.size();
|
||||
Vector<Color> joints_0;
|
||||
joints_0.resize(vertex_count);
|
||||
joints_0.resize(vertex_num);
|
||||
Vector<Color> joints_1;
|
||||
joints_1.resize(vertex_count);
|
||||
joints_1.resize(vertex_num);
|
||||
int32_t weights_8_count = JOINT_GROUP_SIZE * 2;
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) {
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
|
||||
Color joint_0;
|
||||
joint_0.r = a[vertex_i * weights_8_count + 0];
|
||||
joint_0.g = a[vertex_i * weights_8_count + 1];
|
||||
@ -2289,13 +2345,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
|
||||
}
|
||||
attributes["WEIGHTS_0"] = _encode_accessor_as_weights(state, attribs, true);
|
||||
} else if ((a.size() / (JOINT_GROUP_SIZE * 2)) >= vertex_array.size()) {
|
||||
int32_t vertex_count = vertex_array.size();
|
||||
Vector<Color> weights_0;
|
||||
weights_0.resize(vertex_count);
|
||||
weights_0.resize(vertex_num);
|
||||
Vector<Color> weights_1;
|
||||
weights_1.resize(vertex_count);
|
||||
weights_1.resize(vertex_num);
|
||||
int32_t weights_8_count = JOINT_GROUP_SIZE * 2;
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) {
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
|
||||
Color weight_0;
|
||||
weight_0.r = a[vertex_i * weights_8_count + 0];
|
||||
weight_0.g = a[vertex_i * weights_8_count + 1];
|
||||
@ -2459,7 +2514,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
ERR_FAIL_COND_V(!d.has("primitives"), ERR_PARSE_ERROR);
|
||||
|
||||
Array primitives = d["primitives"];
|
||||
const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary();
|
||||
const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] :
|
||||
Dictionary();
|
||||
Ref<EditorSceneImporterMesh> import_mesh;
|
||||
import_mesh.instantiate();
|
||||
String mesh_name = "mesh";
|
||||
@ -2469,6 +2525,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
import_mesh->set_name(_gen_unique_name(state, vformat("%s_%s", state->scene_name, mesh_name)));
|
||||
|
||||
for (int j = 0; j < primitives.size(); j++) {
|
||||
uint32_t flags = 0;
|
||||
Dictionary p = primitives[j];
|
||||
|
||||
Array array;
|
||||
@ -2500,8 +2557,11 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR);
|
||||
int32_t vertex_num = 0;
|
||||
if (a.has("POSITION")) {
|
||||
array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true);
|
||||
PackedVector3Array vertices = _decode_accessor_as_vec3(state, a["POSITION"], true);
|
||||
array[Mesh::ARRAY_VERTEX] = vertices;
|
||||
vertex_num = vertices.size();
|
||||
}
|
||||
if (a.has("NORMAL")) {
|
||||
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
|
||||
@ -2515,6 +2575,60 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
if (a.has("TEXCOORD_1")) {
|
||||
array[Mesh::ARRAY_TEX_UV2] = _decode_accessor_as_vec2(state, a["TEXCOORD_1"], true);
|
||||
}
|
||||
for (int custom_i = 0; custom_i < 3; custom_i++) {
|
||||
Vector<float> cur_custom;
|
||||
Vector<Vector2> texcoord_first;
|
||||
Vector<Vector2> texcoord_second;
|
||||
|
||||
int texcoord_i = 2 + 2 * custom_i;
|
||||
String gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i);
|
||||
int num_channels = 0;
|
||||
if (a.has(gltf_texcoord_key)) {
|
||||
texcoord_first = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true);
|
||||
num_channels = 2;
|
||||
}
|
||||
gltf_texcoord_key = vformat("TEXCOORD_%d", texcoord_i + 1);
|
||||
if (a.has(gltf_texcoord_key)) {
|
||||
texcoord_second = _decode_accessor_as_vec2(state, a[gltf_texcoord_key], true);
|
||||
num_channels = 4;
|
||||
}
|
||||
if (!num_channels) {
|
||||
break;
|
||||
}
|
||||
if (num_channels == 2 || num_channels == 4) {
|
||||
cur_custom.resize(vertex_num * num_channels);
|
||||
for (int32_t uv_i = 0; uv_i < texcoord_first.size() && uv_i < vertex_num; uv_i++) {
|
||||
cur_custom.write[uv_i * num_channels + 0] = texcoord_first[uv_i].x;
|
||||
cur_custom.write[uv_i * num_channels + 1] = texcoord_first[uv_i].y;
|
||||
}
|
||||
// Vector.resize seems to not zero-initialize. Ensure all unused elements are 0:
|
||||
for (int32_t uv_i = texcoord_first.size(); uv_i < vertex_num; uv_i++) {
|
||||
cur_custom.write[uv_i * num_channels + 0] = 0;
|
||||
cur_custom.write[uv_i * num_channels + 1] = 0;
|
||||
}
|
||||
}
|
||||
if (num_channels == 4) {
|
||||
for (int32_t uv_i = 0; uv_i < texcoord_second.size() && uv_i < vertex_num; uv_i++) {
|
||||
// num_channels must be 4
|
||||
cur_custom.write[uv_i * num_channels + 2] = texcoord_second[uv_i].x;
|
||||
cur_custom.write[uv_i * num_channels + 3] = texcoord_second[uv_i].y;
|
||||
}
|
||||
// Vector.resize seems to not zero-initialize. Ensure all unused elements are 0:
|
||||
for (int32_t uv_i = texcoord_second.size(); uv_i < vertex_num; uv_i++) {
|
||||
cur_custom.write[uv_i * num_channels + 2] = 0;
|
||||
cur_custom.write[uv_i * num_channels + 3] = 0;
|
||||
}
|
||||
}
|
||||
if (cur_custom.size() > 0) {
|
||||
array[Mesh::ARRAY_CUSTOM0 + custom_i] = cur_custom;
|
||||
int custom_shift = Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT + custom_i * Mesh::ARRAY_FORMAT_CUSTOM_BITS;
|
||||
if (num_channels == 2) {
|
||||
flags |= Mesh::ARRAY_CUSTOM_RG_FLOAT << custom_shift;
|
||||
} else {
|
||||
flags |= Mesh::ARRAY_CUSTOM_RGBA_FLOAT << custom_shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a.has("COLOR_0")) {
|
||||
array[Mesh::ARRAY_COLOR] = _decode_accessor_as_color(state, a["COLOR_0"], true);
|
||||
has_vertex_color = true;
|
||||
@ -2526,10 +2640,9 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
PackedInt32Array joints_1 = _decode_accessor_as_ints(state, a["JOINTS_1"], true);
|
||||
ERR_FAIL_COND_V(joints_0.size() != joints_0.size(), ERR_INVALID_DATA);
|
||||
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
|
||||
int32_t vertex_count = joints_0.size() / JOINT_GROUP_SIZE;
|
||||
Vector<int> joints;
|
||||
joints.resize(vertex_count * weight_8_count);
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) {
|
||||
joints.resize(vertex_num * weight_8_count);
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
|
||||
joints.write[vertex_i * weight_8_count + 0] = joints_0[vertex_i * JOINT_GROUP_SIZE + 0];
|
||||
joints.write[vertex_i * weight_8_count + 1] = joints_0[vertex_i * JOINT_GROUP_SIZE + 1];
|
||||
joints.write[vertex_i * weight_8_count + 2] = joints_0[vertex_i * JOINT_GROUP_SIZE + 2];
|
||||
@ -2568,9 +2681,8 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
Vector<float> weights;
|
||||
ERR_FAIL_COND_V(weights_0.size() != weights_1.size(), ERR_INVALID_DATA);
|
||||
int32_t weight_8_count = JOINT_GROUP_SIZE * 2;
|
||||
int32_t vertex_count = weights_0.size() / JOINT_GROUP_SIZE;
|
||||
weights.resize(vertex_count * weight_8_count);
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_count; vertex_i++) {
|
||||
weights.resize(vertex_num * weight_8_count);
|
||||
for (int32_t vertex_i = 0; vertex_i < vertex_num; vertex_i++) {
|
||||
weights.write[vertex_i * weight_8_count + 0] = weights_0[vertex_i * JOINT_GROUP_SIZE + 0];
|
||||
weights.write[vertex_i * weight_8_count + 1] = weights_0[vertex_i * JOINT_GROUP_SIZE + 1];
|
||||
weights.write[vertex_i * weight_8_count + 2] = weights_0[vertex_i * JOINT_GROUP_SIZE + 2];
|
||||
@ -2798,7 +2910,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
||||
mat = mat3d;
|
||||
}
|
||||
|
||||
import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String());
|
||||
import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String(), flags);
|
||||
}
|
||||
|
||||
Vector<float> blend_weights;
|
||||
@ -2954,6 +3066,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
|
||||
}
|
||||
}
|
||||
} else { // Relative path to an external image file.
|
||||
uri = uri.uri_decode();
|
||||
uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
|
||||
// ResourceLoader will rely on the file extension to use the relevant loader.
|
||||
// The spec says that if mimeType is defined, it should take precedence (e.g.
|
||||
@ -4897,7 +5010,7 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_instance(Ref<GLTFState> state, MeshIns
|
||||
if (p_mesh_instance->get_material_override().is_valid()) {
|
||||
mat = p_mesh_instance->get_material_override();
|
||||
}
|
||||
import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name);
|
||||
import_mesh->add_surface(primitive_type, arrays, blend_shape_arrays, Dictionary(), mat, surface_name, godot_mesh->surface_get_format(surface_i));
|
||||
}
|
||||
for (int32_t blend_i = 0; blend_i < blend_count; blend_i++) {
|
||||
blend_weights.write[blend_i] = 0.0f;
|
||||
|
@ -543,6 +543,7 @@ void Mesh::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(ARRAY_FORMAT_BLEND_SHAPE_MASK);
|
||||
|
||||
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BASE);
|
||||
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM_BITS);
|
||||
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM0_SHIFT);
|
||||
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM1_SHIFT);
|
||||
BIND_ENUM_CONSTANT(ARRAY_FORMAT_CUSTOM2_SHIFT);
|
||||
|
@ -105,6 +105,7 @@ public:
|
||||
ARRAY_FORMAT_BLEND_SHAPE_MASK = RS::ARRAY_FORMAT_BLEND_SHAPE_MASK,
|
||||
|
||||
ARRAY_FORMAT_CUSTOM_BASE = RS::ARRAY_FORMAT_CUSTOM_BASE,
|
||||
ARRAY_FORMAT_CUSTOM_BITS = RS::ARRAY_FORMAT_CUSTOM_BITS,
|
||||
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,
|
||||
|
@ -409,7 +409,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
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);
|
||||
@ -426,7 +426,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
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)));
|
||||
@ -443,7 +443,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
w[idx * 2 + 0] = Math::make_half_float(c.r);
|
||||
w[idx * 2 + 1] = Math::make_half_float(c.g);
|
||||
}
|
||||
@ -458,7 +458,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
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);
|
||||
@ -475,7 +475,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
w[idx] = c.r;
|
||||
}
|
||||
|
||||
@ -489,7 +489,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
w[idx * 2 + 0] = c.r;
|
||||
w[idx * 2 + 1] = c.g;
|
||||
}
|
||||
@ -504,7 +504,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
w[idx * 3 + 0] = c.r;
|
||||
w[idx * 3 + 1] = c.g;
|
||||
w[idx * 3 + 2] = c.b;
|
||||
@ -520,7 +520,7 @@ Array SurfaceTool::commit_to_arrays() {
|
||||
for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
|
||||
const Vertex &v = vertex_array[idx];
|
||||
|
||||
const Color &c = v.custom[idx];
|
||||
const Color &c = v.custom[fmt];
|
||||
w[idx * 4 + 0] = c.r;
|
||||
w[idx * 4 + 1] = c.g;
|
||||
w[idx * 4 + 2] = c.b;
|
||||
@ -679,6 +679,9 @@ void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, Local
|
||||
_create_list_from_arrays(arr, r_vertex, r_index, lformat);
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, LocalVector<SurfaceTool::Vertex> &ret, uint32_t *r_format) {
|
||||
ret.clear();
|
||||
|
||||
@ -733,8 +736,6 @@ void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays
|
||||
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");
|
||||
@ -832,6 +833,12 @@ void SurfaceTool::create_from_triangle_arrays(const Array &p_arrays) {
|
||||
clear();
|
||||
primitive = Mesh::PRIMITIVE_TRIANGLES;
|
||||
_create_list_from_arrays(p_arrays, &vertex_array, &index_array, format);
|
||||
|
||||
for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
|
||||
if (format & custom_mask[j]) {
|
||||
last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) {
|
||||
@ -841,6 +848,12 @@ void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) {
|
||||
primitive = p_existing->surface_get_primitive_type(p_surface);
|
||||
_create_list(p_existing, p_surface, &vertex_array, &index_array, format);
|
||||
material = p_existing->surface_get_material(p_surface);
|
||||
|
||||
for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
|
||||
if (format & custom_mask[j]) {
|
||||
last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name) {
|
||||
@ -863,6 +876,12 @@ void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_sur
|
||||
Array mesh = arr[shape_idx];
|
||||
ERR_FAIL_COND(mesh.size() != RS::ARRAY_MAX);
|
||||
_create_list_from_arrays(arr[shape_idx], &vertex_array, &index_array, format);
|
||||
|
||||
for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
|
||||
if (format & custom_mask[j]) {
|
||||
last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform3D &p_xform) {
|
||||
@ -878,6 +897,16 @@ void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const
|
||||
LocalVector<int> nindices;
|
||||
_create_list(p_existing, p_surface, &nvertices, &nindices, nformat);
|
||||
format |= nformat;
|
||||
|
||||
for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
|
||||
if (format & custom_mask[j]) {
|
||||
CustomFormat new_format = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
|
||||
if (last_custom_format[j] != CUSTOM_MAX && last_custom_format[j] != new_format) {
|
||||
WARN_PRINT(vformat("Custom %d format %d mismatch when appending format %d", j, last_custom_format[j], new_format));
|
||||
}
|
||||
last_custom_format[j] = new_format;
|
||||
}
|
||||
}
|
||||
int vfrom = vertex_array.size();
|
||||
|
||||
for (uint32_t vi = 0; vi < nvertices.size(); vi++) {
|
||||
|
@ -601,10 +601,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
|
||||
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["CUSTOM0"] = "#define CUSTOM0_USED\n";
|
||||
actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n";
|
||||
actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n";
|
||||
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
|
||||
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
|
||||
|
@ -593,10 +593,10 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
|
||||
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["CUSTOM0"] = "#define CUSTOM0_USED\n";
|
||||
actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n";
|
||||
actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n";
|
||||
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
|
||||
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
|
||||
|
@ -500,7 +500,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
|
||||
case RS::ARRAY_CUSTOM1:
|
||||
case RS::ARRAY_CUSTOM2:
|
||||
case RS::ARRAY_CUSTOM3: {
|
||||
uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (RS::ARRAY_CUSTOM0 - ai))) & ARRAY_FORMAT_CUSTOM_MASK;
|
||||
uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (ai - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK;
|
||||
switch (type) {
|
||||
case ARRAY_CUSTOM_RGBA8_UNORM:
|
||||
case ARRAY_CUSTOM_RGBA8_SNORM:
|
||||
@ -541,14 +541,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
|
||||
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
|
||||
|
||||
Vector<float> array = p_arrays[ai];
|
||||
int32_t s = ARRAY_CUSTOM_R_FLOAT - ai + 1;
|
||||
int32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1;
|
||||
|
||||
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * s, ERR_INVALID_PARAMETER);
|
||||
|
||||
const float *src = array.ptr();
|
||||
|
||||
for (int i = 0; i < p_vertex_array_len; i++) {
|
||||
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], &src[i * s], 4 * s);
|
||||
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], &src[i * s], sizeof(float) * s);
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
@ -938,6 +938,13 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < RS::ARRAY_CUSTOM_COUNT; ++i) {
|
||||
// include custom array format type.
|
||||
if (format & (1 << (ARRAY_CUSTOM0 + i))) {
|
||||
format |= (RS::ARRAY_FORMAT_CUSTOM_MASK << (RS::ARRAY_FORMAT_CUSTOM_BASE + i * RS::ARRAY_FORMAT_CUSTOM_BITS)) & p_compress_format;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t offsets[RS::ARRAY_MAX];
|
||||
|
||||
uint32_t vertex_element_size;
|
||||
@ -1191,7 +1198,7 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
|
||||
case RS::ARRAY_CUSTOM1:
|
||||
case RS::ARRAY_CUSTOM2:
|
||||
case RS::ARRAY_CUSTOM3: {
|
||||
uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (RS::ARRAY_CUSTOM0 - i))) & ARRAY_FORMAT_CUSTOM_MASK;
|
||||
uint32_t type = (p_format >> (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * (i - RS::ARRAY_CUSTOM0))) & ARRAY_FORMAT_CUSTOM_MASK;
|
||||
switch (type) {
|
||||
case ARRAY_CUSTOM_RGBA8_UNORM:
|
||||
case ARRAY_CUSTOM_RGBA8_SNORM:
|
||||
@ -1219,6 +1226,8 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
|
||||
uint32_t s = type - ARRAY_CUSTOM_R_FLOAT + 1;
|
||||
|
||||
Vector<float> arr;
|
||||
arr.resize(s * p_vertex_len);
|
||||
|
||||
float *w = arr.ptrw();
|
||||
|
||||
for (int j = 0; j < p_vertex_len; j++) {
|
||||
|
Loading…
Reference in New Issue
Block a user