FBXLoader::FBXLoader(const char *filename) { m_error = true; if (m_fbx_sdk_manager == nullptr) { m_fbx_sdk_manager = FbxManager::Create(); m_fbx_sdk_manager->SetIOSettings(FbxIOSettings::Create(m_fbx_sdk_manager, IOSROOT)); } FbxImporter *importer = FbxImporter::Create(m_fbx_sdk_manager, ""); FbxScene *scene = FbxScene::Create(m_fbx_sdk_manager, ""); if (!importer->Initialize(filename, -1, m_fbx_sdk_manager->GetIOSettings())) return; if (!importer->Import(scene)) return; importer->Destroy(); FbxNode *root_node = scene->GetRootNode(); if (root_node) { for (int i = 0; i < root_node->GetChildCount(); i++) { FbxNode *child_node = root_node->GetChild(i); if (child_node->GetNodeAttribute() == NULL) continue; FbxNodeAttribute::EType type = child_node->GetNodeAttribute()->GetAttributeType(); if (type != FbxNodeAttribute::eMesh) continue; FbxMesh *mesh = (FbxMesh *) child_node->GetNodeAttribute(); FbxVector4 *vertices = mesh->GetControlPoints(); for (int j = 0; j < mesh->GetPolygonCount(); j++) { int num_verts = mesh->GetPolygonSize(j); assert(num_verts == 3); DirectX::XMFLOAT3 vertex[3]; FbxVector4 polygon_normal(0, 0, 0); for (int k = 0; k < num_verts; k++) { int control_point_idx = mesh->GetPolygonVertex(j, k); FbxVector4 vertex_normal; mesh->GetPolygonVertexNormal(j, k, vertex_normal); polygon_normal += vertex_normal; vertex[k].x = (float) vertices[control_point_idx].mData[0]; vertex[k].y = (float) vertices[control_point_idx].mData[1]; vertex[k].z = (float) vertices[control_point_idx].mData[2]; } if (IsClockwise(vertex, num_verts, polygon_normal)) { for (int i = 0; i < num_verts; i++) m_vertices.push_back(ToD3DCoordinateSystem(vertex[i])); } else { for (int i = 0; i < num_verts; i++) m_vertices.push_back(ToD3DCoordinateSystem(vertex[num_verts - 1 - i])); } } } } for (size_t i = 0; i < m_vertices.size(); i++) m_indices.push_back(i); m_error = false; }
void bsp_tree_create_from_solid(struct BspTree* tree, struct Solid* solid) { size_t alloc_attributes_result = bsp_tree_alloc_attributes(tree, solid->attributes_size); log_assert( alloc_attributes_result >= solid->attributes_size ); size_t num_polygons = solid->indices_size/3; size_t alloc_polygons_result = bsp_tree_alloc_polygons(tree, num_polygons); log_assert( alloc_polygons_result >= num_polygons ); size_t alloc_nodes_result = bsp_tree_alloc_nodes(tree, num_polygons); log_assert( alloc_nodes_result >= num_polygons ); int32_t* workset_polygons_front = malloc(alloc_polygons_result * sizeof(int32_t)); log_assert( workset_polygons_front != NULL ); int32_t* workset_polygons_back = malloc(alloc_polygons_result * sizeof(int32_t)); log_assert( workset_polygons_back != NULL ); float min_x = FLT_MAX; float min_y = FLT_MAX; float min_z = FLT_MAX; float max_x = -FLT_MAX; float max_y = -FLT_MAX; float max_z = -FLT_MAX; for( size_t indices_i = 0; indices_i < solid->indices_size+1; indices_i++ ) { uint32_t src_i = solid->indices[indices_i]; if( indices_i < solid->indices_size ) { VecP* src = &solid->vertices[src_i*VERTEX_SIZE]; VecP* dst = &tree->attributes.vertices[indices_i*VERTEX_SIZE]; vec_copy3f(src, dst); tree->attributes.occupied += 1; if( src[0] < min_x ) { min_x = src[0]; } if( src[1] < min_y ) { min_y = src[1]; } if( src[2] < min_z ) { min_z = src[2]; } if( src[0] > max_x ) { max_x = src[0]; } if( src[1] > max_y ) { max_y = src[1]; } if( src[2] > max_z ) { max_z = src[2]; } } if( indices_i > 0 && indices_i % 3 == 0 ) { size_t poly_i = indices_i / 3 - 1; tree->polygons.array[poly_i].start = poly_i*3*VERTEX_SIZE; tree->polygons.array[poly_i].size = 3; polygon_normal(3, VERTEX_SIZE, &tree->attributes.vertices[poly_i*3*VERTEX_SIZE], tree->polygons.array[poly_i].normal); tree->polygons.occupied += 1; workset_polygons_front[poly_i] = poly_i; } } struct BspNode* root = &tree->nodes.array[0]; bsp_node_create(root); tree->nodes.occupied = 1; root->bounds.half_width = (max_x - min_x)/2.0f; root->bounds.half_height = (max_y - min_y)/2.0f; root->bounds.half_depth = (max_z - min_z)/2.0f; root->bounds.center[0] = min_x + root->bounds.half_width; root->bounds.center[1] = min_y + root->bounds.half_height; root->bounds.center[2] = min_z + root->bounds.half_depth; root->divider = 0; bsp_select_balanced_divider(tree, root, num_polygons, workset_polygons_front, &root->divider); struct BspPoly* root_divider = &tree->polygons.array[root->divider]; const float* root_divider_polygon = &tree->attributes.vertices[root_divider->start]; draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 0, 255}, 0.01f, root_divider->size, root_divider_polygon, root_divider->normal); draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 0, 255}, 0.01f, root_divider->normal, &root_divider_polygon[3], 1.0f, 0.1f); /* draw_plane(&global_static_canvas, MAX_CANVAS_LAYERS-1, (Mat)IDENTITY_MAT, (Color){120, 120, 150, 127}, root_divider->normal, &root_divider_polygon[3], 10.0f); */ for( size_t polygon_i = 0; polygon_i < num_polygons; polygon_i++ ) { size_t cuts_polygon_size = 3; const float* cuts_polygon = &tree->attributes.vertices[polygon_i*cuts_polygon_size*VERTEX_SIZE]; size_t result_size = cuts_polygon_size; struct PolygonCutPoints result_points[cuts_polygon_size]; enum PolygonCutType result_type = polygon_cut(cuts_polygon_size, VERTEX_SIZE, cuts_polygon, root_divider->normal, root_divider_polygon, result_size, result_points); Vec3f cuts_polygon_normal = {0}; polygon_normal(3, VERTEX_SIZE, cuts_polygon, cuts_polygon_normal); switch(result_type) { case POLYGON_COPLANNAR: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_FRONT: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 0, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_BACK: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){0, 0, 255, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); break; case POLYGON_SPANNING: //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 0, 255}, 0.01f, result_size, cuts_polygon, cuts_polygon_normal); if( result_points[0].num_cuts > 0 ) { size_t new_poly_size = cuts_polygon_size+result_points[0].num_cuts+10; size_t front_occupied = 0; float front_vertices[new_poly_size*VERTEX_SIZE]; size_t back_occupied = 0; float back_vertices[new_poly_size*VERTEX_SIZE]; for( size_t result_i = 0; result_i < result_size; result_i++ ) { if( result_points[result_i].type == POLYGON_BACK ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; } else if( result_points[result_i].type == POLYGON_FRONT ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } else if( result_points[result_i].type == POLYGON_COPLANNAR ) { vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; vec_copy3f(&cuts_polygon[result_i*VERTEX_SIZE], &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } if( result_points[result_i].interpolation_index > -1 ) { const VecP* a = &cuts_polygon[result_i*VERTEX_SIZE]; const VecP* b = &cuts_polygon[result_points[result_i].interpolation_index*VERTEX_SIZE]; Vec3f r = {0}; vec_lerp(b, a, result_points[result_i].interpolation_value, r); vec_copy3f(r, &back_vertices[back_occupied*VERTEX_SIZE]); back_occupied += 1; vec_copy3f(r, &front_vertices[front_occupied*VERTEX_SIZE]); front_occupied += 1; } } //printf("front_occupied: %lu\n", front_occupied); //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, red, 0.01f, front_occupied, front_vertices, cuts_polygon_normal); //draw_polygon_wire(&global_static_canvas, 0, (Mat)IDENTITY_MAT, white, 0.01f, back_occupied, back_vertices, cuts_polygon_normal); } break; } } log_fail(__FILE__, __LINE__, "BUILT BSP TREE... OR NOT?\n"); }
/** * メッシュ情報を読み込む * * @param mesh メッシュ情報 */ void FbxFileLoader::load_mesh( FbxMesh* mesh ) { if ( ! mesh ) { return; } if ( ! get_model()->get_mesh() ) { get_model()->set_mesh( create_mesh() ); } VertexIndexMap vertex_index_map; VertexList vertex_list; Mesh::PositionList position_list; Mesh::VertexWeightList vertex_weight_list; // load_mesh_vertex() for ( int n = 0; n < mesh->GetControlPointsCount(); n++ ) { FbxVector4 v = mesh->GetControlPointAt( n ); position_list.push_back( Mesh::Position( static_cast< float >( v[ 0 ] ), static_cast< float >( v[ 1 ] ), static_cast< float >( v[ 2 ] ) ) ); } // load_mesh_vertex_weight() { int skin_count = mesh->GetDeformerCount( FbxDeformer::eSkin ); if ( skin_count > 0 ) { assert( skin_count == 1 ); vertex_weight_list.resize( position_list.size() ); FbxSkin* skin = FbxCast< FbxSkin >( mesh->GetDeformer( 0, FbxDeformer::eSkin ) ); load_mesh_vertex_weight( skin, vertex_weight_list ); } } FbxLayerElementSmoothing* smoothing = 0; // load_mesh_smoothing_info() { FbxLayer* layer = mesh->GetLayer( 0 ); smoothing = layer->GetSmoothing(); } if ( ! smoothing ) { COMMON_THROW_EXCEPTION_MESSAGE( "this FBX format is not supported. ( no smoothing info )" ); } // load_mesh_plygon() FbxLayerElementArrayTemplate< int >* material_indices; mesh->GetMaterialIndices( & material_indices ); for ( int n = 0; n < mesh->GetPolygonCount(); n++ ) { Mesh::VertexGroup* vertex_group = get_model()->get_mesh()->get_vertex_group_at( material_indices->GetAt( n ) ); bool is_smooth = smoothing->GetDirectArray().GetAt( n ) != 0; FbxVector4 polygon_normal( 0.f, 0.f, 0.f ); if ( ! is_smooth ) { // ポリゴンの法線を計算する Mesh::Position p1( position_list.at( mesh->GetPolygonVertex( n, 0 ) ) ); Mesh::Position p2( position_list.at( mesh->GetPolygonVertex( n, 1 ) ) ); Mesh::Position p3( position_list.at( mesh->GetPolygonVertex( n, 2 ) ) ); FbxVector4 a = FbxVector4( p1.x(), p1.y(), p1.z() ); FbxVector4 b = FbxVector4( p2.x(), p2.y(), p2.z() ); FbxVector4 c = FbxVector4( p3.x(), p3.y(), p3.z() ); FbxVector4 ab( b - a ); FbxVector4 bc( c - b ); polygon_normal = ab.CrossProduct( bc ); polygon_normal.Normalize(); } for ( int m = 0; m < mesh->GetPolygonSize( n ); m++ ) { int position_index = mesh->GetPolygonVertex( n, m ); Mesh::Vertex v; v.Position = Mesh::Position( position_list.at( position_index ) ); FbxVector2 uv_vector; bool unmapped; if ( mesh->GetPolygonVertexUV( n, m, "UVMap", uv_vector, unmapped) ) { v.TexCoord = Mesh::TexCoord( static_cast< float >( uv_vector[ 0 ] ), 1.f - static_cast< float >( uv_vector[ 1 ] ) ); } if ( is_smooth ) { FbxVector4 normal_vector; // 頂点の法線 if ( mesh->GetPolygonVertexNormal( n, m, normal_vector ) ) { v.Normal = Mesh::Normal( static_cast< float >( normal_vector[ 0 ] ), static_cast< float >( normal_vector[ 1 ] ), static_cast< float >( normal_vector[ 2 ] ) ); } } else { // ポリゴンの法線 v.Normal = Mesh::Normal( static_cast< float >( polygon_normal[ 0 ] ), static_cast< float >( polygon_normal[ 1 ] ), static_cast< float >( polygon_normal[ 2 ] ) ); } // 頂点の一覧に追加 { VertexIndexMap::iterator i = vertex_index_map.find( v ); if ( i != vertex_index_map.end() ) { vertex_group->add_index( i->second ); } else { Mesh::Index vertex_index = static_cast< Mesh::Index >( get_model()->get_mesh()->get_vertex_count() ); get_model()->get_mesh()->add_vertex( v ); if ( ! vertex_weight_list.empty() ) { get_model()->get_mesh()->add_vertex_weight( vertex_weight_list.at( position_index ) ); } vertex_group->add_index( vertex_index ); vertex_index_map[ v ] = vertex_index; } } } } }