// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.library;

import static net.cellcomputing.himawari.library.CqStats.STATS_INC;
import static net.cellcomputing.himawari.library.EqIntIndex.GPR_poly;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.accessory.primitive.p_int;
import net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.library.types.CqVector3D;
import net.cellcomputing.himawari.library.types.CqVector4D;

/**
 * 
 * サーフェースから作られたポリゴンを格納するクラス。
 * Container surface to store the polygons making up a RiPointsPolygons surface.
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqSurfacePointsPolygons extends CqSurface {

	private int				m_NumPolys;
	private CqPolygonPoints	m_pPoints;		///< Pointer to the associated CqPolygonPoints class.
	private STLVector<p_int>	m_PointCounts	= new STLVector<p_int>(p_int.class);
	private STLVector<p_int>	m_PointIndices	= new STLVector<p_int>(p_int.class);
	
	
	public CqSurfacePointsPolygons( final CqPolygonPoints pPoints, int NumPolys, int nverts[], int verts[])
	{
		m_NumPolys	= NumPolys;
		m_pPoints	= pPoints;
		m_PointCounts.resize( NumPolys );
		int i,vindex=0;
		for( i = 0; i < NumPolys; i++ )
		{
			m_PointCounts.get(i).value = nverts[i];
			int polyvertex;
			for( polyvertex = 0; polyvertex < nverts[i]; polyvertex++ )
				m_PointIndices.add( new p_int( verts[vindex++] ) );
		}
		STATS_INC( GPR_poly );
	}


	/**
	 *  Get the gemoetric bound of this GPrim.
	 */
	public CqBound Bound()
	{
		CqBound B = new CqBound();
		if( m_pPoints!=null && m_pPoints.P()!=null )
		{
			int PointIndex;
			for( PointIndex = m_pPoints.P().Size()-1; PointIndex >= 0; PointIndex-- )
//				B.Encapsulate( (CqVector3D)m_pPoints.P().pValue()[PointIndex] );
				//nttdata 高速化
				//B.Encapsulate( new CqVector3D( (CqVector4D)m_pPoints.P().pValue()[PointIndex] ) );
				B.Encapsulate( new CqVector3D( (CqVector4D)m_pPoints.P().pValue_get( 0 , PointIndex ) ) );
		}
		return(AdjustBoundForTransformationMotion( B ));
	}

	/**
	 * Dice this GPrim.
	 * @return A pointer to a new micropolygrid..
	 */
	@Override
	public CqMicroPolyGridBase Dice()
	{
		return(null);
	}
	
	/** 
	 * Split this GPrim into a number of other GPrims.
	 * @param aSplits A reference to a CqBasicSurface array to fill in with the new GPrim pointers.
	 * @return Integer count of new GPrims created.
	 */
	@Override
	public int Split( STLVector<CqBasicSurface> aSplits )
	{
		int	CreatedPolys = 0;
		int	iP = 0, poly;
		for ( poly = 0; poly < m_NumPolys; poly++ )
		{
			// Create a surface polygon
			CqSurfacePointsPolygon pSurface = new CqSurfacePointsPolygon( m_pPoints, poly, iP );
			boolean fValid = true;
			
			pSurface.aIndices().resize( m_PointCounts.get( poly ).value );
			int i;
			for ( i = 0; i < (long)m_PointCounts.get( poly ).value; i++ )          	// Fill in the points
			{
				if ( (long) m_PointIndices.get( iP ).value >= m_pPoints.P().Size() )
				{
					fValid = false;
					//CqAttributeError( 1, Severity_Normal, "Invalid PointsPolygon index", pSurface.pAttributes() );
					String objname = "unnamed";
					final String[] pattrName = pSurface.pAttributes().GetStringAttribute( "identifier", "name" );
					if ( pattrName != null ) objname = pattrName[ 0 ];
					logger.warning( "Invalid PointsPolygon index in object \"" + objname + "\"" + "\n" );
					
					break;
				}
				pSurface.aIndices().get( i ).value = m_PointIndices.get( iP ).value;
				iP++;
			}
			if ( fValid )
			{
				aSplits.add( pSurface );
				CreatedPolys++;
			}
		}
		return( CreatedPolys );	
	}

	/** 
	 * Determine whether this GPrim is diceable at its current size.
	 */
	@Override
	public boolean Diceable()
	{
		return( false );
	}

	@Override
	final public void Transform( final CqMatrix matTx, final CqMatrix matITTx, final CqMatrix matRTx )
	{
		Transform( matTx, matITTx, matRTx, 0 );
	}
	@Override
	public void Transform( final CqMatrix matTx, final CqMatrix matITTx, final CqMatrix matRTx, int iTime )
	{
		assert( m_pPoints!=null );
		m_pPoints.Transform( matTx, matITTx, matRTx, iTime );
	}

	public boolean IsMotionBlurMatch( CqBasicSurface pSurf )
	{
		return( false );
	}

	public int cUniform()
	{
		return ( m_NumPolys );
	}
	public int cVarying()
	{
		assert( m_pPoints!=null );
		return ( m_pPoints.cVarying() );
	}
	public int cVertex()
	{
		assert( m_pPoints!=null );
		return ( m_pPoints.cVarying() );
	}
	public int cFaceVarying()
	{
		assert( m_pPoints!=null );
		return ( m_pPoints.cFaceVarying() );
	}
	
}
