Exemple #1
0
float Map::FindClosestZ(VERTEX p ) const
{
	// Unlike FindBestZ, this method finds the closest Z value above or below the specified point.
	//
	std::list<float> ZSet;

	NodeRef NodeR = SeekNode(MAP_ROOT_NODE, p.x, p.y);
	
	if( NodeR == NODE_NONE || NodeR >= m_Nodes)
		return 0;
		
	PNODE CurrentNode = &mNodes[NodeR];

	if(!(CurrentNode->flags & nodeFinal))
		return 0; 
		   
	VERTEX p1(p), p2(p), Result;

	p1.z = 999999;
	
	p2.z = BEST_Z_INVALID;

	const uint32 *CurrentFaceList = mFaceLists + CurrentNode->faces.offset;

	for(unsigned long i = 0; i < CurrentNode->faces.count; ++i)
	{
		if(*CurrentFaceList > m_Faces)
			continue;

		PFACE CurrentFace = &mFinalFaces[ *CurrentFaceList ];

		if(CurrentFace->nz > 0 && LineIntersectsFace(CurrentFace, p1, p2, &Result))
			ZSet.push_back(Result.z);
		
		CurrentFaceList++;

	}
	if(ZSet.size() == 0)
		return 0;

	if(ZSet.size() == 1)
		return ZSet.front();

	float ClosestZ = -999999;

	for(list<float>::iterator Iterator = ZSet.begin(); Iterator != ZSet.end(); ++Iterator)
	{
		if(ABS(p.z - (*Iterator)) < ABS(p.z - ClosestZ))
				ClosestZ = (*Iterator);
	}

	return ClosestZ;
}
Exemple #2
0
PNODE Map::SeekNode( PNODE _node, float x, float y )
{
	if( !_node ) return NULL;
	if( x>= _node->minx && x<= _node->maxx && y>= _node->miny && y<= _node->maxy )
	{
		if( _node->mask )
		{
			PNODE tmp;
			tmp = SeekNode( _node->node1, x, y );
			if( tmp ) return tmp;
			tmp = SeekNode( _node->node2, x, y );
			if( tmp ) return tmp;
			tmp = SeekNode( _node->node3, x, y );
			if( tmp ) return tmp;
			tmp = SeekNode( _node->node4, x, y );
			if( tmp ) return tmp;
		}
		else
			return _node;
	}
	return NULL;
}
Exemple #3
0
bool Map::LineIntersectsZoneNoZLeaps(VERTEX start, VERTEX end, float step_mag, VERTEX *result, FACE **on) {
	float z = -999999;
	VERTEX step;
	VERTEX cur;
	cur.x = start.x;
	cur.y = start.y;
	cur.z = start.z;
	
	step.x = end.x - start.x;
	step.y = end.y - start.y;
	step.z = end.z - start.z;
	float factor = step_mag / sqrt(step.x*step.x + step.y*step.y + step.z*step.z);

	step.x *= factor;
	step.y *= factor;
	step.z *= factor;

	int steps = 0;

	if (step.x > 0 && step.x < 0.001f)
		step.x = 0.001f;
	if (step.y > 0 && step.y < 0.001f)
		step.y = 0.001f;
	if (step.z > 0 && step.z < 0.001f)
		step.z = 0.001f;
	if (step.x < 0 && step.x > -0.001f)
		step.x = -0.001f;
	if (step.y < 0 && step.y > -0.001f)
		step.y = -0.001f;
	if (step.z < 0 && step.z > -0.001f)
		step.z = -0.001f;
	
	NodeRef cnode, lnode;
	lnode = 0;
	//while we are not past end
	//always do this once, even if start == end.
	while(cur.x != end.x || cur.y != end.y || cur.z != end.z)
	{
		steps++;
		cnode = SeekNode(GetRoot(), cur.x, cur.y);
		if (cnode == NODE_NONE)
		{
			return(true);
		}		
		VERTEX me;
		me.x = cur.x;
		me.y = cur.y;
		me.z = cur.z;
		VERTEX hit;
		FACE *onhit;
		float best_z = zone->zonemap->FindBestZ(cnode, me, &hit, &onhit);
		float diff = ABS(best_z-z);
//		diff *= sign(diff);
		if (z == -999999 || best_z == -999999 || diff < 12.0)
			z = best_z;
		else
			return(true);
		//look at current location
		if(cnode != NODE_NONE && cnode != lnode) {
			if(LineIntersectsNode(cnode, start, end, result, on))
			{
				return(true);
			}
			lnode = cnode;
		}
		
		//move 1 step
		if (cur.x != end.x)
			cur.x += step.x;
		if (cur.y != end.y)
			cur.y += step.y;
		if (cur.z != end.z)
			cur.z += step.z;
		
		//watch for end conditions
		if ( (cur.x > end.x && end.x >= start.x) || (cur.x < end.x && end.x <= start.x) || (step.x == 0) ) {
			cur.x = end.x;
		}
		if ( (cur.y > end.y && end.y >= start.y) || (cur.y < end.y && end.y <= start.y) || (step.y == 0) ) {
			cur.y = end.y;
		}
		if ( (cur.z > end.z && end.z >= start.z) || (cur.z < end.z && end.z < start.z) || (step.z == 0) ) {
			cur.z = end.z;
		}
	}
	
	//walked entire line and didnt run into anything...
	return(false);
}
Exemple #4
0
float Map::FindBestZ( NodeRef node_r, VERTEX p1, VERTEX *result, FACE **on) const {
	_ZP(Map_FindBestZ);

	p1.z += RuleI(Map, FindBestZHeightAdjust);

	if(RuleB(Map, UseClosestZ))
		return FindClosestZ(p1);

	if(node_r == GetRoot()) {
		node_r = SeekNode(node_r, p1.x, p1.y);
	}
	if( node_r == NODE_NONE || node_r >= m_Nodes) {
		return(BEST_Z_INVALID);
	}
	const PNODE _node = &mNodes[node_r];
	if(!(_node->flags & nodeFinal)) {
		return(BEST_Z_INVALID);   //not a final node... could find the proper node...
	}
	
	VERTEX tmp_result;	//dummy placeholder if they do not ask for a result.
	if(result == NULL)
		result = &tmp_result;
	
	VERTEX p2(p1);
	p2.z = BEST_Z_INVALID;
	
	float best_z = BEST_Z_INVALID;
	int zAttempt;

	unsigned long i;

	PFACE cur;

	// If we don't find a bestZ on the first attempt, we try again from a position CurrentZ + 10 higher
	// This is in case the pathing between waypoints temporarily sends the NPC below ground level.
	// 
	for(zAttempt=1; zAttempt<=2; zAttempt++) {

		const uint32 *cfl = mFaceLists + _node->faces.offset;

#ifdef DEBUG_BEST_Z
printf("Start finding best Z...\n");
#endif
		for(i = 0; i < _node->faces.count; i++) {
			if(*cfl > m_Faces)
		               continue;       //watch for invalid lists, they seem to happen, e.g. in eastwastes.map

			cur = &mFinalFaces[ *cfl ];
//printf("Intersecting with face %lu\n", *cfl);
			if(LineIntersectsFace(cur, p1, p2, result)) {
#ifdef DEBUG_BEST_Z
					printf("  %lu (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)\n",
					*cfl, cur->a.x, cur->a.y, cur->a.z,
					cur->b.x, cur->b.y, cur->b.z, 
					cur->c.x, cur->c.y, cur->c.z);
					printf("Found a z: %.2f\n", result->z);
#endif
				if (result->z > best_z) {
					if(on != NULL)
						*on = cur;
					best_z = result->z;
				}
			}
			cfl++;
		}

		if(best_z != BEST_Z_INVALID) return best_z;

		 p1.z = p1.z + 10 ;   // If we can't find a best Z, the NPC is probably just under the world. Try again from 10 units higher up.
	}

#ifdef DEBUG_BEST_Z
fflush(stdout);
printf("Best Z found: %.2f\n", best_z);
#endif
	return best_z;
}
Exemple #5
0
bool Map::LineIntersectsZone(VERTEX start, VERTEX end, float step_mag, VERTEX *result, FACE **on) const
{
	_ZP(Map_LineIntersectsZone);
	// Cast a ray from start to end, checking for collisions in each node between the two points.
	//
	float stepx, stepy, stepz, curx, cury, curz;

	curx = start.x;
	cury = start.y;
	curz = start.z;

	VERTEX cur = start;
		
	stepx = end.x - start.x;
	stepy = end.y - start.y;
	stepz = end.z - start.z;

	if((stepx == 0) && (stepy == 0) && (stepz == 0))
		return false;

	float factor =  sqrt(stepx*stepx + stepy*stepy + stepz*stepz);

	stepx = (stepx/factor)*step_mag;
	stepy = (stepy/factor)*step_mag;
	stepz = (stepz/factor)*step_mag;

	NodeRef cnode, lnode, finalnode;
	lnode = NODE_NONE;      //last node visited

	cnode = SeekNode(GetRoot(), start.x, start.y);
	finalnode = SeekNode(GetRoot(), end.x, end.y);
	if(cnode == finalnode)
		return LineIntersectsNode(cnode, start, end, result, on);

	do {

		stepx = (float)end.x - curx;
		stepy = (float)end.y - cury;
		stepz = (float)end.z - curz;

		factor =  sqrt(stepx*stepx + stepy*stepy + stepz*stepz);

		stepx = (stepx/factor)*step_mag;
		stepy = (stepy/factor)*step_mag;
		stepz = (stepz/factor)*step_mag;
			
	    	cnode = SeekNode(GetRoot(), curx, cury);
		if(cnode != lnode)
		{
 		    	lnode = cnode;

			if(cnode == NODE_NONE)
				return false;

			if(LineIntersectsNode(cnode, start, end, result, on))
       				return(true);
       	       		
			if(cnode == finalnode)
				return false;
		}
		curx += stepx;
		cury += stepy;
		curz += stepz;

		cur.x = curx;
		cur.y = cury;
		cur.z = curz;

		if(ABS(curx - end.x) < step_mag) cur.x = end.x;
		if(ABS(cury - end.y) < step_mag) cur.y = end.y;
		if(ABS(curz - end.z) < step_mag) cur.z = end.z;

	} while(cur.x != end.x || cur.y != end.y || cur.z != end.z);

	return false;
}
Exemple #6
0
NodeRef Map::SeekNode( NodeRef node_r, float x, float y ) const {
	if(node_r == NODE_NONE || node_r >= m_Nodes) {
		return(NODE_NONE);
	}
	PNODE _node = &mNodes[node_r];
#ifdef DEBUG_SEEK
printf("Seeking node for %u:(%.2f, %.2f) with root 0x%x.\n", node_r, x, y, _node);

printf("	Current Box: (%.2f -> %.2f, %.2f -> %.2f)\n", _node->minx, _node->maxx, _node->miny, _node->maxy);
#endif
	if( x>= _node->minx && x<= _node->maxx && y>= _node->miny && y<= _node->maxy ) {
		if( _node->flags & nodeFinal ) {
#ifdef DEBUG_SEEK
printf("Seeking node for %u:(%.2f, %.2f) with root 0x%x.\n", node_r, x, y, _node);
printf("	Final Node: (%.2f -> %.2f, %.2f -> %.2f)\n", _node->minx, _node->maxx, _node->miny, _node->maxy);
fflush(stdout);
printf("	Final node found with %d faces.\n", _node->faces.count);
/*printf("	Faces:\n");
unsigned long *cfl = mFaceLists + _node->faces.offset;
unsigned long m;
for(m = 0; m < _node->faces.count; m++) {
	FACE *c = &mFinalFaces[ *cfl ];
	printf("	%lu (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f) (%.2f, %.2f, %.2f)\n",
				*cfl, c->a.x, c->a.y, c->a.z,
				c->b.x, c->b.y, c->b.z, 
				c->c.x, c->c.y, c->c.z);
	cfl++;
}*/
#endif
			return node_r;
		}
#ifdef DEBUG_SEEK
printf("	Kids: %u, %u, %u, %u\n", _node->nodes[0], _node->nodes[1], _node->nodes[2], _node->nodes[3]);
		
printf("	Contained In Box: (%.2f -> %.2f, %.2f -> %.2f)\n", _node->minx, _node->maxx, _node->miny, _node->maxy);
		
/*printf("	Node found has children.\n");
if(_node->node1 != NULL) {
	printf("\tNode: (%.2f -> %.2f, %.2f -> %.2f)\n", 
		_node->node1->minx, _node->node1->maxx, _node->node1->miny, _node->node1->maxy);
}
if(_node->node2 != NULL) {
	printf("\tNode: (%.2f -> %.2f, %.2f -> %.2f)\n", 
		_node->node2->minx, _node->node2->maxx, _node->node2->miny, _node->node2->maxy);
}
if(_node->node3 != NULL) {
	printf("\tNode: (%.2f -> %.2f, %.2f -> %.2f)\n", 
		_node->node3->minx, _node->node3->maxx, _node->node3->miny, _node->node3->maxy);
}
if(_node->node4 != NULL) {
	printf("\tNode: (%.2f -> %.2f, %.2f -> %.2f)\n", 
		_node->node4->minx, _node->node4->maxx, _node->node4->miny, _node->node4->maxy);
}*/
#endif
		//NOTE: could precalc these and store them in node headers

		NodeRef tmp = NODE_NONE;
#ifdef OPTIMIZE_QT_LOOKUPS
		float midx = _node->minx + (_node->maxx - _node->minx) * 0.5;
		float midy = _node->miny + (_node->maxy - _node->miny) * 0.5;
		//follow ordering rules from map.h...
		if(x < midx) {
			if(y < midy) { //quad 3
				if(_node->nodes[2] != NODE_NONE && _node->nodes[2] != node_r)
					tmp = SeekNode( _node->nodes[2], x, y );
			} else {	//quad 2
				if(_node->nodes[2] != NODE_NONE && _node->nodes[1] != node_r)
					tmp = SeekNode( _node->nodes[1], x, y );
			}
		} else {
			if(y < midy) {  //quad 4
				if(_node->nodes[2] != NODE_NONE && _node->nodes[3] != node_r)
					tmp = SeekNode( _node->nodes[3], x, y );
			} else {	//quad 1
				if(_node->nodes[2] != NODE_NONE && _node->nodes[0] != node_r)
					tmp = SeekNode( _node->nodes[0], x, y );
			}
		}
		if( tmp != NODE_NONE ) return tmp;
#else
		if(_node->nodes[0] == node_r) return(NODE_NONE); 	//prevent infinite recursion
		tmp = SeekNode( _node->nodes[0], x, y );
		if( tmp != NODE_NONE ) return tmp;
		if(_node->nodes[1] == node_r) return(NODE_NONE); 	//prevent infinite recursion
		tmp = SeekNode( _node->nodes[1], x, y );
		if( tmp != NODE_NONE ) return tmp;
		if(_node->nodes[2] == node_r) return(NODE_NONE); 	//prevent infinite recursion
		tmp = SeekNode( _node->nodes[2], x, y );
		if( tmp != NODE_NONE ) return tmp;
		if(_node->nodes[3] == node_r) return(NODE_NONE); 	//prevent infinite recursion
		tmp = SeekNode( _node->nodes[3], x, y );
		if( tmp != NODE_NONE ) return tmp;
#endif

	}
#ifdef DEBUG_SEEK
printf(" No node found.\n");
#endif
	return(NODE_NONE);
}