Package ca.eandb.jmist.framework.material

Source Code of ca.eandb.jmist.framework.material.FactoredMaterial

/**
*
*/
package ca.eandb.jmist.framework.material;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import ca.eandb.jmist.framework.ScatteredRay;
import ca.eandb.jmist.framework.SurfacePoint;
import ca.eandb.jmist.framework.color.Color;
import ca.eandb.jmist.framework.color.ColorModel;
import ca.eandb.jmist.framework.color.WavelengthPacket;
import ca.eandb.jmist.math.Basis3;
import ca.eandb.jmist.math.MathUtil;
import ca.eandb.jmist.math.Matrix;
import ca.eandb.jmist.math.MatrixBuffer;
import ca.eandb.jmist.math.SphericalCoordinates;
import ca.eandb.jmist.math.Vector3;
import ca.eandb.util.UnimplementedException;

/**
* @author brad
*
*/
public final class FactoredMaterial extends OpaqueMaterial {

  /** Serialization version ID. */
  private static final long serialVersionUID = -7099697194692635348L;

  private final Matrix F[];

  private final Matrix G[];

  private final Matrix u[][];

  private final Matrix v[][];

  private final Matrix Fc[];

  private final Matrix Gc[];

  private final ColorModel colorModel;

  public FactoredMaterial(Matrix F[], Matrix G[], Matrix u[][], Matrix v[][], Matrix Fc[], Matrix Gc[], ColorModel colorModel) {
    this.F = F;
    this.G = G;
    this.u = u;
    this.v = v;
    this.Fc = Fc;
    this.Gc = Gc;
    this.colorModel = colorModel;

//    for (int i = 0; i < F.length; i++) {
//      printMatrix(String.format("F[%d]", i), F[i]);
//    }
//    for (int i = 0; i < G.length; i++) {
//      printMatrix(String.format("G[%d]", i), G[i]);
//    }
//    for (int i = 0; i < Fc.length; i++) {
//      printMatrix(String.format("Fc[%d]", i), Fc[i]);
//    }
//    for (int i = 0; i < Gc.length; i++) {
//      printMatrix(String.format("Gc[%d]", i), Gc[i]);
//    }
//    System.exit(0);
  }
  public static void printMatrix(Matrix A) {
    printMatrix(A, 1.0);
  }

  public static void printMatrix(String name, Matrix A) {
    System.out.print(String.format("%s: ", name));
    printMatrix(A, 1.0);
  }

  public static void printMatrix(Matrix A, double c) {
    System.out.println("-----");
    for (int i = 0; i < A.rows(); i++) {
      for (int j = 0; j < A.columns(); j++) {
        System.out.print(String.format(" %6.3f", A.at(i, j) * c));
      }
      System.out.println();
    }
  }

