Skip to content

Commit d373d20

Browse files
committed
GLTF: Add functions to encode and decode Variants to/from accessors
1 parent 11576b8 commit d373d20

File tree

2 files changed

+328
-0
lines changed

2 files changed

+328
-0
lines changed

modules/gltf/gltf_document.cpp

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,6 +2459,325 @@ Vector<Transform3D> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> p_sta
24592459
return ret;
24602460
}
24612461

2462+
Vector<Variant> GLTFDocument::_decode_accessor_as_variant(Ref<GLTFState> p_state, const GLTFAccessorIndex p_accessor, Variant::Type p_variant_type, GLTFAccessor::GLTFAccessorType p_accessor_type) {
2463+
const Vector<double> attribs = _decode_accessor(p_state, p_accessor, false);
2464+
Vector<Variant> ret;
2465+
ERR_FAIL_COND_V_MSG(attribs.is_empty(), ret, "glTF: The accessor was empty.");
2466+
const int component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type];
2467+
ERR_FAIL_COND_V_MSG(attribs.size() % component_count != 0, ret, "glTF: The accessor size was not a multiple of the component count.");
2468+
const int ret_size = attribs.size() / component_count;
2469+
ret.resize(ret_size);
2470+
for (int i = 0; i < ret_size; i++) {
2471+
switch (p_variant_type) {
2472+
case Variant::BOOL: {
2473+
ret.write[i] = attribs[i * component_count] != 0.0;
2474+
} break;
2475+
case Variant::INT: {
2476+
ret.write[i] = (int64_t)attribs[i * component_count];
2477+
} break;
2478+
case Variant::FLOAT: {
2479+
ret.write[i] = attribs[i * component_count];
2480+
} break;
2481+
case Variant::VECTOR2:
2482+
case Variant::RECT2:
2483+
case Variant::VECTOR3:
2484+
case Variant::VECTOR4:
2485+
case Variant::PLANE:
2486+
case Variant::QUATERNION: {
2487+
// General-purpose code for importing glTF accessor data with any component count into structs up to 4 `real_t`s in size.
2488+
Variant v;
2489+
switch (component_count) {
2490+
case 1: {
2491+
v = Vector4(attribs[i * component_count], 0.0f, 0.0f, 0.0f);
2492+
} break;
2493+
case 2: {
2494+
v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], 0.0f, 0.0f);
2495+
} break;
2496+
case 3: {
2497+
v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], 0.0f);
2498+
} break;
2499+
default: {
2500+
v = Vector4(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]);
2501+
} break;
2502+
}
2503+
// Evil hack that relies on the structure of Variant, but it's the
2504+
// only way to accomplish this without a ton of code duplication.
2505+
*(Variant::Type *)&v = p_variant_type;
2506+
ret.write[i] = v;
2507+
} break;
2508+
case Variant::VECTOR2I:
2509+
case Variant::RECT2I:
2510+
case Variant::VECTOR3I:
2511+
case Variant::VECTOR4I: {
2512+
// General-purpose code for importing glTF accessor data with any component count into structs up to 4 `int32_t`s in size.
2513+
Variant v;
2514+
switch (component_count) {
2515+
case 1: {
2516+
v = Vector4i((int32_t)attribs[i * component_count], 0, 0, 0);
2517+
} break;
2518+
case 2: {
2519+
v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], 0, 0);
2520+
} break;
2521+
case 3: {
2522+
v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], (int32_t)attribs[i * component_count + 2], 0);
2523+
} break;
2524+
default: {
2525+
v = Vector4i((int32_t)attribs[i * component_count], (int32_t)attribs[i * component_count + 1], (int32_t)attribs[i * component_count + 2], (int32_t)attribs[i * component_count + 3]);
2526+
} break;
2527+
}
2528+
// Evil hack that relies on the structure of Variant, but it's the
2529+
// only way to accomplish this without a ton of code duplication.
2530+
*(Variant::Type *)&v = p_variant_type;
2531+
ret.write[i] = v;
2532+
} break;
2533+
// No more generalized hacks, each of the below types needs a lot of repetitive code.
2534+
case Variant::COLOR: {
2535+
Variant v;
2536+
switch (component_count) {
2537+
case 1: {
2538+
v = Color(attribs[i * component_count], 0.0f, 0.0f, 1.0f);
2539+
} break;
2540+
case 2: {
2541+
v = Color(attribs[i * component_count], attribs[i * component_count + 1], 0.0f, 1.0f);
2542+
} break;
2543+
case 3: {
2544+
v = Color(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], 1.0f);
2545+
} break;
2546+
default: {
2547+
v = Color(attribs[i * component_count], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]);
2548+
} break;
2549+
}
2550+
ret.write[i] = v;
2551+
} break;
2552+
case Variant::TRANSFORM2D: {
2553+
Transform2D t;
2554+
switch (component_count) {
2555+
case 4: {
2556+
t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]);
2557+
t.columns[1] = Vector2(attribs[i * component_count + 2], attribs[i * component_count + 3]);
2558+
} break;
2559+
case 9: {
2560+
t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]);
2561+
t.columns[1] = Vector2(attribs[i * component_count + 3], attribs[i * component_count + 4]);
2562+
t.columns[2] = Vector2(attribs[i * component_count + 6], attribs[i * component_count + 7]);
2563+
} break;
2564+
case 16: {
2565+
t.columns[0] = Vector2(attribs[i * component_count + 0], attribs[i * component_count + 1]);
2566+
t.columns[1] = Vector2(attribs[i * component_count + 4], attribs[i * component_count + 5]);
2567+
t.columns[2] = Vector2(attribs[i * component_count + 12], attribs[i * component_count + 13]);
2568+
} break;
2569+
}
2570+
ret.write[i] = t;
2571+
} break;
2572+
case Variant::BASIS: {
2573+
Basis b;
2574+
switch (component_count) {
2575+
case 4: {
2576+
b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 2], 0.0f);
2577+
b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 3], 0.0f);
2578+
} break;
2579+
case 9: {
2580+
b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 3], attribs[i * component_count + 6]);
2581+
b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 4], attribs[i * component_count + 7]);
2582+
b.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 5], attribs[i * component_count + 8]);
2583+
} break;
2584+
case 16: {
2585+
b.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 4], attribs[i * component_count + 8]);
2586+
b.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 5], attribs[i * component_count + 9]);
2587+
b.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 6], attribs[i * component_count + 10]);
2588+
} break;
2589+
}
2590+
ret.write[i] = b;
2591+
} break;
2592+
case Variant::TRANSFORM3D: {
2593+
Transform3D t;
2594+
switch (component_count) {
2595+
case 4: {
2596+
t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 2], 0.0f);
2597+
t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 3], 0.0f);
2598+
} break;
2599+
case 9: {
2600+
t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 3], attribs[i * component_count + 6]);
2601+
t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 4], attribs[i * component_count + 7]);
2602+
t.basis.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 5], attribs[i * component_count + 8]);
2603+
} break;
2604+
case 16: {
2605+
t.basis.rows[0] = Vector3(attribs[i * component_count + 0], attribs[i * component_count + 4], attribs[i * component_count + 8]);
2606+
t.basis.rows[1] = Vector3(attribs[i * component_count + 1], attribs[i * component_count + 5], attribs[i * component_count + 9]);
2607+
t.basis.rows[2] = Vector3(attribs[i * component_count + 2], attribs[i * component_count + 6], attribs[i * component_count + 10]);
2608+
t.origin = Vector3(attribs[i * component_count + 12], attribs[i * component_count + 13], attribs[i * component_count + 14]);
2609+
} break;
2610+
}
2611+
ret.write[i] = t;
2612+
} break;
2613+
case Variant::PROJECTION: {
2614+
Projection p;
2615+
switch (component_count) {
2616+
case 4: {
2617+
p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], 0.0f, 0.0f);
2618+
p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], 0.0f, 0.0f);
2619+
} break;
2620+
case 9: {
2621+
p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], attribs[i * component_count + 2], 0.0f);
2622+
p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], attribs[i * component_count + 6], 0.0f);
2623+
p.columns[2] = Vector4(attribs[i * component_count + 8], attribs[i * component_count + 9], attribs[i * component_count + 10], 0.0f);
2624+
} break;
2625+
case 16: {
2626+
p.columns[0] = Vector4(attribs[i * component_count + 0], attribs[i * component_count + 1], attribs[i * component_count + 2], attribs[i * component_count + 3]);
2627+
p.columns[1] = Vector4(attribs[i * component_count + 4], attribs[i * component_count + 5], attribs[i * component_count + 6], attribs[i * component_count + 7]);
2628+
p.columns[2] = Vector4(attribs[i * component_count + 8], attribs[i * component_count + 9], attribs[i * component_count + 10], attribs[i * component_count + 11]);
2629+
p.columns[3] = Vector4(attribs[i * component_count + 12], attribs[i * component_count + 13], attribs[i * component_count + 14], attribs[i * component_count + 15]);
2630+
} break;
2631+
}
2632+
ret.write[i] = p;
2633+
} break;
2634+
default: {
2635+
ERR_FAIL_V_MSG(ret, "glTF: Cannot decode accessor as Variant of type " + Variant::get_type_name(p_variant_type) + ".");
2636+
}
2637+
}
2638+
}
2639+
return ret;
2640+
}
2641+
2642+
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_variant(Ref<GLTFState> p_state, Vector<Variant> p_attribs, Variant::Type p_variant_type, GLTFAccessor::GLTFAccessorType p_accessor_type, GLTFAccessor::GLTFComponentType p_component_type) {
2643+
const int accessor_component_count = COMPONENT_COUNT_FOR_ACCESSOR_TYPE[p_accessor_type];
2644+
Vector<double> encoded_attribs;
2645+
for (const Variant &v : p_attribs) {
2646+
switch (p_variant_type) {
2647+
case Variant::NIL:
2648+
case Variant::BOOL:
2649+
case Variant::INT:
2650+
case Variant::FLOAT: {
2651+
// For scalar values, just append them. Variant can convert all of these to double. Some padding may also be needed.
2652+
encoded_attribs.append(v);
2653+
if (unlikely(accessor_component_count > 1)) {
2654+
for (int i = 1; i < accessor_component_count; i++) {
2655+
encoded_attribs.append(0.0);
2656+
}
2657+
}
2658+
} break;
2659+
case Variant::VECTOR2:
2660+
case Variant::VECTOR2I:
2661+
case Variant::VECTOR3:
2662+
case Variant::VECTOR3I:
2663+
case Variant::VECTOR4:
2664+
case Variant::VECTOR4I: {
2665+
// Variant can handle converting Vector2/2i/3/3i/4/4i to Vector4 for us.
2666+
Vector4 vec = v;
2667+
if (likely(accessor_component_count < 5)) {
2668+
for (int i = 0; i < accessor_component_count; i++) {
2669+
encoded_attribs.append(vec[i]);
2670+
}
2671+
}
2672+
} break;
2673+
case Variant::PLANE: {
2674+
Plane p = v;
2675+
if (likely(accessor_component_count == 4)) {
2676+
encoded_attribs.append(p.normal.x);
2677+
encoded_attribs.append(p.normal.y);
2678+
encoded_attribs.append(p.normal.z);
2679+
encoded_attribs.append(p.d);
2680+
}
2681+
} break;
2682+
case Variant::QUATERNION: {
2683+
Quaternion q = v;
2684+
if (likely(accessor_component_count < 5)) {
2685+
for (int i = 0; i < accessor_component_count; i++) {
2686+
encoded_attribs.append(q[i]);
2687+
}
2688+
}
2689+
} break;
2690+
case Variant::COLOR: {
2691+
Color c = v;
2692+
if (likely(accessor_component_count < 5)) {
2693+
for (int i = 0; i < accessor_component_count; i++) {
2694+
encoded_attribs.append(c[i]);
2695+
}
2696+
}
2697+
} break;
2698+
case Variant::RECT2:
2699+
case Variant::RECT2I: {
2700+
// Variant can handle converting Rect2i to Rect2 for us.
2701+
Rect2 r = v;
2702+
if (likely(accessor_component_count == 4)) {
2703+
encoded_attribs.append(r.position.x);
2704+
encoded_attribs.append(r.position.y);
2705+
encoded_attribs.append(r.size.x);
2706+
encoded_attribs.append(r.size.y);
2707+
}
2708+
} break;
2709+
case Variant::TRANSFORM2D:
2710+
case Variant::BASIS:
2711+
case Variant::TRANSFORM3D:
2712+
case Variant::PROJECTION: {
2713+
// Variant can handle converting Transform2D/Transform3D/Basis to Projection for us.
2714+
Projection p = v;
2715+
if (accessor_component_count == 16) {
2716+
for (int i = 0; i < 4; i++) {
2717+
encoded_attribs.append(p.columns[i][0]);
2718+
encoded_attribs.append(p.columns[i][1]);
2719+
encoded_attribs.append(p.columns[i][2]);
2720+
encoded_attribs.append(p.columns[i][3]);
2721+
}
2722+
} else if (accessor_component_count == 9) {
2723+
for (int i = 0; i < 3; i++) {
2724+
encoded_attribs.append(p.columns[i][0]);
2725+
encoded_attribs.append(p.columns[i][1]);
2726+
encoded_attribs.append(p.columns[i][2]);
2727+
}
2728+
} else if (accessor_component_count == 4) {
2729+
encoded_attribs.append(p.columns[0][0]);
2730+
encoded_attribs.append(p.columns[0][1]);
2731+
encoded_attribs.append(p.columns[1][0]);
2732+
encoded_attribs.append(p.columns[1][1]);
2733+
}
2734+
} break;
2735+
default: {
2736+
ERR_FAIL_V_MSG(-1, "glTF: Cannot encode accessor from Variant of type " + Variant::get_type_name(p_variant_type) + ".");
2737+
}
2738+
}
2739+
}
2740+
// Determine the min and max values for the accessor.
2741+
Vector<double> type_max;
2742+
type_max.resize(accessor_component_count);
2743+
Vector<double> type_min;
2744+
type_min.resize(accessor_component_count);
2745+
for (int i = 0; i < encoded_attribs.size(); i++) {
2746+
if (Math::is_zero_approx(encoded_attribs[i])) {
2747+
encoded_attribs.write[i] = 0.0;
2748+
} else {
2749+
encoded_attribs.write[i] = _filter_number(encoded_attribs[i]);
2750+
}
2751+
}
2752+
for (int i = 0; i < p_attribs.size(); i++) {
2753+
_calc_accessor_min_max(i, accessor_component_count, type_max, encoded_attribs, type_min);
2754+
}
2755+
_round_min_max_components(type_min, type_max);
2756+
// Encode the data in a buffer view.
2757+
GLTFBufferIndex buffer_view_index = 0;
2758+
if (p_state->buffers.is_empty()) {
2759+
p_state->buffers.push_back(Vector<uint8_t>());
2760+
}
2761+
const int64_t buffer_size = p_state->buffers[buffer_view_index].size();
2762+
Error err = _encode_buffer_view(p_state, encoded_attribs.ptr(), p_attribs.size(), p_accessor_type, p_component_type, false, buffer_size, false, buffer_view_index);
2763+
if (err != OK) {
2764+
return -1;
2765+
}
2766+
// Create the accessor and fill it with the data.
2767+
Ref<GLTFAccessor> accessor;
2768+
accessor.instantiate();
2769+
accessor->max = type_max;
2770+
accessor->min = type_min;
2771+
accessor->count = p_attribs.size();
2772+
accessor->accessor_type = p_accessor_type;
2773+
accessor->component_type = p_component_type;
2774+
accessor->byte_offset = 0;
2775+
accessor->buffer_view = buffer_view_index;
2776+
const GLTFAccessorIndex new_accessor_index = p_state->accessors.size();
2777+
p_state->accessors.push_back(accessor);
2778+
return new_accessor_index;
2779+
}
2780+
24622781
Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
24632782
Array meshes;
24642783
for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < p_state->meshes.size(); gltf_mesh_i++) {

modules/gltf/gltf_document.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,15 @@ class GLTFDocument : public Resource {
175175
Vector<Transform3D> _decode_accessor_as_xform(Ref<GLTFState> p_state,
176176
const GLTFAccessorIndex p_accessor,
177177
const bool p_for_vertex);
178+
Vector<Variant> _decode_accessor_as_variant(Ref<GLTFState> p_state,
179+
const GLTFAccessorIndex p_accessor,
180+
Variant::Type p_variant_type,
181+
GLTFAccessor::GLTFAccessorType p_accessor_type);
182+
GLTFAccessorIndex _encode_accessor_as_variant(Ref<GLTFState> p_state,
183+
Vector<Variant> p_attribs,
184+
Variant::Type p_variant_type,
185+
GLTFAccessor::GLTFAccessorType p_accessor_type,
186+
GLTFAccessor::GLTFComponentType p_component_type = GLTFAccessor::COMPONENT_TYPE_SINGLE_FLOAT);
178187
Error _parse_meshes(Ref<GLTFState> p_state);
179188
Error _serialize_textures(Ref<GLTFState> p_state);
180189
Error _serialize_texture_samplers(Ref<GLTFState> p_state);

0 commit comments

Comments
 (0)