package framework.model3D;

import java.util.ArrayList;
import java.util.Stack;

import javax.media.j3d.Geometry;
import javax.media.j3d.IndexedGeometryArray;
import javax.media.j3d.IndexedTriangleArray;
import javax.media.j3d.IndexedTriangleStripArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;

import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.Stripifier;

public class GeometryCollector extends ObjectVisitor{
	private int totalVertexCount = 0;
	private int totalIndexCount = 0;
	private ArrayList<Geometry> geometryList = new ArrayList<Geometry>(); // 葉のとき、Geometryを保存
	IndexedGeometryArray geometry = null;
//	private Stack<Transform3D> transforms = new Stack<Transform3D>();
	
	int i=0;
	int j=0;
	
	//コンストラクタ
//	public GeometryCollector() {
//		Transform3D t = new Transform3D();
//		transforms.push(t);
//	}
	
	@Override
	public void preVisit(Object3D obj) {
		// TODO Auto-generated method stub
		if(obj.hasChildren()){
//			System.out.println("pre"+i);
//			i++;
		}else{
//			System.out.println("pre"+i+" Leaf");
//			i++;
			Geometry g = ((Shape3D)obj.getBody().getPrimitiveNode()).getGeometry();
			geometryList.add(g);
			totalVertexCount += ((IndexedGeometryArray)g).getVertexCount();
			totalIndexCount += ((IndexedGeometryArray)g).getIndexCount();
		}
		
		
	}
	
	@Override
	public void postVisit(Object3D obj) {
		// TODO Auto-generated method stub
		if(obj.hasChildren()){
//			System.out.println("post"+j);
			j++;
		}else{
//			System.out.println("post"+j+"   Leaf");
			j++;
		}
	}

	public Geometry getGeometry(){
		if (geometry == null) {
			// リスト中の複数の Geometry を1つにまとめる
			int coordinateOfs = 0;
			int indexOfs = 0;
			double coodinates[] = new double[totalVertexCount * 3];
			int indicies[] = new int[totalIndexCount];
			for (int n = 0; n < geometryList.size(); n++) {
				IndexedGeometryArray geometry = (IndexedGeometryArray)geometryList.get(n);
				double tmpCoordinates[] = new double[geometry.getVertexCount() * 3];
				geometry.getCoordinates(0, tmpCoordinates);
				System.arraycopy(tmpCoordinates, 0, coodinates, coordinateOfs * 3, geometry.getVertexCount() * 3);
				int tmpIndicies[] = new int[geometry.getIndexCount()];
				geometry.getCoordinateIndices(0, tmpIndicies);
				for (int m = 0; m < geometry.getIndexCount(); m++) {
					tmpIndicies[m] += coordinateOfs;
				}
				System.arraycopy(tmpIndicies, 0, indicies, indexOfs, geometry.getIndexCount());
				coordinateOfs += geometry.getVertexCount();
				indexOfs += geometry.getIndexCount();
			}
			geometry = new IndexedTriangleArray(totalVertexCount, IndexedTriangleArray.COORDINATES, totalIndexCount);
			geometry.setCoordinates(0, coodinates);
			geometry.setCoordinateIndices(0, indicies);
						
			// 重複している頂点を1つにまとめる
			GeometryUtility.compressGeometry(geometry);
			
//			// IndexedTriangleStripArray　に変換（重複している頂点を1つにまとめるため）
//			GeometryInfo gi = new GeometryInfo(geometry);
//			Stripifier sf = new Stripifier();
//			sf.stripify(gi);
//			geometry = gi.getIndexedGeometryArray();	// IndexedTriangleStripArray が返される
//			
//			// IndexedTriangleArray に変換（GeometryGraph が IndexedTriangleStripArray に未対応のため）
//			if (geometry instanceof IndexedTriangleStripArray) {
//				int numStrips = ((IndexedTriangleStripArray)geometry).getNumStrips();
//				int indexCounts[] = new int[numStrips];
//				((IndexedTriangleStripArray)geometry).getStripIndexCounts(indexCounts);
//				int dstIndicies[] = new int[(((IndexedTriangleStripArray)geometry).getIndexCount() - numStrips * 2) * 3];
//				int dstOfs = 0;
//				int srcOfs = 0;
//				for (int s = 0; s < numStrips; s++) {
//					for (int i = 2; i < indexCounts[s]; i += 2) {
//						dstIndicies[dstOfs] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i - 2);
//						dstIndicies[dstOfs + 1] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i - 1);
//						dstIndicies[dstOfs + 2] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i);
//						dstOfs += 3;
//						if (i + 1 < indexCounts[s]) {
//							dstIndicies[dstOfs] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i);
//							dstIndicies[dstOfs + 1] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i - 1);
//							dstIndicies[dstOfs + 2] = ((IndexedTriangleStripArray)geometry).getCoordinateIndex(srcOfs + i + 1);
//							dstOfs += 3;
//						}
//					}
//					srcOfs += indexCounts[s];
//				}
//				
//				int vertexCount = ((IndexedTriangleStripArray)geometry).getVertexCount();
//				coodinates = new double[vertexCount * 3];
//				((IndexedTriangleStripArray)geometry).getCoordinates(0, coodinates);
//				
//				geometry = new IndexedTriangleArray(vertexCount, IndexedTriangleArray.COORDINATES, dstIndicies.length);
//				geometry.setCoordinates(0, coodinates);
//				geometry.setCoordinateIndices(0, dstIndicies);				
//			}
		}
		return geometry;
	}
}