  public static FactoredMaterial fromFacRep(BufferedReader r, ColorModel cm) throws IOException {
    String line;
    String param = null;
    int outerTerms = -1;
    int innerTerms = -1;
    int thetaOutCount = -1;
    int phiOutCount = -1;
    int thetaPCount = -1;
    int zCount = -1;
    int phiPCount = -1;

    double[] data = null;
    int index = 0;

    while ((line = r.readLine()) != null) {

      // skip empty lines
      line = line.trim();
      if (line.isEmpty()) {
        continue;
      }

      String entry[] = line.split(":", 2);

      if (entry.length == 2) { // header

        String key = entry[0].trim().toLowerCase();
        String value = entry[1].trim();

        if (key.equals("param")) {
          param = value.toLowerCase();
        } else if (key.startsWith("outer terms")) {
          outerTerms = Integer.valueOf(value);
        } else if (key.startsWith("inner terms")) {
          innerTerms = Integer.valueOf(value);
        } else if (key.equals("theta_out count")) {
          thetaOutCount = Integer.valueOf(value);
        } else if (key.equals("phi_out count")) {
          phiOutCount = Integer.valueOf(value);
        } else if (key.equals("theta_p count") || key.equals("theta_2 count")) {
          thetaPCount = Integer.valueOf(value);
        } else if (key.equals("z count")) {
          zCount = Integer.valueOf(value);
        } else if (key.equals("phi_p count") || key.equals("phi_2 count")) {
          phiPCount = Integer.valueOf(value);
        }

      } else if (entry.length == 1) { // data

        if (data == null) { // first line of data

          // Check that all header entries were present
          if (outerTerms <= 0 || innerTerms <= 0 || thetaOutCount <= 0 ||
              phiOutCount <= 0 || thetaPCount <= 0 || zCount <= 0 ||
              phiPCount <= 0 || param == null) {

            throw new IllegalArgumentException("Missing parameters (is file of correct format?)");

          }

          int count =
              outerTerms * (
                  thetaOutCount * phiOutCount +
                  thetaPCount * phiPCount +
                  innerTerms * (thetaPCount + phiPCount)) +
              0 * 3 * (thetaOutCount * phiOutCount + thetaPCount * phiPCount);

          System.out.println(String.format("outer terms: %d", outerTerms));
          System.out.println(String.format("inner terms: %d", innerTerms));
          System.out.println(String.format("theta_p count: %d", thetaPCount));
          System.out.println(String.format("phi_p count: %d", phiPCount));
          System.out.println(String.format("theta_out count: %d", thetaOutCount));
          System.out.println(String.format("phi_out count: %d", phiOutCount));

          System.out.println(String.format("Count = %d", count));
          data = new double[count];

        }

        String values[] = line.split("\\s+");
        for (String value : values) {
          if (index < data.length) {
            data[index] = Double.valueOf(value);
          }
          index++;
        }

      }

    }

    System.out.println(String.format("Expected data: %d", data.length));
    System.out.println(String.format("Actual data  : %d", index));

//    if (index > data.length) {
//      throw new IllegalArgumentException("Too much data");
//    }

    if (index < data.length) {
      throw new IllegalArgumentException("Not enough data");
    }

    Matrix F[] = new Matrix[outerTerms];
    Matrix G[] = new Matrix[outerTerms];
    Matrix u[][] = new Matrix[outerTerms][];
    Matrix v[][] = new Matrix[outerTerms][];

    Matrix Fc[] = new Matrix[3];
    Matrix Gc[] = new Matrix[3];

    index = 0;
    for (int i = 0; i < outerTerms; i++) {
      F[i] = new Matrix(new MatrixBuffer(
          data, thetaOutCount, phiOutCount, index, phiOutCount, 1));
      index += thetaOutCount * phiOutCount;

      G[i] = new Matrix(new MatrixBuffer(
          data, thetaPCount, phiPCount, index, phiPCount, 1));
      index += thetaPCount * phiPCount;

      u[i] = new Matrix[innerTerms];
      v[i] = new Matrix[innerTerms];

      for (int j = 0; j < innerTerms; j++) {
        u[i][j] = new Matrix(new MatrixBuffer(
            data, thetaPCount, 1, index, 1, 1));
        index += thetaPCount;

        v[i][j] = new Matrix(new MatrixBuffer(
            data, phiPCount, 1, index, 1, 1));
        index += phiPCount;
      }
    }

    int FcOffset = index;
    int GcOffset = index + thetaOutCount * phiOutCount * 3;

    for (int i = 0; i < 3; i++) {
      Fc[i] = new Matrix(new MatrixBuffer(
          data, thetaOutCount, phiOutCount, FcOffset + i, 3 * phiOutCount, 3));
      Gc[i] = new Matrix(new MatrixBuffer(
          data, thetaPCount, phiPCount, GcOffset + i, 3 * phiPCount, 3));
    }

    return new FactoredMaterial(F, G, u, v, Fc, Gc, cm);

  }

  public static FactoredMaterial fromFacRep(Reader r, ColorModel cm) throws IOException {
    if (r instanceof BufferedReader) {
      return fromFacRep((BufferedReader) r, cm);
    } else {
      return fromFacRep(new BufferedReader(r), cm);
    }
  }

