//------------------------------------------------------------
// $Id: PRC_searchNextSpc.h,v 1.1.1.1 1999/11/25 06:26:09 yamauchi Exp $
//------------------------------------------------------------
//	(M\pi)^2 
// 	次空間探索用
//	Copyright (C) 1998 Mayumi TOKUNAGA	徳永 麻由美
//			   Hitoshi YAMAUCHI 	山内 斉
//------------------------------------------------------------
#ifndef _searchNextSpcPRC_h
#define _searchNextSpcPRC_h 1

#include "searchNextSpcDDA.h"

//------------------------------
// Proximity Clouds 法で使う Skip Map の要素
//	YAMAUCHI 1998年8月27日(木) 
// objectInfoInASpace.h が素朴な skip 用のマップです．
//	objectInfoInASpace.h には物体数を数える(統計処理用)ものと，物
//	体のあるなしだけ(素朴な skip 用) の 2 つの実装例があります．
//------------------------------
class PRC_skipMapClass {  
protected:    
    OBJINSPC_IMPLEMENT_TYPE mSkipDistance;

public:    
    // constructors
    PRC_skipMapClass(void) : mSkipDistance(0){}
    PRC_skipMapClass(const PRC_skipMapClass& rhs)
    {
	this->mSkipDistance = rhs.mSkipDistance;
    }
    PRC_skipMapClass(const OBJINSPC_IMPLEMENT_TYPE& rhs)
    {
	this->mSkipDistance = rhs;
    }
    const PRC_skipMapClass operator=(const PRC_skipMapClass& rhs)
    {
	if(this != &rhs)
	{
	    this->mSkipDistance = rhs.mSkipDistance;
	}
	return(*this);
    }

    void set(int distance) 
    {
	// 今は内部表現が char なので 127 までしか扱えない
	assert((distance >= 0) && (distance < 128));
	this->mSkipDistance = distance;
    }
    int get(void) const
    {
	return(this->mSkipDistance);
    }

    // for serialize (送信のために OBJINSPC_IMPLEMENT_TYPE で取り出す)
    OBJINSPC_IMPLEMENT_TYPE getObjInfo(void) const
    {
	return(this->mSkipDistance);
    }
    
    friend ostream& operator<<(ostream& s, PRC_skipMapClass& onis)
    {
	s << onis.mSkipDistance;
	return s;
    }

    // operator ==
    friend int operator==(const PRC_skipMapClass &a,
			  const PRC_skipMapClass &b)
    {
	return(a.mSkipDistance == b.mSkipDistance);
    }
    friend int operator!=(const PRC_skipMapClass &a,
			  const PRC_skipMapClass &b)
    {
	return(a.mSkipDistance != b.mSkipDistance);
    }
    
    //----------------------------------------
    // SerializableIF : double の表現が同じ計算機でないと上手くいかない    
    //----------------------------------------
    int getSerializedSize(void) const
    {
	// OBJINSPC_IMPLEMENT_TYPE mObjInfo; 今は char 
	return(1);
    }
    double *newSerializedArray(void)
    {
	double *r = new double[this->getSerializedSize()];
	r[0] = (double)(this->mSkipDistance);
	return(r);
    }
    void deserialize(double *pBuf)
    {
	this->mSkipDistance = (char)(pBuf[0]);
    }

    // for pretty print (出力用) 
    // このクラスは距離を出力するとした．他のものは物体のあるなしを示
    // したりしている．objectInfoInASpace.h を参照のこと．
    const char * getVisualOutDescription(void) const
    {
	return(" Distance");	// 説明: 距離を返すという意味
    }
    int getVisualOut(void) const
    {
	return(this->mSkipDistance);
    }
};

//------------------------------
// Proximity Clouds 法用の DD Unit
//------------------------------
class searchNextSpcPRC : public searchNextSpcDDA {
private:
    searchNextSpcPRC(const searchNextSpcPRC& rhs);
    const searchNextSpcPRC& operator=(const searchNextSpcPRC& rhs);

protected:
    IntVec3 getSpcByPRC(const int skipnum, DDAInfoClass *pDInfo);
    YorN testCanGo(IntVec3* pSpcPos, IntVec3 relapos);
    IntVec3 getNextSubspaceRelative(const int skipnum, DDAInfoClass *ddainfo,IntVec3 spcpos);
    void goNextSpacePRC(IntVec3* pSpcPos, IntVec3 relapos) const;
    YorN testAndGoIfItCan(IntVec3* pSpcPos, IntVec3 relapos) 
    {
	// もし移動できるのならその方向に移動し、YES を返す。
	// できない場合には移動せずに NO を返す。
	if(this->testCanGo(pSpcPos, relapos) == YES)
	{
	    this->goNextSpacePRC(pSpcPos, relapos);
	    return(YES);
	}else
	{
	    return(NO);
	}
    }
public:    
    searchNextSpcPRC(void);
    ~searchNextSpcPRC(void);
    YorN moveRayToNextCalcSubspaceWithSkip(Ray *pRay);

public:    
    array3dClass < PRC_skipMapClass > mObjInSpcMap; 
    //PRC_skipMapClass mObjInSpcMap;
    YorN isObject(const IntVec3& spcpos)
    {
	int idx[3];
	spcpos.getAsArray(idx);
	if(this->mObjInSpcMap.get(idx).get() == 0)
	    return(YES);
	else
	    return(NO);

    }

};






#endif				// #ifndef _searchNextSpc_h

