2023-01-10 15:26:54 +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
# include "core/method_bind_ext.gen.inc"
2014-02-10 02:10:30 +01:00
# define _VERTEX_SNAP 0.0001
# define EQ_VERTEX_DIST 0.00001
2017-08-11 21:10:05 +02:00
bool SurfaceTool : : Vertex : : operator = = ( const Vertex & p_vertex ) const {
2021-05-05 12:44:11 +02:00
if ( vertex ! = p_vertex . vertex ) {
2014-02-10 02:10:30 +01:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( uv ! = p_vertex . uv ) {
2014-05-14 06:22:15 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( uv2 ! = p_vertex . uv2 ) {
2014-05-14 06:22:15 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( normal ! = p_vertex . normal ) {
2014-05-14 06:22:15 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( binormal ! = p_vertex . binormal ) {
2014-05-14 06:22:15 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2021-05-05 12:44:11 +02:00
if ( color ! = p_vertex . color ) {
2014-05-14 06:22:15 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2022-12-07 14:54:59 +01:00
if ( num_bones ! = p_vertex . num_bones ) {
2014-05-14 06:22:15 +02:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-05-14 06:22:15 +02:00
2022-12-07 14:54:59 +01:00
for ( int i = 0 ; i < num_bones ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( bones [ i ] ! = p_vertex . bones [ i ] ) {
2014-02-10 02:10:30 +01:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
2022-12-07 14:54:59 +01:00
for ( int i = 0 ; i < num_bones ; i + + ) {
2021-05-05 12:44:11 +02:00
if ( weights [ i ] ! = p_vertex . weights [ i ] ) {
2014-02-10 02:10:30 +01:00
return false ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
}
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 ) ;
2022-12-07 14:54:59 +01:00
h = hash_djb2_buffer ( ( const uint8_t * ) p_vtx . bones , p_vtx . num_bones * sizeof ( int16_t ) , h ) ;
h = hash_djb2_buffer ( ( const uint8_t * ) p_vtx . weights , p_vtx . num_bones * sizeof ( float ) , h ) ;
2014-05-14 06:22:15 +02:00
return h ;
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
}
2022-12-07 14:54:59 +01:00
bool SurfaceTool : : _sanitize_last_bones_and_weights ( ) {
const int expected_vertices = Vertex : : MAX_BONES ;
if ( ( last_bones . size ( ) = = expected_vertices ) & & ( last_weights . size ( ) = = expected_vertices ) ) {
// already ideal
return true ;
}
ERR_FAIL_COND_V ( last_bones . size ( ) ! = last_weights . size ( ) , false ) ;
int num_orig = last_weights . size ( ) ;
if ( num_orig < expected_vertices ) {
//less than required, fill
for ( int i = last_weights . size ( ) ; i < expected_vertices ; i + + ) {
last_weights . push_back ( 0 ) ;
last_bones . push_back ( 0 ) ;
}
} else if ( num_orig > expected_vertices ) {
//more than required, sort, cap and normalize.
Vector < WeightSort > weights ;
for ( int i = 0 ; i < num_orig ; i + + ) {
WeightSort ws ;
ws . index = last_bones [ i ] ;
ws . weight = last_weights [ i ] ;
weights . push_back ( ws ) ;
}
//sort
weights . sort ( ) ;
//cap
weights . resize ( expected_vertices ) ;
//renormalize
float total = 0 ;
for ( int i = 0 ; i < expected_vertices ; i + + ) {
total + = weights [ i ] . weight ;
}
last_weights . resize ( expected_vertices ) ;
last_bones . resize ( expected_vertices ) ;
for ( int i = 0 ; i < expected_vertices ; i + + ) {
if ( total > 0 ) {
last_weights . write [ i ] = weights [ i ] . weight / total ;
} else {
last_weights . write [ i ] = 0 ;
}
last_bones . write [ i ] = weights [ i ] . index ;
}
}
return true ;
}
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 . tangent = last_tangent . normal ;
vtx . binormal = last_normal . cross ( last_tangent . normal ) . normalized ( ) * last_tangent . d ;
2019-04-13 20:19:26 +02:00
2022-12-07 14:54:59 +01:00
if ( format & Mesh : : ARRAY_FORMAT_WEIGHTS | | format & Mesh : : ARRAY_FORMAT_BONES ) {
ERR_FAIL_COND ( ! _sanitize_last_bones_and_weights ( ) ) ;
2019-04-13 20:19:26 +02:00
2022-12-07 14:54:59 +01:00
vtx . num_bones = last_bones . size ( ) ;
for ( int n = 0 ; n < last_bones . size ( ) ; n + + ) {
vtx . bones [ n ] = last_bones [ n ] ;
vtx . weights [ n ] = last_weights [ n ] ;
2019-04-13 20:19:26 +02:00
}
}
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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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 ;
last_bones = p_bones ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : add_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 ;
last_weights = p_weights ;
2014-02-10 02:10:30 +01:00
}
2014-05-14 06:22:15 +02:00
void SurfaceTool : : add_smooth_group ( bool p_smooth ) {
ERR_FAIL_COND ( ! begun ) ;
2022-12-07 14:54:59 +01:00
smooth_groups [ get_num_draw_vertices ( ) ] = p_smooth ;
2014-05-14 06:22:15 +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 ) \
add_color ( p_colors [ n ] ) ; \
if ( p_uvs . size ( ) > n ) \
add_uv ( p_uvs [ n ] ) ; \
if ( p_uv2s . size ( ) > n ) \
add_uv2 ( p_uv2s [ n ] ) ; \
if ( p_normals . size ( ) > n ) \
add_normal ( p_normals [ n ] ) ; \
if ( p_tangents . size ( ) > n ) \
add_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 + + ) {
2021-05-05 12:44:11 +02:00
if ( ! ( format & ( 1 < < i ) ) ) {
2017-08-02 20:34:55 +02:00
continue ; //not in format
2021-05-05 12:44:11 +02:00
}
2017-08-02 20:34:55 +02:00
switch ( i ) {
case Mesh : : ARRAY_VERTEX :
case Mesh : : ARRAY_NORMAL : {
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > array ;
2014-02-10 02:10:30 +01:00
array . resize ( varr_len ) ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > : : Write w = array . write ( ) ;
2014-02-10 02:10:30 +01:00
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + ) {
const Vertex & v = vertex_array [ n ] ;
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 : {
2022-12-07 14:54:59 +01:00
w [ n ] = v . vertex ;
2014-02-10 02:10:30 +01:00
} break ;
case Mesh : : ARRAY_NORMAL : {
2022-12-07 14:54:59 +01:00
w [ n ] = v . normal ;
2014-02-10 02:10:30 +01:00
} break ;
}
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
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 : {
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > array ;
2014-02-10 02:10:30 +01:00
array . resize ( varr_len ) ;
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > : : Write w = array . write ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int idx = 0 ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + , idx + + ) {
const Vertex & v = vertex_array [ n ] ;
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 ;
}
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
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 : {
2017-01-07 22:25:37 +01:00
PoolVector < float > array ;
2017-03-05 16:44:50 +01:00
array . resize ( varr_len * 4 ) ;
2017-01-07 22:25:37 +01:00
PoolVector < float > : : Write w = array . write ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int idx = 0 ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + , idx + = 4 ) {
const Vertex & v = vertex_array [ n ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
w [ idx + 0 ] = v . tangent . x ;
w [ idx + 1 ] = v . tangent . y ;
w [ idx + 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 ) ) ;
w [ idx + 3 ] = d < 0 ? - 1 : 1 ;
2014-02-10 02:10:30 +01:00
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
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 : {
2017-01-07 22:25:37 +01:00
PoolVector < Color > array ;
2014-02-10 02:10:30 +01:00
array . resize ( varr_len ) ;
2017-01-07 22:25:37 +01:00
PoolVector < Color > : : Write w = array . write ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int idx = 0 ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + , idx + + ) {
const Vertex & v = vertex_array [ n ] ;
2017-03-05 16:44:50 +01:00
w [ idx ] = v . color ;
2014-02-10 02:10:30 +01:00
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
2017-03-05 16:44:50 +01:00
a [ i ] = array ;
2016-03-09 00:00:52 +01:00
} break ;
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_BONES : {
2017-01-07 22:25:37 +01:00
PoolVector < int > array ;
2022-12-07 14:54:59 +01:00
array . resize ( varr_len * Vertex : : MAX_BONES ) ;
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Write w = array . write ( ) ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
int idx = 0 ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + , idx + = Vertex : : MAX_BONES ) {
const Vertex & v = vertex_array [ n ] ;
2016-11-25 00:46:55 +01:00
2022-12-07 14:54:59 +01:00
ERR_CONTINUE ( v . num_bones ! = Vertex : : MAX_BONES ) ;
for ( int j = 0 ; j < Vertex : : MAX_BONES ; j + + ) {
2017-03-05 16:44:50 +01:00
w [ idx + j ] = v . bones [ j ] ;
2016-11-25 00:46:55 +01:00
}
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
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 : {
2017-01-07 22:25:37 +01:00
PoolVector < float > array ;
2022-12-07 14:54:59 +01:00
array . resize ( varr_len * Vertex : : MAX_BONES ) ;
2017-01-07 22:25:37 +01:00
PoolVector < float > : : Write w = array . write ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int idx = 0 ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + , idx + = Vertex : : MAX_BONES ) {
const Vertex & v = vertex_array [ n ] ;
2014-02-10 02:10:30 +01:00
2022-12-07 14:54:59 +01:00
ERR_CONTINUE ( v . num_bones ! = Vertex : : MAX_BONES ) ;
for ( int j = 0 ; j < Vertex : : MAX_BONES ; j + + ) {
2017-03-05 16:44:50 +01:00
w [ idx + j ] = v . weights [ j ] ;
2014-02-10 02:10:30 +01:00
}
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
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
2017-01-07 22:25:37 +01:00
PoolVector < int > array ;
2014-02-10 02:10:30 +01:00
array . resize ( index_array . size ( ) ) ;
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Write w = array . write ( ) ;
2014-02-10 02:10:30 +01:00
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < index_array . size ( ) ; n + + ) {
w [ n ] = index_array [ n ] ;
2014-02-10 02:10:30 +01:00
}
2019-07-05 19:08:43 +02:00
w . release ( ) ;
2017-08-02 20:34:55 +02: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 ;
}
2017-12-09 18:11:26 +01:00
Ref < ArrayMesh > SurfaceTool : : commit ( const Ref < ArrayMesh > & p_existing , uint32_t p_flags ) {
2017-08-02 20:34:55 +02:00
Ref < ArrayMesh > mesh ;
2021-05-05 12:44:11 +02:00
if ( p_existing . is_valid ( ) ) {
2017-08-02 20:34:55 +02:00
mesh = p_existing ;
2021-05-05 12:44:11 +02:00
} else {
2017-08-02 20:34:55 +02:00
mesh . instance ( ) ;
2021-05-05 12:44:11 +02:00
}
2017-08-02 20:34:55 +02:00
int varr_len = vertex_array . size ( ) ;
2021-05-05 12:44:11 +02:00
if ( varr_len = = 0 ) {
2017-08-02 20:34:55 +02:00
return mesh ;
2021-05-05 12:44:11 +02:00
}
2017-08-02 20:34:55 +02:00
int surface = mesh - > get_surface_count ( ) ;
Array a = commit_to_arrays ( ) ;
2017-12-09 18:11:26 +01:00
mesh - > add_surface_from_arrays ( primitive , a , Array ( ) , p_flags ) ;
2017-11-21 01:36:32 +01:00
2021-05-05 12:44:11 +02:00
if ( material . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
mesh - > surface_set_material ( surface , material ) ;
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
return mesh ;
}
void SurfaceTool : : index ( ) {
2021-05-05 12:44:11 +02:00
if ( index_array . size ( ) ) {
2014-05-14 06:22:15 +02:00
return ; //already indexed
2021-05-05 12:44:11 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
HashMap < Vertex , int , VertexHasher > indices ;
2022-12-07 14:54:59 +01:00
LocalVector < Vertex > new_vertices ;
// probably will use less, but this prevents a bunch of resizing
new_vertices . reserve ( vertex_array . size ( ) ) ;
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + ) {
const Vertex & v = vertex_array [ n ] ;
int * idxptr = indices . getptr ( v ) ;
2014-02-10 02:10:30 +01:00
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-07 14:54:59 +01:00
new_vertices . push_back ( v ) ;
indices [ v ] = 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
}
2014-05-14 06:22:15 +02:00
vertex_array . clear ( ) ;
2017-03-05 16:44:50 +01:00
vertex_array = new_vertices ;
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 ( ) {
2021-05-05 12:44:11 +02:00
if ( index_array . size ( ) = = 0 ) {
2014-05-14 06:22:15 +02:00
return ; //nothing to deindex
2021-05-05 12:44:11 +02:00
}
2022-12-07 14:54:59 +01:00
// make a copy of source verts
LocalVector < Vertex > varr = vertex_array ;
vertex_array . resize ( index_array . size ( ) ) ;
Vertex * dest_vert = vertex_array . ptr ( ) ;
for ( uint32_t n = 0 ; n < index_array . size ( ) ; n + + ) {
int idx = index_array [ n ] ;
ERR_FAIL_INDEX ( idx , ( int ) varr . size ( ) ) ;
* dest_vert + + = varr [ idx ] ;
2014-05-14 06:22:15 +02:00
}
2022-12-07 14:54:59 +01: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
}
2022-12-07 14:54:59 +01:00
void SurfaceTool : : _create_list ( const Ref < Mesh > & p_existing , int p_surface , LocalVector < Vertex > * r_vertex , LocalVector < int > * r_index , uint32_t & lformat ) {
2021-04-12 00:06:27 +02:00
ERR_FAIL_COND_MSG ( p_existing . is_null ( ) , " 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 ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( arr . size ( ) ! = VS : : ARRAY_MAX ) ;
2017-08-02 20:34:55 +02:00
_create_list_from_arrays ( arr , r_vertex , r_index , lformat ) ;
}
2017-12-09 18:11:26 +01:00
Vector < SurfaceTool : : Vertex > SurfaceTool : : create_vertex_array_from_triangle_arrays ( const Array & p_arrays ) {
Vector < SurfaceTool : : Vertex > ret ;
PoolVector < Vector3 > varr = p_arrays [ VS : : ARRAY_VERTEX ] ;
PoolVector < Vector3 > narr = p_arrays [ VS : : ARRAY_NORMAL ] ;
PoolVector < float > tarr = p_arrays [ VS : : ARRAY_TANGENT ] ;
PoolVector < Color > carr = p_arrays [ VS : : ARRAY_COLOR ] ;
PoolVector < Vector2 > uvarr = p_arrays [ VS : : ARRAY_TEX_UV ] ;
PoolVector < Vector2 > uv2arr = p_arrays [ VS : : ARRAY_TEX_UV2 ] ;
PoolVector < int > barr = p_arrays [ VS : : ARRAY_BONES ] ;
PoolVector < float > warr = p_arrays [ VS : : ARRAY_WEIGHTS ] ;
int vc = varr . size ( ) ;
2021-05-05 12:44:11 +02:00
if ( vc = = 0 ) {
2017-12-09 18:11:26 +01:00
return ret ;
2021-05-05 12:44:11 +02:00
}
2017-12-09 18:11:26 +01:00
int lformat = 0 ;
PoolVector < Vector3 > : : Read rv ;
if ( varr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_VERTEX ;
rv = varr . read ( ) ;
}
PoolVector < Vector3 > : : Read rn ;
if ( narr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_NORMAL ;
rn = narr . read ( ) ;
}
PoolVector < float > : : Read rt ;
if ( tarr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_TANGENT ;
rt = tarr . read ( ) ;
}
PoolVector < Color > : : Read rc ;
if ( carr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_COLOR ;
rc = carr . read ( ) ;
}
PoolVector < Vector2 > : : Read ruv ;
if ( uvarr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_TEX_UV ;
ruv = uvarr . read ( ) ;
}
PoolVector < Vector2 > : : Read ruv2 ;
if ( uv2arr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_TEX_UV2 ;
ruv2 = uv2arr . read ( ) ;
}
PoolVector < int > : : Read rb ;
if ( barr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_BONES ;
rb = barr . read ( ) ;
}
PoolVector < float > : : Read rw ;
if ( warr . size ( ) ) {
lformat | = VS : : ARRAY_FORMAT_WEIGHTS ;
rw = warr . read ( ) ;
}
2022-12-07 14:54:59 +01:00
ret . resize ( vc ) ;
Vertex * ret_dest = ret . ptrw ( ) ;
2017-12-09 18:11:26 +01:00
for ( int i = 0 ; i < vc ; i + + ) {
2022-12-07 14:54:59 +01:00
Vertex & v = * ret_dest + + ;
2021-05-05 12:44:11 +02:00
if ( lformat & VS : : ARRAY_FORMAT_VERTEX ) {
2017-12-09 18:11:26 +01:00
v . vertex = varr [ i ] ;
2021-05-05 12:44:11 +02:00
}
if ( lformat & VS : : ARRAY_FORMAT_NORMAL ) {
2017-12-09 18:11:26 +01:00
v . normal = narr [ i ] ;
2021-05-05 12:44:11 +02:00
}
2017-12-09 18:11:26 +01:00
if ( lformat & VS : : ARRAY_FORMAT_TANGENT ) {
Plane p ( tarr [ i * 4 + 0 ] , tarr [ i * 4 + 1 ] , tarr [ i * 4 + 2 ] , tarr [ i * 4 + 3 ] ) ;
v . tangent = p . normal ;
v . binormal = p . normal . cross ( v . tangent ) . normalized ( ) * p . d ;
}
2021-05-05 12:44:11 +02:00
if ( lformat & VS : : ARRAY_FORMAT_COLOR ) {
2017-12-09 18:11:26 +01:00
v . color = carr [ i ] ;
2021-05-05 12:44:11 +02:00
}
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV ) {
2017-12-09 18:11:26 +01:00
v . uv = uvarr [ i ] ;
2021-05-05 12:44:11 +02:00
}
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV2 ) {
2017-12-09 18:11:26 +01:00
v . uv2 = uv2arr [ i ] ;
2021-05-05 12:44:11 +02:00
}
2017-12-09 18:11:26 +01:00
if ( lformat & VS : : ARRAY_FORMAT_BONES ) {
2022-12-07 14:54:59 +01:00
v . num_bones = Vertex : : MAX_BONES ;
for ( int b = 0 ; b < Vertex : : MAX_BONES ; b + + ) {
v . bones [ b ] = barr [ i * Vertex : : MAX_BONES + b ] ;
}
2017-12-09 18:11:26 +01:00
}
if ( lformat & VS : : ARRAY_FORMAT_WEIGHTS ) {
2022-12-07 14:54:59 +01:00
v . num_bones = Vertex : : MAX_BONES ;
for ( int b = 0 ; b < Vertex : : MAX_BONES ; b + + ) {
v . weights [ b ] = warr [ i * Vertex : : MAX_BONES + b ] ;
}
2017-12-09 18:11:26 +01:00
}
}
return ret ;
}
2022-12-07 14:54:59 +01:00
void SurfaceTool : : _create_list_from_arrays ( Array arr , LocalVector < Vertex > * r_vertex , LocalVector < int > * r_index , uint32_t & lformat ) {
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > varr = arr [ VS : : ARRAY_VERTEX ] ;
PoolVector < Vector3 > narr = arr [ VS : : ARRAY_NORMAL ] ;
PoolVector < float > tarr = arr [ VS : : ARRAY_TANGENT ] ;
PoolVector < Color > carr = arr [ VS : : ARRAY_COLOR ] ;
PoolVector < Vector2 > uvarr = arr [ VS : : ARRAY_TEX_UV ] ;
PoolVector < Vector2 > uv2arr = arr [ VS : : ARRAY_TEX_UV2 ] ;
PoolVector < int > barr = arr [ VS : : ARRAY_BONES ] ;
PoolVector < float > warr = arr [ VS : : ARRAY_WEIGHTS ] ;
2014-02-10 02:10:30 +01:00
int vc = varr . size ( ) ;
2021-05-05 12:44:11 +02:00
if ( vc = = 0 ) {
2014-02-10 02:10:30 +01:00
return ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
lformat = 0 ;
2014-02-10 02:10:30 +01:00
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > : : Read rv ;
2014-02-10 02:10:30 +01:00
if ( varr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_VERTEX ;
rv = varr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < Vector3 > : : Read rn ;
2014-02-10 02:10:30 +01:00
if ( narr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_NORMAL ;
rn = narr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < float > : : Read rt ;
2014-02-10 02:10:30 +01:00
if ( tarr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_TANGENT ;
rt = tarr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < Color > : : Read rc ;
2014-02-10 02:10:30 +01:00
if ( carr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_COLOR ;
rc = carr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > : : Read ruv ;
2014-02-10 02:10:30 +01:00
if ( uvarr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_TEX_UV ;
ruv = uvarr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < Vector2 > : : Read ruv2 ;
2014-02-10 02:10:30 +01:00
if ( uv2arr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_TEX_UV2 ;
ruv2 = uv2arr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < int > : : Read rb ;
2014-02-10 02:10:30 +01:00
if ( barr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_BONES ;
rb = barr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-01-07 22:25:37 +01:00
PoolVector < float > : : Read rw ;
2014-02-10 02:10:30 +01:00
if ( warr . size ( ) ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_WEIGHTS ;
rw = warr . read ( ) ;
2014-02-10 02:10:30 +01:00
}
2022-12-07 14:54:59 +01:00
DEV_ASSERT ( vc ) ;
uint32_t start = r_vertex - > size ( ) ;
r_vertex - > resize ( start + vc ) ;
Vertex * vert_dest = & r_vertex - > operator [ ] ( start ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < vc ; i + + ) {
2022-12-07 14:54:59 +01:00
Vertex & v = * vert_dest + + ;
2021-05-05 12:44:11 +02:00
if ( lformat & VS : : ARRAY_FORMAT_VERTEX ) {
2017-03-05 16:44:50 +01:00
v . vertex = varr [ i ] ;
2021-05-05 12:44:11 +02:00
}
if ( lformat & VS : : ARRAY_FORMAT_NORMAL ) {
2017-03-05 16:44:50 +01:00
v . normal = narr [ i ] ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
if ( lformat & VS : : ARRAY_FORMAT_TANGENT ) {
Plane p ( tarr [ i * 4 + 0 ] , tarr [ i * 4 + 1 ] , tarr [ i * 4 + 2 ] , tarr [ i * 4 + 3 ] ) ;
v . tangent = p . normal ;
2017-08-02 20:34:55 +02:00
v . binormal = p . normal . cross ( v . tangent ) . normalized ( ) * p . d ;
2014-02-10 02:10:30 +01:00
}
2021-05-05 12:44:11 +02:00
if ( lformat & VS : : ARRAY_FORMAT_COLOR ) {
2017-03-05 16:44:50 +01:00
v . color = carr [ i ] ;
2021-05-05 12:44:11 +02:00
}
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV ) {
2017-03-05 16:44:50 +01:00
v . uv = uvarr [ i ] ;
2021-05-05 12:44:11 +02:00
}
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV2 ) {
2017-03-05 16:44:50 +01:00
v . uv2 = uv2arr [ i ] ;
2021-05-05 12:44:11 +02:00
}
2017-03-05 16:44:50 +01:00
if ( lformat & VS : : ARRAY_FORMAT_BONES ) {
2022-12-07 14:54:59 +01:00
v . num_bones = Vertex : : MAX_BONES ;
for ( int b = 0 ; b < Vertex : : MAX_BONES ; b + + ) {
v . bones [ b ] = barr [ i * Vertex : : MAX_BONES + b ] ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( lformat & VS : : ARRAY_FORMAT_WEIGHTS ) {
2022-12-07 14:54:59 +01:00
v . num_bones = Vertex : : MAX_BONES ;
for ( int b = 0 ; b < Vertex : : MAX_BONES ; b + + ) {
v . weights [ b ] = warr [ i * Vertex : : MAX_BONES + b ] ;
}
2014-02-10 02:10:30 +01:00
}
}
//indices
2017-03-05 16:44:50 +01:00
PoolVector < int > idx = arr [ VS : : ARRAY_INDEX ] ;
2014-02-10 02:10:30 +01:00
int is = idx . size ( ) ;
if ( is ) {
2017-03-05 16:44:50 +01:00
lformat | = VS : : ARRAY_FORMAT_INDEX ;
PoolVector < int > : : Read iarr = idx . read ( ) ;
2022-12-07 14:54:59 +01:00
uint32_t ind_start = r_index - > size ( ) ;
r_index - > resize ( ind_start + is ) ;
int * ind_dest = & r_index - > operator [ ] ( ind_start ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < is ; i + + ) {
2022-12-07 14:54:59 +01:00
* ind_dest = iarr [ i ] ;
ind_dest + + ;
2014-02-10 02:10:30 +01:00
}
}
}
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 ) ;
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : create_from ( const Ref < Mesh > & p_existing , int p_surface ) {
2021-04-12 00:06:27 +02:00
ERR_FAIL_COND_MSG ( p_existing . is_null ( ) , " 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 ) ;
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-04-12 00:06:27 +02:00
ERR_FAIL_COND_MSG ( p_existing . is_null ( ) , " 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 ( ) ) ;
Array mesh = arr [ shape_idx ] ;
ERR_FAIL_COND ( mesh . size ( ) ! = VS : : ARRAY_MAX ) ;
_create_list_from_arrays ( arr [ shape_idx ] , & vertex_array , & index_array , format ) ;
}
2022-05-31 20:26:21 +02:00
// returns number of indices found within the subset
int SurfaceTool : : create_from_subset ( const SurfaceTool & p_source , const LocalVector < uint32_t > & p_ids , uint32_t p_subset_id ) {
clear ( ) ;
bool was_indexed = p_source . index_array . size ( ) ! = 0 ;
// expecting deindexed input for now as easier to deal with
ERR_FAIL_COND_V ( was_indexed , 0 ) ;
// only deals with triangles
ERR_FAIL_COND_V ( p_source . primitive ! = Mesh : : PRIMITIVE_TRIANGLES , 0 ) ;
primitive = p_source . primitive ;
uint32_t num_source_tris = p_source . vertex_array . size ( ) / 3 ;
DEV_ASSERT ( ( p_source . vertex_array . size ( ) % 3 ) = = 0 ) ;
ERR_FAIL_COND_V ( num_source_tris ! = p_ids . size ( ) , 0 ) ;
const Vertex * v [ 3 ] ;
const Vertex * input = p_source . vertex_array . ptr ( ) ;
HashMap < Vertex , int , VertexHasher > indices ;
for ( uint32_t t = 0 ; t < num_source_tris ; t + + ) {
v [ 0 ] = input + + ;
v [ 1 ] = input + + ;
v [ 2 ] = input + + ;
if ( p_ids [ t ] = = p_subset_id ) {
// we can use this triangle
for ( int i = 0 ; i < 3 ; i + + ) {
const Vertex & vert = * v [ i ] ;
int * idxptr = indices . getptr ( vert ) ;
int idx ;
if ( ! idxptr ) {
idx = indices . size ( ) ;
vertex_array . push_back ( vert ) ;
indices [ vert ] = idx ;
} else {
idx = * idxptr ;
}
index_array . push_back ( idx ) ;
} // for i
} // bound intersects
}
// steal the format from the source surface tool
format = p_source . format ;
format | = Mesh : : ARRAY_FORMAT_INDEX ;
return get_num_draw_vertices ( ) ;
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : append_from ( const Ref < Mesh > & p_existing , int p_surface , const Transform & p_xform ) {
2021-04-12 00:06:27 +02:00
ERR_FAIL_COND_MSG ( p_existing . is_null ( ) , " 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
}
2022-12-07 14:54:59 +01:00
uint32_t nformat ;
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 ;
2014-02-10 02:10:30 +01:00
int vfrom = vertex_array . size ( ) ;
2022-12-07 14:54:59 +01:00
if ( nvertices . size ( ) ) {
vertex_array . resize ( vfrom + nvertices . size ( ) ) ;
Vertex * dest_vert = & vertex_array [ vfrom ] ;
for ( uint32_t n = 0 ; n < nvertices . size ( ) ; n + + ) {
Vertex & v = * dest_vert + + ;
v = nvertices [ n ] ;
v . vertex = p_xform . xform ( v . vertex ) ;
if ( nformat & VS : : ARRAY_FORMAT_NORMAL ) {
v . normal = p_xform . basis . xform ( v . normal ) ;
}
if ( nformat & VS : : ARRAY_FORMAT_TANGENT ) {
v . tangent = p_xform . basis . xform ( v . tangent ) ;
v . binormal = p_xform . basis . xform ( v . binormal ) ;
}
2014-02-10 02:10:30 +01:00
}
2022-12-07 14:54:59 +01:00
} // if there were new vertices to add
2014-02-10 02:10:30 +01:00
2022-12-07 14:54:59 +01:00
if ( nindices . size ( ) ) {
int ind_start = index_array . size ( ) ;
index_array . resize ( ind_start + nindices . size ( ) ) ;
int * dest_ind = & index_array [ ind_start ] ;
2014-02-10 02:10:30 +01:00
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < nindices . size ( ) ; n + + ) {
int dst_index = nindices [ n ] + vfrom ;
* dest_ind + + = dst_index ;
}
} // if there were new indices to add
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 {
2022-12-07 14:54:59 +01:00
Vector < SurfaceTool : : Vertex * > vertices ;
Vector < 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 ) ;
if ( triangle_data . indices . size ( ) > 0 ) {
return triangle_data . indices . size ( ) / 3 ;
} else {
return triangle_data . vertices . size ( ) / 3 ;
}
2014-10-14 06:01:25 +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
}
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 ;
if ( triangle_data . indices . size ( ) > 0 ) {
2022-12-07 14:54:59 +01:00
int index = triangle_data . indices [ iFace * 3 + iVert ] ;
2018-11-26 16:09:52 +01:00
if ( index < triangle_data . vertices . size ( ) ) {
2022-12-07 14:54:59 +01:00
v = triangle_data . vertices [ index ] - > vertex ;
2018-11-26 16:09:52 +01:00
}
} else {
2022-12-07 14:54:59 +01:00
v = triangle_data . vertices [ 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 ;
if ( triangle_data . indices . size ( ) > 0 ) {
2022-12-07 14:54:59 +01:00
int index = triangle_data . indices [ iFace * 3 + iVert ] ;
2018-11-26 16:09:52 +01:00
if ( index < triangle_data . vertices . size ( ) ) {
2022-12-07 14:54:59 +01:00
v = triangle_data . vertices [ index ] - > normal ;
2018-11-26 16:09:52 +01:00
}
} else {
2022-12-07 14:54:59 +01:00
v = triangle_data . vertices [ 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
}
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 ;
if ( triangle_data . indices . size ( ) > 0 ) {
2022-12-07 14:54:59 +01:00
int index = triangle_data . indices [ iFace * 3 + iVert ] ;
2018-11-26 16:09:52 +01:00
if ( index < triangle_data . vertices . size ( ) ) {
2022-12-07 14:54:59 +01:00
v = triangle_data . vertices [ index ] - > uv ;
2018-11-26 16:09:52 +01:00
}
} else {
2022-12-07 14:54:59 +01:00
v = triangle_data . vertices [ 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 ) ;
2021-05-04 16:00:45 +02:00
Vertex * vtx = nullptr ;
2018-11-26 16:09:52 +01:00
if ( triangle_data . indices . size ( ) > 0 ) {
2022-12-07 14:54:59 +01:00
int index = triangle_data . indices [ iFace * 3 + iVert ] ;
2018-11-26 16:09:52 +01:00
if ( index < triangle_data . vertices . size ( ) ) {
2022-12-07 14:54:59 +01:00
vtx = triangle_data . vertices [ index ] ;
2018-11-26 16:09:52 +01:00
}
} else {
2022-12-07 14:54:59 +01:00
vtx = triangle_data . vertices [ iFace * 3 + iVert ] ;
2018-11-26 16:09:52 +01:00
}
2014-05-14 06:22:15 +02:00
2021-05-04 16:00:45 +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 ;
2021-05-04 16:00:45 +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 ;
triangle_data . vertices . resize ( vertex_array . size ( ) ) ;
2017-03-05 16:44:50 +01:00
int idx = 0 ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < vertex_array . size ( ) ; n + + ) {
Vertex & v = vertex_array [ n ] ;
triangle_data . vertices . write [ idx + + ] = & v ;
v . binormal = Vector3 ( ) ;
v . tangent = Vector3 ( ) ;
2014-10-14 06:01:25 +02:00
}
2018-11-26 16:09:52 +01:00
triangle_data . indices . resize ( index_array . size ( ) ) ;
2022-12-07 14:54:59 +01:00
for ( uint32_t n = 0 ; n < index_array . size ( ) ; n + + ) {
triangle_data . indices . write [ n ] = index_array [ n ] ;
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 ( ) ;
2017-03-05 16:44:50 +01:00
HashMap < Vertex , Vector3 , VertexHasher > vertex_hash ;
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
int count = 0 ;
bool smooth = false ;
2022-12-07 14:54:59 +01:00
int smooth_group_start = 0 ;
2021-05-05 12:44:11 +02:00
if ( smooth_groups . has ( 0 ) ) {
2017-03-05 16:44:50 +01:00
smooth = smooth_groups [ 0 ] ;
2021-05-05 12:44:11 +02:00
}
2014-05-14 06:22:15 +02:00
2022-12-07 14:54:59 +01:00
for ( uint32_t t = 0 ; t < vertex_array . size ( ) ; t + = 3 ) {
Vertex * v [ 3 ] ;
v [ 0 ] = & vertex_array [ t ] ;
v [ 1 ] = & vertex_array [ t + 1 ] ;
v [ 2 ] = & vertex_array [ t + 2 ] ;
2014-05-14 06:22:15 +02:00
2018-02-14 20:14:23 +01:00
Vector3 normal ;
2021-05-05 12:44:11 +02:00
if ( ! p_flip ) {
2022-12-07 14:54:59 +01:00
normal = Plane ( v [ 0 ] - > vertex , v [ 1 ] - > vertex , v [ 2 ] - > vertex ) . normal ;
2021-05-05 12:44:11 +02:00
} else {
2022-12-07 14:54:59 +01:00
normal = Plane ( v [ 2 ] - > vertex , v [ 1 ] - > vertex , v [ 0 ] - > vertex ) . normal ;
2021-05-05 12:44:11 +02:00
}
2014-05-14 06:22:15 +02:00
if ( smooth ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2022-12-07 14:54:59 +01:00
Vector3 * lv = vertex_hash . getptr ( * v [ i ] ) ;
2014-05-14 06:22:15 +02:00
if ( ! lv ) {
2022-12-07 14:54:59 +01:00
vertex_hash . set ( * v [ i ] , normal ) ;
2014-05-14 06:22:15 +02:00
} else {
2017-03-05 16:44:50 +01:00
( * lv ) + = normal ;
2014-05-14 06:22:15 +02:00
}
}
} else {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2022-12-07 14:54:59 +01:00
v [ i ] - > normal = normal ;
2014-05-14 06:22:15 +02:00
}
}
2017-03-05 16:44:50 +01:00
count + = 3 ;
2014-05-14 06:22:15 +02:00
2022-12-07 14:54:59 +01:00
// terminating smooth group, bake the smoothing group
if ( smooth_groups . has ( count ) ) {
_apply_smoothing_group ( vertex_hash , smooth_group_start , count , smooth ) ;
smooth_group_start = count ;
2014-05-14 06:22:15 +02:00
}
}
2022-12-07 14:54:59 +01:00
// always terminate the last smoothing group
_apply_smoothing_group ( vertex_hash , smooth_group_start , vertex_array . size ( ) , smooth ) ;
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 ( ) ;
smooth_groups . clear ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2022-12-07 14:54:59 +01:00
void SurfaceTool : : _apply_smoothing_group ( HashMap < Vertex , Vector3 , VertexHasher > & r_vertex_hash , uint32_t p_from , uint32_t p_to , bool & r_smooth ) {
if ( r_vertex_hash . size ( ) ) {
for ( uint32_t n = p_from ; n < p_to ; n + + ) {
Vertex & v = vertex_array [ n ] ;
Vector3 * lv = r_vertex_hash . getptr ( v ) ;
if ( lv ) {
v . normal = lv - > normalized ( ) ;
}
}
}
r_vertex_hash . clear ( ) ;
if ( p_to < vertex_array . size ( ) ) {
r_smooth = smooth_groups [ p_to ] ;
}
}
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
}
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 ( ) ;
2014-05-14 06:22:15 +02:00
smooth_groups . clear ( ) ;
2017-07-18 02:05:38 +02:00
material . unref ( ) ;
2014-02-10 02:10:30 +01:00
}
void SurfaceTool : : _bind_methods ( ) {
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " add_color " , " color " ) , & SurfaceTool : : add_color ) ;
ClassDB : : bind_method ( D_METHOD ( " add_normal " , " normal " ) , & SurfaceTool : : add_normal ) ;
ClassDB : : bind_method ( D_METHOD ( " add_tangent " , " tangent " ) , & SurfaceTool : : add_tangent ) ;
ClassDB : : bind_method ( D_METHOD ( " add_uv " , " uv " ) , & SurfaceTool : : add_uv ) ;
ClassDB : : bind_method ( D_METHOD ( " add_uv2 " , " uv2 " ) , & SurfaceTool : : add_uv2 ) ;
ClassDB : : bind_method ( D_METHOD ( " add_bones " , " bones " ) , & SurfaceTool : : add_bones ) ;
ClassDB : : bind_method ( D_METHOD ( " add_weights " , " weights " ) , & SurfaceTool : : add_weights ) ;
ClassDB : : bind_method ( D_METHOD ( " add_smooth_group " , " smooth " ) , & SurfaceTool : : add_smooth_group ) ;
2017-07-31 11:10:41 +02:00
2019-02-13 09:23:29 +01: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 ( Vector < 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 ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_material " , " material " ) , & SurfaceTool : : set_material ) ;
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 ) ;
2017-12-10 00:43:30 +01:00
ClassDB : : bind_method ( D_METHOD ( " commit " , " existing " , " flags " ) , & SurfaceTool : : commit , DEFVAL ( Variant ( ) ) , DEFVAL ( Mesh : : ARRAY_COMPRESS_DEFAULT ) ) ;
2019-02-27 15:51:04 +01:00
ClassDB : : bind_method ( D_METHOD ( " commit_to_arrays " ) , & SurfaceTool : : commit_to_arrays ) ;
2014-02-10 02:10:30 +01:00
}
SurfaceTool : : SurfaceTool ( ) {
2017-03-05 16:44:50 +01:00
first = false ;
begun = false ;
primitive = Mesh : : PRIMITIVE_LINES ;
format = 0 ;
2014-02-10 02:10:30 +01:00
}