/*
 * @(#)test3d.java        1.0 2002/08/01
 *
 * Copyright 2001-2006 by Danger Research, Inc.
 * 3101 Park Blvd, Palo Alto, CA  94301
 * All rights reserved.
 */
package com.danger.test3d;

import danger.app.*;
import danger.audio.*;
import danger.system.*;
import danger.ui.*;
import danger.util.*;
import java.util.Random;
import java.util.Vector;


/**
 * DOCUMENT ME!
 *
 * @author $author$
 * @version $Revision$
 */
public class test3d extends Application
{
	//~ Instance fields --------------------------------------------------------

	test3dWindow mWindow;
	test3dEngine mEngine;
	Timer		 mTimer;
	static test3d sInstance;
	//~ Constructors -----------------------------------------------------------

	//*	--------------------	test3d
	public test3d()
	{
		super();
		sInstance = this;
		mEngine     = new test3dEngine();
		mWindow     = new test3dWindow(mEngine);
		mWindow.setTitle("3D Test");
		mEngine.setWindow(mWindow);
		mEngine.loadObjects();
	}

	//~ Methods ----------------------------------------------------------------

	/**
	 * DOCUMENT ME!
	 */
	public void resume()
	{
		mWindow.show();

		if (mTimer == null)
		{
			mTimer = new Timer(50, true, mWindow);
		}

		mTimer.start();
	}

	/**
	 * DOCUMENT ME!
	 */
	public void suspend()
	{
		mTimer.stop();
		mWindow.hide();
	}
}


class test3dWindow extends ScreenWindow
{
	//~ Instance fields --------------------------------------------------------

	Random		 mRandom;
	Vector		 mObjects;
	test3dEngine mEngine;

	//~ Constructors -----------------------------------------------------------

	/**
	 * Creates a new test3dWindow object.
	 *
	 * @param eng DOCUMENT ME!
	 */
	public test3dWindow(test3dEngine eng)
	{
		super();

		mRandom		 = new Random();
		mObjects     = new Vector();
		mEngine		 = eng;
	}

	private test3dWindow()
	{
	}

	//~ Methods ----------------------------------------------------------------

