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
/*************************************************************************/
2019-01-01 12:53:14 +01:00
/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2019 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
# 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 {
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
if ( vertex ! = p_vertex . vertex )
2014-02-10 02:10:30 +01:00
return false ;
2017-08-11 21:10:05 +02:00
if ( uv ! = p_vertex . uv )
2014-05-14 06:22:15 +02:00
return false ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
if ( uv2 ! = p_vertex . uv2 )
2014-05-14 06:22:15 +02:00
return false ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
if ( normal ! = p_vertex . normal )
2014-05-14 06:22:15 +02:00
return false ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
if ( binormal ! = p_vertex . binormal )
2014-05-14 06:22:15 +02:00
return false ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
if ( color ! = p_vertex . color )
2014-05-14 06:22:15 +02:00
return false ;
2014-02-10 02:10:30 +01:00
2017-08-11 21:10:05 +02:00
if ( bones . size ( ) ! = p_vertex . bones . size ( ) )
2014-05-14 06:22:15 +02:00
return false ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < bones . size ( ) ; i + + ) {
2017-08-11 21:10:05 +02:00
if ( bones [ i ] ! = p_vertex . bones [ i ] )
2014-02-10 02:10:30 +01:00
return false ;
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < weights . size ( ) ; i + + ) {
2017-08-11 21:10:05 +02:00
if ( weights [ i ] ! = p_vertex . weights [ i ] )
2014-02-10 02:10:30 +01:00
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 ) {
2014-02-10 02:10:30 +01:00
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 ) ;
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 ;
vtx . binormal = last_normal . cross ( last_tangent . normal ) . normalized ( ) * last_tangent . d ;
2019-04-13 20:19:26 +02:00
const int expected_vertices = 4 ;
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
float total = 0 ;
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
}
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 ) ;
if ( index_array . size ( ) ) {
2017-03-05 16:44:50 +01:00
smooth_groups [ index_array . size ( ) ] = p_smooth ;
2014-05-14 06:22:15 +02:00
} else {
2017-03-05 16:44:50 +01:00
smooth_groups [ vertex_array . size ( ) ] = 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 ) ;
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 ( ) {
2014-02-10 02:10:30 +01:00
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 + + ) {
2014-02-10 02:10:30 +01:00
2017-08-02 20:34:55 +02:00
if ( ! ( format & ( 1 < < i ) ) )
continue ; //not in format
switch ( i ) {
2014-02-10 02:10:30 +01:00
2017-08-02 20:34:55 +02:00
case Mesh : : ARRAY_VERTEX :
case Mesh : : ARRAY_NORMAL : {
2014-02-10 02:10:30 +01:00
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
2017-03-05 16:44:50 +01:00
int idx = 0 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) , idx + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
const Vertex & v = E - > get ( ) ;
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 ;
}
}
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 : {
2014-02-10 02:10:30 +01:00
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 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) , idx + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
const Vertex & v = E - > get ( ) ;
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 : {
2014-02-10 02:10:30 +01:00
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 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) , idx + = 4 ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
const Vertex & v = E - > get ( ) ;
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 : {
2014-02-10 02:10:30 +01:00
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 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) , idx + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
const Vertex & v = E - > get ( ) ;
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 : {
2016-11-25 00:46:55 +01:00
2017-01-07 22:25:37 +01:00
PoolVector < int > array ;
2017-03-05 16:44:50 +01:00
array . resize ( varr_len * 4 ) ;
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 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) , idx + = 4 ) {
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
const Vertex & v = E - > get ( ) ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( v . bones . size ( ) ! = 4 ) ;
2016-11-25 00:46:55 +01:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < 4 ; j + + ) {
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 : {
2014-02-10 02:10:30 +01:00
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 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) , idx + = 4 ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
const Vertex & v = E - > get ( ) ;
ERR_CONTINUE ( v . weights . size ( ) ! = 4 ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < 4 ; j + + ) {
2016-11-25 00:46:55 +01:00
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 : {
2014-02-10 02:10:30 +01:00
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
2017-03-05 16:44:50 +01:00
int idx = 0 ;
for ( List < int > : : Element * E = index_array . front ( ) ; E ; E = E - > next ( ) , idx + + ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
w [ idx ] = E - > get ( ) ;
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 ;
if ( p_existing . is_valid ( ) )
mesh = p_existing ;
else
mesh . instance ( ) ;
int varr_len = vertex_array . size ( ) ;
if ( varr_len = = 0 )
return mesh ;
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
2014-02-10 02:10:30 +01:00
if ( material . is_valid ( ) )
2017-03-05 16:44:50 +01:00
mesh - > surface_set_material ( surface , material ) ;
2014-02-10 02:10:30 +01:00
return mesh ;
}
void SurfaceTool : : index ( ) {
2014-05-14 06:22:15 +02:00
if ( index_array . size ( ) )
return ; //already indexed
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
HashMap < Vertex , int , VertexHasher > indices ;
2014-05-14 06:22:15 +02:00
List < Vertex > new_vertices ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int * idxptr = indices . getptr ( E - > get ( ) ) ;
2014-05-14 06:22:15 +02:00
int idx ;
if ( ! idxptr ) {
2017-03-05 16:44:50 +01:00
idx = indices . size ( ) ;
2014-05-14 06:22:15 +02:00
new_vertices . push_back ( E - > get ( ) ) ;
2017-03-05 16:44:50 +01:00
indices [ E - > get ( ) ] = 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 ( ) {
2017-03-05 16:44:50 +01:00
if ( index_array . size ( ) = = 0 )
2014-05-14 06:22:15 +02:00
return ; //nothing to deindex
2017-03-05 16:44:50 +01:00
Vector < Vertex > varr ;
2014-05-14 06:22:15 +02:00
varr . resize ( vertex_array . size ( ) ) ;
2017-03-05 16:44:50 +01:00
int idx = 0 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2018-07-25 03:11:03 +02:00
varr . write [ idx + + ] = E - > get ( ) ;
2014-05-14 06:22:15 +02:00
}
vertex_array . clear ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < int > : : Element * E = index_array . front ( ) ; E ; E = E - > next ( ) ) {
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( E - > get ( ) , varr . size ( ) ) ;
2014-05-14 06:22:15 +02:00
vertex_array . push_back ( varr [ E - > get ( ) ] ) ;
}
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
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : _create_list ( const Ref < Mesh > & p_existing , int p_surface , List < Vertex > * r_vertex , List < int > * r_index , int & lformat ) {
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 ( ) ;
if ( vc = = 0 )
return ret ;
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 ( ) ;
}
for ( int i = 0 ; i < vc ; i + + ) {
Vertex v ;
if ( lformat & VS : : ARRAY_FORMAT_VERTEX )
v . vertex = varr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_NORMAL )
v . normal = narr [ i ] ;
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 ;
}
if ( lformat & VS : : ARRAY_FORMAT_COLOR )
v . color = carr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV )
v . uv = uvarr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV2 )
v . uv2 = uv2arr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_BONES ) {
Vector < int > b ;
b . resize ( 4 ) ;
2018-07-25 03:11:03 +02:00
b . write [ 0 ] = barr [ i * 4 + 0 ] ;
b . write [ 1 ] = barr [ i * 4 + 1 ] ;
b . write [ 2 ] = barr [ i * 4 + 2 ] ;
b . write [ 3 ] = barr [ i * 4 + 3 ] ;
2017-12-09 18:11:26 +01:00
v . bones = b ;
}
if ( lformat & VS : : ARRAY_FORMAT_WEIGHTS ) {
Vector < float > w ;
w . resize ( 4 ) ;
2018-07-25 03:11:03 +02:00
w . write [ 0 ] = warr [ i * 4 + 0 ] ;
w . write [ 1 ] = warr [ i * 4 + 1 ] ;
w . write [ 2 ] = warr [ i * 4 + 2 ] ;
w . write [ 3 ] = warr [ i * 4 + 3 ] ;
2017-12-09 18:11:26 +01:00
v . weights = w ;
}
ret . push_back ( v ) ;
}
return ret ;
}
2017-08-02 20:34:55 +02:00
void SurfaceTool : : _create_list_from_arrays ( Array arr , List < Vertex > * r_vertex , List < int > * r_index , int & lformat ) {
2014-02-10 02:10:30 +01:00
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 ( ) ;
2017-03-05 16:44:50 +01:00
if ( vc = = 0 )
2014-02-10 02:10:30 +01:00
return ;
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
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < vc ; i + + ) {
2014-02-10 02:10:30 +01:00
Vertex v ;
2017-03-05 16:44:50 +01:00
if ( lformat & VS : : ARRAY_FORMAT_VERTEX )
v . vertex = varr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_NORMAL )
v . normal = narr [ i ] ;
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
}
2017-03-05 16:44:50 +01:00
if ( lformat & VS : : ARRAY_FORMAT_COLOR )
v . color = carr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV )
v . uv = uvarr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_TEX_UV2 )
v . uv2 = uv2arr [ i ] ;
if ( lformat & VS : : ARRAY_FORMAT_BONES ) {
2014-02-10 02:10:30 +01:00
Vector < int > b ;
b . resize ( 4 ) ;
2018-07-25 03:11:03 +02:00
b . write [ 0 ] = barr [ i * 4 + 0 ] ;
b . write [ 1 ] = barr [ i * 4 + 1 ] ;
b . write [ 2 ] = barr [ i * 4 + 2 ] ;
b . write [ 3 ] = barr [ i * 4 + 3 ] ;
2017-03-05 16:44:50 +01:00
v . bones = b ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( lformat & VS : : ARRAY_FORMAT_WEIGHTS ) {
2014-02-10 02:10:30 +01:00
Vector < float > w ;
w . resize ( 4 ) ;
2018-07-25 03:11:03 +02:00
w . write [ 0 ] = warr [ i * 4 + 0 ] ;
w . write [ 1 ] = warr [ i * 4 + 1 ] ;
w . write [ 2 ] = warr [ i * 4 + 2 ] ;
w . write [ 3 ] = warr [ i * 4 + 3 ] ;
2017-03-05 16:44:50 +01:00
v . weights = w ;
2014-02-10 02:10:30 +01:00
}
r_vertex - > push_back ( v ) ;
}
//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 ( ) ;
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 ) {
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 ) {
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 ) ;
}
2017-03-05 16:44:50 +01:00
void SurfaceTool : : append_from ( const Ref < Mesh > & p_existing , int p_surface , const Transform & p_xform ) {
2014-02-10 02:10:30 +01:00
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
}
int nformat ;
List < Vertex > nvertices ;
List < 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 ( ) ;
2017-03-05 16:44:50 +01:00
for ( List < Vertex > : : Element * E = nvertices . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vertex v = E - > get ( ) ;
v . vertex = p_xform . xform ( v . vertex ) ;
if ( nformat & VS : : ARRAY_FORMAT_NORMAL ) {
v . normal = p_xform . basis . xform ( v . normal ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
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
}
vertex_array . push_back ( v ) ;
}
2017-03-05 16:44:50 +01:00
for ( List < int > : : Element * E = nindices . front ( ) ; E ; E = E - > next ( ) ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int dst_index = E - > get ( ) + 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 {
Vector < List < SurfaceTool : : Vertex > : : Element * > vertices ;
Vector < List < int > : : Element * > indices ;
} ;
} // namespace
2017-03-05 16:44:50 +01:00
int SurfaceTool : : mikktGetNumFaces ( const SMikkTSpaceContext * pContext ) {
2014-02-10 02:10:30 +01:00
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-02-10 02:10:30 +01:00
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 ) {
2014-02-10 02:10:30 +01:00
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 ) {
int index = triangle_data . indices [ iFace * 3 + iVert ] - > get ( ) ;
if ( index < triangle_data . vertices . size ( ) ) {
v = triangle_data . vertices [ index ] - > get ( ) . vertex ;
}
} else {
v = triangle_data . vertices [ iFace * 3 + iVert ] - > get ( ) . vertex ;
}
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 ) {
2014-02-10 02:10:30 +01:00
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 ) {
int index = triangle_data . indices [ iFace * 3 + iVert ] - > get ( ) ;
if ( index < triangle_data . vertices . size ( ) ) {
v = triangle_data . vertices [ index ] - > get ( ) . normal ;
}
} else {
v = triangle_data . vertices [ iFace * 3 + iVert ] - > get ( ) . normal ;
}
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 ) {
2014-02-10 02:10:30 +01:00
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 ) {
int index = triangle_data . indices [ iFace * 3 + iVert ] - > get ( ) ;
if ( index < triangle_data . vertices . size ( ) ) {
v = triangle_data . vertices [ index ] - > get ( ) . uv ;
}
} else {
v = triangle_data . vertices [ iFace * 3 + iVert ] - > get ( ) . uv ;
}
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 ) ;
Vertex * vtx = NULL ;
if ( triangle_data . indices . size ( ) > 0 ) {
int index = triangle_data . indices [ iFace * 3 + iVert ] - > get ( ) ;
if ( index < triangle_data . vertices . size ( ) ) {
vtx = & triangle_data . vertices [ index ] - > get ( ) ;
}
} else {
vtx = & triangle_data . vertices [ iFace * 3 + iVert ] - > get ( ) ;
}
2014-05-14 06:22:15 +02:00
2018-11-26 16:09:52 +01:00
if ( vtx ! = NULL ) {
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 ( ) {
2014-05-14 06:22:15 +02:00
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 ;
mkif . m_setTSpaceBasic = NULL ;
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 ;
for ( List < Vertex > : : Element * E = vertex_array . front ( ) ; E ; E = E - > next ( ) ) {
2018-11-26 16:09:52 +01:00
triangle_data . vertices . write [ idx + + ] = E ;
2017-03-05 16:44:50 +01:00
E - > get ( ) . binormal = Vector3 ( ) ;
E - > get ( ) . 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 ( ) ) ;
idx = 0 ;
for ( List < int > : : Element * E = index_array . front ( ) ; E ; E = E - > next ( ) ) {
triangle_data . indices . write [ idx + + ] = E ;
}
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 ) {
2014-02-10 02:10:30 +01:00
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 ;
2014-05-14 06:22:15 +02:00
if ( smooth_groups . has ( 0 ) )
2017-03-05 16:44:50 +01:00
smooth = smooth_groups [ 0 ] ;
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
List < Vertex > : : Element * B = vertex_array . front ( ) ;
for ( List < Vertex > : : Element * E = B ; E ; ) {
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
List < Vertex > : : Element * v [ 3 ] ;
v [ 0 ] = E ;
v [ 1 ] = v [ 0 ] - > next ( ) ;
2014-05-14 06:22:15 +02:00
ERR_FAIL_COND ( ! v [ 1 ] ) ;
2017-03-05 16:44:50 +01:00
v [ 2 ] = v [ 1 ] - > next ( ) ;
2014-05-14 06:22:15 +02:00
ERR_FAIL_COND ( ! v [ 2 ] ) ;
2017-03-05 16:44:50 +01:00
E = v [ 2 ] - > next ( ) ;
2014-05-14 06:22:15 +02:00
2018-02-14 20:14:23 +01:00
Vector3 normal ;
if ( ! p_flip )
normal = Plane ( v [ 0 ] - > get ( ) . vertex , v [ 1 ] - > get ( ) . vertex , v [ 2 ] - > get ( ) . vertex ) . normal ;
else
normal = Plane ( v [ 2 ] - > get ( ) . vertex , v [ 1 ] - > get ( ) . vertex , v [ 0 ] - > get ( ) . vertex ) . normal ;
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 + + ) {
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
Vector3 * lv = vertex_hash . getptr ( v [ i ] - > get ( ) ) ;
2014-05-14 06:22:15 +02:00
if ( ! lv ) {
2017-03-05 16:44:50 +01:00
vertex_hash . set ( v [ i ] - > get ( ) , 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 + + ) {
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
v [ i ] - > get ( ) . 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
if ( smooth_groups . has ( count ) | | ! E ) {
if ( vertex_hash . size ( ) ) {
2017-03-05 16:44:50 +01:00
while ( B ! = E ) {
2014-05-14 06:22:15 +02:00
2017-03-05 16:44:50 +01:00
Vector3 * lv = vertex_hash . getptr ( B - > get ( ) ) ;
2014-05-14 06:22:15 +02:00
if ( lv ) {
2017-03-05 16:44:50 +01:00
B - > get ( ) . normal = lv - > normalized ( ) ;
2014-05-14 06:22:15 +02:00
}
2017-03-05 16:44:50 +01:00
B = B - > next ( ) ;
2014-05-14 06:22:15 +02:00
}
} else {
2017-03-05 16:44:50 +01:00
B = E ;
2014-05-14 06:22:15 +02:00
}
vertex_hash . clear ( ) ;
if ( E ) {
2017-03-05 16:44:50 +01:00
smooth = smooth_groups [ count ] ;
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 ( ) ;
smooth_groups . clear ( ) ;
}
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 ) {
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
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
}