package org.freehep.j3d.plot;
import javax.media.j3d.Node;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* @author Joy Kyriakopulos (joyk@fnal.gov)
* @version $Id: SurfaceBuilder.java 8584 2006-08-10 23:06:37Z duns $
*/
public class SurfaceBuilder extends AbstractPlotBuilder
{
private static final Color3b grey = new Color3b((byte) 50, (byte) 50, (byte) 50);
private static final Rainbow rainbow = new Rainbow();
private TimeStamp timeStamp = TimeStamp.sharedInstance();
private Shape3D shape;
/**
* @param data Bin Contents
*/
public Node buildContent(NormalizedBinned2DData data)
{
shape = createShape();
shape.setCapability(shape.ALLOW_GEOMETRY_WRITE);
shape.setGeometry(buildGeometry(data));
return shape;
}
public void updatePlot(NormalizedBinned2DData data)
{
shape.setGeometry(buildGeometry(data));
}
private Geometry buildGeometry(NormalizedBinned2DData data)
{
timeStamp.print("Starting SurfaceBuilder.buildContent()");
int nXbins = data.xBins();
int nYbins = data.yBins();
float xBinWidth = 1.f/nXbins;
float yBinWidth = 1.f/nYbins;
float x, y, z;
int i, j, k, l;
Point3d bcoord[] = new Point3d[((int)nXbins-1)*((int)nYbins-1)*4 ];
Color3b bcolor[] = new Color3b[((int)nXbins-1)*((int)nYbins-1)*4 ];
for(i=0;i<((int)nXbins-1)*((int)nYbins-1)*4;i++) {
bcoord[i] = new Point3d();
bcolor[i] = new Color3b();
}
// System.out.println(" ok");
// Fill bcoord array with points that compose the surface
int bcur=0;
for (k=0, x=-.5f; k<(int)nXbins-1; k++, x+=xBinWidth)
for(l=0, y = -.5f; l<(int)nYbins-1; l++, y+=yBinWidth) {
// Point x,y
bcoord[bcur].x = x+xBinWidth/2.f;
bcoord[bcur].y = y+yBinWidth/2.f;
bcoord[bcur].z = data.zAt(k,l);
bcolor[bcur] = data.colorAt(k,l);
bcur++;
// Next point in y direction
bcoord[bcur].x = x+xBinWidth/2.f;
bcoord[bcur].y = y+1.5f*xBinWidth;
bcoord[bcur].z = data.zAt(k,l+1);
bcolor[bcur] = data.colorAt(k,l+1);
bcur++;
// Next point diagonally
bcoord[bcur].x = x+1.5f*xBinWidth;
bcoord[bcur].y = y+1.5f*yBinWidth;
bcoord[bcur].z = data.zAt(k+1,l+1);
bcolor[bcur] = data.colorAt(k+1,l+1);
bcur++;
// Next point in x direction
bcoord[bcur].x = x+1.5f*xBinWidth;
bcoord[bcur].y = y+yBinWidth/2.f;
bcoord[bcur].z = data.zAt(k+1,l);
bcolor[bcur] = data.colorAt(k+1,l);
bcur++;
}
// System.out.print("debug3:");
// We make a GeometryInfo object so that normals can be generated
// for us and geometry stripified for us. J3D documentation
// says it's best to do these two steps in this order.
GeometryInfo geom = new GeometryInfo(GeometryInfo.QUAD_ARRAY);
//geom.setNormals(normals);
geom.setCoordinates(bcoord);
geom.setColors(bcolor);
NormalGenerator ng = new NormalGenerator();
ng.generateNormals(geom);
// Make normals conform to our "handedness" of z direction
// i.e. change their sign
Vector3f normals[] = geom.getNormals();
for (i=0; i< normals.length; ++i) {
normals[i].x = -normals[i].x;
normals[i].y = -normals[i].y;
normals[i].z = -normals[i].z;
}
geom.setNormals(normals);
Stripifier st = new Stripifier();
st.stripify(geom);
geom.recomputeIndices();
System.out.print("Surface geometry done.\n");
timeStamp.print("finished, now finalizing, point count = "+bcur);
return geom.getGeometryArray();
}
Shape3D createShape()
{
Shape3D surface = new Shape3D();
timeStamp.print("geometry set");
surface.setAppearance(createMaterialAppearance());
return surface;
}
private Appearance createMaterialAppearance()
{
Appearance materialAppear = new Appearance();
PolygonAttributes polyAttrib = new PolygonAttributes();
polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
materialAppear.setPolygonAttributes(polyAttrib);
Material material = new Material();
// set diffuse color to red (this color will only be used
// if lighting disabled - per-vertex color overrides)
material.setDiffuseColor(new Color3f(1.0f, 0.0f, 0.0f));
materialAppear.setMaterial(material);
return materialAppear;
}
}