	/**
	 * DOCUMENT ME!
	 *
	 * @param inPen DOCUMENT ME!
	 */
	public void paint(Pen inPen)
	{
		inPen.setColor(Color.BLACK);
		inPen.fillRect(getBounds());

		synchronized (mObjects)
		{
			int size = mObjects.size();

			for (int i = 0; i < size; i++)
			{
				object3d obj = (object3d) mObjects.elementAt(i);
				obj.draw(inPen);
			}
		}
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param e DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public boolean receiveEvent(Event e)
	{
		boolean handled = false;
		int     w = e.what;

		switch (e.type)
		{
			case Event.EVENT_TIMER:
				mEngine.tick();

				return true;

			case Event.EVENT_WIDGET_DOWN:

				if (w == Event.DEVICE_WHEEL_BUTTON)
				{
					mEngine.buttonDown();

					return true;
				}
				else if (w == Event.DEVICE_WHEEL)
				{
					mEngine.scrollDown();

					return true;
				}

				break;

			case Event.EVENT_WIDGET_UP:

				if (w == Event.DEVICE_WHEEL)
				{
					mEngine.scrollUp();

					return true;
				}

				if ((w == Event.DEVICE_BUTTON_BACK) ||
					(w == Event.DEVICE_BUTTON_CANCEL))
				{
					getApplication().returnToLauncher();

					return true;
				}

				break;
		}

		return super.receiveEvent(e);
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param obj DOCUMENT ME!
	 */
	public void addObject(object3d obj)
	{
		synchronized (mObjects)
		{
			mObjects.addElement(obj);
		}
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param obj DOCUMENT ME!
	 */
	public void removeObject(object3d obj)
	{
		synchronized (mObjects)
		{
			mObjects.removeElement(obj);
		}
	}
}


class test3dEngine
{
	//~ Instance fields --------------------------------------------------------

	int			 angleX;
	int			 angleY;
	int			 angleZ;
	int			 mCurrentAngle;
	test3dWindow mWin;
	Bitmap mBitmap;

	//~ Constructors -----------------------------------------------------------

	/**
	 * Creates a new test3dEngine object.
	 */
	public test3dEngine()
	{
		mBitmap = test3d.sInstance.getBitmap(Resources.ID_TEXTURE);
		System.out.println("bitmap " + mBitmap);
	}

	//~ Methods ----------------------------------------------------------------

	/**
	 * DOCUMENT ME!
	 */
	public void loadObjects()
	{
		object3d obj;

		obj = new object3d(14, 0, 25);
		obj.setVertex(0,
			new point3d(Fixed.fromInt(-1), Fixed.fromInt(-1), Fixed.fromInt(-1)));
		obj.setVertex(1,
			new point3d(Fixed.fromInt(-1), Fixed.fromInt(1), Fixed.fromInt(-1)));
		obj.setVertex(2,
			new point3d(Fixed.fromInt(1), Fixed.fromInt(1), Fixed.fromInt(-1)));
		obj.setVertex(3,
			new point3d(Fixed.fromInt(1), Fixed.fromInt(-1), Fixed.fromInt(-1)));
		obj.setVertex(4,
			new point3d(Fixed.fromInt(-1), Fixed.fromInt(-1), Fixed.fromInt(1)));
		obj.setVertex(5,
			new point3d(Fixed.fromInt(-1), Fixed.fromInt(1), Fixed.fromInt(1)));
		obj.setVertex(6,
			new point3d(Fixed.fromInt(1), Fixed.fromInt(1), Fixed.fromInt(1)));
		obj.setVertex(7,
			new point3d(Fixed.fromInt(1), Fixed.fromInt(-1), Fixed.fromInt(1)));

		obj.setVertex(8,
			new point3d(Fixed.fromInt(0), Fixed.fromInt(0),
				-Fixed.fromReal(1, 1, 2)));
		obj.setVertex(9,
			new point3d(Fixed.fromInt(0), Fixed.fromInt(0),
				Fixed.fromReal(1, 1, 2)));
		obj.setVertex(10,
			new point3d(Fixed.fromInt(0), -Fixed.fromReal(1, 1, 2),
				Fixed.fromInt(0)));
		obj.setVertex(11,
			new point3d(Fixed.fromInt(0), Fixed.fromReal(1, 1, 2),
				Fixed.fromInt(0)));
		obj.setVertex(12,
			new point3d(-Fixed.fromReal(1, 1, 2), Fixed.fromInt(0),
				Fixed.fromInt(0)));
		obj.setVertex(13,
			new point3d(Fixed.fromReal(1, 1, 2), Fixed.fromInt(0),
				Fixed.fromInt(0)));

		obj.setSurface(0, 8, 1, 0);
		obj.setSurface(1, 8, 2, 1);
		obj.setSurface(2, 8, 3, 2);
		obj.setSurface(3, 8, 0, 3);

		obj.setSurface(4, 13, 6, 2);
		obj.setSurface(5, 13, 2, 3);
		obj.setSurface(6, 13, 3, 7);
		obj.setSurface(7, 13, 7, 6);

		obj.setSurface(8, 11, 5, 1);
		obj.setSurface(9, 11, 1, 2);
		obj.setSurface(10, 11, 2, 6);
		obj.setSurface(11, 11, 6, 5);

		obj.setSurface(12, 9, 5, 6);
		obj.setSurface(13, 9, 6, 7);
		obj.setSurface(14, 9, 7, 4);
		obj.setSurface(15, 9, 4, 5);

		obj.setSurface(16, 12, 1, 5);
		obj.setSurface(17, 12, 5, 4);
		obj.setSurface(18, 12, 4, 0);
		obj.setSurface(19, 12, 0, 1);
		obj.setSurface(20, 12, 1, 5);

		obj.setSurface(21, 10, 3, 0);
		obj.setSurface(22, 10, 7, 3);
		obj.setSurface(23, 10, 4, 7);
		obj.setSurface(24, 10, 0, 4);

		for (int count = 0; count < 25; count++)
		{
			obj.setSurfaceTexture(count, mBitmap);
		}
/*
*/

	/*
		obj = new object3d(4, 0, 1);

		obj.setVertex(0, new point3d(Fixed.fromInt(-1), Fixed.fromInt(-1), 0));
		obj.setVertex(1, new point3d(Fixed.fromInt(-1), Fixed.fromInt(1), 0));
		obj.setVertex(2, new point3d(Fixed.fromInt(1), Fixed.fromInt(1), 0));
		obj.setVertex(3, new point3d(Fixed.fromInt(1), Fixed.fromInt(-1), 0));

		obj.setSurface(0, 0, 1, 2);
	*/
		mWin.addObject(obj);
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param win DOCUMENT ME!
	 */
	public void setWindow(test3dWindow win)
	{
		mWin = win;
	}

	/**
	 * DOCUMENT ME!
	 */
	public void buttonDown()
	{
		mCurrentAngle++;

		if (mCurrentAngle >= 3)
		{
			mCurrentAngle = 0;
		}
	}

	/**
	 * DOCUMENT ME!
	 */
	public void scrollUp()
	{
		switch (mCurrentAngle)
		{
			case 0:
				angleX++;

				break;

			case 1:
				angleY++;

				break;

			case 2:
				angleZ++;

				break;
		}

		tick();
	}

	/**
	 * DOCUMENT ME!
	 */
	public void scrollDown()
	{
		switch (mCurrentAngle)
		{
			case 0:

				if (angleX == 0)
				{
					angleX = 360;
				}

				angleX--;

				break;

			case 1:

				if (angleY == 0)
				{
					angleY = 360;
				}

				angleY--;

				break;

			case 2:

				if (angleZ == 0)
				{
					angleZ = 360;
				}

				angleZ--;

				break;
		}

		tick();
	}

	/**
	 * DOCUMENT ME!
	 */
	public void tick()
	{
		// cycle through the objects in the view
		synchronized (mWin.mObjects)
		{
			int size = mWin.mObjects.size();

			for (int i = 0; i < size; i++)
			{
				object3d obj = (object3d) mWin.mObjects.elementAt(i);

				obj.startTransformation();

				//				obj.incScale(Fixed.fromReal(0, 1, 2));
				obj.scale(Fixed.fromInt(40));
				obj.rotateZ(angleX++);
				obj.rotateY(angleY++);
				obj.rotateX(angleZ++);
				obj.translate(Fixed.fromInt(mWin.getWidth() / 2),
					Fixed.fromInt(mWin.getHeight() / 2), 0);
				obj.endTransformation();
			}
		}

		mWin.invalidate();
	}
}
