generate method

dynamic generate([
  1. dynamic builder,
  2. dynamic output
])
override

Implementation

generate([builder, output]) {
  var method = this.method;

  var type = this.getNodeType(builder);
  var inputType = this.getInputType(builder);

  var a = this.aNode;
  var b = this.bNode;
  var c = this.cNode;

  var isWebGL = builder.renderer.isWebGLRenderer == true;

  if (isWebGL &&
      (method == MathNode.DFDX || method == MathNode.DFDY) &&
      output == 'vec3') {
    // Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988

    return new JoinNode([
      new MathNode(method, new SplitNode(a, 'x')),
      new MathNode(method, new SplitNode(a, 'y')),
      new MathNode(method, new SplitNode(a, 'z'))
    ]).build(builder);
  } else if (method == MathNode.TRANSFORM_DIRECTION) {
    // dir can be either a direction vector or a normal vector
    // upper-left 3x3 of matrix is assumed to be orthogonal

    var tA = a;
    var tB = b;

    if (builder.isMatrix(tA.getNodeType(builder))) {
      tB = new ExpressionNode(
          "${builder.getType('vec4')}( ${tB.build(builder, 'vec3')}, 0.0 )",
          'vec4');
    } else {
      tA = new ExpressionNode(
          "${builder.getType('vec4')}( ${tA.build(builder, 'vec3')}, 0.0 )",
          'vec4');
    }

    var mulNode = new SplitNode(new OperatorNode('*', tA, tB), 'xyz');

    return new MathNode(MathNode.NORMALIZE, mulNode).build(builder);
  } else if (method == MathNode.SATURATE) {
    return "clamp( ${a.build(builder, inputType)}, 0.0, 1.0 )";
  } else if (method == MathNode.NEGATE) {
    return '( -' + a.build(builder, inputType) + ' )';
  } else if (method == MathNode.INVERT) {
    return '( 1.0 - ' + a.build(builder, inputType) + ' )';
  } else {
    var params = [];

    if (method == MathNode.CROSS) {
      params.addAll([a.build(builder, type), b.build(builder, type)]);
    } else if (method == MathNode.STEP) {
      params.addAll([
        a.build(
            builder,
            builder.getTypeLength(a.getNodeType(builder)) == 1
                ? 'float'
                : inputType),
        b.build(builder, inputType)
      ]);
    } else if ((isWebGL &&
            (method == MathNode.MIN || method == MathNode.MAX)) ||
        method == MathNode.MOD) {
      params.addAll([
        a.build(builder, inputType),
        b.build(
            builder,
            builder.getTypeLength(b.getNodeType(builder)) == 1
                ? 'float'
                : inputType)
      ]);
    } else if (method == MathNode.REFRACT) {
      params.addAll([
        a.build(builder, inputType),
        b.build(builder, inputType),
        c.build(builder, 'float')
      ]);
    } else if (method == MathNode.MIX) {
      params.addAll([
        a.build(builder, inputType),
        b.build(builder, inputType),
        c.build(
            builder,
            builder.getTypeLength(c.getNodeType(builder)) == 1
                ? 'float'
                : inputType)
      ]);
    } else {
      params.addAll([a.build(builder, inputType)]);

      if (c != null) {
        params.addAll(
            [b.build(builder, inputType), c.build(builder, inputType)]);
      } else if (b != null) {
        params.add(b.build(builder, inputType));
      }
    }

    return "${builder.getMethod(method)}( ${params.join(', ')} )";
  }
}