// 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.EqVariableType.*;
import static net.cellcomputing.himawari.library.EqVariableClass.*;
import static net.cellcomputing.himawari.library.EqEnvVars.*;
import static net.cellcomputing.himawari.library.CqCurve.EssSplitDecision.*;
import static net.cellcomputing.himawari.library.CqStats.STATS_INC;
import static net.cellcomputing.himawari.library.CqStats.STATS_SETI;
import static net.cellcomputing.himawari.library.CqStats.STATS_GETI;
import static net.cellcomputing.himawari.library.EqIntIndex.GEO_crv_splits;
import static net.cellcomputing.himawari.library.EqIntIndex.GEO_crv_patch;
import static net.cellcomputing.himawari.library.EqIntIndex.GEO_crv_patch_created;
import static net.cellcomputing.himawari.library.EqIntIndex.GEO_crv_crv;
import static net.cellcomputing.himawari.library.EqIntIndex.GEO_crv_crv_created;
import static net.cellcomputing.himawari.library.RiGlobal.USES;
import static net.cellcomputing.himawari.library.RendermanInterface.RiBezierBasis;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.accessory.primitive.p_String;
import net.cellcomputing.himawari.accessory.primitive.p_float;
import net.cellcomputing.himawari.accessory.primitive.p_int;
import net.cellcomputing.himawari.library.types.CqColor;
import net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.library.types.CqVector3D;
import net.cellcomputing.himawari.library.types.CqVector4D;

