/*
 * $Id: VertexIntensity.java,v 1.5 2000/06/15 13:55:51 yamauchi Exp $
 *     (M\pi)^2 : VertexIntensity 
 *	Copyright 1999 By YAMAUCHI Hitoshi 山内 斉 
 *	@author YAMAUCHI Hitoshi 山内 斉
 *	
 * original source VertexIntensity.h
 * 
 * 1999年7月30日(金)
 */

package jp.ac.tohoku.is.archi.mpi2.obj;

import java.io.Serializable;
import jp.ac.tohoku.is.archi.mpi2.util.Vector3;
import jp.ac.tohoku.is.archi.mpi2.util.IntVec3;
import jp.ac.tohoku.is.archi.mpi2.sysparam.Mpi2Enum;
import jp.ac.tohoku.is.archi.mpi2.util.*;

/**
 * 頂点とポリゴン番号と輝度の情報
 */
public final class VertexIntensity 
implements Encodable		// Serializable
{
    private int     mPolygonID;	// 頂点の属していたポリゴン番号
    private IntVec3 mDestSpcPos; // 到着次空間指標
    private Vector3 mIntensity;	// 頂点の輝度
    private Vector3 mVertexPos;	// 頂点の座標

    //-- 未送信方向(斜めに移動する場合には2回送信が必要であり、この値が 
    //-- DIR_HERE でないということは未送信の方向があるということ  
    //-- と考えたが効率の良い実装が手間なためにまずは rank で送信する。
    //-- IMPROVE HERE
    //--     IntVec3 mNextSpcPos;	// 次に着く空間指標
    //--     DIR_3D  mRestDir;

    // 送信・受信時のタグ
    public static int getTAG()
    { 
	return(Mpi2Enum.TAG_INT_VER); 
    }
    
    public VertexIntensity()
    {
	this.mPolygonID	= -1;	// illegal value
	this.mDestSpcPos= null;
	this.mIntensity	= null;
	this.mVertexPos	= null;
    }

    public VertexIntensity(VertexIntensity rhs)
    {
	this.mPolygonID		= rhs.mPolygonID;
	this.mDestSpcPos	= new IntVec3(rhs.mDestSpcPos);
	this.mIntensity		= new Vector3(rhs.mIntensity);
	this.mVertexPos		= new Vector3(rhs.mVertexPos);
    }

    /**
     * set する場合には new はされないので共有しないものは new で渡すこと
     * @param aPolygonID 	Shading 時に同じポリゴンを識別するための ID
     * @param aDestSpcPos	送信先空間番号 (spcpos)
     * @param anIntensity	輝度
     * @param aVertexPos		この頂点座標
     */
    public void set(int aPolygonID, 	  IntVec3 aDestSpcPos,
		    Vector3 anIntensity,  Vector3 aVertexPos)
    {
	if(aPolygonID < 0)
	{	
	    throw new RuntimeException("Error! : VertexIntensity.set() " + 
				       "illegal polygon id " + aPolygonID);
	    // FIXHERE commMpi2_exit(1);
	}
	this.mPolygonID  = aPolygonID;
	this.mDestSpcPos = aDestSpcPos;
	this.mIntensity  = anIntensity;
	this.mVertexPos	 = aVertexPos;
    }
    public void setDestSpcPos(IntVec3 destspcpos) 
    {
	this.mDestSpcPos = destspcpos;
    }

    public int	   getPolygonID()	{ return(this.mPolygonID);  	}
    public IntVec3 peekDestSpcPos()	{ return(this.mDestSpcPos); 	}
    public Vector3 peekIntensity()	{ return(this.mIntensity);  	}
    public Vector3 peekVertexPos()	{ return(this.mVertexPos);	}



    /*
     * Implements Encodable
     */
    private final static int mSizeInDouble = 
    1 +					// int     mPolygonID;
    IntVec3.ZERO.sizeInDouble() + 	// IntVec3 mDestSpcPos;
    IntVec3.ZERO.sizeInDouble() + 	// Vector3 mIntensity;
    Vector3.ZERO.sizeInDouble(); 	// Vector3 mVertexPos;

    public int sizeInDouble() 
    {
	return(mSizeInDouble);
    }
    public void encodeInDouble(double[] array, int offset) 
    {
	int idx = 0;

	array[offset] = (double)(this.mPolygonID);
	idx += 1;

	this.mDestSpcPos.encodeInDouble(array, offset + idx);
	idx += this.mDestSpcPos.sizeInDouble();

	this.mIntensity.encodeInDouble(array, offset + idx);
	idx += this.mIntensity.sizeInDouble();

	this.mVertexPos.encodeInDouble(array, offset + idx);
	// idx += this.mVertexPos.sizeInDouble();
    }

    /*
     * Implements ObjectDecoder
     */
    private static class VertexIntensityObjectDecoder implements ObjectDecoder 
    {
    	public int sizeInDouble() 
	{
	    return(mSizeInDouble);
	}
    	public Object decodeFromDouble(double[] array, int offset)
	{
	    int idx = 0;

	    Vector3.getObjectDecoder();
	    IntVec3.getObjectDecoder();
	    
	    int polygonID = (int)(array[offset + idx]);
	    idx  += 1;
	    
	    IntVec3 destspcpos = (IntVec3)
		(IntVec3.getObjectDecoder().decodeFromDouble(array, 
							     offset + idx));
	    idx  += destspcpos.sizeInDouble();

	    Vector3 intensity = (Vector3)
		(Vector3.getObjectDecoder().decodeFromDouble(array, 
							     offset + idx));
	    idx  += intensity.sizeInDouble();

	    Vector3 vertexpos = (Vector3)
		(Vector3.getObjectDecoder().decodeFromDouble(array, 
							     offset + idx));
	    // idx  += vertexpos.sizeInDouble();
	    
	    VertexIntensity vi = new VertexIntensity();
	    vi.set(polygonID, destspcpos, intensity, vertexpos);
	    
	    return(vi);
	}
    }
    private final static ObjectDecoder mODInstance 
    	= new VertexIntensityObjectDecoder();
    public static ObjectDecoder getObjectDecoder() 
    {
	return(mODInstance);
    }
}
