/*
A simple demonstration of VisAD's volume rendering capabilities. 
*/

import java.rmi.RemoteException;
import javax.swing.*;
import visad.*;
import visad.java3d.DisplayImplJ3D;

public class visad_3D_render {

  public static void main(String[] args)
    throws VisADException, RemoteException
  {
    // create types
    RealType x = RealType.getRealType("x");
    RealType y = RealType.getRealType("y");
    RealType z = RealType.getRealType("z");
    RealTupleType xyz = new RealTupleType(x, y, z);
    RealType value = RealType.getRealType("value");

    // generate some regular samples
    int size = 32;
    int count = size * size * size;
    Linear3DSet set = new Linear3DSet(xyz,
      0, 1000, size, 0, 1000, size, 0, 1000, size);
    float[][] samples = set.getSamples(false);

    // build field
    FunctionType ftype = new FunctionType(xyz, value);
    FlatField field = new FlatField(ftype, set);
    float[][] values = new float[1][count];
    for (int i=0; i<count; i++) {
      values[0][i] = 1500 - (Math.abs(samples[0][i] - 500) +
        Math.abs(samples[1][i] - 500) + Math.abs(samples[2][i] - 500));
    }
    field.setSamples(values, false);

    // create display
    DisplayImpl display = new DisplayImplJ3D("display");
    display.getGraphicsModeControl().setPointSize(5.0f);
    display.addMap(new ScalarMap(x, Display.XAxis));
    display.addMap(new ScalarMap(y, Display.YAxis));
    display.addMap(new ScalarMap(z, Display.ZAxis));
    ScalarMap color = new ScalarMap(value, Display.RGBA);
    display.addMap(color);

    // assign alpha channel
    BaseColorControl cc = (BaseColorControl) color.getControl();
    cc.setTable(tweakAlpha(cc.getTable()));

    // add data to display
    DataReferenceImpl ref = new DataReferenceImpl("ref");
    ref.setData(field);
    display.addReference(ref);

    // show display onscreen
    JFrame frame = new JFrame("Linear rendering test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(display.getComponent());
    frame.setBounds(200, 200, 600, 600);
    frame.show();
  }

  private static float[][] tweakAlpha(float[][] table) {
    int pow = 2;
    int len = table[3].length;
    for (int i=0; i<len; i++) {
      table[3][i] = (float) Math.pow((double) i / len, pow);
    }
    return table;
  }

}