/**
 * 
 * A single segment or sub-segment from a cubic curve.
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqCubicCurveSegment extends CqCurve {
	
	/**
	 * CqCubicCurveSegment constructor.
	 */
	public CqCubicCurveSegment()
	{ 
		super();
	}
	
	/**
	 * CqCubicCurveSegment copy constructor.
	 */
	public CqCubicCurveSegment( final CqCubicCurveSegment from )
	{
		super();
	    this.assignment( from );
	}
	
	/**
	 * Assignment operator.
	 *
	 * @param from  CqCubicCurveSegment to make this one equal to.
	 *
	 * @return Reference to *this.
	 */
	public CqCubicCurveSegment assignment( final CqCubicCurveSegment from	)
	{
	    this.assignment( (CqCurve)from );
	    return ( this );
	}

	/**
	 * Implements natural subdivision for this curve segment.
	 *
	 * @param pParam        Original parameter.
	 * @param pParam1       First new parameter.
	 * @param pParam2       Second new parameter.
	 * @param u             true if the split is along u (should
	 *                              always be false!)
	 */
	@Override
	public void  NaturalSubdivide(
	    CqParameter pParam,
	    CqParameter pParam1, CqParameter pParam2,
	    boolean u
	)
	{
	    assert( u == false );
	    switch ( pParam.Type().getValue() )
	    {
	    case type_float:
	        {
	            CqParameterTyped<p_float, p_float> pTParam   = (CqParameterTyped<p_float, p_float>)( pParam );
	            CqParameterTyped<p_float, p_float> pTResult1 = (CqParameterTyped<p_float, p_float>)( pParam1 );
	            CqParameterTyped<p_float, p_float> pTResult2 = (CqParameterTyped<p_float, p_float>)( pParam2 );
	            TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_integer:
	        {
	            CqParameterTyped<p_int, p_float> pTParam   = (CqParameterTyped<p_int, p_float>)( pParam );
	            CqParameterTyped<p_int, p_float> pTResult1 = (CqParameterTyped<p_int, p_float>)( pParam1 );
	            CqParameterTyped<p_int, p_float> pTResult2 = (CqParameterTyped<p_int, p_float>)( pParam2 );
	            TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_point:
	    case type_vector:
	    case type_normal:
	        {
	            CqParameterTyped<CqVector3D, CqVector3D> pTParam   = (CqParameterTyped<CqVector3D, CqVector3D>)( pParam );
	            CqParameterTyped<CqVector3D, CqVector3D> pTResult1 = (CqParameterTyped<CqVector3D, CqVector3D>)( pParam1 );
	            CqParameterTyped<CqVector3D, CqVector3D> pTResult2 = (CqParameterTyped<CqVector3D, CqVector3D>)( pParam2 );
	            TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_hpoint:
	        {
	            CqParameterTyped<CqVector4D, CqVector3D> pTParam   = (CqParameterTyped<CqVector4D, CqVector3D>)( pParam );
	            CqParameterTyped<CqVector4D, CqVector3D> pTResult1 = (CqParameterTyped<CqVector4D, CqVector3D>)( pParam1 );
	            CqParameterTyped<CqVector4D, CqVector3D> pTResult2 = (CqParameterTyped<CqVector4D, CqVector3D>)( pParam2 );
	            TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }


	    case type_color:
	        {
	            CqParameterTyped<CqColor, CqColor> pTParam   = (CqParameterTyped<CqColor, CqColor>)( pParam );
	            CqParameterTyped<CqColor, CqColor> pTResult1 = (CqParameterTyped<CqColor, CqColor>)( pParam1 );
	            CqParameterTyped<CqColor, CqColor> pTResult2 = (CqParameterTyped<CqColor, CqColor>)( pParam2 );
	            TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_string:
	        {
	            CqParameterTyped<p_String, p_String> pTParam   = (CqParameterTyped<p_String, p_String>)( pParam );
	            CqParameterTyped<p_String, p_String> pTResult1 = (CqParameterTyped<p_String, p_String>)( pParam1 );
	            CqParameterTyped<p_String, p_String> pTResult2 = (CqParameterTyped<p_String, p_String>)( pParam2 );
	            TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_matrix:
	        {
	            //			CqParameterTyped<CqMatrix, CqMatrix> pTParam = (CqParameterTyped<CqMatrix, CqMatrix>)( pParam );
	            //			CqParameterTyped<CqMatrix, CqMatrix> pTResult1 = (CqParameterTyped<CqMatrix, CqMatrix>)( pParam1 );
	            //			CqParameterTyped<CqMatrix, CqMatrix> pTResult2 = (CqParameterTyped<CqMatrix, CqMatrix>)( pParam2 );
	            //			TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            //			break;
	        }

	    default:
	        {
	            break;
	        }
	    }

	}

	/**
	 * Implements natural subdivision for this curve segment.
	 *
	 * @param pParam        Original parameter.
	 * @param pParam1       First new parameter.
	 * @param pParam2       Second new parameter.
	 * @param u             true if the split is along u (should
	 *                              always be false!)
	 */
	public void VaryingNaturalSubdivide(
	    CqParameter pParam,
	    CqParameter pParam1, CqParameter pParam2,
	    boolean u
	)
	{

	    assert( u == false );
	    switch ( pParam.Type().getValue() )
	    {
	    case type_float:
	        {
	            CqParameterTyped<p_float, p_float> pTParam = (CqParameterTyped<p_float, p_float>)( pParam );
	            CqParameterTyped<p_float, p_float> pTResult1 = (CqParameterTyped<p_float, p_float>)( pParam1 );
	            CqParameterTyped<p_float, p_float> pTResult2 = (CqParameterTyped<p_float, p_float>)( pParam2 );
	            VaryingTypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_integer:
	        {
	            CqParameterTyped<p_int, p_float> pTParam = (CqParameterTyped<p_int, p_float>)( pParam );
	            CqParameterTyped<p_int, p_float> pTResult1 = (CqParameterTyped<p_int, p_float>)( pParam1 );
	            CqParameterTyped<p_int, p_float> pTResult2 = (CqParameterTyped<p_int, p_float>)( pParam2 );
	            VaryingTypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_point:
	    case type_vector:
	    case type_normal:
	        {
	            CqParameterTyped<CqVector3D, CqVector3D> pTParam = (CqParameterTyped<CqVector3D, CqVector3D>)( pParam );
	            CqParameterTyped<CqVector3D, CqVector3D> pTResult1 = (CqParameterTyped<CqVector3D, CqVector3D>)( pParam1 );
	            CqParameterTyped<CqVector3D, CqVector3D> pTResult2 = (CqParameterTyped<CqVector3D, CqVector3D>)( pParam2 );
	            VaryingTypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_hpoint:
	        {
	            CqParameterTyped<CqVector4D, CqVector3D> pTParam = (CqParameterTyped<CqVector4D, CqVector3D>)( pParam );
	            CqParameterTyped<CqVector4D, CqVector3D> pTResult1 = (CqParameterTyped<CqVector4D, CqVector3D>)( pParam1 );
	            CqParameterTyped<CqVector4D, CqVector3D> pTResult2 = (CqParameterTyped<CqVector4D, CqVector3D>)( pParam2 );
	            VaryingTypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }


	    case type_color:
	        {
	            CqParameterTyped<CqColor, CqColor> pTParam = (CqParameterTyped<CqColor, CqColor>)( pParam );
	            CqParameterTyped<CqColor, CqColor> pTResult1 = (CqParameterTyped<CqColor, CqColor>)( pParam1 );
	            CqParameterTyped<CqColor, CqColor> pTResult2 = (CqParameterTyped<CqColor, CqColor>)( pParam2 );
	            VaryingTypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_string:
	        {
	            CqParameterTyped<p_String, p_String> pTParam = (CqParameterTyped<p_String, p_String>)( pParam );
	            CqParameterTyped<p_String, p_String> pTResult1 = (CqParameterTyped<p_String, p_String>)( pParam1 );
	            CqParameterTyped<p_String, p_String> pTResult2 = (CqParameterTyped<p_String, p_String>)( pParam2 );
	            VaryingTypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            break;
	        }

	    case type_matrix:
	        {
	            //			CqParameterTyped<CqMatrix, CqMatrix> pTParam = (CqParameterTyped<CqMatrix, CqMatrix>)( pParam );
	            //			CqParameterTyped<CqMatrix, CqMatrix> pTResult1 = (CqParameterTyped<CqMatrix, CqMatrix>)( pParam1 );
	            //			CqParameterTyped<CqMatrix, CqMatrix> pTResult2 = (CqParameterTyped<CqMatrix, CqMatrix>)( pParam2 );
	            //			TypedNaturalSubdivide( pTParam, pTResult1, pTResult2, u );
	            //			break;
	        }

	    default:
	        {
	            break;
	        }
	    }

	}

	/**
	 * Splits a CqCubicCurveSegment into either two smaller segments or a
	 * patch.
	 *
	 * @param aSplits       Vector to store the split objects in.
	 *
	 * @return      The number of objects we've created.
	 */
	@Override
	public int Split( STLVector<CqBasicSurface> aSplits )
	{
	    // Split based on the decision
	    switch( m_splitDecision )
	    {
	    case Split_Patch:
	        {
	            // split into a patch
	            int cPatches = SplitToPatch( aSplits );
	            STATS_INC( GEO_crv_splits );
	            STATS_INC( GEO_crv_patch );
	            STATS_SETI( GEO_crv_patch_created, STATS_GETI( GEO_crv_patch_created ) + cPatches );

	            return cPatches;
	        }
	    case Split_Curve:
	        {
	            // split into smaller curves
	            int cCurves = SplitToCurves( aSplits );
	            STATS_INC( GEO_crv_splits );
	            STATS_INC( GEO_crv_crv );
	            STATS_SETI( GEO_crv_crv_created, STATS_GETI( GEO_crv_crv_created ) + cCurves );

	            return cCurves;
	        }
	    default:
//	        throw;
	    	return -1;
	    }
	}



	/**
	 * Splits a cubic curve segment into two smaller curves.
	 *
	 * @param aSplits       Vector of split surfaces to add the segment to.
	 *
	 * @return Number of created objects.
	 */
	public int SplitToCurves( STLVector<CqBasicSurface> aSplits )
	{

	    // split into more curves
	    //  This bit right here looks a lot like CqSurface::Split().
	    //  The difference is that we *don't* want the default splitter
	    //  to handle varying class variables because it inconveniently
	    //  sets them up to have 4 elements.

	    aSplits.add( new CqCubicCurveSegment() );
	    aSplits.add( new CqCubicCurveSegment() );

	    aSplits.get( 0 ) .SetSurfaceParameters( this );
	    aSplits.get( 0 ) .SetEyeSplitCount( EyeSplitCount() );

	    aSplits.get( 1 ) .SetSurfaceParameters( this );
	    aSplits.get( 1 ) .SetEyeSplitCount( EyeSplitCount() );

	    // Iterate through any user parameters, subdividing and storing
	    //  the second value in the target surface.
//	    STLVector<CqParameter*>::iterator iUP;
	    for ( CqParameter iUP : m_aUserParams )
	    {

	        // clone the parameters
	        CqParameter pNewA = ( iUP ) .Clone();
	        CqParameter pNewB = ( iUP ) .Clone();

	        // let the standard system handle all but varying class
	        //  primitive variables
	        if ( ( iUP ) .Class().getValue() == class_varying )
	        {
	            // for varying class variables, we want to
	            //  handle them the same way as vertex class
	            //  variables for the simple case of a
	            //  CqSingleCurveLinear
	            VaryingNaturalSubdivide( ( iUP ), pNewA, pNewB, false );
	        }
	        else
	        {
	            ( iUP ) .Subdivide( pNewA, pNewB, false, this );
	        }

	        ( (CqSurface)aSplits.get( 0 ) ) . AddPrimitiveVariable( pNewA );
	        ( (CqSurface)aSplits.get( 1 ) ) . AddPrimitiveVariable( pNewB );

	    }

	    return 2;

	}

	/**
	 * Converts a linear curve segment into a patch for rendering.
	 *
	 * @param aSplits       Vector of split surfaces to add the segment to.
	 *
	 * @return Number of created objects.
	 */
	public int SplitToPatch( STLVector<CqBasicSurface> aSplits )
	{

	    // first, we find the following vectors:
	    //  direction     - from the first point to the second along the line
	    //                      segment
	    //  normal0       - normal at the first point
	    //  normal1       - normal at the second point
	    //  widthOffset0  - offset to account for the width of the patch at
	    //                      the first point
	    //  widthOffset1  - offset to account for the width of the patch at
	    //                      the second point
	   

		//【改】aqsis1.01変更************************************************************
		// note: Not really happy about this, but by shifting the calculation value 
		// slightly along the curve for tangent calculation of endpoints, we avoid
		// problems with curves that have duplicated points at one or other ends.
		// See bug #1102605
		CqVector3D direction0 = CalculateTangent(0.01f);
		CqVector3D direction3 = CalculateTangent(0.99f);
//		CqVector3D direction0 = new CqVector3D( ((CqVector4D)P().pValue( 1 )[0]) .sub( ((CqVector4D)P().pValue( 0 )[0]) ) );
//	    CqVector3D direction3 = new CqVector3D( ((CqVector4D)P().pValue( 3 )[0]) .sub( ((CqVector4D)P().pValue( 2 )[0]) ) );
		//*********************************************************************************
		
		CqVector3D direction1 = CalculateTangent(0.333f);
		CqVector3D direction2 = CalculateTangent(0.666f);

	    CqVector3D normal0, normal1, normal2, normal3;
	    normal0 = new CqVector3D(); normal1 = new CqVector3D(); normal2 = new CqVector3D(); normal3 = new CqVector3D();
	    GetNormal( 0, normal0 );
	    GetNormal( 1, normal3 );
	    normal1 = ( ( normal3.sub( normal0 ) ).div(3.0f) ).add( normal0 );
	    normal2 = ( ( ( normal3.sub( normal0 ) ).div(3.0f) ).mul( 2.0f ) ).add( normal0 );

	    normal0.Unit();
	    normal1.Unit();
	    normal2.Unit();
	    normal3.Unit();

	    CqVector3D widthOffset02 = normal0.mod( direction0 );
	    CqVector3D widthOffset12 = normal1.mod( direction1 );
	    CqVector3D widthOffset22 = normal2.mod( direction2 );
	    CqVector3D widthOffset32 = normal3.mod( direction3 );

	    float width0 = ((p_float)width().pValue_get( 0 , 0 )).value;
	    float width3 = ((p_float)width().pValue_get( 1 , 0 )).value;
	    float width1 = ( ( width3 - width0 ) / 3.0f ) + width0;
	    float width2 = ( ( ( width3 - width0 ) / 3.0f ) * 2.0f ) + width0;

	    widthOffset02.assignMul(
	        width0 / widthOffset02.Magnitude() / 6.0f );
	    widthOffset12.assignMul(
	        width1 / widthOffset12.Magnitude() / 6.0f );
	    widthOffset22.assignMul(
	        width2 / widthOffset22.Magnitude() / 6.0f );
	    widthOffset32.assignMul(
	        width3 / widthOffset32.Magnitude() / 6.0f );

	    CqVector3D widthOffset0 = widthOffset02.mul( 3 );
	    CqVector3D widthOffset1 = widthOffset12.mul( 3 );
	    CqVector3D widthOffset2 = widthOffset22.mul( 3 );
	    CqVector3D widthOffset3 = widthOffset32.mul( 3 );

	    // next, we create the bilinear patch
	    CqSurfacePatchBicubic pPatch = new CqSurfacePatchBicubic();
	    pPatch.SetSurfaceParameters( this );
	    pPatch.SetDefaultPrimitiveVariables();

	    // set the points on the patch
	    pPatch.AddPrimitiveVariable(
	        new CqParameterTypedVertex <
	        CqVector4D, CqVector3D
	        > ( "P", 1, new EqVariableType(type_hpoint), CqVector4D.class, CqVector3D.class )
	    );
	    pPatch.P().SetSize( 16 );
	    ((CqVector4D)pPatch.P().pValue_get( 0  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 0 , 0 )) ).add( widthOffset0 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 1  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 0 , 0 )) ).add( widthOffset02 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 2  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 0 , 0 )) ).sub( widthOffset02 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 3  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 0 , 0 )) ).sub( widthOffset0 ) );

	    ((CqVector4D)pPatch.P().pValue_get( 4  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 1 , 0 )) ).add( widthOffset1 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 5  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 1 , 0 )) ).add( widthOffset12 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 6  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 1 , 0 )) ).sub( widthOffset12 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 7  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 1 , 0 )) ).sub( widthOffset1 ) );

	    ((CqVector4D)pPatch.P().pValue_get( 8  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 2 , 0 )) ).add( widthOffset2 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 9  , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 2 , 0 )) ).add( widthOffset22 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 10 , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 2 , 0 )) ).sub( widthOffset22 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 11 , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 2 , 0 )) ).sub( widthOffset2 ) );

	    ((CqVector4D)pPatch.P().pValue_get( 12 , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 3 , 0 )) ).add( widthOffset3 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 13 , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 3 , 0 )) ).add( widthOffset32 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 14 , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 3 , 0 )) ).sub( widthOffset32 ) );
	    ((CqVector4D)pPatch.P().pValue_get( 15 , 0 )).assignment( new CqVector3D( ((CqVector4D)P().pValue_get( 3 , 0 )) ).sub( widthOffset3 ) );
	    
	    // set the normals on the patch
	    //	pPatch.AddPrimitiveVariable(
	    //	    new CqParameterTypedVertex <
	    //	    CqVector3D, type_normal, CqVector3D
	    //	    > ( "N", 0 )
	    //	);
	    //	pPatch.N() .SetSize( 16 );
	    //	( *pPatch.N() ) [ 0  ] = ( *pPatch.N() ) [ 1  ] = ( *pPatch.N() ) [ 2  ] = ( *pPatch.N() ) [ 3  ] = normal0;
	    //	( *pPatch.N() ) [ 4  ] = ( *pPatch.N() ) [ 5  ] = ( *pPatch.N() ) [ 6  ] = ( *pPatch.N() ) [ 7  ] = normal1;
	    //	( *pPatch.N() ) [ 8  ] = ( *pPatch.N() ) [ 9  ] = ( *pPatch.N() ) [ 10 ] = ( *pPatch.N() ) [ 11 ] = normal2;
	    //	( *pPatch.N() ) [ 12 ] = ( *pPatch.N() ) [ 13 ] = ( *pPatch.N() ) [ 14 ] = ( *pPatch.N() ) [ 15 ] = normal3;

	    int bUses = Uses();

	    // set u, v coordinates of the patch
	    if ( USES( bUses, EnvVars_u ) || USES( bUses, EnvVars_v ) )
	    {
	        ((p_float)pPatch.u().pValue_get( 0 , 0 )).value = ((p_float)pPatch.u().pValue_get( 2 , 0 )).value = 0.0f;
	        ((p_float)pPatch.u().pValue_get( 1 , 0 )).value = ((p_float)pPatch.u().pValue_get( 3 , 0 )).value = 1.0f;
	        ((p_float)pPatch.v().pValue_get( 0 , 0 )).value = ((p_float)pPatch.v().pValue_get( 1 , 0 )).value = ((p_float)v().pValue_get( 0 , 0 )).value;
	        ((p_float)pPatch.v().pValue_get( 2 , 0 )).value = ((p_float)pPatch.v().pValue_get( 3 , 0 )).value = ((p_float)v().pValue_get( 1 , 0 )).value;
	    }

	    // helllllp!!! WHAT DO I DO WITH s,t!!!???
	    //  for now, they're set equal to u and v
	    if ( USES( bUses, EnvVars_s ) || USES( bUses, EnvVars_t ) )
	    {
	    	((p_float)pPatch.s().pValue_get( 0 , 0 )).value = ((p_float)pPatch.s().pValue_get( 2 , 0 )).value = 0.0f;
	    	((p_float)pPatch.s().pValue_get( 1 , 0 )).value = ((p_float)pPatch.s().pValue_get( 3 , 0 )).value = 1.0f;
	    	((p_float)pPatch.t().pValue_get( 0 , 0 )).value = ((p_float)pPatch.t().pValue_get( 1 , 0 )).value = ((p_float)v().pValue_get( 0 , 0 )).value;
	    	((p_float)pPatch.t().pValue_get( 2 , 0 )).value = ((p_float)pPatch.t().pValue_get( 3 , 0 )).value = ((p_float)v().pValue_get( 1 , 0 )).value;
			
		}

	    // set any remaining user parameters
