package vgp.tutor.texture;

import java.awt.Image;
import java.util.Enumeration;

import jv.geom.PgElementSet;
import jv.geom.PgTexture;
import jv.object.PsDebug;
import jv.object.PsPanel;
import jv.objectGui.PsImage;
import jv.project.PvDisplayIf;
import jv.project.PjProject;
import jv.project.PvViewerIf;
import jv.vecmath.PdVector;

/**
 * Demo project for using texture on surfaces.
 * 
 * @see			jv.geom.PgPointSet
 * @see			jv.geom.PgElementSet
 * @see			jv.geom.PgTexture
 * @author		Konrad Polthier
 * @version		26.04.01, 1.20 revised (kp) Use applet parameters.<br>
 *					04.10.99, 1.10 revised (kp) Slight tuning.<br>
 *					02.01.99, 1.00 created (kp)
 */
public class PjTexturedSurface extends PjProject {
	protected	PgElementSet		m_geom;
	protected	PsImage				m_image;
	protected	String				m_defaultImageFile	= "vgp/tutor/texture/images/Water.jpg";
	protected	String				m_imageFile				= m_defaultImageFile;
	protected	String				m_surfaceName			= "torus";
	protected	int					m_numULines = 15, m_numVLines = 10;

	public PjTexturedSurface() {
		super("Textured Surface");
		m_geom = new PgElementSet(3);
		if (getClass() == PjTexturedSurface.class)
			init();
	}
	public void init() {
		// m_geom.computePlane(m_numULines, m_numVLines, 0., 0., 5., 5.);
		m_geom.computeTorus(m_numULines, m_numVLines, 2., 1.);
		// m_geom.computeSphere(m_numULines, m_numVLines, 5.);
		m_geom.makeVertexNormals();
		m_geom.makeElementNormals();
		m_geom.showBackface(false);
		m_geom.showEdges(false);
		super.init();
	}
	public void start() {
		PvViewerIf viewer = getViewer();
		if (viewer != null) {
			String surfaceName = viewer.getParameter("vgp.tutor.texture.PjTexturedSurface#surface");
			if (surfaceName != null) {
				m_surfaceName = surfaceName;
			}
			String imageFile = viewer.getParameter("vgp.tutor.texture.PjTexturedSurface#image");
			if (imageFile != null) {
				m_imageFile = imageFile;
			}
		}
		if (m_surfaceName.equalsIgnoreCase("torus"))
			m_geom.computeTorus(m_numULines, m_numVLines, 2., 1.);
		else if (m_surfaceName.equalsIgnoreCase("sphere"))
			m_geom.computeSphere(m_numULines, m_numVLines, 5.);
		else
			m_geom.computePlane(m_numULines, m_numVLines, 0., 0., 5., 5.);
		m_geom.makeVertexNormals();
		m_geom.makeElementNormals();
		m_geom.showBackface(false);
		m_geom.showEdges(false);
		
		m_geom.setName("Textured Surface");

		m_geom.setDimOfTextures(2);
		m_geom.assureVertexTextures();
		m_geom.showVertexTexture(true);

		// Generate texture coordinates in [0,1]*[0,1]
		PdVector [] texCoord = m_geom.getVertexTextures();
		double uFac = 1./(-1.+m_numULines);
		double vFac = 1./(-1.+m_numVLines);
		int ind = 0;
		for (int i=0; i<m_numULines; i++) {
			double u = uFac*i;
			for (int j=0; j<m_numVLines; j++) {
				double v = vFac*j;
				texCoord[ind].m_data[0] = u;
				texCoord[ind].m_data[1] = v;
				ind++;
			}
		}
		PsImage texImage = new PsImage(m_imageFile);
		if (texImage != null) {
			texImage.loadImage();
			Image img = texImage.getImage();
			if (img != null) {
				PgTexture texture = new PgTexture();
				texture.setImage(img);
				m_geom.setTexture(texture);
				m_geom.update(m_geom);
			}
		}

		addGeometry(m_geom);
		selectGeometry(m_geom);
		getDisplay().showDepthcue(true);
		// Setting the geometry invokes a repaint, therefore do it at the end
		super.start();
	}
	/**
	 * Update the class whenever a child has changed.
	 * Method is usually invoked from the children.
	 */
	public boolean update(Object event) {
		if (PsDebug.NOTIFY) PsDebug.notify("called");
		if (event == getInspector(PsPanel.INFO)) {
			Enumeration e = m_geom.getDisplays();
			while (e.hasMoreElements()) {
				PvDisplayIf disp = (PvDisplayIf)e.nextElement();
				if (m_image != null)
					disp.setBackgroundImage(m_image.getImage());
				else
					disp.setBackgroundImage((Image)null);
				disp.update(null);
			}
			return true;
		}
		return super.update(event);
	}    
}

