Create tangent array if mesh created without tangents
This extends our previous change to ensure that compressed meshes have tangents Now we ensure tangents are always used. This greatly simplifies our compression code at the cost of a small amount of bandwidth
This commit is contained in:
parent
4c96e9676b
commit
031f221b9d
|
@ -166,7 +166,7 @@ void ImmediateMesh::surface_end() {
|
||||||
normal_tangent_stride += sizeof(uint32_t);
|
normal_tangent_stride += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
uint32_t tangent_offset = 0;
|
uint32_t tangent_offset = 0;
|
||||||
if (uses_tangents) {
|
if (uses_tangents || uses_normals) {
|
||||||
format |= ARRAY_FORMAT_TANGENT;
|
format |= ARRAY_FORMAT_TANGENT;
|
||||||
tangent_offset = vertex_stride * vertices.size() + normal_tangent_stride;
|
tangent_offset = vertex_stride * vertices.size() + normal_tangent_stride;
|
||||||
normal_tangent_stride += sizeof(uint32_t);
|
normal_tangent_stride += sizeof(uint32_t);
|
||||||
|
@ -202,9 +202,16 @@ void ImmediateMesh::surface_end() {
|
||||||
|
|
||||||
*normal = value;
|
*normal = value;
|
||||||
}
|
}
|
||||||
if (uses_tangents) {
|
if (uses_tangents || uses_normals) {
|
||||||
uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * normal_tangent_stride + tangent_offset];
|
uint32_t *tangent = (uint32_t *)&surface_vertex_ptr[i * normal_tangent_stride + tangent_offset];
|
||||||
Vector2 t = tangents[i].normal.octahedron_tangent_encode(tangents[i].d);
|
Vector2 t;
|
||||||
|
if (uses_tangents) {
|
||||||
|
t = tangents[i].normal.octahedron_tangent_encode(tangents[i].d);
|
||||||
|
} else {
|
||||||
|
Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normals[i].normalized());
|
||||||
|
t = tan.octahedron_tangent_encode(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
value |= (uint16_t)CLAMP(t.x * 65535, 0, 65535);
|
value |= (uint16_t)CLAMP(t.x * 65535, 0, 65535);
|
||||||
value |= (uint16_t)CLAMP(t.y * 65535, 0, 65535) << 16;
|
value |= (uint16_t)CLAMP(t.y * 65535, 0, 65535) << 16;
|
||||||
|
|
|
@ -635,7 +635,8 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
|
||||||
// If using compression we store tangent while storing vertices.
|
// If using compression we store tangent while storing vertices.
|
||||||
if (!(p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
|
if (!(p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
|
||||||
Variant::Type type = p_arrays[ai].get_type();
|
Variant::Type type = p_arrays[ai].get_type();
|
||||||
ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY && type != Variant::NIL, ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
if (type == Variant::PACKED_FLOAT32_ARRAY) {
|
if (type == Variant::PACKED_FLOAT32_ARRAY) {
|
||||||
Vector<float> array = p_arrays[ai];
|
Vector<float> array = p_arrays[ai];
|
||||||
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
|
||||||
|
@ -657,7 +658,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
|
||||||
|
|
||||||
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
|
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
|
||||||
}
|
}
|
||||||
} else { // PACKED_FLOAT64_ARRAY
|
} else if (type == Variant::PACKED_FLOAT64_ARRAY) {
|
||||||
Vector<double> array = p_arrays[ai];
|
Vector<double> array = p_arrays[ai];
|
||||||
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
|
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
|
||||||
const double *src_ptr = array.ptr();
|
const double *src_ptr = array.ptr();
|
||||||
|
@ -676,6 +677,30 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
|
||||||
vector[0] = 65535;
|
vector[0] = 65535;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
|
||||||
|
}
|
||||||
|
} else { // No tangent array.
|
||||||
|
ERR_FAIL_COND_V(p_arrays[RS::ARRAY_NORMAL].get_type() != Variant::PACKED_VECTOR3_ARRAY, ERR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
Vector<Vector3> normal_array = p_arrays[RS::ARRAY_NORMAL];
|
||||||
|
ERR_FAIL_COND_V(normal_array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER);
|
||||||
|
const Vector3 *normal_src = normal_array.ptr();
|
||||||
|
// Set data for tangent.
|
||||||
|
for (int i = 0; i < p_vertex_array_len; i++) {
|
||||||
|
// Generate an arbitrary vector that is tangential to normal.
|
||||||
|
Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normal_src[i].normalized());
|
||||||
|
Vector2 res = tan.octahedron_tangent_encode(1.0);
|
||||||
|
uint16_t vector[2] = {
|
||||||
|
(uint16_t)CLAMP(res.x * 65535, 0, 65535),
|
||||||
|
(uint16_t)CLAMP(res.y * 65535, 0, 65535),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vector[0] == 0 && vector[1] == 65535) {
|
||||||
|
// (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection.
|
||||||
|
// So we sanitize here.
|
||||||
|
vector[0] = 65535;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
|
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1172,6 +1197,11 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
ERR_FAIL_COND_V(array_len == 0, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(array_len == 0, ERR_INVALID_DATA);
|
||||||
|
} else if (i == RS::ARRAY_NORMAL) {
|
||||||
|
if (p_arrays[RS::ARRAY_TANGENT].get_type() == Variant::NIL) {
|
||||||
|
// We must use tangents if using normals.
|
||||||
|
format |= (1ULL << RS::ARRAY_TANGENT);
|
||||||
|
}
|
||||||
} else if (i == RS::ARRAY_BONES) {
|
} else if (i == RS::ARRAY_BONES) {
|
||||||
switch (p_arrays[i].get_type()) {
|
switch (p_arrays[i].get_type()) {
|
||||||
case Variant::PACKED_INT32_ARRAY: {
|
case Variant::PACKED_INT32_ARRAY: {
|
||||||
|
@ -1242,11 +1272,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
|
||||||
ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_NORMAL), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using tangents without normal array.");
|
ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_NORMAL), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using tangents without normal array.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && !(format & RS::ARRAY_FORMAT_TANGENT)) {
|
|
||||||
// If no tangent array provided, we will generate one.
|
|
||||||
format |= RS::ARRAY_FORMAT_TANGENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vertex_array_size = (vertex_element_size + normal_element_size) * array_len;
|
int vertex_array_size = (vertex_element_size + normal_element_size) * array_len;
|
||||||
int attrib_array_size = attrib_element_size * array_len;
|
int attrib_array_size = attrib_element_size * array_len;
|
||||||
int skin_array_size = skin_element_size * array_len;
|
int skin_array_size = skin_element_size * array_len;
|
||||||
|
|
Loading…
Reference in New Issue