//	    STLVector<CqParameter*>::iterator iUP;
	    for ( CqParameter iUP : m_aUserParams )
	    {
	        if (
	            ( ( iUP ) .hash() != hp ) &&
	            ( ( iUP ) .hash() != hn ) &&
	            ( ( iUP ) .hash() != hu ) &&
	            ( ( iUP ) .hash() != hv )
	        )
	        {

	            if ( ( iUP ) .Class().getValue() == class_vertex )
	            {
	                // copy "vertex" class variables
	                CqParameter pNewUP =
	                    ( iUP ) .CloneType(
	                        ( iUP ) .strName(),
	                        ( iUP ) .Count()
	                    );
	                pNewUP.SetSize( pPatch.cVertex() );

	                pNewUP.SetValue( ( iUP ), 0,  0 );
	                pNewUP.SetValue( ( iUP ), 1,  0 );
	                pNewUP.SetValue( ( iUP ), 2,  0 );
	                pNewUP.SetValue( ( iUP ), 3,  0 );
	                pNewUP.SetValue( ( iUP ), 4,  1 );
	                pNewUP.SetValue( ( iUP ), 5,  1 );
	                pNewUP.SetValue( ( iUP ), 6,  1 );
	                pNewUP.SetValue( ( iUP ), 7,  1 );
	                pNewUP.SetValue( ( iUP ), 8,  2 );
	                pNewUP.SetValue( ( iUP ), 9,  2 );
	                pNewUP.SetValue( ( iUP ), 10, 2 );
	                pNewUP.SetValue( ( iUP ), 11, 2 );
	                pNewUP.SetValue( ( iUP ), 12, 3 );
	                pNewUP.SetValue( ( iUP ), 13, 3 );
	                pNewUP.SetValue( ( iUP ), 14, 3 );
	                pNewUP.SetValue( ( iUP ), 15, 3 );
	                pPatch.AddPrimitiveVariable( pNewUP );

	            }
	            else if ( ( iUP ) .Class().getValue() == class_varying )
	            {
	                // copy "varying" class variables
	                CqParameter pNewUP =
	                    ( iUP ) .CloneType(
	                        ( iUP ) .strName(),
	                        ( iUP ) .Count()
	                    );
	                pNewUP.SetSize( pPatch.cVarying() );

	                pNewUP.SetValue( ( iUP ), 0, 0 );
	                pNewUP.SetValue( ( iUP ), 1, 0 );
	                pNewUP.SetValue( ( iUP ), 2, 1 );
	                pNewUP.SetValue( ( iUP ), 3, 1 );
	                pPatch.AddPrimitiveVariable( pNewUP );

	            }
	            else if (
	                ( ( iUP ) .Class().getValue() == class_uniform ) ||
	                ( ( iUP ) .Class().getValue() == class_constant )
	            )
	            {

	                // copy "uniform" or "constant" class variables
	                CqParameter pNewUP =
	                    ( iUP ) .CloneType(
	                        ( iUP ) .strName(),
	                        ( iUP ) .Count()
	                    );
	                assert( pPatch.cUniform() == 1 );
	                pNewUP.SetSize( pPatch.cUniform() );

	                pNewUP.SetValue( ( iUP ), 0, 0 );
	                pPatch.AddPrimitiveVariable( pNewUP );
	            }
	        }
	    }

	    // add the patch to the split surfaces vector
	    aSplits.add( pPatch );

	    return 1;
	}

	/** Calculate the tangent at a given u on the curve segment using de Casteljau */
	public CqVector3D CalculateTangent( float u )
	{
//		int i;
//		std::vector<CqVector4D> pg(4), pg0(4);
		CqVector4D[] pg  = new CqVector4D[]{ new CqVector4D(), new CqVector4D(), new CqVector4D(), new CqVector4D() };
		CqVector4D[] pg0 = new CqVector4D[]{ new CqVector4D(), new CqVector4D(), new CqVector4D(), new CqVector4D() };
		
		for(int i=0; i <= 3; i++){ 
//			pg[i] = pg0[i] = ((CqVector4D)P().pValue( i )[0]);
			pg[i].assignment( (CqVector4D)P().pValue_get( i , 0 ) );
			pg0[i].assignment( (CqVector4D)P().pValue_get( i , 0 ) );
		}
		for(int j=1; j <= 3; j++)
		{
			for(int i=0; i <= 3-j; i++)
			{ 
				pg0[i].assignment(pg[i]);
				pg[i].assignment( pg[i].mul(1-u).add( pg[i+1].mul(u) ) );
			}
		}
		return new CqVector3D( (pg[1].sub(pg0[0])).mul(3) );
	}

	private static CqMatrix matMim1 = new CqMatrix();

	/** Convert from the current basis into Bezier for processing.
	 *
	 *  \param matBasis	Basis to convert from.
	 */
	public void ConvertToBezierBasis( CqMatrix matBasis )
	{
	    int i, j;

	    if ( matMim1.fIdentity() )
	    {
	        for ( i = 0; i < 4; i++ )
	            for ( j = 0; j < 4; j++ )
	                matMim1.m_aaElement[ i ][ j ] =  RiBezierBasis[ i ][ j ] ;
	        matMim1.SetfIdentity( false );
	        matMim1 = matMim1.Inverse();
	    }

	    CqMatrix matMj = new CqMatrix( matBasis );
	    CqMatrix matConv = matMj.multiply( matMim1 );

	    CqMatrix matCP = new CqMatrix();;
	    for ( i = 0; i < 4; i++ )
	    {
//	        matCP[ 0 ][ i ] = P().pValue(i)[0].x();
//	        matCP[ 1 ][ i ] = P().pValue(i)[0].y();
//	        matCP[ 2 ][ i ] = P().pValue(i)[0].z();
//	        matCP[ 3 ][ i ] = P().pValue(i)[0].h();
	        matCP.m_aaElement[ 0 ][ i ] = ((CqVector4D)P().pValue_get(i, 0 )).x ;
	        matCP.m_aaElement[ 1 ][ i ] =  ((CqVector4D)P().pValue_get(i, 0 )).y ;
	        matCP.m_aaElement[ 2 ][ i ] =  ((CqVector4D)P().pValue_get(i, 0 )).z ;
	        matCP.m_aaElement[ 3 ][ i ] = ((CqVector4D)P().pValue_get(i, 0 )).w ;
	    }
	    matCP.SetfIdentity( false );

	    matCP = matConv.Transpose().multiply( matCP );

	    for ( i = 0; i < 4; i++ )
	    {
	    	((CqVector4D)P().pValue_get(i, 0 )).x( matCP.m_aaElement[ 0 ][ i ] );
	    	((CqVector4D)P().pValue_get(i, 0 )).y( matCP.m_aaElement[ 1 ][ i ] );
	    	((CqVector4D)P().pValue_get(i, 0 )).z( matCP.m_aaElement[ 2 ][ i ] );
	    	((CqVector4D)P().pValue_get(i, 0 )).h( matCP.m_aaElement[ 3 ][ i ] );
	    }
	}
	
    /** Returns the number of facevarying class parameters. */
    public	int	cFaceVarying()
    {
        return 0;
    }
    /** Returns the number of uniform class parameters. */
    public	int cUniform()
    {
        return 1;
    }
    /** Returns the number of varying class parameters. */
    public	int cVarying()
    {
        return 2;
    }
    /** Returns the number of vertex class parameters. */
    public	int	cVertex()
    {
        return 4;
    }
    
    /** Typed natural subdivision for the surface. */
    @Override
    protected <T, SLT> void TypedNaturalSubdivide(
        CqParameterTyped<T, SLT> pParam,
        CqParameterTyped<T, SLT> pResult1,
        CqParameterTyped<T, SLT> pResult2,
        boolean u
    )
    {
        // we can only split curves along v, so enforce this
        assert( u == false );

        CqParameterTyped<T, SLT> pTParam   = (CqParameterTyped<T, SLT>)( pParam );
        CqParameterTyped<T, SLT> pTResult1 = (CqParameterTyped<T, SLT>)( pResult1 );
        CqParameterTyped<T, SLT> pTResult2 = (CqParameterTyped<T, SLT>)( pResult2 );

      	T t = (T)pTResult1.pValue_get( 0 , 0);
    	//型の判別を行う。
    	//インスタンスがp_floatのとき
    	if( t instanceof p_float )
    	{
    		float pTParam0 = ((p_float)pTParam.pValue_get( 0 , 0 )).value;
    		float pTParam1 = ((p_float)pTParam.pValue_get( 0 , 1 )).value;
    		float pTParam2 = ((p_float)pTParam.pValue_get( 0 , 2 )).value;
    		float pTParam3 = ((p_float)pTParam.pValue_get( 0 , 3 )).value;
    		
    		((p_float)pTResult1.pValue_get( 0 , 0 )).value = pTParam0;
    		((p_float)pTResult1.pValue_get( 0 , 1 )).value = ( ( pTParam0 + pTParam1 ) / 2.0f );
    		((p_float)pTResult1.pValue_get( 0 , 2 )).value = ( ((p_float)pTResult1.pValue_get( 0 , 1 )).value / 2.0f + ( pTParam1 + pTParam2 ) / 4.0f );
    		
    		((p_float)pTResult2.pValue_get( 0 , 3 )).value = pTParam3;
    		((p_float)pTResult2.pValue_get( 0 , 2 )).value = ( ( pTParam2 + pTParam3 ) / 2.0f );
    		((p_float)pTResult2.pValue_get( 0 , 1 )).value = ( ((p_float)pTResult2.pValue_get( 0 , 2 )).value / 2.0f + ( pTParam1 + pTParam2 ) / 4.0f );
    		
    		((p_float)pTResult1.pValue_get( 0 , 3 )).value = ( ( ((p_float)pTResult1.pValue_get( 0 , 2 )).value + ((p_float)pTResult2.pValue_get( 0 , 1 )).value ) / 2.0f );
    		((p_float)pTResult2.pValue_get( 0 , 0 )).value = ((p_float)pTResult1.pValue_get( 0 , 3 )).value;
    		
    	}//インスタンスがp_intのとき
    	else if( t instanceof p_int )
    	{
       		int pTParam0 = ((p_int)pTParam.pValue_get( 0 , 0 )).value;
    		int pTParam1 = ((p_int)pTParam.pValue_get( 0 , 1 )).value;
    		int pTParam2 = ((p_int)pTParam.pValue_get( 0 , 2 )).value;
    		int pTParam3 = ((p_int)pTParam.pValue_get( 0 , 3 )).value;
    		
    		((p_int)pTResult1.pValue_get( 0 , 0 )).value = pTParam0;
    		((p_int)pTResult1.pValue_get( 0 , 1 )).value = ( ( pTParam0 + pTParam1 ) / 2 );
    		((p_int)pTResult1.pValue_get( 0 , 2 )).value = ( ((p_int)pTResult1.pValue_get( 0 , 1 )).value / 2 + ( pTParam1 + pTParam2 ) / 4 );
    		
    		((p_int)pTResult2.pValue_get( 0 , 3 )).value = pTParam3;
    		((p_int)pTResult2.pValue_get( 0 , 2 )).value = ( ( pTParam2 + pTParam3 ) / 2 );
    		((p_int)pTResult2.pValue_get( 0 , 1 )).value = ( ((p_int)pTResult2.pValue_get( 0 , 2 )).value / 2 + ( pTParam1 + pTParam2 ) / 4 );
    		
    		((p_int)pTResult1.pValue_get( 0 , 3 )).value = ( ( ((p_int)pTResult1.pValue_get( 0 , 2 )).value + ((p_int)pTResult2.pValue_get( 0 , 1 )).value ) / 2 );
    		((p_int)pTResult2.pValue_get( 0 , 0 )).value = ((p_int)pTResult1.pValue_get( 0 , 3 )).value;
 
    	}//インスタンスがp_Stringのとき
    	else if( t instanceof p_String )
    	{
     		String pTParam0 = ((p_String)pTParam.pValue_get( 0 , 0 )).value;
    		String pTParam1 = ((p_String)pTParam.pValue_get( 0 , 1 )).value;
    		String pTParam2 = ((p_String)pTParam.pValue_get( 0 , 2 )).value;
    		String pTParam3 = ((p_String)pTParam.pValue_get( 0 , 3 )).value;
    		
    		((p_String)pTResult1.pValue_get( 0 , 0 )).value = pTParam0;
    		((p_String)pTResult1.pValue_get( 0 , 1 )).value = ( ( pTParam0 + pTParam1 ) );
    		((p_String)pTResult1.pValue_get( 0 , 2 )).value = ( ((p_String)pTResult1.pValue_get( 0 , 1 )).value + ( pTParam1 + pTParam2 ) );
    		
    		((p_String)pTResult2.pValue_get( 0 , 3 )).value = pTParam3;
    		((p_String)pTResult2.pValue_get( 0 , 2 )).value = ( ( pTParam2 + pTParam3 ) );
    		((p_String)pTResult2.pValue_get( 0 , 1 )).value = ( ((p_String)pTResult2.pValue_get( 0 , 2 )).value + ( pTParam1 + pTParam2 ) );
    		
    		((p_String)pTResult1.pValue_get( 0 , 3 )).value = ( ( ((p_String)pTResult1.pValue_get( 0 , 2 )).value + ((p_String)pTResult2.pValue_get( 0 , 1 )).value ) );
    		((p_String)pTResult2.pValue_get( 0 , 0 )).value = ((p_String)pTResult1.pValue_get( 0 , 3 )).value;
 
    	}//インスタンスがCqMatrixのとき
    	else if( t instanceof CqMatrix )
    	{
     		CqMatrix pTParam0 = ((CqMatrix)pTParam.pValue_get( 0 , 0 ));
    		CqMatrix pTParam1 = ((CqMatrix)pTParam.pValue_get( 0 , 1 ));
    		CqMatrix pTParam2 = ((CqMatrix)pTParam.pValue_get( 0 , 2 ));
    		CqMatrix pTParam3 = ((CqMatrix)pTParam.pValue_get( 0 , 3 ));
    		
    		((CqMatrix)pTResult1.pValue_get( 0 , 0 )).assignment( pTParam0 );
    		((CqMatrix)pTResult1.pValue_get( 0 , 1 )).assignment( ( pTParam0.add(pTParam1) ).mulInv( 0.5f ) );
    		((CqMatrix)pTResult1.pValue_get( 0 , 2 )).assignment( ((CqMatrix)pTResult1.pValue_get( 0 , 1 )).mulInv(0.5f) .add( ( pTParam1.add(pTParam2) ).mulInv(0.25f) ) );
    		
    		((CqMatrix)pTResult2.pValue_get( 0 , 3 )).assignment( pTParam3 );
    		((CqMatrix)pTResult2.pValue_get( 0 , 2 )).assignment( ( pTParam2.add(pTParam3) ) .mulInv(0.5f) );
    		((CqMatrix)pTResult2.pValue_get( 0 , 1 )).assignment( ((CqMatrix)pTResult2.pValue_get( 0 , 2 )).mulInv(0.5f) .add( ( pTParam1.add(pTParam2) ).mulInv(0.25f) ) );
    		
    		((CqMatrix)pTResult1.pValue_get( 0 , 3 )).assignment( ( ((CqMatrix)pTResult1.pValue_get( 0 , 2 )) .add( ((CqMatrix)pTResult2.pValue_get( 0 , 1 )) ) ).mulInv(0.5f) );
    		((CqMatrix)pTResult2.pValue_get( 0 , 0 )).assignment( ((CqMatrix)pTResult1.pValue_get( 0 , 3 )) );
  
    	}//インスタンスがCqColorのとき
    	else if( t instanceof CqColor )
    	{
    		CqColor pTParam0 = ((CqColor)pTParam.pValue_get( 0 , 0 ));
    		CqColor pTParam1 = ((CqColor)pTParam.pValue_get( 0 , 1 ));
    		CqColor pTParam2 = ((CqColor)pTParam.pValue_get( 0 , 2 ));
    		CqColor pTParam3 = ((CqColor)pTParam.pValue_get( 0 , 3 ));
    		
    		((CqColor)pTResult1.pValue_get( 0 , 0 )).assignment( pTParam0 );
    		((CqColor)pTResult1.pValue_get( 0 , 1 )).assignment( ( pTParam0.add(pTParam1) ).div( 2.0f ) );
    		((CqColor)pTResult1.pValue_get( 0 , 2 )).assignment( ((CqColor)pTResult1.pValue_get( 0 , 1 )).div(2.0f) .add( ( pTParam1.add(pTParam2) ).div(4.0f) ) );
    		
    		((CqColor)pTResult2.pValue_get( 0 , 3 )).assignment( pTParam3 );
    		((CqColor)pTResult2.pValue_get( 0 , 2 )).assignment( ( pTParam2.add(pTParam3) ) .div(2.0f) );
    		((CqColor)pTResult2.pValue_get( 0 , 1 )).assignment( ((CqColor)pTResult2.pValue_get( 0 , 2 )).div(2.0f) .add( ( pTParam1.add(pTParam2) ).div(4.0f) ) );
    		
    		((CqColor)pTResult1.pValue_get( 0 , 3 )).assignment( ( ((CqColor)pTResult1.pValue_get( 0 , 2 )) .add( ((CqColor)pTResult2.pValue_get( 0 , 1 )) ) ).div(2.0f) );
    		((CqColor)pTResult2.pValue_get( 0 , 0 )).assignment( ((CqColor)pTResult1.pValue_get( 0 , 3 )) );
    		
    	}//インスタンスがCqVector3Dのとき
    	else if( t instanceof CqVector3D )
    	{
    		CqVector3D pTParam0 = ((CqVector3D)pTParam.pValue_get( 0 , 0 ));
    		CqVector3D pTParam1 = ((CqVector3D)pTParam.pValue_get( 0 , 1 ));
    		CqVector3D pTParam2 = ((CqVector3D)pTParam.pValue_get( 0 , 2 ));
    		CqVector3D pTParam3 = ((CqVector3D)pTParam.pValue_get( 0 , 3 ));
    		
    		((CqVector3D)pTResult1.pValue_get( 0 , 0 )).assignment( pTParam0 );
    		((CqVector3D)pTResult1.pValue_get( 0 , 1 )).assignment( ( pTParam0.add(pTParam1) ).div( 2.0f ) );
    		((CqVector3D)pTResult1.pValue_get( 0 , 2 )).assignment( ((CqVector3D)pTResult1.pValue_get( 0 , 1 )).div(2.0f) .add( ( pTParam1.add(pTParam2) ).div(4.0f) ) );
    		
    		((CqVector3D)pTResult2.pValue_get( 0 , 3 )).assignment( pTParam3 );
    		((CqVector3D)pTResult2.pValue_get( 0 , 2 )).assignment( ( pTParam2.add(pTParam3) ) .div(2.0f) );
    		((CqVector3D)pTResult2.pValue_get( 0 , 1 )).assignment( ((CqVector3D)pTResult2.pValue_get( 0 , 2 )).div(2.0f) .add( ( pTParam1.add(pTParam2) ).div(4.0f) ) );
    		
    		((CqVector3D)pTResult1.pValue_get( 0 , 3 )).assignment( ( ((CqVector3D)pTResult1.pValue_get( 0 , 2 )) .add( ((CqVector3D)pTResult2.pValue_get( 0 , 1 )) ) ).div(2.0f) );
    		((CqVector3D)pTResult2.pValue_get( 0 , 0 )).assignment( ((CqVector3D)pTResult1.pValue_get( 0 , 3 )) );
    		
    	}//インスタンスがCqVector4Dのとき
    	else if( t instanceof CqVector4D )
    	{
    		CqVector4D pTParam0 = ((CqVector4D)pTParam.pValue_get( 0 , 0 ));
    		CqVector4D pTParam1 = ((CqVector4D)pTParam.pValue_get( 0 , 1 ));
    		CqVector4D pTParam2 = ((CqVector4D)pTParam.pValue_get( 0 , 2 ));
    		CqVector4D pTParam3 = ((CqVector4D)pTParam.pValue_get( 0 , 3 ));
    		
    		((CqVector4D)pTResult1.pValue_get( 0 , 0 )).assignment( pTParam0 );
    		((CqVector4D)pTResult1.pValue_get( 0 , 1 )).assignment( ( pTParam0.add(pTParam1) ).div( 2.0f ) );
    		((CqVector4D)pTResult1.pValue_get( 0 , 2 )).assignment( ((CqVector4D)pTResult1.pValue_get( 0 , 1 )).div(2.0f) .add( ( pTParam1.add(pTParam2) ).div(4.0f) ) );
    		
    		((CqVector4D)pTResult2.pValue_get( 0 , 3 )).assignment( pTParam3 );
    		((CqVector4D)pTResult2.pValue_get( 0 , 2 )).assignment( ( pTParam2.add(pTParam3) ) .div(2.0f) );
    		((CqVector4D)pTResult2.pValue_get( 0 , 1 )).assignment( ((CqVector4D)pTResult2.pValue_get( 0 , 2 )).div(2.0f) .add( ( pTParam1.add(pTParam2) ).div(4.0f) ) );
    		
    		((CqVector4D)pTResult1.pValue_get( 0 , 3 )).assignment( ( ((CqVector4D)pTResult1.pValue_get( 0 , 2 )) .add( ((CqVector4D)pTResult2.pValue_get( 0 , 1 )) ) ).div(2.0f) );
    		((CqVector4D)pTResult2.pValue_get( 0 , 0 )).assignment( ((CqVector4D)pTResult1.pValue_get( 0 , 3 )) );
    		
    	}
    	else{ //想定しないインスタンスの型。
    	}
        
        //オリジナル。
//        pTResult1.pValue() [ 0 ] = pTParam.pValue() [ 0 ];
//        pTResult1.pValue() [ 1 ] = static_cast<T>( ( pTParam.pValue() [ 0 ] + pTParam.pValue() [ 1 ] ) / 2.0f );
//        pTResult1.pValue() [ 2 ] = static_cast<T>( pTResult1.pValue() [ 1 ] / 2.0f + ( pTParam.pValue() [ 1 ] + pTParam.pValue() [ 2 ] ) / 4.0f );
//
//        pTResult2.pValue() [ 3 ] = pTParam.pValue() [ 3 ];
//        pTResult2.pValue() [ 2 ] = static_cast<T>( ( pTParam.pValue() [ 2 ] + pTParam.pValue() [ 3 ] ) / 2.0f );
//        pTResult2.pValue() [ 1 ] = static_cast<T>( pTResult2.pValue() [ 2 ] / 2.0f + ( pTParam.pValue() [ 1 ] + pTParam.pValue() [ 2 ] ) / 4.0f );
//
//        pTResult1.pValue() [ 3 ] = static_cast<T>( ( pTResult1.pValue() [ 2 ] + pTResult2.pValue() [ 1 ] ) / 2.0f );
//        pTResult2.pValue() [ 0 ] = pTResult1.pValue() [ 3 ];
    }

    /** Typed natural subdivision for the surface. */
    protected <T, SLT> void VaryingTypedNaturalSubdivide(
        CqParameterTyped<T, SLT> pParam,
        CqParameterTyped<T, SLT> pResult1,
        CqParameterTyped<T, SLT> pResult2,
        boolean u
    )
    {
        // we can only split curves along v, so enforce this
        assert( u == false );
        
        CqParameterTyped<T, SLT> pTParam   = (CqParameterTyped<T, SLT>)( pParam );
        CqParameterTyped<T, SLT> pTResult1 = (CqParameterTyped<T, SLT>)( pResult1 );
        CqParameterTyped<T, SLT> pTResult2 = (CqParameterTyped<T, SLT>)( pResult2 );
        
    	T t = (T)pTResult1.pValue_get( 0 ,0 );
    	//型の判別を行う。
    	//インスタンスがp_floatのとき
    	if( t instanceof p_float )
    	{
    		((p_float)pTResult1.pValue_get( 0 , 0 )).value = ((p_float)pTParam.pValue_get( 0 , 0 )).value;
    		((p_float)pTResult1.pValue_get( 0 , 1 )).value = ((p_float)pTResult2.pValue_get( 0 , 0 )).value = ( ((p_float)pTParam.pValue_get( 0 , 0 )).value + ((p_float)pTParam.pValue_get( 0 , 1 )).value ) * 0.5f;
    		((p_float)pTResult2.pValue_get( 0 , 1 )).value = ((p_float)pTParam.pValue_get( 0 , 1 )).value;
    		
    	}//インスタンスがp_intのとき
    	else if( t instanceof p_int )
    	{
      		((p_int)pTResult1.pValue_get( 0 , 0 )).value = ((p_int)pTParam.pValue_get( 0 , 0 )).value;
    		((p_int)pTResult1.pValue_get( 0 , 1 )).value = ((p_int)pTResult2.pValue_get( 0 , 0 )).value = (int)( ( ((p_int)pTParam.pValue_get( 0 , 0 )).value + ((p_int)pTParam.pValue_get( 0 , 1 )).value ) * 0.5f );
    		((p_int)pTResult2.pValue_get( 0 , 1 )).value = ((p_int)pTParam.pValue_get( 0 , 1 )).value;
  
    	}//インスタンスがp_Stringのとき
    	else if( t instanceof p_String )
    	{
      		((p_String)pTResult1.pValue_get( 0 , 0 )).value = ((p_String)pTParam.pValue_get( 0 , 0 )).value;
    		((p_String)pTResult1.pValue_get( 0 , 1 )).value = ((p_String)pTResult2.pValue_get( 0 , 0 )).value = ( ((p_String)pTParam.pValue_get( 0 , 0 )).value + ((p_String)pTParam.pValue_get( 0 , 1 )).value );
    		((p_String)pTResult2.pValue_get( 0 , 1 )).value = ((p_String)pTParam.pValue_get( 0 , 1 )).value;
 
    	}//インスタンスがCqMatrixのとき
    	else if( t instanceof CqMatrix )
    	{
      		((CqMatrix)pTResult1.pValue_get( 0 , 0 )).assignment( (CqMatrix)pTParam.pValue_get( 0 , 0 ) );
    		((CqMatrix)pTResult1.pValue_get( 0 , 1 )).assignment( ((CqMatrix)pTResult2.pValue_get( 0 , 0 )).assignment( ( ((CqMatrix)pTParam.pValue_get( 0 , 0 )).add( (CqMatrix)pTParam.pValue_get( 0 , 1 ) ) ) .multiply( 0.5f ) ) );
    		((CqMatrix)pTResult2.pValue_get( 0 , 1 )).assignment( (CqMatrix)pTParam.pValue_get( 0 , 1 ) );
   
    	}//インスタンスがCqColorのとき
    	else if( t instanceof CqColor )
    	{
      		((CqColor)pTResult1.pValue_get( 0 , 0 )).assignment( (CqColor)pTParam.pValue_get( 0 , 0 ) );
    		((CqColor)pTResult1.pValue_get( 0 , 1 )).assignment( ((CqColor)pTResult2.pValue_get( 0 , 0 )).assignment( ( ((CqColor)pTParam.pValue_get( 0 , 0 )).add( (CqColor)pTParam.pValue_get( 0 , 1 ) ) ) .mul( 0.5f ) ) );
    		((CqColor)pTResult2.pValue_get( 0 , 1 )).assignment( (CqColor)pTParam.pValue_get( 0 , 1 ) );
    		
    	}//インスタンスがCqVector3Dのとき
    	else if( t instanceof CqVector3D )
    	{
    		((CqVector3D)pTResult1.pValue_get( 0 , 0 )).assignment( (CqVector3D)pTParam.pValue_get( 0 , 0 ) );
    		((CqVector3D)pTResult1.pValue_get( 0 , 1 )).assignment( ((CqVector3D)pTResult2.pValue_get( 0 , 0 )).assignment( ( ((CqVector3D)pTParam.pValue_get( 0 , 0 )).add( (CqVector3D)pTParam.pValue_get( 0 , 1 ) ) ) .mul( 0.5f ) ) );
    		((CqVector3D)pTResult2.pValue_get( 0 , 1 )).assignment( (CqVector3D)pTParam.pValue_get( 0 , 1 ) );
    		
    	}//インスタンスがCqVector4Dのとき
    	else if( t instanceof CqVector4D )
    	{
    		((CqVector4D)pTResult1.pValue_get( 0 , 0 )).assignment( (CqVector4D)pTParam.pValue_get( 0 , 0 ) );
    		((CqVector4D)pTResult1.pValue_get( 0 , 1 )).assignment( ((CqVector4D)pTResult2.pValue_get( 0 , 0 )).assignment( ( ((CqVector4D)pTParam.pValue_get( 0 , 0 )).add( (CqVector4D)pTParam.pValue_get( 0 , 1 ) ) ) .mul( 0.5f ) ) );
    		((CqVector4D)pTResult2.pValue_get( 0 , 1 )).assignment( (CqVector4D)pTParam.pValue_get( 0 , 1 ) );
    		
    	}
    	else{ //想定しないインスタンスの型。
    	}

        //オリジナル。
//        pTResult1.pValue() [ 0 ] = pTParam.pValue() [ 0 ];
//        pTResult1.pValue() [ 1 ] = pTResult2.pValue() [ 0 ] = static_cast<T>( ( pTParam.pValue() [ 0 ] + pTParam.pValue() [ 1 ] ) * 0.5f );
//        pTResult2.pValue() [ 1 ] = pTParam.pValue() [ 1 ];
    }

    

}
