buildMaterial method

Future<Material?> buildMaterial(
  1. Map<String, dynamic> data
)

Implementation

Future<Material?> buildMaterial(Map<String,dynamic> data ) async{
  final effect = await getEffect( data['url'] );
  final Map<String,dynamic> technique = effect['profile']['technique'];
  Material? material;

  switch ( technique['type'] ) {
    case 'phong':
    case 'blinn':
      material = MeshPhongMaterial();
      break;
    case 'lambert':
      material = MeshLambertMaterial();
      break;
    default:
      material = MeshBasicMaterial();
      break;
  }

  material.name = data['name'] ?? '';

  Future<Texture?> getTexture( textureObject, [colorSpace]) async{
    final sampler = effect['profile']['samplers'][ textureObject['id'] ];
    var image;

    // get image

    if ( sampler != null ) {
      final surface = effect['profile']['surfaces'][ sampler['source'] ];
      image = await getImage( surface['init_from'] );
    }
    else {
      console.warning( 'ColladaLoader: Undefined sampler. Access image directly (see #12530).' );
      image = await getImage( textureObject['id'] );
    }

    // create texture if image is avaiable

    if ( image != null ) {
      final loader = getTextureLoader( image );
      final Texture texture = (await loader.unknown( image ))!;
      final extra = textureObject['extra'];

      if ( extra != null && extra['technique'] != null && !isEmpty( extra['technique'] )) {
        final technique = extra['technique'];

        texture.wrapS = technique['wrapU'] ? RepeatWrapping : ClampToEdgeWrapping;
        texture.wrapT = technique['wrapV'] ? RepeatWrapping : ClampToEdgeWrapping;

        texture.offset.setValues( technique['offsetU'] ?? 0, technique['offsetV'] ?? 0 );
        texture.repeat.setValues( technique['repeatU'] ?? 1, technique['repeatV'] ?? 1 );
      }
      else {
        texture.wrapS = RepeatWrapping;
        texture.wrapT = RepeatWrapping;
      }

      if ( colorSpace != null ) {
        texture.colorSpace = colorSpace;
      }

      return texture;
    }
    else {
      console.warning( 'ColladaLoader: Couldn\'t create texture with ID: ${textureObject['id']}');
      return null;
    }
  }

  final Map<String,dynamic> parameters = technique['parameters'];

  for ( final key in parameters.keys ) {
    final Map<String,dynamic> parameter = parameters[ key ];

    switch ( key ) {
      case 'diffuse':
        if ( parameter['color']  != null ) material.color.copyFromArray( parameter['color'] );
        if ( parameter['texture']  != null ) material.map = await getTexture( parameter['texture'], SRGBColorSpace );
        break;
      case 'specular':
        if ( parameter['color']  != null && material.specular  != null ) material.specular?.copyFromArray( parameter['color'] );
        if ( parameter['texture'] != null) material.specularMap = await getTexture( parameter['texture'] );
        break;
      case 'bump':
        if ( parameter['texture']  != null ) material.normalMap = await getTexture( parameter['texture'] );
        break;
      case 'ambient':
        if ( parameter['texture']  != null ) material.lightMap = await getTexture( parameter['texture'], SRGBColorSpace );
        break;
      case 'shininess':
        if ( parameter['float']  != null && material.shininess  != null ) material.shininess = parameter['float'];
        break;
      case 'emission':
        if ( parameter['color'] != null && material.emissive  != null ) material.emissive?.copyFromArray( parameter['color'] );
        if ( parameter['texture']  != null ) material.emissiveMap = await getTexture( parameter['texture'], SRGBColorSpace );
        break;
    }
  }

  material.color.convertSRGBToLinear();
  if ( material.specular != null) material.specular?.convertSRGBToLinear();
  if ( material.emissive != null) material.emissive?.convertSRGBToLinear();

  Map<String,dynamic>? transparent = parameters[ 'transparent' ];
  Map<String,dynamic>? transparency = parameters[ 'transparency' ];

  // <transparency> does not exist but <transparent>

  if ( transparency == null && transparent != null) {
    transparency = {
      'float': 1
    };
  }

  // <transparent> does not exist but <transparency>

  if ( transparent == null && transparency != null) {
    transparent = {
      'opaque': 'A_ONE',
      'data': {
        'color': [ 1, 1, 1, 1 ]
      } };
  }

  if ( transparent != null && transparency != null) {
    // handle case if a texture exists but no color

    if ( transparent['data']?['texture'] != null) {
      material.transparent = true;
    }
    else {
      final List<double> color = transparent['data']['color'];
      switch ( transparent['opaque'] ) {
        case 'A_ONE':
          material.opacity = color[ 3 ] * transparency['float'];
          break;
        case 'RGB_ZERO':
          material.opacity = 1 - ( color[ 0 ] * transparency['float'] );
          break;
        case 'A_ZERO':
          material.opacity = 1 - ( color[ 3 ] * transparency['float'] );
          break;
        case 'RGB_ONE':
          material.opacity = color[ 0 ] * transparency['float'];
          break;
        default:
          console.warning( 'ColladaLoader: Invalid opaque type "%s" of transparent tag. ${transparent['opaque']}');
      }

      if ( material.opacity < 1 ) material.transparent = true;
    }
  }

  if ( technique['extra']?['technique'] != null ) {
    final techniques = technique['extra']['technique'];

    for ( final k in techniques ) {
      final v = techniques[ k ];

      switch ( k ) {
        case 'double_sided':
          material.side = ( v == 1 ? DoubleSide : FrontSide );
          break;
        case 'bump':
          material.normalMap = await getTexture( v.texture );
          material.normalScale = Vector2( 1, 1 );
          break;
      }
    }
  }

  return material;
}