|
@@ -596,7 +596,7 @@ enum OldArrayFormat {
|
|
|
OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1,
|
|
|
OLD_ARRAY_FLAG_USE_16_BIT_BONES = OLD_ARRAY_COMPRESS_INDEX << 2,
|
|
|
OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3,
|
|
|
-
|
|
|
+ OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION = OLD_ARRAY_COMPRESS_INDEX << 4,
|
|
|
};
|
|
|
|
|
|
#ifndef DISABLE_DEPRECATED
|
|
@@ -626,6 +626,27 @@ static Mesh::PrimitiveType _old_primitives[7] = {
|
|
|
};
|
|
|
#endif // DISABLE_DEPRECATED
|
|
|
|
|
|
+// Convert Octahedron-mapped normalized vector back to Cartesian
|
|
|
+// Assumes normalized format (elements of v within range [-1, 1])
|
|
|
+Vector3 _oct_to_norm(const Vector2 v) {
|
|
|
+ Vector3 res(v.x, v.y, 1 - (Math::absf(v.x) + Math::absf(v.y)));
|
|
|
+ float t = MAX(-res.z, 0.0f);
|
|
|
+ res.x += t * -SIGN(res.x);
|
|
|
+ res.y += t * -SIGN(res.y);
|
|
|
+ return res.normalized();
|
|
|
+}
|
|
|
+
|
|
|
+// Convert Octahedron-mapped normalized tangent vector back to Cartesian
|
|
|
+// out_sign provides the direction for the original cartesian tangent
|
|
|
+// Assumes normalized format (elements of v within range [-1, 1])
|
|
|
+Vector3 _oct_to_tangent(const Vector2 v, float *out_sign) {
|
|
|
+ Vector2 v_decompressed = v;
|
|
|
+ v_decompressed.y = Math::absf(v_decompressed.y) * 2 - 1;
|
|
|
+ Vector3 res = _oct_to_norm(v_decompressed);
|
|
|
+ *out_sign = SIGN(v[1]);
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) {
|
|
|
uint32_t dst_vertex_stride;
|
|
|
uint32_t dst_attribute_stride;
|
|
@@ -692,66 +713,133 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma
|
|
|
}
|
|
|
} break;
|
|
|
case OLD_ARRAY_NORMAL: {
|
|
|
- if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) {
|
|
|
- const float multiplier = 1.f / 127.f * 1023.0f;
|
|
|
+ if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
|
|
|
+ if ((p_old_format & OLD_ARRAY_COMPRESS_NORMAL) && (p_old_format & OLD_ARRAY_FORMAT_TANGENT) && (p_old_format & OLD_ARRAY_COMPRESS_TANGENT)) {
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
|
|
|
+ const Vector2 src_vec(src[0] / 127.0f, src[1] / 127.0f);
|
|
|
+
|
|
|
+ const Vector3 res = _oct_to_norm(src_vec) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(res.x * 1023.0f), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(res.y * 1023.0f), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(res.z * 1023.0f), 0, 1023) << 20;
|
|
|
+ }
|
|
|
+ src_offset += sizeof(int8_t) * 2;
|
|
|
+ } else {
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
|
|
|
+ const Vector2 src_vec(src[0] / 32767.0f, src[1] / 32767.0f);
|
|
|
+
|
|
|
+ const Vector3 res = _oct_to_norm(src_vec) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(res.x * 1023.0f), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(res.y * 1023.0f), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(res.z * 1023.0f), 0, 1023) << 20;
|
|
|
+ }
|
|
|
+ src_offset += sizeof(int16_t) * 2;
|
|
|
+ }
|
|
|
+ } else { // No Octahedral compression
|
|
|
+ if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) {
|
|
|
+ const float multiplier = 1.f / 127.f * 1023.0f;
|
|
|
|
|
|
- for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
- const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
- uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
|
|
|
|
|
|
- *dst = 0;
|
|
|
- *dst |= CLAMP(int(src[0] * multiplier), 0, 1023);
|
|
|
- *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10;
|
|
|
- *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20;
|
|
|
- }
|
|
|
- src_offset += sizeof(uint32_t);
|
|
|
- } else {
|
|
|
- for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
- const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
- uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(src[0] * multiplier), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20;
|
|
|
+ }
|
|
|
+ src_offset += sizeof(uint32_t);
|
|
|
+ } else {
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]];
|
|
|
|
|
|
- *dst = 0;
|
|
|
- *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023);
|
|
|
- *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10;
|
|
|
- *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20;
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20;
|
|
|
+ }
|
|
|
+ src_offset += sizeof(float) * 3;
|
|
|
}
|
|
|
- src_offset += sizeof(float) * 3;
|
|
|
}
|
|
|
|
|
|
} break;
|
|
|
case OLD_ARRAY_TANGENT: {
|
|
|
- if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) {
|
|
|
- const float multiplier = 1.f / 127.f * 1023.0f;
|
|
|
-
|
|
|
- for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
- const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
- uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
|
|
|
-
|
|
|
- *dst = 0;
|
|
|
- *dst |= CLAMP(int(src[0] * multiplier), 0, 1023);
|
|
|
- *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10;
|
|
|
- *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20;
|
|
|
- if (src[3] > 0) {
|
|
|
- *dst |= 3 << 30;
|
|
|
+ if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) {
|
|
|
+ if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { // int8
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
|
|
|
+ const Vector2 src_vec(src[0] / 127.0f, src[1] / 127.0f);
|
|
|
+ float out_sign;
|
|
|
+ const Vector3 res = _oct_to_tangent(src_vec, &out_sign) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
|
|
|
+
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(res.x * 1023.0), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(res.y * 1023.0), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(res.z * 1023.0), 0, 1023) << 20;
|
|
|
+ if (out_sign > 0) {
|
|
|
+ *dst |= 3 << 30;
|
|
|
+ }
|
|
|
}
|
|
|
+ src_offset += sizeof(int8_t) * 2;
|
|
|
+ } else { // int16
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
|
|
|
+ const Vector2 src_vec(src[0] / 32767.0f, src[1] / 32767.0f);
|
|
|
+ float out_sign;
|
|
|
+ Vector3 res = _oct_to_tangent(src_vec, &out_sign) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
|
|
|
+
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(res.x * 1023.0), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(res.y * 1023.0), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(res.z * 1023.0), 0, 1023) << 20;
|
|
|
+ if (out_sign > 0) {
|
|
|
+ *dst |= 3 << 30;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ src_offset += sizeof(int16_t) * 2;
|
|
|
}
|
|
|
- src_offset += sizeof(uint32_t);
|
|
|
- } else {
|
|
|
- for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
- const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
- uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
|
|
|
-
|
|
|
- *dst = 0;
|
|
|
- *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023);
|
|
|
- *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10;
|
|
|
- *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20;
|
|
|
- if (src[3] > 0) {
|
|
|
- *dst |= 3 << 30;
|
|
|
+ } else { // No Octahedral compression
|
|
|
+ if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) {
|
|
|
+ const float multiplier = 1.f / 127.f * 1023.0f;
|
|
|
+
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
|
|
|
+
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(src[0] * multiplier), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20;
|
|
|
+ if (src[3] > 0) {
|
|
|
+ *dst |= 3 << 30;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ src_offset += sizeof(uint32_t);
|
|
|
+ } else {
|
|
|
+ for (uint32_t i = 0; i < p_elements; i++) {
|
|
|
+ const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset];
|
|
|
+ uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]];
|
|
|
+
|
|
|
+ *dst = 0;
|
|
|
+ *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023);
|
|
|
+ *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10;
|
|
|
+ *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20;
|
|
|
+ if (src[3] > 0) {
|
|
|
+ *dst |= 3 << 30;
|
|
|
+ }
|
|
|
}
|
|
|
+ src_offset += sizeof(float) * 4;
|
|
|
}
|
|
|
- src_offset += sizeof(float) * 4;
|
|
|
}
|
|
|
-
|
|
|
} break;
|
|
|
case OLD_ARRAY_COLOR: {
|
|
|
if (p_old_format & OLD_ARRAY_COMPRESS_COLOR) {
|