2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* surface_tool.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "surface_tool.h"
2018-09-11 18:13:45 +02:00
2014-02-10 02:10:30 +01:00
# define EQ_VERTEX_DIST 0.00001
2020-12-12 13:06:59 +01:00
SurfaceTool : : OptimizeVertexCacheFunc SurfaceTool : : optimize_vertex_cache_func = nullptr ;
SurfaceTool : : SimplifyFunc SurfaceTool : : simplify_func = nullptr ;
2021-04-10 07:44:36 +02:00
SurfaceTool : : SimplifyWithAttribFunc SurfaceTool : : simplify_with_attrib_func = nullptr ;
2021-01-09 19:04:09 +01:00
SurfaceTool : : SimplifyScaleFunc SurfaceTool : : simplify_scale_func = nullptr ;
SurfaceTool : : SimplifySloppyFunc SurfaceTool : : simplify_sloppy_func = nullptr ;
2022-02-04 16:28:18 +01:00
SurfaceTool : : GenerateRemapFunc SurfaceTool : : generate_remap_func = nullptr ;
SurfaceTool : : RemapVertexFunc SurfaceTool : : remap_vertex_func = nullptr ;
SurfaceTool : : RemapIndexFunc SurfaceTool : : remap_index_func = nullptr ;
void SurfaceTool : : strip_mesh_arrays ( PackedVector3Array & r_vertices , PackedInt32Array & r_indices ) {
ERR_FAIL_COND_MSG ( ! generate_remap_func | | ! remap_vertex_func | | ! remap_index_func , " Meshoptimizer library is not initialized. " ) ;
Vector < uint32_t > remap ;
remap . resize ( r_vertices . size ( ) ) ;
2022-10-24 22:40:34 +02:00
uint32_t new_vertex_count = generate_remap_func ( remap . ptrw ( ) , ( unsigned int * ) r_indices . ptr ( ) , r_indices . size ( ) , r_vertices . ptr ( ) , r_vertices . size ( ) , sizeof ( Vector3 ) ) ;
2022-02-04 16:28:18 +01:00
remap_vertex_func ( r_vertices . ptrw ( ) , r_vertices . ptr ( ) , r_vertices . size ( ) , sizeof ( Vector3 ) , remap . ptr ( ) ) ;
r_vertices . resize ( new_vertex_count ) ;
remap_index_func ( ( unsigned int * ) r_indices . ptrw ( ) , ( unsigned int * ) r_indices . ptr ( ) , r_indices . size ( ) , remap . ptr ( ) ) ;
HashMap < const int * , bool , TriangleHasher , TriangleHasher > found_triangles ;
int * idx_ptr = r_indices . ptrw ( ) ;
int filtered_indices_count = 0 ;
for ( int i = 0 ; i < r_indices . size ( ) / 3 ; i + + ) {
const int * tri = idx_ptr + ( i * 3 ) ;
if ( tri [ 0 ] = = tri [ 1 ] | | tri [ 1 ] = = tri [ 2 ] | | tri [ 2 ] = = tri [ 0 ] ) {
continue ;
}
if ( found_triangles . has ( tri ) ) {
continue ;
}
if ( i ! = filtered_indices_count ) {
memcpy ( idx_ptr + ( filtered_indices_count * 3 ) , tri , sizeof ( int ) * 3 ) ;
}
found_triangles [ tri ] = true ;
filtered_indices_count + + ;
}
r_indices . resize ( filtered_indices_count * 3 ) ;
}
2020-12-12 13:06:59 +01:00
2017-08-11 21:10:05 +02:00
bool SurfaceTool : : Vertex : : operator = = ( const Vertex & p_vertex ) const {
2020-05-14 16:41:43 +02:00
if ( vertex ! = p_vertex . vertex ) {
2014-02-10 02:10:30 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( uv ! = p_vertex . uv ) {
2014-05-14 06:22:15 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( uv2 ! = p_vertex . uv2 ) {
2014-05-14 06:22:15 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( normal ! = p_vertex . normal ) {
2014-05-14 06:22:15 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( binormal ! = p_vertex . binormal ) {
2014-05-14 06:22:15 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( color ! = p_vertex . color ) {
2014-05-14 06:22:15 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( bones . size ( ) ! = p_vertex . bones . size ( ) ) {
2014-05-14 06:22:15 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bones . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( bones [ i ] ! = p_vertex . bones [ i ] ) {
2014-02-10 02:10:30 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < weights . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( weights [ i ] ! = p_vertex . weights [ i ] ) {
2014-02-10 02:10:30 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-12-08 19:58:49 +01:00
for ( int i = 0 ; i < RS : : ARRAY_CUSTOM_COUNT ; i + + ) {
2020-12-02 02:40:47 +01:00
if ( custom [ i ] ! = p_vertex . custom [ i ] ) {
return false ;
}
}
2020-12-12 13:06:59 +01:00
if ( smooth_group ! = p_vertex . smooth_group ) {
return false ;
}
2014-05-14 06:22:15 +02:00
return true ;
}
2014-02-10 02:10:30 +01:00
2014-05-14 06:22:15 +02:00
uint32_t SurfaceTool : : VertexHasher : : hash ( const Vertex & p_vtx ) {
2017-03-05 16:44:50 +01:00
uint32_t h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . vertex , sizeof ( real_t ) * 3 ) ;
h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . normal , sizeof ( real_t ) * 3 , h ) ;
h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . binormal , sizeof ( real_t ) * 3 , h ) ;
h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . tangent , sizeof ( real_t ) * 3 , h ) ;
h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . uv , sizeof ( real_t ) * 2 , h ) ;
h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . uv2 , sizeof ( real_t ) * 2 , h ) ;
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 ) ;
2020-12-02 02:40:47 +01:00
h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . custom [ 0 ] , sizeof ( Color ) * RS : : ARRAY_CUSTOM_COUNT , h ) ;
2022-06-18 16:20:55 +02:00
h = hash_murmur3_one_32 ( p_vtx . smooth_group , h ) ;
h = hash_fmix32 ( h ) ;
2014-05-14 06:22:15 +02:00
return h ;
2014-02-10 02:10:30 +01:00
}
2022-10-29 22:37:09 +02:00
bool SurfaceTool : : SmoothGroupVertex : : operator = = ( const SmoothGroupVertex & p_vertex ) const {
if ( vertex ! = p_vertex . vertex ) {
return false ;
}
if ( smooth_group ! = p_vertex . smooth_group ) {
return false ;
}
return true ;
}
uint32_t SurfaceTool : : SmoothGroupVertexHasher : : hash ( const SmoothGroupVertex & p_vtx ) {
uint32_t h = hash_djb2_buffer ( ( const uint8_t * ) & p_vtx . vertex , sizeof ( real_t ) * 3 ) ;
h = hash_murmur3_one_32 ( p_vtx . smooth_group , h ) ;
h = hash_fmix32 ( h ) ;
return h ;
}
2022-02-04 16:28:18 +01:00
uint32_t SurfaceTool : : TriangleHasher : : hash ( const int * p_triangle ) {
int t0 = p_triangle [ 0 ] ;
int t1 = p_triangle [ 1 ] ;
int t2 = p_triangle [ 2 ] ;
2022-02-16 13:56:32 +01:00
if ( t0 > t1 ) {
2022-02-04 16:28:18 +01:00
SWAP ( t0 , t1 ) ;
2022-02-16 13:56:32 +01:00
}
if ( t1 > t2 ) {
2022-02-04 16:28:18 +01:00
SWAP ( t1 , t2 ) ;
2022-02-16 13:56:32 +01:00
}
if ( t0 > t1 ) {
2022-02-04 16:28:18 +01:00
SWAP ( t0 , t1 ) ;
2022-02-16 13:56:32 +01:00
}
2022-02-04 16:28:18 +01:00
return ( t0 * 73856093 ) ^ ( t1 * 19349663 ) ^ ( t2 * 83492791 ) ;
}
bool SurfaceTool : : TriangleHasher : : compare ( const int * p_lhs , const int * p_rhs ) {
int r0 = p_rhs [ 0 ] ;
int r1 = p_rhs [ 1 ] ;
int r2 = p_rhs [ 2 ] ;
2022-02-16 13:56:32 +01:00
if ( r0 > r1 ) {
2022-02-04 16:28:18 +01:00
SWAP ( r0 , r1 ) ;
2022-02-16 13:56:32 +01:00
}
if ( r1 > r2 ) {
2022-02-04 16:28:18 +01:00
SWAP ( r1 , r2 ) ;
2022-02-16 13:56:32 +01:00
}
if ( r0 > r1 ) {
2022-02-04 16:28:18 +01:00
SWAP ( r0 , r1 ) ;
2022-02-16 13:56:32 +01:00
}
2022-02-04 16:28:18 +01:00
int l0 = p_lhs [ 0 ] ;
int l1 = p_lhs [ 1 ] ;
int l2 = p_lhs [ 2 ] ;
2022-02-16 13:56:32 +01:00
if ( l0 > l1 ) {
2022-02-04 16:28:18 +01:00
SWAP ( l0 , l1 ) ;
2022-02-16 13:56:32 +01:00
}
if ( l1 > l2 ) {
2022-02-04 16:28:18 +01:00
SWAP ( l1 , l2 ) ;
2022-02-16 13:56:32 +01:00
}
if ( l0 > l1 ) {
2022-02-04 16:28:18 +01:00
SWAP ( l0 , l1 ) ;
2022-02-16 13:56:32 +01:00
}
2022-02-04 16:28:18 +01:00
return l0 = = r0 & & l1 = = r1 & & l2 = = r2 ;
}
2014-02-10 02:10:30 +01:00
void SurfaceTool : : begin ( Mesh : : PrimitiveType p_primitive ) {
clear ( ) ;
2017-03-05 16:44:50 +01:00
primitive = p_primitive ;
begun = true ;
first = true ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_vertex ( const Vector3 & p_vertex ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
Vertex vtx ;
2017-03-05 16:44:50 +01:00
vtx . vertex = p_vertex ;
vtx . color = last_color ;
vtx . normal = last_normal ;
vtx . uv = last_uv ;
2017-12-09 18:11:26 +01:00
vtx . uv2 = last_uv2 ;
2017-03-05 16:44:50 +01:00
vtx . weights = last_weights ;
vtx . bones = last_bones ;
vtx . tangent = last_tangent . normal ;
2020-05-10 16:47:11 +02:00
vtx . binormal = last_normal . cross ( last_tangent . normal ) . normalized ( ) * last_tangent . d ;
2020-12-12 13:06:59 +01:00
vtx . smooth_group = last_smooth_group ;
2020-12-02 02:40:47 +01:00
for ( int i = 0 ; i < RS : : ARRAY_CUSTOM_COUNT ; i + + ) {
vtx . custom [ i ] = last_custom [ i ] ;
}
2019-04-13 20:19:26 +02:00
2020-12-02 02:40:47 +01:00
const int expected_vertices = skin_weights = = SKIN_8_WEIGHTS ? 8 : 4 ;
2019-04-13 20:19:26 +02:00
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
ERR_FAIL_COND ( vtx . weights . size ( ) ! = vtx . bones . size ( ) ) ;
if ( vtx . weights . size ( ) < expected_vertices ) {
2019-05-19 12:34:40 +02:00
//less than required, fill
2019-04-13 20:19:26 +02:00
for ( int i = vtx . weights . size ( ) ; i < expected_vertices ; i + + ) {
vtx . weights . push_back ( 0 ) ;
vtx . bones . push_back ( 0 ) ;
}
} else if ( vtx . weights . size ( ) > expected_vertices ) {
//more than required, sort, cap and normalize.
Vector < WeightSort > weights ;
for ( int i = 0 ; i < vtx . weights . size ( ) ; i + + ) {
WeightSort ws ;
ws . index = vtx . bones [ i ] ;
ws . weight = vtx . weights [ i ] ;
weights . push_back ( ws ) ;
}
//sort
weights . sort ( ) ;
//cap
weights . resize ( expected_vertices ) ;
//renormalize
2021-02-09 18:24:36 +01:00
float total = 0.0 ;
2019-04-13 20:19:26 +02:00
for ( int i = 0 ; i < expected_vertices ; i + + ) {
total + = weights [ i ] . weight ;
}
vtx . weights . resize ( expected_vertices ) ;
vtx . bones . resize ( expected_vertices ) ;
for ( int i = 0 ; i < expected_vertices ; i + + ) {
if ( total > 0 ) {
vtx . weights . write [ i ] = weights [ i ] . weight / total ;
} else {
vtx . weights . write [ i ] = 0 ;
}
vtx . bones . write [ i ] = weights [ i ] . index ;
}
}
}
2014-02-10 02:10:30 +01:00
vertex_array . push_back ( vtx ) ;
2017-03-05 16:44:50 +01:00
first = false ;
2019-04-13 20:19:26 +02:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_VERTEX ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_color ( Color p_color ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_COLOR ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_COLOR ;
last_color = p_color ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_normal ( const Vector3 & p_normal ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_NORMAL ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_NORMAL ;
last_normal = p_normal ;
2014-02-10 02:10:30 +01:00
}
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_tangent ( const Plane & p_tangent ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_TANGENT ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_TANGENT ;
last_tangent = p_tangent ;
2014-02-10 02:10:30 +01:00
}
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_uv ( const Vector2 & p_uv ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_TEX_UV ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_TEX_UV ;
last_uv = p_uv ;
2014-02-10 02:10:30 +01:00
}
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_uv2 ( const Vector2 & p_uv2 ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_TEX_UV2 ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_TEX_UV2 ;
last_uv2 = p_uv2 ;
2014-02-10 02:10:30 +01:00
}
2022-06-12 01:15:44 +02:00
void SurfaceTool : : set_custom ( int p_channel_index , const Color & p_custom ) {
ERR_FAIL_INDEX ( p_channel_index , RS : : ARRAY_CUSTOM_COUNT ) ;
2020-12-02 02:40:47 +01:00
ERR_FAIL_COND ( ! begun ) ;
2022-06-12 01:15:44 +02:00
ERR_FAIL_COND ( last_custom_format [ p_channel_index ] = = CUSTOM_MAX ) ;
2020-12-02 02:40:47 +01:00
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 } ;
2022-06-12 01:15:44 +02:00
ERR_FAIL_COND ( ! first & & ! ( format & mask [ p_channel_index ] ) ) ;
2020-12-02 02:40:47 +01:00
if ( first ) {
2022-06-12 01:15:44 +02:00
format | = mask [ p_channel_index ] ;
2020-12-02 02:40:47 +01:00
}
2022-06-12 01:15:44 +02:00
last_custom [ p_channel_index ] = p_custom ;
2020-12-02 02:40:47 +01:00
}
void SurfaceTool : : set_bones ( const Vector < int > & p_bones ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_BONES ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_BONES ;
2020-12-02 02:40:47 +01:00
if ( skin_weights = = SKIN_8_WEIGHTS ) {
format | = Mesh : : ARRAY_FLAG_USE_8_BONE_WEIGHTS ;
}
2017-03-05 16:44:50 +01:00
last_bones = p_bones ;
2014-02-10 02:10:30 +01:00
}
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_weights ( const Vector < float > & p_weights ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! first & & ! ( format & Mesh : : ARRAY_FORMAT_WEIGHTS ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_WEIGHTS ;
2020-12-02 02:40:47 +01:00
if ( skin_weights = = SKIN_8_WEIGHTS ) {
format | = Mesh : : ARRAY_FLAG_USE_8_BONE_WEIGHTS ;
}
2017-03-05 16:44:50 +01:00
last_weights = p_weights ;
2014-02-10 02:10:30 +01:00
}
2020-12-12 13:06:59 +01:00
void SurfaceTool : : set_smooth_group ( uint32_t p_group ) {
last_smooth_group = p_group ;
2014-05-14 06:22:15 +02:00
}
2023-04-25 00:21:32 +02:00
void SurfaceTool : : _add_triangle_fan ( const Vector < Vector3 > & p_vertices , const Vector < Vector2 > & p_uvs , const Vector < Color > & p_colors , const Vector < Vector2 > & p_uv2s , const Vector < Vector3 > & p_normals , const TypedArray < Plane > & p_tangents ) {
2023-06-08 17:45:26 +02:00
add_triangle_fan ( p_vertices , p_uvs , p_colors , p_uv2s , p_normals , Variant ( p_tangents ) ) ;
2023-04-25 00:21:32 +02:00
}
2019-02-13 09:23:29 +01:00
void SurfaceTool : : add_triangle_fan ( const Vector < Vector3 > & p_vertices , const Vector < Vector2 > & p_uvs , const Vector < Color > & p_colors , const Vector < Vector2 > & p_uv2s , const Vector < Vector3 > & p_normals , const Vector < Plane > & p_tangents ) {
2016-04-18 19:33:54 +02:00
ERR_FAIL_COND ( ! begun ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( primitive ! = Mesh : : PRIMITIVE_TRIANGLES ) ;
2019-02-13 09:23:29 +01:00
ERR_FAIL_COND ( p_vertices . size ( ) < 3 ) ;
2017-03-05 16:44:50 +01:00
# define ADD_POINT(n) \
{ \
if ( p_colors . size ( ) > n ) \
2020-12-02 02:40:47 +01:00
set_color ( p_colors [ n ] ) ; \
2017-03-05 16:44:50 +01:00
if ( p_uvs . size ( ) > n ) \
2020-12-02 02:40:47 +01:00
set_uv ( p_uvs [ n ] ) ; \
2017-03-05 16:44:50 +01:00
if ( p_uv2s . size ( ) > n ) \
2020-12-02 02:40:47 +01:00
set_uv2 ( p_uv2s [ n ] ) ; \
2017-03-05 16:44:50 +01:00
if ( p_normals . size ( ) > n ) \
2020-12-02 02:40:47 +01:00
set_normal ( p_normals [ n ] ) ; \
2017-03-05 16:44:50 +01:00
if ( p_tangents . size ( ) > n ) \
2020-12-02 02:40:47 +01:00
set_tangent ( p_tangents [ n ] ) ; \
2019-02-13 09:23:29 +01:00
add_vertex ( p_vertices [ n ] ) ; \
2016-04-18 19:33:54 +02:00
}
2019-02-13 09:23:29 +01:00
for ( int i = 0 ; i < p_vertices . size ( ) - 2 ; i + + ) {
2016-04-18 19:33:54 +02:00
ADD_POINT ( 0 ) ;
2017-03-05 16:44:50 +01:00
ADD_POINT ( i + 1 ) ;
ADD_POINT ( i + 2 ) ;
2016-04-18 19:33:54 +02:00
}
# undef ADD_POINT
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_index ( int p_index ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! begun ) ;
2021-02-18 22:43:39 +01:00
ERR_FAIL_COND ( p_index < 0 ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_INDEX ;
2014-02-10 02:10:30 +01:00
index_array . push_back ( p_index ) ;
}
2017-08-02 20:34:55 +02:00
Array SurfaceTool : : commit_to_arrays ( ) {
2017-03-05 16:44:50 +01:00
int varr_len = vertex_array . size ( ) ;
2014-02-10 02:10:30 +01:00
Array a ;
a . resize ( Mesh : : ARRAY_MAX ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < Mesh : : ARRAY_MAX ; i + + ) {
2023-08-29 21:04:32 +02:00
if ( ! ( format & ( 1ULL < < i ) ) ) {
2017-08-02 20:34:55 +02:00
continue ; //not in format
2020-05-14 16:41:43 +02:00
}
2017-08-02 20:34:55 +02:00
switch ( i ) {
case Mesh : : ARRAY_VERTEX :
case Mesh : : ARRAY_NORMAL : {
2020-02-17 22:06:54 +01:00
Vector < Vector3 > array ;
2014-02-10 02:10:30 +01:00
array . resize ( varr_len ) ;
2020-02-17 22:06:54 +01:00
Vector3 * w = array . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
switch ( i ) {
2014-02-10 02:10:30 +01:00
case Mesh : : ARRAY_VERTEX : {
2017-03-05 16:44:50 +01:00
w [ idx ] = v . vertex ;
2014-02-10 02:10:30 +01:00
} break ;
case Mesh : : ARRAY_NORMAL : {
2017-03-05 16:44:50 +01:00
w [ idx ] = v . normal ;
2014-02-10 02:10:30 +01:00
} break ;
}
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2014-02-10 02:10:30 +01:00
} break ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_TEX_UV :
case Mesh : : ARRAY_TEX_UV2 : {
2020-02-17 22:06:54 +01:00
Vector < Vector2 > array ;
2014-02-10 02:10:30 +01:00
array . resize ( varr_len ) ;
2020-02-17 22:06:54 +01:00
Vector2 * w = array . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
switch ( i ) {
2014-02-10 02:10:30 +01:00
case Mesh : : ARRAY_TEX_UV : {
2017-03-05 16:44:50 +01:00
w [ idx ] = v . uv ;
2014-02-10 02:10:30 +01:00
} break ;
case Mesh : : ARRAY_TEX_UV2 : {
2017-03-05 16:44:50 +01:00
w [ idx ] = v . uv2 ;
2014-02-10 02:10:30 +01:00
} break ;
}
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2014-02-10 02:10:30 +01:00
} break ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_TANGENT : {
2020-02-17 22:06:54 +01:00
Vector < float > array ;
2017-03-05 16:44:50 +01:00
array . resize ( varr_len * 4 ) ;
2020-02-17 22:06:54 +01:00
float * w = array . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2014-02-10 02:10:30 +01:00
2021-06-12 00:40:13 +02:00
w [ idx * 4 + 0 ] = v . tangent . x ;
w [ idx * 4 + 1 ] = v . tangent . y ;
w [ idx * 4 + 2 ] = v . tangent . z ;
2014-10-14 06:01:25 +02:00
//float d = v.tangent.dot(v.binormal,v.normal);
2017-03-05 16:44:50 +01:00
float d = v . binormal . dot ( v . normal . cross ( v . tangent ) ) ;
2021-06-12 00:40:13 +02:00
w [ idx * 4 + 3 ] = d < 0 ? - 1 : 1 ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2014-02-10 02:10:30 +01:00
} break ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_COLOR : {
2020-02-17 22:06:54 +01:00
Vector < Color > array ;
2014-02-10 02:10:30 +01:00
array . resize ( varr_len ) ;
2020-02-17 22:06:54 +01:00
Color * w = array . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2017-03-05 16:44:50 +01:00
w [ idx ] = v . color ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2016-03-09 00:00:52 +01:00
} break ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2021-09-09 06:29:14 +02:00
const Color & c = v . custom [ fmt ] ;
2020-12-02 02:40:47 +01:00
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 ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_BONES : {
2020-12-02 02:40:47 +01:00
int count = skin_weights = = SKIN_8_WEIGHTS ? 8 : 4 ;
2020-02-17 22:06:54 +01:00
Vector < int > array ;
2020-12-02 02:40:47 +01:00
array . resize ( varr_len * count ) ;
2021-06-07 21:30:07 +02:00
array . fill ( 0 ) ;
2020-02-17 22:06:54 +01:00
int * w = array . ptrw ( ) ;
2016-11-25 00:46:55 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2016-11-25 00:46:55 +01:00
2023-02-12 14:14:03 +01:00
if ( v . bones . size ( ) ! = count ) {
2021-06-07 21:30:07 +02:00
ERR_PRINT_ONCE ( vformat ( " Invalid bones size %d vs count %d " , v . bones . size ( ) , count ) ) ;
continue ;
}
2016-11-25 00:46:55 +01:00
2020-12-02 02:40:47 +01:00
for ( int j = 0 ; j < count ; j + + ) {
2020-12-16 15:07:08 +01:00
w [ idx * count + j ] = v . bones [ j ] ;
2016-11-25 00:46:55 +01:00
}
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2016-11-25 00:46:55 +01:00
} break ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_WEIGHTS : {
2020-02-17 22:06:54 +01:00
Vector < float > array ;
2020-12-02 02:40:47 +01:00
int count = skin_weights = = SKIN_8_WEIGHTS ? 8 : 4 ;
array . resize ( varr_len * count ) ;
2021-06-07 21:30:07 +02:00
array . fill ( 0.0f ) ;
2020-02-17 22:06:54 +01:00
float * w = array . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < vertex_array . size ( ) ; idx + + ) {
const Vertex & v = vertex_array [ idx ] ;
2023-02-12 14:14:03 +01:00
if ( v . weights . size ( ) ! = count ) {
2021-06-07 21:30:07 +02:00
ERR_PRINT_ONCE ( vformat ( " Invalid weight size %d vs count %d " , v . weights . size ( ) , count ) ) ;
continue ;
}
2014-02-10 02:10:30 +01:00
2020-12-02 02:40:47 +01:00
for ( int j = 0 ; j < count ; j + + ) {
2020-12-16 15:07:08 +01:00
w [ idx * count + j ] = v . weights [ j ] ;
2014-02-10 02:10:30 +01:00
}
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2014-02-10 02:10:30 +01:00
} break ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_INDEX : {
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( index_array . size ( ) = = 0 ) ;
2014-02-10 02:10:30 +01:00
2020-02-17 22:06:54 +01:00
Vector < int > array ;
2014-02-10 02:10:30 +01:00
array . resize ( index_array . size ( ) ) ;
2020-02-17 22:06:54 +01:00
int * w = array . ptrw ( ) ;
2014-02-10 02:10:30 +01:00
2020-12-12 13:06:59 +01:00
for ( uint32_t idx = 0 ; idx < index_array . size ( ) ; idx + + ) {
w [ idx ] = index_array [ idx ] ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2014-02-10 02:10:30 +01:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2014-02-10 02:10:30 +01:00
}
}
2017-08-02 20:34:55 +02:00
return a ;
}
2023-08-29 21:04:32 +02:00
Ref < ArrayMesh > SurfaceTool : : commit ( const Ref < ArrayMesh > & p_existing , uint64_t p_compress_flags ) {
2017-08-02 20:34:55 +02:00
Ref < ArrayMesh > mesh ;
2020-05-14 16:41:43 +02:00
if ( p_existing . is_valid ( ) ) {
2017-08-02 20:34:55 +02:00
mesh = p_existing ;
2020-05-14 16:41:43 +02:00
} else {
2021-06-18 00:03:09 +02:00
mesh . instantiate ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-08-02 20:34:55 +02:00
int varr_len = vertex_array . size ( ) ;
2020-05-14 16:41:43 +02:00
if ( varr_len = = 0 ) {
2017-08-02 20:34:55 +02:00
return mesh ;
2020-05-14 16:41:43 +02:00
}
2017-08-02 20:34:55 +02:00
int surface = mesh - > get_surface_count ( ) ;
Array a = commit_to_arrays ( ) ;
2023-10-12 22:01:41 +02:00
uint64_t compress_flags = ( p_compress_flags > > RS : : ARRAY_COMPRESS_FLAGS_BASE ) < < RS : : ARRAY_COMPRESS_FLAGS_BASE ;
static const uint64_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 } ;
2022-06-12 01:15:44 +02:00
for ( int i = 0 ; i < RS : : ARRAY_CUSTOM_COUNT ; i + + ) {
if ( last_custom_format [ i ] ! = CUSTOM_MAX ) {
2023-10-12 22:01:41 +02:00
compress_flags | = uint64_t ( last_custom_format [ i ] ) < < shift [ i ] ;
2022-06-12 01:15:44 +02:00
}
}
mesh - > add_surface_from_arrays ( primitive , a , Array ( ) , Dictionary ( ) , compress_flags ) ;
2017-11-21 01:36:32 +01:00
2020-05-14 16:41:43 +02:00
if ( material . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
mesh - > surface_set_material ( surface , material ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return mesh ;
}
void SurfaceTool : : index ( ) {
2020-05-14 16:41:43 +02:00
if ( index_array . size ( ) ) {
2014-05-14 06:22:15 +02:00
return ; //already indexed
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
HashMap < Vertex , int , VertexHasher > indices ;
2020-12-12 13:06:59 +01:00
LocalVector < Vertex > old_vertex_array = vertex_array ;
vertex_array . clear ( ) ;
2014-02-10 02:10:30 +01:00
2022-12-29 01:24:45 +01:00
for ( const Vertex & vertex : old_vertex_array ) {
int * idxptr = indices . getptr ( vertex ) ;
2014-05-14 06:22:15 +02:00
int idx ;
if ( ! idxptr ) {
2017-03-05 16:44:50 +01:00
idx = indices . size ( ) ;
2022-12-29 01:24:45 +01:00
vertex_array . push_back ( vertex ) ;
indices [ vertex ] = idx ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
idx = * idxptr ;
2014-02-10 02:10:30 +01:00
}
2014-05-14 06:22:15 +02:00
index_array . push_back ( idx ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_INDEX ;
2014-02-10 02:10:30 +01:00
}
void SurfaceTool : : deindex ( ) {
2020-05-14 16:41:43 +02:00
if ( index_array . size ( ) = = 0 ) {
2014-05-14 06:22:15 +02:00
return ; //nothing to deindex
2020-05-14 16:41:43 +02:00
}
2020-12-12 13:06:59 +01:00
LocalVector < Vertex > old_vertex_array = vertex_array ;
2014-05-14 06:22:15 +02:00
vertex_array . clear ( ) ;
2022-12-29 01:24:45 +01:00
for ( const int & index : index_array ) {
ERR_FAIL_COND ( uint32_t ( index ) > = old_vertex_array . size ( ) ) ;
2020-12-12 13:06:59 +01:00
vertex_array . push_back ( old_vertex_array [ index ] ) ;
2014-05-14 06:22:15 +02:00
}
2017-03-05 16:44:50 +01:00
format & = ~ Mesh : : ARRAY_FORMAT_INDEX ;
2017-08-02 20:34:55 +02:00
index_array . clear ( ) ;
2014-02-10 02:10:30 +01:00
}
2023-08-29 21:04:32 +02:00
void SurfaceTool : : _create_list ( const Ref < Mesh > & p_existing , int p_surface , LocalVector < Vertex > * r_vertex , LocalVector < int > * r_index , uint64_t & lformat ) {
2021-05-02 05:17:27 +02:00
ERR_FAIL_NULL_MSG ( p_existing , " First argument in SurfaceTool::_create_list() must be a valid object of type Mesh " ) ;
2014-02-10 02:10:30 +01:00
Array arr = p_existing - > surface_get_arrays ( p_surface ) ;
2020-03-27 19:21:27 +01:00
ERR_FAIL_COND ( arr . size ( ) ! = RS : : ARRAY_MAX ) ;
2017-08-02 20:34:55 +02:00
_create_list_from_arrays ( arr , r_vertex , r_index , lformat ) ;
}
2023-05-17 17:22:26 +02:00
const uint32_t SurfaceTool : : custom_mask [ RS : : ARRAY_CUSTOM_COUNT ] = { Mesh : : ARRAY_FORMAT_CUSTOM0 , Mesh : : ARRAY_FORMAT_CUSTOM1 , Mesh : : ARRAY_FORMAT_CUSTOM2 , Mesh : : ARRAY_FORMAT_CUSTOM3 } ;
const uint32_t SurfaceTool : : 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 } ;
2021-09-09 06:29:14 +02:00
2023-08-29 21:04:32 +02:00
void SurfaceTool : : create_vertex_array_from_triangle_arrays ( const Array & p_arrays , LocalVector < SurfaceTool : : Vertex > & ret , uint64_t * r_format ) {
2020-12-12 13:06:59 +01:00
ret . clear ( ) ;
2017-12-09 18:11:26 +01:00
2020-03-27 19:21:27 +01:00
Vector < Vector3 > varr = p_arrays [ RS : : ARRAY_VERTEX ] ;
Vector < Vector3 > narr = p_arrays [ RS : : ARRAY_NORMAL ] ;
Vector < float > tarr = p_arrays [ RS : : ARRAY_TANGENT ] ;
Vector < Color > carr = p_arrays [ RS : : ARRAY_COLOR ] ;
Vector < Vector2 > uvarr = p_arrays [ RS : : ARRAY_TEX_UV ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
Vector < float > custom_float [ RS : : ARRAY_CUSTOM_COUNT ] ;
2017-12-09 18:11:26 +01:00
int vc = varr . size ( ) ;
2020-05-14 16:41:43 +02:00
if ( vc = = 0 ) {
2020-12-02 02:40:47 +01:00
if ( r_format ) {
* r_format = 0 ;
}
2020-12-12 13:06:59 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-12-09 18:11:26 +01:00
2023-10-12 22:01:41 +02:00
uint64_t lformat = 0 ;
2017-12-09 18:11:26 +01:00
if ( varr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_VERTEX ;
2017-12-09 18:11:26 +01:00
}
if ( narr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_NORMAL ;
2017-12-09 18:11:26 +01:00
}
if ( tarr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_TANGENT ;
2017-12-09 18:11:26 +01:00
}
if ( carr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_COLOR ;
2017-12-09 18:11:26 +01:00
}
if ( uvarr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_TEX_UV ;
2017-12-09 18:11:26 +01:00
}
if ( uv2arr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_TEX_UV2 ;
2017-12-09 18:11:26 +01:00
}
2020-12-02 02:40:47 +01:00
int wcount = 0 ;
if ( barr . size ( ) & & warr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_BONES ;
2020-12-02 02:40:47 +01:00
lformat | = RS : : ARRAY_FORMAT_WEIGHTS ;
wcount = barr . size ( ) / varr . size ( ) ;
if ( wcount = = 8 ) {
lformat | = RS : : ARRAY_FLAG_USE_8_BONE_WEIGHTS ;
}
2017-12-09 18:11:26 +01:00
}
2020-12-02 02:40:47 +01:00
2017-12-09 18:11:26 +01:00
if ( warr . size ( ) ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_WEIGHTS ;
2017-12-09 18:11:26 +01:00
}
2020-12-02 02:40:47 +01:00
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 ] ;
}
}
}
2017-12-09 18:11:26 +01:00
for ( int i = 0 ; i < vc ; i + + ) {
Vertex v ;
2020-05-14 16:41:43 +02:00
if ( lformat & RS : : ARRAY_FORMAT_VERTEX ) {
2017-12-09 18:11:26 +01:00
v . vertex = varr [ i ] ;
2020-05-14 16:41:43 +02:00
}
if ( lformat & RS : : ARRAY_FORMAT_NORMAL ) {
2017-12-09 18:11:26 +01:00
v . normal = narr [ i ] ;
2020-05-14 16:41:43 +02:00
}
2020-03-27 19:21:27 +01:00
if ( lformat & RS : : ARRAY_FORMAT_TANGENT ) {
2017-12-09 18:11:26 +01:00
Plane p ( tarr [ i * 4 + 0 ] , tarr [ i * 4 + 1 ] , tarr [ i * 4 + 2 ] , tarr [ i * 4 + 3 ] ) ;
v . tangent = p . normal ;
2020-05-10 16:47:11 +02:00
v . binormal = p . normal . cross ( v . tangent ) . normalized ( ) * p . d ;
2017-12-09 18:11:26 +01:00
}
2020-05-14 16:41:43 +02:00
if ( lformat & RS : : ARRAY_FORMAT_COLOR ) {
2017-12-09 18:11:26 +01:00
v . color = carr [ i ] ;
2020-05-14 16:41:43 +02:00
}
if ( lformat & RS : : ARRAY_FORMAT_TEX_UV ) {
2017-12-09 18:11:26 +01:00
v . uv = uvarr [ i ] ;
2020-05-14 16:41:43 +02:00
}
if ( lformat & RS : : ARRAY_FORMAT_TEX_UV2 ) {
2017-12-09 18:11:26 +01:00
v . uv2 = uv2arr [ i ] ;
2020-05-14 16:41:43 +02:00
}
2020-03-27 19:21:27 +01:00
if ( lformat & RS : : ARRAY_FORMAT_BONES ) {
2017-12-09 18:11:26 +01:00
Vector < int > b ;
2020-12-02 02:40:47 +01:00
b . resize ( wcount ) ;
for ( int j = 0 ; j < wcount ; j + + ) {
b . write [ j ] = barr [ i * wcount + j ] ;
}
2017-12-09 18:11:26 +01:00
v . bones = b ;
}
2020-03-27 19:21:27 +01:00
if ( lformat & RS : : ARRAY_FORMAT_WEIGHTS ) {
2017-12-09 18:11:26 +01:00
Vector < float > w ;
2020-12-02 02:40:47 +01:00
w . resize ( wcount ) ;
for ( int j = 0 ; j < wcount ; j + + ) {
w . write [ j ] = warr [ i * wcount + j ] ;
}
2017-12-09 18:11:26 +01:00
v . weights = w ;
}
2020-12-02 02:40:47 +01:00
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 ] ;
}
}
}
2017-12-09 18:11:26 +01:00
ret . push_back ( v ) ;
}
2020-12-02 02:40:47 +01:00
if ( r_format ) {
* r_format = lformat ;
2020-05-14 16:41:43 +02:00
}
2020-12-02 02:40:47 +01:00
}
2014-02-10 02:10:30 +01:00
2023-08-29 21:04:32 +02:00
void SurfaceTool : : _create_list_from_arrays ( Array arr , LocalVector < Vertex > * r_vertex , LocalVector < int > * r_index , uint64_t & lformat ) {
2020-12-12 13:06:59 +01:00
create_vertex_array_from_triangle_arrays ( arr , * r_vertex , & lformat ) ;
ERR_FAIL_COND ( r_vertex - > size ( ) = = 0 ) ;
2014-02-10 02:10:30 +01:00
//indices
2020-12-12 13:06:59 +01:00
r_index - > clear ( ) ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
Vector < int > idx = arr [ RS : : ARRAY_INDEX ] ;
2014-02-10 02:10:30 +01:00
int is = idx . size ( ) ;
if ( is ) {
2020-03-27 19:21:27 +01:00
lformat | = RS : : ARRAY_FORMAT_INDEX ;
2020-02-17 22:06:54 +01:00
const int * iarr = idx . ptr ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < is ; i + + ) {
2014-02-10 02:10:30 +01:00
r_index - > push_back ( iarr [ i ] ) ;
}
}
}
2017-08-02 20:34:55 +02:00
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 ) ;
2021-09-09 06:29:14 +02:00
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 ) ;
}
}
2017-08-02 20:34:55 +02:00
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : create_from ( const Ref < Mesh > & p_existing , int p_surface ) {
2021-05-02 05:17:27 +02:00
ERR_FAIL_NULL_MSG ( p_existing , " First argument in SurfaceTool::create_from() must be a valid object of type Mesh " ) ;
2014-02-10 02:10:30 +01:00
clear ( ) ;
2017-03-05 16:44:50 +01:00
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 ) ;
2021-09-09 06:29:14 +02:00
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 ) ;
}
}
2014-02-10 02:10:30 +01:00
}
2019-07-10 11:54:12 +02:00
void SurfaceTool : : create_from_blend_shape ( const Ref < Mesh > & p_existing , int p_surface , const String & p_blend_shape_name ) {
2021-05-02 05:17:27 +02:00
ERR_FAIL_NULL_MSG ( p_existing , " First argument in SurfaceTool::create_from_blend_shape() must be a valid object of type Mesh " ) ;
2019-02-27 15:51:04 +01:00
clear ( ) ;
primitive = p_existing - > surface_get_primitive_type ( p_surface ) ;
Array arr = p_existing - > surface_get_blend_shape_arrays ( p_surface ) ;
Array blend_shape_names ;
int32_t shape_idx = - 1 ;
for ( int32_t i = 0 ; i < p_existing - > get_blend_shape_count ( ) ; i + + ) {
String name = p_existing - > get_blend_shape_name ( i ) ;
if ( name = = p_blend_shape_name ) {
shape_idx = i ;
break ;
}
}
ERR_FAIL_COND ( shape_idx = = - 1 ) ;
ERR_FAIL_COND ( shape_idx > = arr . size ( ) ) ;
2023-05-02 08:48:48 +02:00
Array blendshape_mesh_arrays = arr [ shape_idx ] ;
ERR_FAIL_COND ( blendshape_mesh_arrays . size ( ) ! = RS : : ARRAY_MAX ) ;
Array source_mesh_arrays = p_existing - > surface_get_arrays ( p_surface ) ;
ERR_FAIL_COND ( source_mesh_arrays . size ( ) ! = RS : : ARRAY_MAX ) ;
// Copy BlendShape vertex data over while keeping e.g. bones, weights, index from existing mesh intact.
source_mesh_arrays [ RS : : ARRAY_VERTEX ] = blendshape_mesh_arrays [ RS : : ARRAY_VERTEX ] ;
source_mesh_arrays [ RS : : ARRAY_NORMAL ] = blendshape_mesh_arrays [ RS : : ARRAY_NORMAL ] ;
source_mesh_arrays [ RS : : ARRAY_TANGENT ] = blendshape_mesh_arrays [ RS : : ARRAY_TANGENT ] ;
_create_list_from_arrays ( source_mesh_arrays , & vertex_array , & index_array , format ) ;
material = p_existing - > surface_get_material ( p_surface ) ;
format = p_existing - > surface_get_format ( p_surface ) ;
2021-09-09 06:29:14 +02:00
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 ) ;
}
}
2019-02-27 15:51:04 +01:00
}
2020-10-17 07:08:21 +02:00
void SurfaceTool : : append_from ( const Ref < Mesh > & p_existing , int p_surface , const Transform3D & p_xform ) {
2021-05-02 05:17:27 +02:00
ERR_FAIL_NULL_MSG ( p_existing , " First argument in SurfaceTool::append_from() must be a valid object of type Mesh " ) ;
2017-03-05 16:44:50 +01:00
if ( vertex_array . size ( ) = = 0 ) {
primitive = p_existing - > surface_get_primitive_type ( p_surface ) ;
format = 0 ;
2014-02-10 02:10:30 +01:00
}
2023-08-29 21:04:32 +02:00
uint64_t nformat = 0 ;
2020-12-12 13:06:59 +01:00
LocalVector < Vertex > nvertices ;
LocalVector < int > nindices ;
2017-03-05 16:44:50 +01:00
_create_list ( p_existing , p_surface , & nvertices , & nindices , nformat ) ;
format | = nformat ;
2021-09-09 06:29:14 +02:00
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 ) ;
last_custom_format [ j ] = new_format ;
}
}
2014-02-10 02:10:30 +01:00
int vfrom = vertex_array . size ( ) ;
2022-12-29 01:24:45 +01:00
for ( Vertex & v : nvertices ) {
2017-03-05 16:44:50 +01:00
v . vertex = p_xform . xform ( v . vertex ) ;
2020-03-27 19:21:27 +01:00
if ( nformat & RS : : ARRAY_FORMAT_NORMAL ) {
2017-03-05 16:44:50 +01:00
v . normal = p_xform . basis . xform ( v . normal ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-27 19:21:27 +01:00
if ( nformat & RS : : ARRAY_FORMAT_TANGENT ) {
2017-03-05 16:44:50 +01:00
v . tangent = p_xform . basis . xform ( v . tangent ) ;
v . binormal = p_xform . basis . xform ( v . binormal ) ;
2014-02-10 02:10:30 +01:00
}
vertex_array . push_back ( v ) ;
}
2022-12-29 01:24:45 +01:00
for ( const int & index : nindices ) {
int dst_index = index + vfrom ;
2014-02-10 02:10:30 +01:00
index_array . push_back ( dst_index ) ;
}
2018-08-24 09:35:07 +02:00
if ( index_array . size ( ) % 3 ) {
WARN_PRINT ( " SurfaceTool: Index array not a multiple of 3. " ) ;
}
2014-02-10 02:10:30 +01:00
}
2014-10-14 06:01:25 +02:00
//mikktspace callbacks
2018-11-26 16:09:52 +01:00
namespace {
struct TangentGenerationContextUserData {
2020-12-12 13:06:59 +01:00
LocalVector < SurfaceTool : : Vertex > * vertices ;
LocalVector < int > * indices ;
2018-11-26 16:09:52 +01:00
} ;
} // namespace
2017-03-05 16:44:50 +01:00
int SurfaceTool : : mikktGetNumFaces ( const SMikkTSpaceContext * pContext ) {
2018-11-26 16:09:52 +01:00
TangentGenerationContextUserData & triangle_data = * reinterpret_cast < TangentGenerationContextUserData * > ( pContext - > m_pUserData ) ;
2020-12-12 13:06:59 +01:00
if ( triangle_data . indices - > size ( ) > 0 ) {
return triangle_data . indices - > size ( ) / 3 ;
2018-11-26 16:09:52 +01:00
} else {
2020-12-12 13:06:59 +01:00
return triangle_data . vertices - > size ( ) / 3 ;
2018-11-26 16:09:52 +01:00
}
2014-10-14 06:01:25 +02:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
int SurfaceTool : : mikktGetNumVerticesOfFace ( const SMikkTSpaceContext * pContext , const int iFace ) {
2014-10-14 06:01:25 +02:00
return 3 ; //always 3
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void SurfaceTool : : mikktGetPosition ( const SMikkTSpaceContext * pContext , float fvPosOut [ ] , const int iFace , const int iVert ) {
2018-11-26 16:09:52 +01:00
TangentGenerationContextUserData & triangle_data = * reinterpret_cast < TangentGenerationContextUserData * > ( pContext - > m_pUserData ) ;
Vector3 v ;
2020-12-12 13:06:59 +01:00
if ( triangle_data . indices - > size ( ) > 0 ) {
uint32_t index = triangle_data . indices - > operator [ ] ( iFace * 3 + iVert ) ;
if ( index < triangle_data . vertices - > size ( ) ) {
v = triangle_data . vertices - > operator [ ] ( index ) . vertex ;
2018-11-26 16:09:52 +01:00
}
} else {
2020-12-12 13:06:59 +01:00
v = triangle_data . vertices - > operator [ ] ( iFace * 3 + iVert ) . vertex ;
2018-11-26 16:09:52 +01:00
}
2017-03-05 16:44:50 +01:00
fvPosOut [ 0 ] = v . x ;
fvPosOut [ 1 ] = v . y ;
fvPosOut [ 2 ] = v . z ;
2014-10-14 06:01:25 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
void SurfaceTool : : mikktGetNormal ( const SMikkTSpaceContext * pContext , float fvNormOut [ ] , const int iFace , const int iVert ) {
2018-11-26 16:09:52 +01:00
TangentGenerationContextUserData & triangle_data = * reinterpret_cast < TangentGenerationContextUserData * > ( pContext - > m_pUserData ) ;
Vector3 v ;
2020-12-12 13:06:59 +01:00
if ( triangle_data . indices - > size ( ) > 0 ) {
uint32_t index = triangle_data . indices - > operator [ ] ( iFace * 3 + iVert ) ;
if ( index < triangle_data . vertices - > size ( ) ) {
v = triangle_data . vertices - > operator [ ] ( index ) . normal ;
2018-11-26 16:09:52 +01:00
}
} else {
2020-12-12 13:06:59 +01:00
v = triangle_data . vertices - > operator [ ] ( iFace * 3 + iVert ) . normal ;
2018-11-26 16:09:52 +01:00
}
2017-03-05 16:44:50 +01:00
fvNormOut [ 0 ] = v . x ;
fvNormOut [ 1 ] = v . y ;
fvNormOut [ 2 ] = v . z ;
2014-10-14 06:01:25 +02:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void SurfaceTool : : mikktGetTexCoord ( const SMikkTSpaceContext * pContext , float fvTexcOut [ ] , const int iFace , const int iVert ) {
2018-11-26 16:09:52 +01:00
TangentGenerationContextUserData & triangle_data = * reinterpret_cast < TangentGenerationContextUserData * > ( pContext - > m_pUserData ) ;
Vector2 v ;
2020-12-12 13:06:59 +01:00
if ( triangle_data . indices - > size ( ) > 0 ) {
uint32_t index = triangle_data . indices - > operator [ ] ( iFace * 3 + iVert ) ;
if ( index < triangle_data . vertices - > size ( ) ) {
v = triangle_data . vertices - > operator [ ] ( index ) . uv ;
2018-11-26 16:09:52 +01:00
}
} else {
2020-12-12 13:06:59 +01:00
v = triangle_data . vertices - > operator [ ] ( iFace * 3 + iVert ) . uv ;
2018-11-26 16:09:52 +01:00
}
2017-03-05 16:44:50 +01:00
fvTexcOut [ 0 ] = v . x ;
fvTexcOut [ 1 ] = v . y ;
2014-10-14 06:01:25 +02:00
}
2017-08-29 13:47:29 +02:00
void SurfaceTool : : mikktSetTSpaceDefault ( const SMikkTSpaceContext * pContext , const float fvTangent [ ] , const float fvBiTangent [ ] , const float fMagS , const float fMagT ,
const tbool bIsOrientationPreserving , const int iFace , const int iVert ) {
2018-11-26 16:09:52 +01:00
TangentGenerationContextUserData & triangle_data = * reinterpret_cast < TangentGenerationContextUserData * > ( pContext - > m_pUserData ) ;
2020-04-02 01:20:12 +02:00
Vertex * vtx = nullptr ;
2020-12-12 13:06:59 +01:00
if ( triangle_data . indices - > size ( ) > 0 ) {
uint32_t index = triangle_data . indices - > operator [ ] ( iFace * 3 + iVert ) ;
if ( index < triangle_data . vertices - > size ( ) ) {
vtx = & triangle_data . vertices - > operator [ ] ( index ) ;
2018-11-26 16:09:52 +01:00
}
} else {
2020-12-12 13:06:59 +01:00
vtx = & triangle_data . vertices - > operator [ ] ( iFace * 3 + iVert ) ;
2018-11-26 16:09:52 +01:00
}
2014-05-14 06:22:15 +02:00
2020-04-02 01:20:12 +02:00
if ( vtx ! = nullptr ) {
2018-11-26 16:09:52 +01:00
vtx - > tangent = Vector3 ( fvTangent [ 0 ] , fvTangent [ 1 ] , fvTangent [ 2 ] ) ;
2018-12-08 03:43:46 +01:00
vtx - > binormal = Vector3 ( - fvBiTangent [ 0 ] , - fvBiTangent [ 1 ] , - fvBiTangent [ 2 ] ) ; // for some reason these are reversed, something with the coordinate system in Godot
2018-11-26 16:09:52 +01:00
}
2014-10-14 06:01:25 +02:00
}
2014-05-14 06:22:15 +02:00
2014-10-14 06:01:25 +02:00
void SurfaceTool : : generate_tangents ( ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( ! ( format & Mesh : : ARRAY_FORMAT_TEX_UV ) ) ;
ERR_FAIL_COND ( ! ( format & Mesh : : ARRAY_FORMAT_NORMAL ) ) ;
2014-05-14 06:22:15 +02:00
2014-10-14 06:01:25 +02:00
SMikkTSpaceInterface mkif ;
2017-03-05 16:44:50 +01:00
mkif . m_getNormal = mikktGetNormal ;
mkif . m_getNumFaces = mikktGetNumFaces ;
mkif . m_getNumVerticesOfFace = mikktGetNumVerticesOfFace ;
mkif . m_getPosition = mikktGetPosition ;
mkif . m_getTexCoord = mikktGetTexCoord ;
2017-08-29 13:47:29 +02:00
mkif . m_setTSpace = mikktSetTSpaceDefault ;
2020-04-02 01:20:12 +02:00
mkif . m_setTSpaceBasic = nullptr ;
2014-05-14 06:22:15 +02:00
2014-10-14 06:01:25 +02:00
SMikkTSpaceContext msc ;
2017-03-05 16:44:50 +01:00
msc . m_pInterface = & mkif ;
2014-05-14 06:22:15 +02:00
2018-11-26 16:09:52 +01:00
TangentGenerationContextUserData triangle_data ;
2020-12-12 13:06:59 +01:00
triangle_data . vertices = & vertex_array ;
2022-12-29 01:24:45 +01:00
for ( Vertex & vertex : vertex_array ) {
vertex . binormal = Vector3 ( ) ;
vertex . tangent = Vector3 ( ) ;
2018-11-26 16:09:52 +01:00
}
2020-12-12 13:06:59 +01:00
triangle_data . indices = & index_array ;
2018-11-26 16:09:52 +01:00
msc . m_pUserData = & triangle_data ;
2014-05-14 06:22:15 +02:00
2014-10-14 06:01:25 +02:00
bool res = genTangSpaceDefault ( & msc ) ;
2014-05-14 06:22:15 +02:00
2014-10-14 06:01:25 +02:00
ERR_FAIL_COND ( ! res ) ;
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_TANGENT ;
2014-02-10 02:10:30 +01:00
}
2018-02-14 20:14:23 +01:00
void SurfaceTool : : generate_normals ( bool p_flip ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( primitive ! = Mesh : : PRIMITIVE_TRIANGLES ) ;
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
bool was_indexed = index_array . size ( ) ;
2014-05-14 06:22:15 +02:00
deindex ( ) ;
2020-12-12 13:06:59 +01:00
ERR_FAIL_COND ( ( vertex_array . size ( ) % 3 ) ! = 0 ) ;
2014-05-14 06:22:15 +02:00
2022-10-29 22:37:09 +02:00
HashMap < SmoothGroupVertex , Vector3 , SmoothGroupVertexHasher > smooth_hash ;
2014-05-14 06:22:15 +02:00
2020-12-12 13:06:59 +01:00
for ( uint32_t vi = 0 ; vi < vertex_array . size ( ) ; vi + = 3 ) {
Vertex * v = & vertex_array [ vi ] ;
2014-05-14 06:22:15 +02:00
2018-02-14 20:14:23 +01:00
Vector3 normal ;
2020-05-14 16:41:43 +02:00
if ( ! p_flip ) {
2020-12-12 13:06:59 +01:00
normal = Plane ( v [ 0 ] . vertex , v [ 1 ] . vertex , v [ 2 ] . vertex ) . normal ;
2020-05-14 16:41:43 +02:00
} else {
2020-12-12 13:06:59 +01:00
normal = Plane ( v [ 2 ] . vertex , v [ 1 ] . vertex , v [ 0 ] . vertex ) . normal ;
2020-05-14 16:41:43 +02:00
}
2014-05-14 06:22:15 +02:00
2020-12-12 13:06:59 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2022-10-29 22:37:09 +02:00
// Add face normal to smooth vertex influence if vertex is member of a smoothing group
if ( v [ i ] . smooth_group ! = UINT32_MAX ) {
Vector3 * lv = smooth_hash . getptr ( v [ i ] ) ;
if ( ! lv ) {
smooth_hash . insert ( v [ i ] , normal ) ;
} else {
( * lv ) + = normal ;
}
2014-05-14 06:22:15 +02:00
} else {
2022-10-29 22:37:09 +02:00
v [ i ] . normal = normal ;
2014-05-14 06:22:15 +02:00
}
2020-12-12 13:06:59 +01:00
}
}
2014-05-14 06:22:15 +02:00
2022-12-29 01:24:45 +01:00
for ( Vertex & vertex : vertex_array ) {
2022-10-29 22:37:09 +02:00
if ( vertex . smooth_group ! = UINT32_MAX ) {
Vector3 * lv = smooth_hash . getptr ( vertex ) ;
if ( ! lv ) {
vertex . normal = Vector3 ( ) ;
} else {
vertex . normal = lv - > normalized ( ) ;
}
2014-05-14 06:22:15 +02:00
}
}
2017-03-05 16:44:50 +01:00
format | = Mesh : : ARRAY_FORMAT_NORMAL ;
2014-05-14 06:22:15 +02:00
if ( was_indexed ) {
index ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : set_material ( const Ref < Material > & p_material ) {
material = p_material ;
2014-02-10 02:10:30 +01:00
}
2021-03-19 13:57:52 +01:00
Ref < Material > SurfaceTool : : get_material ( ) const {
return material ;
}
2014-02-10 02:10:30 +01:00
void SurfaceTool : : clear ( ) {
2017-03-05 16:44:50 +01:00
begun = false ;
primitive = Mesh : : PRIMITIVE_LINES ;
format = 0 ;
2017-01-14 18:03:38 +01:00
last_bones . clear ( ) ;
2014-02-10 02:10:30 +01:00
last_weights . clear ( ) ;
index_array . clear ( ) ;
vertex_array . clear ( ) ;
2017-07-18 02:05:38 +02:00
material . unref ( ) ;
2020-12-12 13:06:59 +01:00
last_smooth_group = 0 ;
2020-12-02 02:40:47 +01:00
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 ;
}
2022-06-12 01:15:44 +02:00
void SurfaceTool : : set_custom_format ( int p_channel_index , CustomFormat p_format ) {
ERR_FAIL_INDEX ( p_channel_index , RS : : ARRAY_CUSTOM_COUNT ) ;
ERR_FAIL_COND ( ! begun ) ;
ERR_FAIL_INDEX ( p_format , CUSTOM_MAX + 1 ) ;
last_custom_format [ p_channel_index ] = p_format ;
2020-12-02 02:40:47 +01:00
}
2021-03-19 13:57:52 +01:00
2022-06-12 01:15:44 +02:00
Mesh : : PrimitiveType SurfaceTool : : get_primitive_type ( ) const {
2021-03-19 13:57:52 +01:00
return primitive ;
}
2022-06-12 01:15:44 +02:00
SurfaceTool : : CustomFormat SurfaceTool : : get_custom_format ( int p_channel_index ) const {
ERR_FAIL_INDEX_V ( p_channel_index , RS : : ARRAY_CUSTOM_COUNT , CUSTOM_MAX ) ;
return last_custom_format [ p_channel_index ] ;
2014-02-10 02:10:30 +01:00
}
2020-12-12 13:06:59 +01:00
void SurfaceTool : : optimize_indices_for_cache ( ) {
2023-09-09 17:52:40 +02:00
ERR_FAIL_NULL ( optimize_vertex_cache_func ) ;
2020-12-12 13:06:59 +01:00
ERR_FAIL_COND ( index_array . size ( ) = = 0 ) ;
2022-06-12 01:15:44 +02:00
ERR_FAIL_COND ( primitive ! = Mesh : : PRIMITIVE_TRIANGLES ) ;
2021-08-02 17:07:18 +02:00
ERR_FAIL_COND ( index_array . size ( ) % 3 ! = 0 ) ;
2020-12-12 13:06:59 +01:00
LocalVector old_index_array = index_array ;
2021-04-27 16:19:21 +02:00
memset ( index_array . ptr ( ) , 0 , index_array . size ( ) * sizeof ( int ) ) ;
2020-12-12 13:06:59 +01:00
optimize_vertex_cache_func ( ( unsigned int * ) index_array . ptr ( ) , ( unsigned int * ) old_index_array . ptr ( ) , old_index_array . size ( ) , vertex_array . size ( ) ) ;
}
2022-06-12 01:15:44 +02:00
AABB SurfaceTool : : get_aabb ( ) const {
ERR_FAIL_COND_V ( vertex_array . size ( ) = = 0 , AABB ( ) ) ;
2020-12-12 13:06:59 +01:00
AABB aabb ;
for ( uint32_t i = 0 ; i < vertex_array . size ( ) ; i + + ) {
if ( i = = 0 ) {
aabb . position = vertex_array [ i ] . vertex ;
} else {
aabb . expand_to ( vertex_array [ i ] . vertex ) ;
}
}
2022-06-12 01:15:44 +02:00
return aabb ;
2020-12-12 13:06:59 +01:00
}
Vector < int > SurfaceTool : : generate_lod ( float p_threshold , int p_target_index_count ) {
2023-06-06 10:27:29 +02:00
WARN_DEPRECATED_MSG ( R " *(The " SurfaceTool . generate_lod ( ) " method is deprecated. Consider using " ImporterMesh . generate_lods ( ) " instead.)* " ) ;
2020-12-12 13:06:59 +01:00
Vector < int > lod ;
2023-09-09 17:52:40 +02:00
ERR_FAIL_NULL_V ( simplify_func , lod ) ;
2021-10-16 20:21:46 +02:00
ERR_FAIL_COND_V ( p_target_index_count < 0 , lod ) ;
2020-12-12 13:06:59 +01:00
ERR_FAIL_COND_V ( vertex_array . size ( ) = = 0 , lod ) ;
ERR_FAIL_COND_V ( index_array . size ( ) = = 0 , lod ) ;
2021-09-27 14:35:56 +02:00
ERR_FAIL_COND_V ( index_array . size ( ) % 3 ! = 0 , lod ) ;
2021-10-16 20:21:46 +02:00
ERR_FAIL_COND_V ( index_array . size ( ) < ( unsigned int ) p_target_index_count , lod ) ;
2020-12-12 13:06:59 +01:00
lod . resize ( index_array . size ( ) ) ;
LocalVector < float > vertices ; //uses floats
vertices . resize ( vertex_array . size ( ) * 3 ) ;
for ( uint32_t i = 0 ; i < vertex_array . size ( ) ; i + + ) {
vertices [ i * 3 + 0 ] = vertex_array [ i ] . vertex . x ;
vertices [ i * 3 + 1 ] = vertex_array [ i ] . vertex . y ;
vertices [ i * 3 + 2 ] = vertex_array [ i ] . vertex . z ;
}
2020-12-17 19:56:59 +01:00
float error ;
2022-12-22 16:22:33 +01:00
const int simplify_options = SIMPLIFY_LOCK_BORDER ;
uint32_t index_count = simplify_func ( ( unsigned int * ) lod . ptrw ( ) , ( unsigned int * ) index_array . ptr ( ) , index_array . size ( ) , vertices . ptr ( ) , vertex_array . size ( ) , sizeof ( float ) * 3 , p_target_index_count , p_threshold , simplify_options , & error ) ;
2020-12-12 13:06:59 +01:00
ERR_FAIL_COND_V ( index_count = = 0 , lod ) ;
lod . resize ( index_count ) ;
return lod ;
}
2014-02-10 02:10:30 +01:00
void SurfaceTool : : _bind_methods ( ) {
2020-12-02 02:40:47 +01:00
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 ) ;
2022-06-12 01:15:44 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_format " , " channel_index " , " format " ) , & SurfaceTool : : set_custom_format ) ;
ClassDB : : bind_method ( D_METHOD ( " get_custom_format " , " channel_index " ) , & SurfaceTool : : get_custom_format ) ;
2020-12-02 02:40:47 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " begin " , " primitive " ) , & SurfaceTool : : begin ) ;
2017-07-31 11:10:41 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " add_vertex " , " vertex " ) , & SurfaceTool : : add_vertex ) ;
2020-12-02 02:40:47 +01:00
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 ) ;
2022-06-12 01:15:44 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_custom " , " channel_index " , " custom_color " ) , & SurfaceTool : : set_custom ) ;
2020-12-12 13:06:59 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_smooth_group " , " index " ) , & SurfaceTool : : set_smooth_group ) ;
2017-07-31 11:10:41 +02:00
2023-04-25 00:21:32 +02:00
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 ( TypedArray < Plane > ( ) ) ) ;
2017-07-31 11:10:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_index " , " index " ) , & SurfaceTool : : add_index ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " index " ) , & SurfaceTool : : index ) ;
ClassDB : : bind_method ( D_METHOD ( " deindex " ) , & SurfaceTool : : deindex ) ;
2018-02-14 20:14:23 +01:00
ClassDB : : bind_method ( D_METHOD ( " generate_normals " , " flip " ) , & SurfaceTool : : generate_normals , DEFVAL ( false ) ) ;
2017-07-31 11:10:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " generate_tangents " ) , & SurfaceTool : : generate_tangents ) ;
2020-12-12 13:06:59 +01:00
ClassDB : : bind_method ( D_METHOD ( " optimize_indices_for_cache " ) , & SurfaceTool : : optimize_indices_for_cache ) ;
2022-06-12 01:15:44 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_aabb " ) , & SurfaceTool : : get_aabb ) ;
2020-12-12 13:06:59 +01:00
ClassDB : : bind_method ( D_METHOD ( " generate_lod " , " nd_threshold " , " target_index_count " ) , & SurfaceTool : : generate_lod , DEFVAL ( 3 ) ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_material " , " material " ) , & SurfaceTool : : set_material ) ;
2022-06-12 01:15:44 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_primitive_type " ) , & SurfaceTool : : get_primitive_type ) ;
2017-07-31 11:10:41 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & SurfaceTool : : clear ) ;
2017-07-31 11:10:41 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " create_from " , " existing " , " surface " ) , & SurfaceTool : : create_from ) ;
2019-02-27 15:51:04 +01:00
ClassDB : : bind_method ( D_METHOD ( " create_from_blend_shape " , " existing " , " surface " , " blend_shape " ) , & SurfaceTool : : create_from_blend_shape ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " append_from " , " existing " , " surface " , " transform " ) , & SurfaceTool : : append_from ) ;
2020-12-02 02:40:47 +01:00
ClassDB : : bind_method ( D_METHOD ( " commit " , " existing " , " flags " ) , & SurfaceTool : : commit , DEFVAL ( Variant ( ) ) , DEFVAL ( 0 ) ) ;
2019-02-27 15:51:04 +01:00
ClassDB : : bind_method ( D_METHOD ( " commit_to_arrays " ) , & SurfaceTool : : commit_to_arrays ) ;
2020-12-02 02:40:47 +01:00
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 ) ;
2014-02-10 02:10:30 +01:00
}
SurfaceTool : : SurfaceTool ( ) {
2020-12-02 02:40:47 +01:00
for ( int i = 0 ; i < RS : : ARRAY_CUSTOM_COUNT ; i + + ) {
last_custom_format [ i ] = CUSTOM_MAX ;
}
2014-02-10 02:10:30 +01:00
}