  public static FactoredMaterial fromFacRep(InputStream is, ColorModel cm) throws IOException {
    return fromFacRep(new InputStreamReader(is), cm);
  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.material.AbstractMaterial#bsdf(ca.eandb.jmist.framework.SurfacePoint, ca.eandb.jmist.math.Vector3, ca.eandb.jmist.math.Vector3, ca.eandb.jmist.framework.color.WavelengthPacket)
   */
  @Override
  public Color bsdf(SurfacePoint x, Vector3 in, Vector3 out,
      WavelengthPacket lambda) {

    Vector3 p = out.unit().minus(in.unit()).unit();
    Basis3 basis = x.getShadingBasis();
    SphericalCoordinates omegaO = SphericalCoordinates.fromCartesian(out, basis).canonical();
    SphericalCoordinates omegaP = SphericalCoordinates.fromCartesian(p, basis).canonical();

    double NdotI = -basis.w().dot(in);
    double NdotO = basis.w().dot(out);
    double spf = 0.0;

    if (NdotI * NdotO < 0.0) {
      return lambda.getColorModel().getBlack(lambda);
    }

    double phiO = omegaO.azimuthal() < 0.0 ? omegaO.azimuthal() + 2.0 * Math.PI : omegaO.azimuthal();
    double phiP = omegaP.azimuthal() < 0.0 ? omegaP.azimuthal() + 2.0 * Math.PI : omegaP.azimuthal();
    phiP -= phiO;
    if (phiP < 0.0) { phiP += 2.0 * Math.PI; }

    int J = F.length;
    for (int j = 0; j < J; j++) {
      double Fj = MathUtil.bilinearInterpolate(
          0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, F[j],
          omegaO.polar(), phiO, false, true);

//      double t = (double) (F[j].rows() - 1) * omegaO.polar() / (0.5 * Math.PI);
//      if (Math.abs(t - Math.round(t)) < 0.05) {
//        Fj = 0;
//      }

//      double Gj = 0.0;
//
//      int K = u[j].length;
//      for (int k = 0; k < K; k++) {
//        double ujk = MathUtil.interpolate(0, 0.5 * Math.PI, u[j][k].elements(), omegaP.polar());
//        double vjk = MathUtil.interpolate(0, 2.0 * Math.PI, v[j][k].elements(), phiP);
//
//        Gj += ujk * vjk;
//      }
      double Gj = MathUtil.bilinearInterpolate(
          0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, G[j],
          omegaP.polar(), phiP, false, true);

      spf += Fj * Gj;
    }

    double intensity = spf / NdotI;

    double Fr = MathUtil.bilinearInterpolate(
        0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, Fc[0],
        omegaO.polar(), phiO);
    double Fg = MathUtil.bilinearInterpolate(
        0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, Fc[1],
        omegaO.polar(), phiO);
    double Fb = MathUtil.bilinearInterpolate(
        0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, Fc[2],
        omegaO.polar(), phiO);
    double Gr = MathUtil.bilinearInterpolate(
        0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, Gc[0],
        omegaP.polar(), phiP);
    double Gg = MathUtil.bilinearInterpolate(
        0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, Gc[1],
        omegaP.polar(), phiP);
    double Gb = MathUtil.bilinearInterpolate(
        0, 0.5 * Math.PI, 0.0, 2.0 * Math.PI, Gc[2],
        omegaP.polar(), phiP);

    double r = Fr * Gr * intensity;
    double g = Fg * Gg * intensity;
    double b = Fb * Gb * intensity;
//    double r = intensity;
//    double g = intensity;
//    double b = intensity;
//
//    intensity = Math.log(intensity + 1);

//    double dist = Math.abs(intensity - (1.0 / Math.PI));
//    return colorModel.getGray(Math.max(1.0 - dist,  0.0), lambda);
//    if (dist < 0.05) {
//      return colorModel.fromRGB(1.0, 0.0, 0.0).sample(lambda);
//    } else if (dist < 0.1) {
//      return colorModel.fromRGB(0.0, 1.0, 0.0).sample(lambda);
//    }
//
//
    return colorModel.fromRGB(r, g, b).sample(lambda);

  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.material.AbstractMaterial#scatter(ca.eandb.jmist.framework.SurfacePoint, ca.eandb.jmist.math.Vector3, boolean, ca.eandb.jmist.framework.color.WavelengthPacket, double, double, double)
   */
  @Override
  public ScatteredRay scatter(SurfacePoint x, Vector3 v, boolean adjoint,
      WavelengthPacket lambda, double ru, double rv, double rj) {
    throw new UnimplementedException();
  }

  /* (non-Javadoc)
   * @see ca.eandb.jmist.framework.material.AbstractMaterial#getScatteringPDF(ca.eandb.jmist.framework.SurfacePoint, ca.eandb.jmist.math.Vector3, ca.eandb.jmist.math.Vector3, boolean, ca.eandb.jmist.framework.color.WavelengthPacket)
   */
  @Override
  public double getScatteringPDF(SurfacePoint x, Vector3 in, Vector3 out,
      boolean adjoint, WavelengthPacket lambda) {
    throw new UnimplementedException();
  }

}
TOP

Related Classes of ca.eandb.jmist.framework.material.FactoredMaterial

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.