Пример #1
0
void ESceneAIMapTool::BuildNodes(bool bFromSelectedOnly)
{
	// begin
	m_Nodes.reserve	(1024*1024);

	// Initialize hash
//	hash_Initialize ();

    R_ASSERT(!m_Nodes.empty());
    // Estimate nodes
    Fvector	Pos,LevelSize;
    m_AIBBox.getsize	(LevelSize);
    float estimated_nodes	= (LevelSize.x/m_Params.fPatchSize)*(LevelSize.z/m_Params.fPatchSize);

    SPBItem* pb = UI->ProgressStart(1, "Building nodes...");
    // General cycle
    for (int k=0; k<(int)m_Nodes.size(); k++){
        SAINode* N 			= m_Nodes[k];
    	if (bFromSelectedOnly && !N->flags.is(SAINode::flSelected)) continue;
        // left 
        if (0==N->n1){
            Pos.set			(N->Pos);
            Pos.x			-=	m_Params.fPatchSize;
            N->n1			=	BuildNode(N->Pos,Pos,false);
        }
        // fwd
        if (0==N->n2){
            Pos.set			(N->Pos);
            Pos.z			+=	m_Params.fPatchSize;
            N->n2			=	BuildNode(N->Pos,Pos,false);
        }
        // right
        if (0==N->n3){
            Pos.set			(N->Pos);
            Pos.x			+=	m_Params.fPatchSize;
            N->n3			=	BuildNode(N->Pos,Pos,false);
        }
        // back
        if (0==N->n4){
            Pos.set			(N->Pos);
            Pos.z			-=	m_Params.fPatchSize;
            N->n4			=	BuildNode(N->Pos,Pos,false);
        }
    	if (bFromSelectedOnly){
	        // select neighbour nodes
            if (N->n1) N->n1->flags.set(SAINode::flSelected,TRUE);
            if (N->n2) N->n2->flags.set(SAINode::flSelected,TRUE);
            if (N->n3) N->n3->flags.set(SAINode::flSelected,TRUE);
            if (N->n4) N->n4->flags.set(SAINode::flSelected,TRUE);
        }
        
        if (k%512==0) {
            float	p1	= float(k)/float(m_Nodes.size());
            float	p2	= float(m_Nodes.size())/estimated_nodes;
            float	p	= 0.1f*p1+0.9f*p2;

            clamp	(p,0.f,1.f);
            pb->Update(p);
            // check need abort && redraw
            if (k%32768==0) UI->RedrawScene(true);
            if (UI->NeedAbort()) break;
        }
    }
    UI->ProgressEnd(pb);
}
Пример #2
0
void ESceneAIMapTool::SmoothNodes()
{
    SPBItem* pb = UI->ProgressStart(m_Nodes.size(), "Smoothing nodes...");

	AINodeVec	smoothed;	smoothed.reserve(m_Nodes.size());
	U8Vec		mark;		mark.assign		(m_Nodes.size(),0);

    int	sm_nodes=0;
    
    EnumerateNodes			();
	for (AINodeIt it=m_Nodes.begin(); it!=m_Nodes.end(); it++){
		SAINode& 	N 		= **it;
        Fvector		P1,P2,P3,P4,P,REF;
        int			c;

		if (N.flags.is(SAINode::flSelected)){
        	sm_nodes++;
        
            // smooth point LF
            {
                bool	bCorner	= false;

                c=1;	N.PointLF(REF,m_Params.fPatchSize);	P1.set(REF);
                if (N.nLeft()) {
                    SAINode& L = *N.nLeft();

                    L.PointFR(P,m_Params.fPatchSize);	merge(P1);
                    if (L.nForward()) {
                        bCorner = true;
                        SAINode& C = *L.nForward();

                        C.PointRB(P,m_Params.fPatchSize);	merge(P1);
                    }
                }
                if (N.nForward()) {
                    SAINode& F = *N.nForward();

                    F.PointBL(P,m_Params.fPatchSize);	merge(P1);
                    if ((!bCorner) && F.nLeft()) {
                        bCorner = true;

                        SAINode& C = *F.nLeft();
                        C.PointRB(P,m_Params.fPatchSize);	merge(P1);
                    }
                }
                R_ASSERT(c<=4);
                P1.div(float(c));
            }

            // smooth point FR
            {
                bool	bCorner = false;

                c=1;	N.PointFR(REF,m_Params.fPatchSize); P2.set(REF);
                if (N.nForward()) {
                    SAINode& F = *N.nForward();

                    F.PointRB(P,m_Params.fPatchSize);	merge(P2);
                    if (F.nRight()) {
                        bCorner = true;
                        SAINode& C = *F.nRight();

                        C.PointBL(P,m_Params.fPatchSize);	merge(P2);
                    }
                }
                if (N.nRight()) {
                    SAINode& R = *N.nRight();

                    R.PointLF(P,m_Params.fPatchSize);	merge(P2);
                    if ((!bCorner) && R.nForward()) {
                        bCorner = true;

                        SAINode& C = *R.nForward();
                        C.PointBL(P,m_Params.fPatchSize);	merge(P2);
                    }
                }
                R_ASSERT(c<=4);
                P2.div(float(c));
            }

            // smooth point RB
            {
                bool	bCorner = false;

                c=1;	N.PointRB(REF,m_Params.fPatchSize); P3.set(REF);
                if (N.nRight()) {
                    SAINode& R = *N.nRight();

                    R.PointBL(P,m_Params.fPatchSize);	merge(P3);
                    if (R.nBack()) {
                        bCorner = true;
                        SAINode& C = *R.nBack();

                        C.PointLF(P,m_Params.fPatchSize);	merge(P3);
                    }
                }
                if (N.nBack()) {
                    SAINode& B = *N.nBack();

                    B.PointFR(P,m_Params.fPatchSize);	merge(P3);
                    if ((!bCorner) && B.nRight()) {
                        bCorner = true;

                        SAINode& C = *B.nRight();
                        C.PointLF(P,m_Params.fPatchSize);	merge(P3);
                    }
                }
                R_ASSERT(c<=4);
                P3.div(float(c));
            }

            // smooth point BL
            {
                bool	bCorner = false;

                c=1;	N.PointBL(REF,m_Params.fPatchSize); P4.set(REF);
                if (N.nBack()) {
                    SAINode& B = *N.nBack();

                    B.PointLF(P,m_Params.fPatchSize);	merge(P4);
                    if (B.nLeft()) {
                        bCorner = true;
                        SAINode& C = *B.nLeft();

                        C.PointFR(P,m_Params.fPatchSize);	merge(P4);
                    }
                }
                if (N.nLeft()) {
                    SAINode& L = *N.nLeft();

                    L.PointRB(P,m_Params.fPatchSize);	merge(P4);
                    if ((!bCorner) && L.nBack()) {
                        bCorner = true;

                        SAINode& C = *L.nBack();
                        C.PointFR(P,m_Params.fPatchSize);	merge(P4);
                    }
                }
                R_ASSERT(c<=4);
                P4.div(float(c));
            }

            // align plane
            Fvector data[4]; data[0]=P1; data[1]=P2; data[2]=P3; data[3]=P4;
            Fvector vOffs,vNorm,D;
            vNorm.set(N.Plane.n);
            vOffs.set(N.Pos);
            Mgc::OrthogonalPlaneFit(
                4,(Mgc::Vector3*)data,
                *((Mgc::Vector3*)&vOffs),
                *((Mgc::Vector3*)&vNorm)
            );
            if (vNorm.y<0) vNorm.invert();
            // create _new node
            SAINode* NEW 	= xr_new<SAINode>(N);
            NEW->n1 		= (SAINode*)(N.n1?N.n1->idx:InvalidNode);
            NEW->n2 		= (SAINode*)(N.n2?N.n2->idx:InvalidNode);
            NEW->n3 		= (SAINode*)(N.n3?N.n3->idx:InvalidNode);
            NEW->n4 		= (SAINode*)(N.n4?N.n4->idx:InvalidNode);
            NEW->Plane.build(vOffs,vNorm);
            D.set			(0,1,0);
            N.Plane.intersectRayPoint(N.Pos,D,NEW->Pos);	// "project" position
            smoothed.push_back	(NEW);
        }else{
            // create _new node
            SAINode* NEW 	= xr_new<SAINode>(N);
            NEW->n1 		= (SAINode*)(N.n1?N.n1->idx:InvalidNode);
            NEW->n2 		= (SAINode*)(N.n2?N.n2->idx:InvalidNode);
            NEW->n3 		= (SAINode*)(N.n3?N.n3->idx:InvalidNode);
            NEW->n4 		= (SAINode*)(N.n4?N.n4->idx:InvalidNode);
            smoothed.push_back	(NEW);
        }

        int k = it-m_Nodes.begin();
        if (k%128==0) {
            pb->Update(k);
            if (UI->NeedAbort()) break;
        }
    }
    UI->ProgressEnd(pb);
    Clear				(true);
    m_Nodes 			= smoothed;
	DenumerateNodes		();
    hash_FillFromNodes	();

    UpdateHLSelected	();
    
	if (sm_nodes) 		Scene->UndoSave();
}
Пример #3
0
int ESceneAIMapTool::BuildNodes(const Fvector& pos, int sz, bool bIC)
{
    // Align emitter
    Fvector			Pos = pos;
    SnapXZ			(Pos,m_Params.fPatchSize);
    Pos.y			+= 1;
    Fvector			Dir; Dir.set(0,-1,0);

	int cnt			= 0;		
    if (m_CFModel)
    	cnt=Scene->RayQuery(PQ,Pos,Dir,3,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,m_CFModel);
    else
    	cnt=Scene->RayQuery(PQ,Pos,Dir,3,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,GetSnapList());

    if (0==cnt) {
        ELog.Msg	(mtInformation,"Can't align position.");
        return		0;
    } else {
        Pos.y 		= Pos.y - PQ.r_begin()->range;
    }
		
    // Build first node
    int oldcount 	= m_Nodes.size();
    SAINode* start 	= BuildNode(Pos,Pos,bIC);
    if (!start)		return 0;

    // Estimate nodes
    float estimated_nodes	= (2*sz-1)*(2*sz-1);

	SPBItem* pb 	= 0;
    if (estimated_nodes>1024) pb = UI->ProgressStart(1, "Building nodes...");
    float radius			= sz*m_Params.fPatchSize-EPS_L;
    // General cycle
    for (int k=0; k<(int)m_Nodes.size(); k++){
        SAINode* N 			= m_Nodes[k];
        // left 
        if (0==N->n1){
            Pos.set			(N->Pos);
            Pos.x			-=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n1		=	BuildNode(N->Pos,Pos,bIC);
        }
        // fwd
        if (0==N->n2){
            Pos.set			(N->Pos);
            Pos.z			+=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n2		=	BuildNode(N->Pos,Pos,bIC);
        }
        // right
        if (0==N->n3){
            Pos.set			(N->Pos);
            Pos.x			+=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n3		=	BuildNode(N->Pos,Pos,bIC);
        }
        // back
        if (0==N->n4){
            Pos.set			(N->Pos);
            Pos.z			-=	m_Params.fPatchSize;
            if (Pos.distance_to(start->Pos)<=radius)
	            N->n4		=	BuildNode(N->Pos,Pos,bIC);
        }
        if (estimated_nodes>1024){
            if (k%128==0) {
                float	p1	= float(k)/float(m_Nodes.size());
                float	p2	= float(m_Nodes.size())/estimated_nodes;
                float	p	= 0.1f*p1+0.9f*p2;

                clamp	(p,0.f,1.f);
                pb->Update(p);
                // check need abort && redraw
                if (UI->NeedAbort()) break;
            }
        }
    }
	if (estimated_nodes>1024) UI->ProgressEnd(pb);
    return oldcount-m_Nodes.size();
}