2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* surface_tool.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01:00
/* */
/* 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 _VERTEX_SNAP 0.0001
# 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 ;
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 ) ;
2020-12-12 13:06:59 +01:00
h = hash_djb2_one_32 ( p_vtx . smooth_group , 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
}
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
}
2020-12-02 02:40:47 +01:00
void SurfaceTool : : set_custom ( int p_index , const Color & p_custom ) {
ERR_FAIL_INDEX ( p_index , RS : : ARRAY_CUSTOM_COUNT ) ;
ERR_FAIL_COND ( ! begun ) ;
ERR_FAIL_COND ( last_custom_format [ p_index ] = = CUSTOM_MAX ) ;
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 } ;
static const uint32_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 } ;
ERR_FAIL_COND ( ! first & & ! ( format & mask [ p_index ] ) ) ;
if ( first ) {
format | = mask [ p_index ] ;
format | = last_custom_format [ p_index ] < < shift [ p_index ] ;
}
last_custom [ p_index ] = p_custom ;
}
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
}
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 + + ) {
2020-05-14 16:41:43 +02:00
if ( ! ( format & ( 1 < < 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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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 ] ;
2020-12-02 02:40:47 +01:00
const Color & c = v . custom [ idx ] ;
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
2021-06-07 21:30:07 +02:00
if ( v . bones . size ( ) > count ) {
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 ] ;
2021-06-07 21:30:07 +02:00
if ( v . weights . size ( ) > count ) {
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 ;
}
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 ;
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 {
2017-08-02 20:34:55 +02:00
mesh . instance ( ) ;
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 ( ) ;
2019-08-19 00:40:52 +02:00
mesh - > add_surface_from_arrays ( primitive , a , Array ( ) , Dictionary ( ) , p_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
2020-12-12 13:06:59 +01:00
for ( uint32_t i = 0 ; i < old_vertex_array . size ( ) ; i + + ) {
int * idxptr = indices . getptr ( old_vertex_array [ i ] ) ;
2014-05-14 06:22:15 +02:00
int idx ;
if ( ! idxptr ) {
2017-03-05 16:44:50 +01:00
idx = indices . size ( ) ;
2020-12-12 13:06:59 +01:00
vertex_array . push_back ( old_vertex_array [ i ] ) ;
indices [ old_vertex_array [ i ] ] = 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 ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t i = 0 ; i < index_array . size ( ) ; i + + ) {
uint32_t index = index_array [ i ] ;
ERR_FAIL_COND ( index > = old_vertex_array . size ( ) ) ;
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
}
2020-12-12 13:06: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-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 ) ;
}
2020-12-12 13:06:59 +01:00
void SurfaceTool : : create_vertex_array_from_triangle_arrays ( const Array & p_arrays , LocalVector < SurfaceTool : : Vertex > & ret , uint32_t * r_format ) {
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
2020-02-18 14:57:11 +01:00
int 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
static const uint32_t custom_mask [ RS : : ARRAY_CUSTOM_COUNT ] = { Mesh : : ARRAY_FORMAT_CUSTOM0 , Mesh : : ARRAY_FORMAT_CUSTOM1 , Mesh : : ARRAY_FORMAT_CUSTOM2 , Mesh : : ARRAY_FORMAT_CUSTOM3 } ;
static const uint32_t 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 } ;
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
2020-12-12 13:06:59 +01:00
void SurfaceTool : : _create_list_from_arrays ( Array arr , LocalVector < Vertex > * r_vertex , LocalVector < int > * r_index , uint32_t & lformat ) {
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 ) ;
}
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 ) ;
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 ( ) ) ;
Array mesh = arr [ shape_idx ] ;
2020-03-27 19:21:27 +01:00
ERR_FAIL_COND ( mesh . size ( ) ! = RS : : ARRAY_MAX ) ;
2019-02-27 15:51:04 +01:00
_create_list_from_arrays ( arr [ shape_idx ] , & vertex_array , & index_array , format ) ;
}
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
}
2020-12-02 02:40:47 +01:00
uint32_t nformat ;
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 ;
2014-02-10 02:10:30 +01:00
int vfrom = vertex_array . size ( ) ;
2020-12-12 13:06:59 +01:00
for ( uint32_t vi = 0 ; vi < nvertices . size ( ) ; vi + + ) {
Vertex v = nvertices [ vi ] ;
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 ) ;
}
2020-12-12 13:06:59 +01:00
for ( uint32_t i = 0 ; i < nindices . size ( ) ; i + + ) {
int dst_index = nindices [ i ] + 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 ;
for ( uint32_t i = 0 ; i < vertex_array . size ( ) ; i + + ) {
vertex_array [ i ] . binormal = Vector3 ( ) ;
vertex_array [ i ] . 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
2020-12-12 13:06:59 +01:00
HashMap < Vertex , Vector3 , VertexHasher > vertex_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 + + ) {
Vector3 * lv = vertex_hash . getptr ( v [ i ] ) ;
if ( ! lv ) {
vertex_hash . set ( v [ i ] , normal ) ;
2014-05-14 06:22:15 +02:00
} else {
2020-12-12 13:06:59 +01:00
( * lv ) + = 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
2020-12-12 13:06:59 +01:00
for ( uint32_t vi = 0 ; vi < vertex_array . size ( ) ; vi + + ) {
Vector3 * lv = vertex_hash . getptr ( vertex_array [ vi ] ) ;
if ( ! lv ) {
vertex_array [ vi ] . normal = Vector3 ( ) ;
} else {
vertex_array [ vi ] . 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 ;
}
void SurfaceTool : : set_custom_format ( int p_index , CustomFormat p_format ) {
ERR_FAIL_INDEX ( p_index , RS : : ARRAY_CUSTOM_COUNT ) ;
ERR_FAIL_COND ( begun ) ;
last_custom_format [ p_index ] = p_format ;
}
2021-03-19 13:57:52 +01:00
Mesh : : PrimitiveType SurfaceTool : : get_primitive ( ) const {
return primitive ;
}
2020-12-02 02:40:47 +01:00
SurfaceTool : : CustomFormat SurfaceTool : : get_custom_format ( int p_index ) const {
ERR_FAIL_INDEX_V ( p_index , RS : : ARRAY_CUSTOM_COUNT , CUSTOM_MAX ) ;
return last_custom_format [ p_index ] ;
2014-02-10 02:10:30 +01:00
}
2020-12-12 13:06:59 +01:00
void SurfaceTool : : optimize_indices_for_cache ( ) {
ERR_FAIL_COND ( optimize_vertex_cache_func = = nullptr ) ;
ERR_FAIL_COND ( index_array . size ( ) = = 0 ) ;
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 ( ) ) ;
}
float SurfaceTool : : get_max_axis_length ( ) const {
ERR_FAIL_COND_V ( vertex_array . size ( ) = = 0 , 0 ) ;
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 ) ;
}
}
return aabb . get_longest_axis_size ( ) ;
}
Vector < int > SurfaceTool : : generate_lod ( float p_threshold , int p_target_index_count ) {
Vector < int > lod ;
ERR_FAIL_COND_V ( simplify_func = = nullptr , lod ) ;
ERR_FAIL_COND_V ( vertex_array . size ( ) = = 0 , lod ) ;
ERR_FAIL_COND_V ( index_array . size ( ) = = 0 , lod ) ;
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 ;
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 , & 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 ) ;
ClassDB : : bind_method ( D_METHOD ( " set_custom_format " , " index " , " format " ) , & SurfaceTool : : set_custom_format ) ;
ClassDB : : bind_method ( D_METHOD ( " get_custom_format " , " index " ) , & SurfaceTool : : get_custom_format ) ;
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 ) ;
ClassDB : : bind_method ( D_METHOD ( " set_custom " , " index " , " custom " ) , & 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
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 ) ;
2020-12-12 13:06:59 +01:00
ClassDB : : bind_method ( D_METHOD ( " optimize_indices_for_cache " ) , & SurfaceTool : : optimize_indices_for_cache ) ;
ClassDB : : bind_method ( D_METHOD ( " get_max_axis_length " ) , & SurfaceTool : : get_max_axis_length ) ;
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 ) ;
2021-03-19 13:57:52 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_primitive " ) , & SurfaceTool : : get_primitive ) ;
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
}