2020-12-21 15:39:32 +00:00
/*************************************************************************/
/* scene_importer_mesh.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
2021-01-01 19:13:46 +00:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2020-12-21 15:39:32 +00: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. */
/*************************************************************************/
# include "scene_importer_mesh.h"
2021-04-10 05:44:36 +00:00
# include "core/math/math_defs.h"
2020-12-21 15:39:32 +00:00
# include "scene/resources/surface_tool.h"
void EditorSceneImporterMesh : : add_blend_shape ( const String & p_name ) {
ERR_FAIL_COND ( surfaces . size ( ) > 0 ) ;
blend_shapes . push_back ( p_name ) ;
}
int EditorSceneImporterMesh : : get_blend_shape_count ( ) const {
return blend_shapes . size ( ) ;
}
String EditorSceneImporterMesh : : get_blend_shape_name ( int p_blend_shape ) const {
ERR_FAIL_INDEX_V ( p_blend_shape , blend_shapes . size ( ) , String ( ) ) ;
return blend_shapes [ p_blend_shape ] ;
}
void EditorSceneImporterMesh : : set_blend_shape_mode ( Mesh : : BlendShapeMode p_blend_shape_mode ) {
blend_shape_mode = p_blend_shape_mode ;
}
Mesh : : BlendShapeMode EditorSceneImporterMesh : : get_blend_shape_mode ( ) const {
return blend_shape_mode ;
}
void EditorSceneImporterMesh : : add_surface ( Mesh : : PrimitiveType p_primitive , const Array & p_arrays , const Array & p_blend_shapes , const Dictionary & p_lods , const Ref < Material > & p_material , const String & p_name ) {
ERR_FAIL_COND ( p_blend_shapes . size ( ) ! = blend_shapes . size ( ) ) ;
ERR_FAIL_COND ( p_arrays . size ( ) ! = Mesh : : ARRAY_MAX ) ;
Surface s ;
s . primitive = p_primitive ;
s . arrays = p_arrays ;
s . name = p_name ;
2020-12-24 08:01:07 +00:00
Vector < Vector3 > vertex_array = p_arrays [ Mesh : : ARRAY_VERTEX ] ;
int vertex_count = vertex_array . size ( ) ;
ERR_FAIL_COND ( vertex_count = = 0 ) ;
2020-12-21 15:39:32 +00:00
for ( int i = 0 ; i < blend_shapes . size ( ) ; i + + ) {
Array bsdata = p_blend_shapes [ i ] ;
ERR_FAIL_COND ( bsdata . size ( ) ! = Mesh : : ARRAY_MAX ) ;
2020-12-24 08:01:07 +00:00
Vector < Vector3 > vertex_data = bsdata [ Mesh : : ARRAY_VERTEX ] ;
ERR_FAIL_COND ( vertex_data . size ( ) ! = vertex_count ) ;
2020-12-21 15:39:32 +00:00
Surface : : BlendShape bs ;
bs . arrays = bsdata ;
s . blend_shape_data . push_back ( bs ) ;
}
List < Variant > lods ;
p_lods . get_key_list ( & lods ) ;
for ( List < Variant > : : Element * E = lods . front ( ) ; E ; E = E - > next ( ) ) {
ERR_CONTINUE ( ! E - > get ( ) . is_num ( ) ) ;
Surface : : LOD lod ;
lod . distance = E - > get ( ) ;
lod . indices = p_lods [ E - > get ( ) ] ;
ERR_CONTINUE ( lod . indices . size ( ) = = 0 ) ;
s . lods . push_back ( lod ) ;
}
s . material = p_material ;
surfaces . push_back ( s ) ;
mesh . unref ( ) ;
}
int EditorSceneImporterMesh : : get_surface_count ( ) const {
return surfaces . size ( ) ;
}
Mesh : : PrimitiveType EditorSceneImporterMesh : : get_surface_primitive_type ( int p_surface ) {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , Mesh : : PRIMITIVE_MAX ) ;
return surfaces [ p_surface ] . primitive ;
}
Array EditorSceneImporterMesh : : get_surface_arrays ( int p_surface ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , Array ( ) ) ;
return surfaces [ p_surface ] . arrays ;
}
String EditorSceneImporterMesh : : get_surface_name ( int p_surface ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , String ( ) ) ;
return surfaces [ p_surface ] . name ;
}
Array EditorSceneImporterMesh : : get_surface_blend_shape_arrays ( int p_surface , int p_blend_shape ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , Array ( ) ) ;
ERR_FAIL_INDEX_V ( p_blend_shape , surfaces [ p_surface ] . blend_shape_data . size ( ) , Array ( ) ) ;
return surfaces [ p_surface ] . blend_shape_data [ p_blend_shape ] . arrays ;
}
int EditorSceneImporterMesh : : get_surface_lod_count ( int p_surface ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , 0 ) ;
return surfaces [ p_surface ] . lods . size ( ) ;
}
Vector < int > EditorSceneImporterMesh : : get_surface_lod_indices ( int p_surface , int p_lod ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , Vector < int > ( ) ) ;
ERR_FAIL_INDEX_V ( p_lod , surfaces [ p_surface ] . lods . size ( ) , Vector < int > ( ) ) ;
return surfaces [ p_surface ] . lods [ p_lod ] . indices ;
}
float EditorSceneImporterMesh : : get_surface_lod_size ( int p_surface , int p_lod ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , 0 ) ;
ERR_FAIL_INDEX_V ( p_lod , surfaces [ p_surface ] . lods . size ( ) , 0 ) ;
return surfaces [ p_surface ] . lods [ p_lod ] . distance ;
}
Ref < Material > EditorSceneImporterMesh : : get_surface_material ( int p_surface ) const {
ERR_FAIL_INDEX_V ( p_surface , surfaces . size ( ) , Ref < Material > ( ) ) ;
return surfaces [ p_surface ] . material ;
}
2021-03-19 12:57:52 +00:00
void EditorSceneImporterMesh : : set_surface_material ( int p_surface , const Ref < Material > & p_material ) {
ERR_FAIL_INDEX ( p_surface , surfaces . size ( ) ) ;
surfaces . write [ p_surface ] . material = p_material ;
}
2021-04-10 05:44:36 +00:00
Basis EditorSceneImporterMesh : : compute_rotation_matrix_from_ortho_6d ( Vector3 p_x_raw , Vector3 p_y_raw ) {
Vector3 x = p_x_raw . normalized ( ) ;
Vector3 z = x . cross ( p_y_raw ) ;
z = z . normalized ( ) ;
Vector3 y = z . cross ( x ) ;
Basis basis ;
basis . set_axis ( Vector3 : : AXIS_X , x ) ;
basis . set_axis ( Vector3 : : AXIS_Y , y ) ;
basis . set_axis ( Vector3 : : AXIS_Z , z ) ;
return basis ;
}
2020-12-21 15:39:32 +00:00
void EditorSceneImporterMesh : : generate_lods ( ) {
if ( ! SurfaceTool : : simplify_func ) {
return ;
}
2021-01-09 18:04:09 +00:00
if ( ! SurfaceTool : : simplify_scale_func ) {
return ;
}
if ( ! SurfaceTool : : simplify_sloppy_func ) {
return ;
}
2021-04-10 05:44:36 +00:00
if ( ! SurfaceTool : : simplify_with_attrib_func ) {
return ;
}
2020-12-21 15:39:32 +00:00
for ( int i = 0 ; i < surfaces . size ( ) ; i + + ) {
if ( surfaces [ i ] . primitive ! = Mesh : : PRIMITIVE_TRIANGLES ) {
continue ;
}
surfaces . write [ i ] . lods . clear ( ) ;
Vector < Vector3 > vertices = surfaces [ i ] . arrays [ RS : : ARRAY_VERTEX ] ;
Vector < int > indices = surfaces [ i ] . arrays [ RS : : ARRAY_INDEX ] ;
if ( indices . size ( ) = = 0 ) {
continue ; //no lods if no indices
}
2021-04-10 05:44:36 +00:00
Vector < Vector3 > normals = surfaces [ i ] . arrays [ RS : : ARRAY_NORMAL ] ;
2020-12-21 15:39:32 +00:00
uint32_t vertex_count = vertices . size ( ) ;
const Vector3 * vertices_ptr = vertices . ptr ( ) ;
2021-04-10 05:44:36 +00:00
Vector < float > attributes ;
Vector < float > normal_weights ;
int32_t attribute_count = 6 ;
if ( normals . size ( ) ) {
attributes . resize ( normals . size ( ) * attribute_count ) ;
for ( int32_t normal_i = 0 ; normal_i < normals . size ( ) ; normal_i + + ) {
Basis basis ;
basis . set_euler ( normals [ normal_i ] ) ;
Vector3 basis_x = basis . get_axis ( 0 ) ;
Vector3 basis_y = basis . get_axis ( 1 ) ;
basis = compute_rotation_matrix_from_ortho_6d ( basis_x , basis_y ) ;
basis_x = basis . get_axis ( 0 ) ;
basis_y = basis . get_axis ( 1 ) ;
attributes . write [ normal_i * attribute_count + 0 ] = basis_x . x ;
attributes . write [ normal_i * attribute_count + 1 ] = basis_x . y ;
attributes . write [ normal_i * attribute_count + 2 ] = basis_x . z ;
attributes . write [ normal_i * attribute_count + 3 ] = basis_y . x ;
attributes . write [ normal_i * attribute_count + 4 ] = basis_y . y ;
attributes . write [ normal_i * attribute_count + 5 ] = basis_y . z ;
}
normal_weights . resize ( vertex_count ) ;
for ( int32_t weight_i = 0 ; weight_i < normal_weights . size ( ) ; weight_i + + ) {
normal_weights . write [ weight_i ] = 1.0 ;
}
} else {
attribute_count = 0 ;
}
const int min_indices = 10 ;
const float error_tolerance = 1.44224 ' 95703 ; // Cube root of 3
const float threshold = 1.0 / error_tolerance ;
int index_target = indices . size ( ) * threshold ;
float max_mesh_error_percentage = 1e0 f ;
float mesh_error = 0.0f ;
2021-06-18 19:40:10 +00:00
float scale = SurfaceTool : : simplify_scale_func ( ( const float * ) vertices_ptr , vertex_count , sizeof ( Vector3 ) ) ;
2020-12-21 15:39:32 +00:00
while ( index_target > min_indices ) {
Vector < int > new_indices ;
new_indices . resize ( indices . size ( ) ) ;
2021-04-10 05:44:36 +00:00
size_t new_len = SurfaceTool : : simplify_with_attrib_func ( ( unsigned int * ) new_indices . ptrw ( ) , ( const unsigned int * ) indices . ptr ( ) , indices . size ( ) , ( const float * ) vertices_ptr , vertex_count , sizeof ( Vector3 ) , index_target , max_mesh_error_percentage , & mesh_error , ( float * ) attributes . ptrw ( ) , normal_weights . ptrw ( ) , attribute_count ) ;
if ( ( int ) new_len > ( index_target * error_tolerance ) ) {
break ;
2020-12-21 15:39:32 +00:00
}
Surface : : LOD lod ;
2021-06-18 19:40:10 +00:00
lod . distance = mesh_error * scale ;
2021-06-20 07:03:06 +00:00
if ( Math : : is_zero_approx ( mesh_error ) ) {
2021-04-10 05:44:36 +00:00
break ;
2021-01-09 18:04:09 +00:00
}
2021-04-10 05:44:36 +00:00
if ( new_len < = 0 ) {
break ;
}
new_indices . resize ( new_len ) ;
2020-12-21 15:39:32 +00:00
lod . indices = new_indices ;
2021-04-10 05:44:36 +00:00
print_line ( " Lod " + itos ( surfaces . write [ i ] . lods . size ( ) ) + " begin with " + itos ( indices . size ( ) / 3 ) + " triangles and shoot for " + itos ( index_target / 3 ) + " triangles. Got " + itos ( new_len / 3 ) + " triangles. Lod screen ratio " + rtos ( lod . distance ) ) ;
2020-12-21 15:39:32 +00:00
surfaces . write [ i ] . lods . push_back ( lod ) ;
2021-04-10 05:44:36 +00:00
index_target * = threshold ;
2020-12-21 15:39:32 +00:00
}
}
}
bool EditorSceneImporterMesh : : has_mesh ( ) const {
return mesh . is_valid ( ) ;
}
2021-03-19 12:57:52 +00:00
Ref < ArrayMesh > EditorSceneImporterMesh : : get_mesh ( const Ref < Mesh > & p_base ) {
2020-12-21 15:39:32 +00:00
ERR_FAIL_COND_V ( surfaces . size ( ) = = 0 , Ref < ArrayMesh > ( ) ) ;
if ( mesh . is_null ( ) ) {
2021-03-19 12:57:52 +00:00
if ( p_base . is_valid ( ) ) {
mesh = p_base ;
}
if ( mesh . is_null ( ) ) {
2021-06-17 22:03:09 +00:00
mesh . instantiate ( ) ;
2021-03-19 12:57:52 +00:00
}
mesh - > set_name ( get_name ( ) ) ;
if ( has_meta ( " import_id " ) ) {
mesh - > set_meta ( " import_id " , get_meta ( " import_id " ) ) ;
}
2020-12-21 15:39:32 +00:00
for ( int i = 0 ; i < blend_shapes . size ( ) ; i + + ) {
mesh - > add_blend_shape ( blend_shapes [ i ] ) ;
}
mesh - > set_blend_shape_mode ( blend_shape_mode ) ;
for ( int i = 0 ; i < surfaces . size ( ) ; i + + ) {
Array bs_data ;
if ( surfaces [ i ] . blend_shape_data . size ( ) ) {
for ( int j = 0 ; j < surfaces [ i ] . blend_shape_data . size ( ) ; j + + ) {
bs_data . push_back ( surfaces [ i ] . blend_shape_data [ j ] . arrays ) ;
}
}
Dictionary lods ;
if ( surfaces [ i ] . lods . size ( ) ) {
for ( int j = 0 ; j < surfaces [ i ] . lods . size ( ) ; j + + ) {
lods [ surfaces [ i ] . lods [ j ] . distance ] = surfaces [ i ] . lods [ j ] . indices ;
}
}
mesh - > add_surface_from_arrays ( surfaces [ i ] . primitive , surfaces [ i ] . arrays , bs_data , lods ) ;
if ( surfaces [ i ] . material . is_valid ( ) ) {
mesh - > surface_set_material ( mesh - > get_surface_count ( ) - 1 , surfaces [ i ] . material ) ;
}
if ( surfaces [ i ] . name ! = String ( ) ) {
mesh - > surface_set_name ( mesh - > get_surface_count ( ) - 1 , surfaces [ i ] . name ) ;
}
}
2021-01-25 15:20:11 +00:00
2021-03-19 12:57:52 +00:00
mesh - > set_lightmap_size_hint ( lightmap_size_hint ) ;
2021-01-25 15:20:11 +00:00
if ( shadow_mesh . is_valid ( ) ) {
Ref < ArrayMesh > shadow = shadow_mesh - > get_mesh ( ) ;
mesh - > set_shadow_mesh ( shadow ) ;
}
2020-12-21 15:39:32 +00:00
}
return mesh ;
}
void EditorSceneImporterMesh : : clear ( ) {
surfaces . clear ( ) ;
blend_shapes . clear ( ) ;
mesh . unref ( ) ;
}
2021-01-25 15:20:11 +00:00
void EditorSceneImporterMesh : : create_shadow_mesh ( ) {
if ( shadow_mesh . is_valid ( ) ) {
shadow_mesh . unref ( ) ;
}
//no shadow mesh for blendshapes
if ( blend_shapes . size ( ) > 0 ) {
return ;
}
//no shadow mesh for skeletons
for ( int i = 0 ; i < surfaces . size ( ) ; i + + ) {
if ( surfaces [ i ] . arrays [ RS : : ARRAY_BONES ] . get_type ( ) ! = Variant : : NIL ) {
return ;
}
if ( surfaces [ i ] . arrays [ RS : : ARRAY_WEIGHTS ] . get_type ( ) ! = Variant : : NIL ) {
return ;
}
}
2021-06-17 22:03:09 +00:00
shadow_mesh . instantiate ( ) ;
2021-01-25 15:20:11 +00:00
for ( int i = 0 ; i < surfaces . size ( ) ; i + + ) {
LocalVector < int > vertex_remap ;
Vector < Vector3 > new_vertices ;
Vector < Vector3 > vertices = surfaces [ i ] . arrays [ RS : : ARRAY_VERTEX ] ;
int vertex_count = vertices . size ( ) ;
{
Map < Vector3 , int > unique_vertices ;
const Vector3 * vptr = vertices . ptr ( ) ;
for ( int j = 0 ; j < vertex_count ; j + + ) {
Vector3 v = vptr [ j ] ;
Map < Vector3 , int > : : Element * E = unique_vertices . find ( v ) ;
if ( E ) {
vertex_remap . push_back ( E - > get ( ) ) ;
} else {
int vcount = unique_vertices . size ( ) ;
unique_vertices [ v ] = vcount ;
vertex_remap . push_back ( vcount ) ;
new_vertices . push_back ( v ) ;
}
}
}
Array new_surface ;
new_surface . resize ( RS : : ARRAY_MAX ) ;
Dictionary lods ;
// print_line("original vertex count: " + itos(vertices.size()) + " new vertex count: " + itos(new_vertices.size()));
new_surface [ RS : : ARRAY_VERTEX ] = new_vertices ;
Vector < int > indices = surfaces [ i ] . arrays [ RS : : ARRAY_INDEX ] ;
if ( indices . size ( ) ) {
int index_count = indices . size ( ) ;
const int * index_rptr = indices . ptr ( ) ;
Vector < int > new_indices ;
new_indices . resize ( indices . size ( ) ) ;
int * index_wptr = new_indices . ptrw ( ) ;
for ( int j = 0 ; j < index_count ; j + + ) {
int index = index_rptr [ j ] ;
ERR_FAIL_INDEX ( index , vertex_count ) ;
index_wptr [ j ] = vertex_remap [ index ] ;
}
new_surface [ RS : : ARRAY_INDEX ] = new_indices ;
// Make sure the same LODs as the full version are used.
// This makes it more coherent between rendered model and its shadows.
for ( int j = 0 ; j < surfaces [ i ] . lods . size ( ) ; j + + ) {
indices = surfaces [ i ] . lods [ j ] . indices ;
index_count = indices . size ( ) ;
index_rptr = indices . ptr ( ) ;
new_indices . resize ( indices . size ( ) ) ;
index_wptr = new_indices . ptrw ( ) ;
for ( int k = 0 ; k < index_count ; k + + ) {
int index = index_rptr [ j ] ;
ERR_FAIL_INDEX ( index , vertex_count ) ;
index_wptr [ j ] = vertex_remap [ index ] ;
}
lods [ surfaces [ i ] . lods [ j ] . distance ] = new_indices ;
}
}
shadow_mesh - > add_surface ( surfaces [ i ] . primitive , new_surface , Array ( ) , lods , Ref < Material > ( ) , surfaces [ i ] . name ) ;
}
}
Ref < EditorSceneImporterMesh > EditorSceneImporterMesh : : get_shadow_mesh ( ) const {
return shadow_mesh ;
}
2020-12-21 15:39:32 +00:00
void EditorSceneImporterMesh : : _set_data ( const Dictionary & p_data ) {
clear ( ) ;
if ( p_data . has ( " blend_shape_names " ) ) {
blend_shapes = p_data [ " blend_shape_names " ] ;
}
if ( p_data . has ( " surfaces " ) ) {
Array surface_arr = p_data [ " surfaces " ] ;
for ( int i = 0 ; i < surface_arr . size ( ) ; i + + ) {
Dictionary s = surface_arr [ i ] ;
ERR_CONTINUE ( ! s . has ( " primitive " ) ) ;
ERR_CONTINUE ( ! s . has ( " arrays " ) ) ;
Mesh : : PrimitiveType prim = Mesh : : PrimitiveType ( int ( s [ " primitive " ] ) ) ;
ERR_CONTINUE ( prim > = Mesh : : PRIMITIVE_MAX ) ;
Array arr = s [ " arrays " ] ;
Dictionary lods ;
String name ;
if ( s . has ( " name " ) ) {
name = s [ " name " ] ;
}
if ( s . has ( " lods " ) ) {
lods = s [ " lods " ] ;
}
Array blend_shapes ;
if ( s . has ( " blend_shapes " ) ) {
blend_shapes = s [ " blend_shapes " ] ;
}
Ref < Material > material ;
if ( s . has ( " material " ) ) {
material = s [ " material " ] ;
}
add_surface ( prim , arr , blend_shapes , lods , material , name ) ;
}
}
}
Dictionary EditorSceneImporterMesh : : _get_data ( ) const {
Dictionary data ;
if ( blend_shapes . size ( ) ) {
data [ " blend_shape_names " ] = blend_shapes ;
}
Array surface_arr ;
for ( int i = 0 ; i < surfaces . size ( ) ; i + + ) {
Dictionary d ;
d [ " primitive " ] = surfaces [ i ] . primitive ;
d [ " arrays " ] = surfaces [ i ] . arrays ;
if ( surfaces [ i ] . blend_shape_data . size ( ) ) {
Array bs_data ;
for ( int j = 0 ; j < surfaces [ i ] . blend_shape_data . size ( ) ; j + + ) {
bs_data . push_back ( surfaces [ i ] . blend_shape_data [ j ] . arrays ) ;
}
d [ " blend_shapes " ] = bs_data ;
}
if ( surfaces [ i ] . lods . size ( ) ) {
Dictionary lods ;
for ( int j = 0 ; j < surfaces [ i ] . lods . size ( ) ; j + + ) {
lods [ surfaces [ i ] . lods [ j ] . distance ] = surfaces [ i ] . lods [ j ] . indices ;
}
d [ " lods " ] = lods ;
}
if ( surfaces [ i ] . material . is_valid ( ) ) {
d [ " material " ] = surfaces [ i ] . material ;
}
if ( surfaces [ i ] . name ! = String ( ) ) {
d [ " name " ] = surfaces [ i ] . name ;
}
surface_arr . push_back ( d ) ;
}
data [ " surfaces " ] = surface_arr ;
return data ;
}
2021-03-19 12:57:52 +00:00
Vector < Face3 > EditorSceneImporterMesh : : get_faces ( ) const {
Vector < Face3 > faces ;
for ( int i = 0 ; i < surfaces . size ( ) ; i + + ) {
if ( surfaces [ i ] . primitive = = Mesh : : PRIMITIVE_TRIANGLES ) {
Vector < Vector3 > vertices = surfaces [ i ] . arrays [ Mesh : : ARRAY_VERTEX ] ;
Vector < int > indices = surfaces [ i ] . arrays [ Mesh : : ARRAY_INDEX ] ;
if ( indices . size ( ) ) {
for ( int j = 0 ; j < indices . size ( ) ; j + = 3 ) {
Face3 f ;
f . vertex [ 0 ] = vertices [ indices [ j + 0 ] ] ;
f . vertex [ 1 ] = vertices [ indices [ j + 1 ] ] ;
f . vertex [ 2 ] = vertices [ indices [ j + 2 ] ] ;
faces . push_back ( f ) ;
}
} else {
for ( int j = 0 ; j < vertices . size ( ) ; j + = 3 ) {
Face3 f ;
f . vertex [ 0 ] = vertices [ j + 0 ] ;
f . vertex [ 1 ] = vertices [ j + 1 ] ;
f . vertex [ 2 ] = vertices [ j + 2 ] ;
faces . push_back ( f ) ;
}
}
}
}
return faces ;
}
Vector < Ref < Shape3D > > EditorSceneImporterMesh : : convex_decompose ( ) const {
ERR_FAIL_COND_V ( ! Mesh : : convex_composition_function , Vector < Ref < Shape3D > > ( ) ) ;
const Vector < Face3 > faces = get_faces ( ) ;
2021-07-07 19:14:12 +00:00
Vector < Vector < Face3 > > decomposed = Mesh : : convex_composition_function ( faces , - 1 ) ;
2021-03-19 12:57:52 +00:00
Vector < Ref < Shape3D > > ret ;
for ( int i = 0 ; i < decomposed . size ( ) ; i + + ) {
Set < Vector3 > points ;
for ( int j = 0 ; j < decomposed [ i ] . size ( ) ; j + + ) {
points . insert ( decomposed [ i ] [ j ] . vertex [ 0 ] ) ;
points . insert ( decomposed [ i ] [ j ] . vertex [ 1 ] ) ;
points . insert ( decomposed [ i ] [ j ] . vertex [ 2 ] ) ;
}
Vector < Vector3 > convex_points ;
convex_points . resize ( points . size ( ) ) ;
{
Vector3 * w = convex_points . ptrw ( ) ;
int idx = 0 ;
for ( Set < Vector3 > : : Element * E = points . front ( ) ; E ; E = E - > next ( ) ) {
w [ idx + + ] = E - > get ( ) ;
}
}
Ref < ConvexPolygonShape3D > shape ;
2021-06-17 22:03:09 +00:00
shape . instantiate ( ) ;
2021-03-19 12:57:52 +00:00
shape - > set_points ( convex_points ) ;
ret . push_back ( shape ) ;
}
return ret ;
}
Ref < Shape3D > EditorSceneImporterMesh : : create_trimesh_shape ( ) const {
Vector < Face3 > faces = get_faces ( ) ;
if ( faces . size ( ) = = 0 ) {
return Ref < Shape3D > ( ) ;
}
Vector < Vector3 > face_points ;
face_points . resize ( faces . size ( ) * 3 ) ;
for ( int i = 0 ; i < face_points . size ( ) ; i + = 3 ) {
Face3 f = faces . get ( i / 3 ) ;
face_points . set ( i , f . vertex [ 0 ] ) ;
face_points . set ( i + 1 , f . vertex [ 1 ] ) ;
face_points . set ( i + 2 , f . vertex [ 2 ] ) ;
}
Ref < ConcavePolygonShape3D > shape = memnew ( ConcavePolygonShape3D ) ;
shape - > set_faces ( face_points ) ;
return shape ;
}
Ref < NavigationMesh > EditorSceneImporterMesh : : create_navigation_mesh ( ) {
Vector < Face3 > faces = get_faces ( ) ;
if ( faces . size ( ) = = 0 ) {
return Ref < NavigationMesh > ( ) ;
}
Map < Vector3 , int > unique_vertices ;
LocalVector < int > face_indices ;
for ( int i = 0 ; i < faces . size ( ) ; i + + ) {
for ( int j = 0 ; j < 3 ; j + + ) {
Vector3 v = faces [ i ] . vertex [ j ] ;
int idx ;
if ( unique_vertices . has ( v ) ) {
idx = unique_vertices [ v ] ;
} else {
idx = unique_vertices . size ( ) ;
unique_vertices [ v ] = idx ;
}
face_indices . push_back ( idx ) ;
}
}
Vector < Vector3 > vertices ;
vertices . resize ( unique_vertices . size ( ) ) ;
for ( Map < Vector3 , int > : : Element * E = unique_vertices . front ( ) ; E ; E = E - > next ( ) ) {
vertices . write [ E - > get ( ) ] = E - > key ( ) ;
}
Ref < NavigationMesh > nm ;
2021-06-17 22:03:09 +00:00
nm . instantiate ( ) ;
2021-03-19 12:57:52 +00:00
nm - > set_vertices ( vertices ) ;
Vector < int > v3 ;
v3 . resize ( 3 ) ;
for ( uint32_t i = 0 ; i < face_indices . size ( ) ; i + = 3 ) {
v3 . write [ 0 ] = face_indices [ i + 0 ] ;
v3 . write [ 1 ] = face_indices [ i + 1 ] ;
v3 . write [ 2 ] = face_indices [ i + 2 ] ;
nm - > add_polygon ( v3 ) ;
}
return nm ;
}
2021-04-25 21:36:39 +00:00
extern bool ( * array_mesh_lightmap_unwrap_callback ) ( float p_texel_size , const float * p_vertices , const float * p_normals , int p_vertex_count , const int * p_indices , int p_index_count , const uint8_t * p_cache_data , bool * r_use_cache , uint8_t * * r_mesh_cache , int * r_mesh_cache_size , float * * r_uv , int * * r_vertex , int * r_vertex_count , int * * r_index , int * r_index_count , int * r_size_hint_x , int * r_size_hint_y ) ;
2021-03-19 12:57:52 +00:00
struct EditorSceneImporterMeshLightmapSurface {
Ref < Material > material ;
LocalVector < SurfaceTool : : Vertex > vertices ;
Mesh : : PrimitiveType primitive = Mesh : : PrimitiveType : : PRIMITIVE_MAX ;
uint32_t format = 0 ;
String name ;
} ;
2020-10-17 05:08:21 +00:00
Error EditorSceneImporterMesh : : lightmap_unwrap_cached ( const Transform3D & p_base_transform , float p_texel_size , const Vector < uint8_t > & p_src_cache , Vector < uint8_t > & r_dst_cache ) {
2021-03-19 12:57:52 +00:00
ERR_FAIL_COND_V ( ! array_mesh_lightmap_unwrap_callback , ERR_UNCONFIGURED ) ;
ERR_FAIL_COND_V_MSG ( blend_shapes . size ( ) ! = 0 , ERR_UNAVAILABLE , " Can't unwrap mesh with blend shapes. " ) ;
2021-04-25 21:36:39 +00:00
LocalVector < float > vertices ;
LocalVector < float > normals ;
LocalVector < int > indices ;
LocalVector < float > uv ;
LocalVector < Pair < int , int > > uv_indices ;
2021-03-19 12:57:52 +00:00
Vector < EditorSceneImporterMeshLightmapSurface > lightmap_surfaces ;
// Keep only the scale
2021-04-25 21:36:39 +00:00
Basis basis = p_base_transform . get_basis ( ) ;
Vector3 scale = Vector3 ( basis . get_axis ( 0 ) . length ( ) , basis . get_axis ( 1 ) . length ( ) , basis . get_axis ( 2 ) . length ( ) ) ;
2020-10-17 05:08:21 +00:00
Transform3D transform ;
2021-04-25 21:36:39 +00:00
transform . scale ( scale ) ;
2021-03-19 12:57:52 +00:00
Basis normal_basis = transform . basis . inverse ( ) . transposed ( ) ;
for ( int i = 0 ; i < get_surface_count ( ) ; i + + ) {
EditorSceneImporterMeshLightmapSurface s ;
s . primitive = get_surface_primitive_type ( i ) ;
ERR_FAIL_COND_V_MSG ( s . primitive ! = Mesh : : PRIMITIVE_TRIANGLES , ERR_UNAVAILABLE , " Only triangles are supported for lightmap unwrap. " ) ;
Array arrays = get_surface_arrays ( i ) ;
s . material = get_surface_material ( i ) ;
s . name = get_surface_name ( i ) ;
SurfaceTool : : create_vertex_array_from_triangle_arrays ( arrays , s . vertices , & s . format ) ;
2021-04-25 21:36:39 +00:00
PackedVector3Array rvertices = arrays [ Mesh : : ARRAY_VERTEX ] ;
2021-03-19 12:57:52 +00:00
int vc = rvertices . size ( ) ;
2021-04-25 21:36:39 +00:00
PackedVector3Array rnormals = arrays [ Mesh : : ARRAY_NORMAL ] ;
2021-03-19 12:57:52 +00:00
int vertex_ofs = vertices . size ( ) / 3 ;
vertices . resize ( ( vertex_ofs + vc ) * 3 ) ;
normals . resize ( ( vertex_ofs + vc ) * 3 ) ;
uv_indices . resize ( vertex_ofs + vc ) ;
for ( int j = 0 ; j < vc ; j + + ) {
2021-04-25 21:36:39 +00:00
Vector3 v = transform . xform ( rvertices [ j ] ) ;
Vector3 n = normal_basis . xform ( rnormals [ j ] ) . normalized ( ) ;
vertices [ ( j + vertex_ofs ) * 3 + 0 ] = v . x ;
vertices [ ( j + vertex_ofs ) * 3 + 1 ] = v . y ;
vertices [ ( j + vertex_ofs ) * 3 + 2 ] = v . z ;
normals [ ( j + vertex_ofs ) * 3 + 0 ] = n . x ;
normals [ ( j + vertex_ofs ) * 3 + 1 ] = n . y ;
normals [ ( j + vertex_ofs ) * 3 + 2 ] = n . z ;
uv_indices [ j + vertex_ofs ] = Pair < int , int > ( i , j ) ;
2021-03-19 12:57:52 +00:00
}
2021-04-25 21:36:39 +00:00
PackedInt32Array rindices = arrays [ Mesh : : ARRAY_INDEX ] ;
2021-03-19 12:57:52 +00:00
int ic = rindices . size ( ) ;
2021-04-25 21:36:39 +00:00
float eps = 1.19209290e-7 F ; // Taken from xatlas.h
2021-03-19 12:57:52 +00:00
if ( ic = = 0 ) {
for ( int j = 0 ; j < vc / 3 ; j + + ) {
2021-04-25 21:36:39 +00:00
Vector3 p0 = transform . xform ( rvertices [ j * 3 + 0 ] ) ;
Vector3 p1 = transform . xform ( rvertices [ j * 3 + 1 ] ) ;
Vector3 p2 = transform . xform ( rvertices [ j * 3 + 2 ] ) ;
if ( ( p0 - p1 ) . length_squared ( ) < eps | | ( p1 - p2 ) . length_squared ( ) < eps | | ( p2 - p0 ) . length_squared ( ) < eps ) {
2021-03-19 12:57:52 +00:00
continue ;
}
indices . push_back ( vertex_ofs + j * 3 + 0 ) ;
indices . push_back ( vertex_ofs + j * 3 + 1 ) ;
indices . push_back ( vertex_ofs + j * 3 + 2 ) ;
}
} else {
for ( int j = 0 ; j < ic / 3 ; j + + ) {
2021-04-25 21:36:39 +00:00
Vector3 p0 = transform . xform ( rvertices [ rindices [ j * 3 + 0 ] ] ) ;
Vector3 p1 = transform . xform ( rvertices [ rindices [ j * 3 + 1 ] ] ) ;
Vector3 p2 = transform . xform ( rvertices [ rindices [ j * 3 + 2 ] ] ) ;
if ( ( p0 - p1 ) . length_squared ( ) < eps | | ( p1 - p2 ) . length_squared ( ) < eps | | ( p2 - p0 ) . length_squared ( ) < eps ) {
2021-03-19 12:57:52 +00:00
continue ;
}
2021-04-25 21:36:39 +00:00
indices . push_back ( vertex_ofs + rindices [ j * 3 + 0 ] ) ;
indices . push_back ( vertex_ofs + rindices [ j * 3 + 1 ] ) ;
indices . push_back ( vertex_ofs + rindices [ j * 3 + 2 ] ) ;
2021-03-19 12:57:52 +00:00
}
}
lightmap_surfaces . push_back ( s ) ;
}
//unwrap
2021-04-25 21:36:39 +00:00
bool use_cache = true ; // Used to request cache generation and to know if cache was used
uint8_t * gen_cache ;
int gen_cache_size ;
2021-03-19 12:57:52 +00:00
float * gen_uvs ;
int * gen_vertices ;
int * gen_indices ;
int gen_vertex_count ;
int gen_index_count ;
int size_x ;
int size_y ;
2021-04-25 21:36:39 +00:00
bool ok = array_mesh_lightmap_unwrap_callback ( p_texel_size , vertices . ptr ( ) , normals . ptr ( ) , vertices . size ( ) / 3 , indices . ptr ( ) , indices . size ( ) , p_src_cache . ptr ( ) , & use_cache , & gen_cache , & gen_cache_size , & gen_uvs , & gen_vertices , & gen_vertex_count , & gen_indices , & gen_index_count , & size_x , & size_y ) ;
2021-03-19 12:57:52 +00:00
if ( ! ok ) {
return ERR_CANT_CREATE ;
}
//remove surfaces
clear ( ) ;
//create surfacetools for each surface..
2021-04-25 21:36:39 +00:00
LocalVector < Ref < SurfaceTool > > surfaces_tools ;
2021-03-19 12:57:52 +00:00
for ( int i = 0 ; i < lightmap_surfaces . size ( ) ; i + + ) {
Ref < SurfaceTool > st ;
2021-06-17 22:03:09 +00:00
st . instantiate ( ) ;
2021-03-19 12:57:52 +00:00
st - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
st - > set_material ( lightmap_surfaces [ i ] . material ) ;
st - > set_meta ( " name " , lightmap_surfaces [ i ] . name ) ;
surfaces_tools . push_back ( st ) ; //stay there
}
print_verbose ( " Mesh: Gen indices: " + itos ( gen_index_count ) ) ;
2021-04-25 21:36:39 +00:00
2021-03-19 12:57:52 +00:00
//go through all indices
for ( int i = 0 ; i < gen_index_count ; i + = 3 ) {
2021-04-25 21:36:39 +00:00
ERR_FAIL_INDEX_V ( gen_vertices [ gen_indices [ i + 0 ] ] , ( int ) uv_indices . size ( ) , ERR_BUG ) ;
ERR_FAIL_INDEX_V ( gen_vertices [ gen_indices [ i + 1 ] ] , ( int ) uv_indices . size ( ) , ERR_BUG ) ;
ERR_FAIL_INDEX_V ( gen_vertices [ gen_indices [ i + 2 ] ] , ( int ) uv_indices . size ( ) , ERR_BUG ) ;
2021-03-19 12:57:52 +00:00
ERR_FAIL_COND_V ( uv_indices [ gen_vertices [ gen_indices [ i + 0 ] ] ] . first ! = uv_indices [ gen_vertices [ gen_indices [ i + 1 ] ] ] . first | | uv_indices [ gen_vertices [ gen_indices [ i + 0 ] ] ] . first ! = uv_indices [ gen_vertices [ gen_indices [ i + 2 ] ] ] . first , ERR_BUG ) ;
int surface = uv_indices [ gen_vertices [ gen_indices [ i + 0 ] ] ] . first ;
for ( int j = 0 ; j < 3 ; j + + ) {
SurfaceTool : : Vertex v = lightmap_surfaces [ surface ] . vertices [ uv_indices [ gen_vertices [ gen_indices [ i + j ] ] ] . second ] ;
if ( lightmap_surfaces [ surface ] . format & Mesh : : ARRAY_FORMAT_COLOR ) {
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_color ( v . color ) ;
2021-03-19 12:57:52 +00:00
}
if ( lightmap_surfaces [ surface ] . format & Mesh : : ARRAY_FORMAT_TEX_UV ) {
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_uv ( v . uv ) ;
2021-03-19 12:57:52 +00:00
}
if ( lightmap_surfaces [ surface ] . format & Mesh : : ARRAY_FORMAT_NORMAL ) {
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_normal ( v . normal ) ;
2021-03-19 12:57:52 +00:00
}
if ( lightmap_surfaces [ surface ] . format & Mesh : : ARRAY_FORMAT_TANGENT ) {
Plane t ;
t . normal = v . tangent ;
t . d = v . binormal . dot ( v . normal . cross ( v . tangent ) ) < 0 ? - 1 : 1 ;
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_tangent ( t ) ;
2021-03-19 12:57:52 +00:00
}
if ( lightmap_surfaces [ surface ] . format & Mesh : : ARRAY_FORMAT_BONES ) {
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_bones ( v . bones ) ;
2021-03-19 12:57:52 +00:00
}
if ( lightmap_surfaces [ surface ] . format & Mesh : : ARRAY_FORMAT_WEIGHTS ) {
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_weights ( v . weights ) ;
2021-03-19 12:57:52 +00:00
}
Vector2 uv2 ( gen_uvs [ gen_indices [ i + j ] * 2 + 0 ] , gen_uvs [ gen_indices [ i + j ] * 2 + 1 ] ) ;
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > set_uv2 ( uv2 ) ;
2021-03-19 12:57:52 +00:00
2021-04-25 21:36:39 +00:00
surfaces_tools [ surface ] - > add_vertex ( v . vertex ) ;
2021-03-19 12:57:52 +00:00
}
}
//generate surfaces
2021-04-25 21:36:39 +00:00
for ( unsigned int i = 0 ; i < surfaces_tools . size ( ) ; i + + ) {
surfaces_tools [ i ] - > index ( ) ;
Array arrays = surfaces_tools [ i ] - > commit_to_arrays ( ) ;
add_surface ( surfaces_tools [ i ] - > get_primitive ( ) , arrays , Array ( ) , Dictionary ( ) , surfaces_tools [ i ] - > get_material ( ) , surfaces_tools [ i ] - > get_meta ( " name " ) ) ;
2021-03-19 12:57:52 +00:00
}
set_lightmap_size_hint ( Size2 ( size_x , size_y ) ) ;
2021-04-25 21:36:39 +00:00
if ( gen_cache_size > 0 ) {
r_dst_cache . resize ( gen_cache_size ) ;
memcpy ( r_dst_cache . ptrw ( ) , gen_cache , gen_cache_size ) ;
memfree ( gen_cache ) ;
}
if ( ! use_cache ) {
// Cache was not used, free the buffers
memfree ( gen_vertices ) ;
memfree ( gen_indices ) ;
memfree ( gen_uvs ) ;
2021-03-19 12:57:52 +00:00
}
return OK ;
}
void EditorSceneImporterMesh : : set_lightmap_size_hint ( const Size2i & p_size ) {
lightmap_size_hint = p_size ;
}
Size2i EditorSceneImporterMesh : : get_lightmap_size_hint ( ) const {
return lightmap_size_hint ;
}
2020-12-21 15:39:32 +00:00
void EditorSceneImporterMesh : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " add_blend_shape " , " name " ) , & EditorSceneImporterMesh : : add_blend_shape ) ;
ClassDB : : bind_method ( D_METHOD ( " get_blend_shape_count " ) , & EditorSceneImporterMesh : : get_blend_shape_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_blend_shape_name " , " blend_shape_idx " ) , & EditorSceneImporterMesh : : get_blend_shape_name ) ;
ClassDB : : bind_method ( D_METHOD ( " set_blend_shape_mode " , " mode " ) , & EditorSceneImporterMesh : : set_blend_shape_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_blend_shape_mode " ) , & EditorSceneImporterMesh : : get_blend_shape_mode ) ;
2021-02-18 07:47:06 +00:00
ClassDB : : bind_method ( D_METHOD ( " add_surface " , " primitive " , " arrays " , " blend_shapes " , " lods " , " material " , " name " ) , & EditorSceneImporterMesh : : add_surface , DEFVAL ( Array ( ) ) , DEFVAL ( Dictionary ( ) ) , DEFVAL ( Ref < Material > ( ) ) , DEFVAL ( String ( ) ) ) ;
2020-12-21 15:39:32 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_surface_count " ) , & EditorSceneImporterMesh : : get_surface_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_primitive_type " , " surface_idx " ) , & EditorSceneImporterMesh : : get_surface_primitive_type ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_name " , " surface_idx " ) , & EditorSceneImporterMesh : : get_surface_name ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_arrays " , " surface_idx " ) , & EditorSceneImporterMesh : : get_surface_arrays ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_blend_shape_arrays " , " surface_idx " , " blend_shape_idx " ) , & EditorSceneImporterMesh : : get_surface_blend_shape_arrays ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_lod_count " , " surface_idx " ) , & EditorSceneImporterMesh : : get_surface_lod_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_lod_size " , " surface_idx " , " lod_idx " ) , & EditorSceneImporterMesh : : get_surface_lod_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_lod_indices " , " surface_idx " , " lod_idx " ) , & EditorSceneImporterMesh : : get_surface_lod_indices ) ;
ClassDB : : bind_method ( D_METHOD ( " get_surface_material " , " surface_idx " ) , & EditorSceneImporterMesh : : get_surface_material ) ;
ClassDB : : bind_method ( D_METHOD ( " get_mesh " ) , & EditorSceneImporterMesh : : get_mesh ) ;
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & EditorSceneImporterMesh : : clear ) ;
ClassDB : : bind_method ( D_METHOD ( " _set_data " , " data " ) , & EditorSceneImporterMesh : : _set_data ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_data " ) , & EditorSceneImporterMesh : : _get_data ) ;
2021-03-19 12:57:52 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_lightmap_size_hint " , " size " ) , & EditorSceneImporterMesh : : set_lightmap_size_hint ) ;
ClassDB : : bind_method ( D_METHOD ( " get_lightmap_size_hint " ) , & EditorSceneImporterMesh : : get_lightmap_size_hint ) ;
2020-12-21 15:39:32 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : DICTIONARY , " _data " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR ) , " _set_data " , " _get_data " ) ;
}