void RenderVisTreeClass::initialize_render_tree()
{
	// LP change: using growable list
	Nodes.clear();
	node_data Dummy;
	Dummy.flags = 0;				// Fake initialization to shut up CW
	Nodes.push_back(Dummy);
	INITIALIZE_NODE(&Nodes.front(), view->origin_polygon_index, 0, NULL, NULL);
}
예제 #2
0
int8_t
push_front_DequeList(DequeList *deque, void *obj, size_t objsize, int flag) {
  Node *tmp;

  CHECK_VARN(deque, EINVAL);
  CHECK_VARN(obj, EINVAL);
  CHECK_OBJSIZE(deque,objsize,EINVAL);

  INITIALIZE_NODE(tmp,deque,obj,flag);

  if (!S(deque)) {
    H(deque) = T(deque) = tmp;
    S(deque)++;
  } else {
    ADD_FRONT(tmp, deque);
  }

  return SUCCESS;
allocobjfail:
  ADD_FREE_NODE(deque,tmp);
allocfail:
  return -EALLOCF;
}
예제 #3
0
int8_t
push_StackList(StackList * stack, void *obj, size_t objsize, int8_t flag)
{
  Node *tmp;

  CHECK_VARN(stack, EINVAL);
  CHECK_VARN(obj, EINVAL);
  CHECK_OBJSIZE(stack,objsize,EINVAL);

  INITIALIZE_NODE(tmp,stack,obj,flag);

  if (!S(stack)) {
    H(stack) = T(stack) = tmp;
    S(stack)++;
  } else {
    ADD_BACK(tmp, stack);
  }
  return SUCCESS;
allocobjfail:
  ADD_FREE_NODE(stack,tmp);
allocfail:
  return EALLOCF;
}
예제 #4
0
void *
insert_BinaryTree(BinaryTree * tree, void *obj, size_t objsize, int flag)
{
  Node *ptr = NULL, *tmp = NULL;
  int res = 0;
  CHECK_VARN(tree,NULL);
  CHECK_VARN(obj,NULL);
  CHECK_OBJSIZE(tree, objsize,NULL);
  INITIALIZE_NODE(tmp,tree,obj,flag);

  if(!S(tree)) {
	  H(tree) = tmp;
	  tmp->ptr[PARENT] = NULL;
	  S(tree)++;
  } else {
	  ptr = H(tree);
	  TRAVERSE_TREE(ptr,tree,tmp->objptr,res,objsize);
	  if(res < 0) {
		  if(ptr->ptr[RIGHT] == T(tree)) {
			  T(tree) = tmp;
		  }
		  INSERT_RIGHT(ptr,tmp);
	  } else if(res > 0) {
		  INSERT_LEFT(ptr,tmp);
	  } else {
		  DELETE_OBJPTR(tree,tmp);
		  ADD_FREE_NODE(tree,tmp);
	  }
  }
  return tmp;
allocobjfail:
  ADD_FREE_NODE(tree,tmp);
allocfail:
  ALLOCFAIL(object);
  return NULL;
}
예제 #5
0
// LP change: make it better able to do long-distance views
// Using parent index instead of pointer to avoid stale-pointer bug
void RenderVisTreeClass::cast_render_ray(long_vector2d *_vector, int16 endpoint_index,
	node_data* parent, int16 bias) /* _clockwise or _counterclockwise for walking endpoints */
{
	auto polygon_index = parent->polygon_index;

	do
	{
		auto clipping_endpoint_index = endpoint_index;
		int16 clipping_line_index;
		auto clip_flags = next_polygon_along_line(&polygon_index,
		(world_point2d *) &view->origin, _vector, &clipping_endpoint_index, &clipping_line_index, bias);
		
		if (polygon_index == NONE)
		{
			if (clip_flags & _split_render_ray)
			{
				cast_render_ray( _vector, endpoint_index, parent, _clockwise_bias);
				cast_render_ray( _vector, endpoint_index, parent, _counterclockwise_bias);
			}
			continue;
		}
		
		node_data **node_reference, *node;
		
		/* find the old node referencing this polygon transition or build one */
		for( node_reference = &parent->children; *node_reference && (*node_reference)->polygon_index != polygon_index;
				node_reference = &(*node_reference)->siblings)
			;
		node = *node_reference;
		if (!node)
		{
			// LP change: using growable list
			// Contents get swapped when the length starts to exceed the capacity.
			// When they are not NULL,
			// "parent", "siblings" and "children" are pointers to members,
			// "reference" is a pointer to a member with an offset.
			// Cast the pointers to whatever size of integer the system uses.
			const size_t Length = Nodes.size();
			
			node_data Dummy;
			Dummy.flags = 0;				// Fake initialization to shut up CW
			Nodes.push_back(Dummy);
			node = &Nodes[Length];		// The length here is the "old" length
			
			*node_reference = node;
			INITIALIZE_NODE(node, polygon_index, 0, parent, node_reference);
			
			// Place new node in tree if it has gotten rooted
			if (Length > 0)
			{
				node_data *CurrNode = &Nodes.front();
			while(true)
			{
				const int32 PolyDiff = int32(polygon_index) - int32(CurrNode->polygon_index);
				if (PolyDiff > 0)
				{
					node_data *NextNode = CurrNode->PS_Greater;
					if (NextNode)
						// Advance
						CurrNode = NextNode;
					else
					{
						// Attach to end
						CurrNode->PS_Greater = node;
						break;
					}
				}
				else if (PolyDiff < 0)
				{
					node_data *NextNode = CurrNode->PS_Less;
					if (NextNode)
						// Advance
						CurrNode = NextNode;
					else
					{
						// Attach to end
						CurrNode->PS_Less = node;
						break;
					}
				}
				else // Equal
				{
					node_data *NextNode = CurrNode->PS_Shared;
					if (NextNode)
						// Splice node into shared-polygon chain
						node->PS_Shared = NextNode;
					CurrNode->PS_Shared = node;
					break;
				}
			}
			}
		}

		/* update the line clipping information, if necessary, for this node (don't add
			duplicates */
		if (clipping_line_index != NONE)
		{
			
			if (!TEST_RENDER_FLAG(clipping_line_index, _line_has_clip_data))
				calculate_line_clipping_information(clipping_line_index, clip_flags);
			clipping_line_index	= line_clip_indexes[clipping_line_index];
			
			ix i;
			const auto nodeClippingLineCount = node->clipping_line_count;
			
			for( i = 0; i < nodeClippingLineCount && node->clipping_lines[i] != clipping_line_index; ++i)
				;
			if (i == nodeClippingLineCount)
			{
				assert(node->clipping_line_count < MAXIMUM_CLIPPING_LINES_PER_NODE);
				node->clipping_lines[ node->clipping_line_count++ ] = clipping_line_index;
			}
		}
		
		/* update endpoint clipping information for this node if we have a valid endpoint with clip */
		if( !isNONE(clipping_endpoint_index) && clip_flags & ( _clip_left | _clip_right ) )
		{
			clipping_endpoint_index = calculate_endpoint_clipping_information(
				clipping_endpoint_index, clip_flags);
			
			// Be sure it's valid
			if (!isNONE(clipping_endpoint_index)  && node->clipping_endpoint_count < MAXIMUM_CLIPPING_ENDPOINTS_PER_NODE)
				node->clipping_endpoints[ node->clipping_endpoint_count++ ] = clipping_endpoint_index;
		}
		
		parent = node;
	
	}
	while (polygon_index != NONE);
}
// LP change: make it better able to do long-distance views
// Using parent index instead of pointer to avoid stale-pointer bug
void RenderVisTreeClass::cast_render_ray(
	long_vector2d *_vector, // world_vector2d *vector,
	short endpoint_index,
	int ParentIndex, /* 0==root */
	short bias) /* _clockwise or _counterclockwise for walking endpoints */
{
	// LP: keep the parent-node pointer and index in sync with each other:
	node_data *parent =  &Nodes.front() + ParentIndex;
	
	short polygon_index= parent->polygon_index;

//	dprintf("shooting at e#%d of p#%d", endpoint_index, polygon_index);
	
	do
	{
		short clipping_endpoint_index= endpoint_index;
		short clipping_line_index;
		uint16 clip_flags= next_polygon_along_line(&polygon_index, (world_point2d *) &view->origin, _vector, &clipping_endpoint_index, &clipping_line_index, bias);
		
		if (polygon_index==NONE)
		{
			if (clip_flags&_split_render_ray)
			{
				cast_render_ray(_vector, endpoint_index, ParentIndex, _clockwise_bias);
				cast_render_ray(_vector, endpoint_index, ParentIndex, _counterclockwise_bias);
				// LP: could have reallocated, so keep in sync!
				parent =  &Nodes.front() + ParentIndex;
			}
		}
		else
		{
			node_data **node_reference, *node;
			
			/* find the old node referencing this polygon transition or build one */
			for (node_reference= &parent->children;
					*node_reference && (*node_reference)->polygon_index!=polygon_index;
					node_reference= &(*node_reference)->siblings)
				;
			node= *node_reference;
			if (!node)
			{
				// LP change: using growable list
				// Contents get swapped when the length starts to exceed the capacity.
				// When they are not NULL,
				// "parent", "siblings" and "children" are pointers to members,
				// "reference" is a pointer to a member with an offset.
				// Cast the pointers to whatever size of integer the system uses.
				size_t Length = Nodes.size();
				POINTER_DATA OldNodePointer = POINTER_CAST(&Nodes.front());
				
				// Add a dummy object and check if the pointer got changed
				node_data Dummy;
				Dummy.flags = 0;				// Fake initialization to shut up CW
				Nodes.push_back(Dummy);
				POINTER_DATA NewNodePointer = POINTER_CAST(&Nodes.front());

				if (NewNodePointer != OldNodePointer)				
				{
					for (size_t k=0; k<Length; k++)
					{
						node_data &Node = Nodes[k];
						// If NULL, then these pointers were already copied.
						if (Node.parent)
							Node.parent = (node_data *)(NewNodePointer + (POINTER_CAST(Node.parent) - OldNodePointer));
						if (Node.reference)
							Node.reference = (node_data **)(NewNodePointer + (POINTER_CAST(Node.reference) - OldNodePointer));
						if (Node.siblings)
							Node.siblings = (node_data *)(NewNodePointer + (POINTER_CAST(Node.siblings) - OldNodePointer));
						if (Node.children)
							Node.children = (node_data *)(NewNodePointer + (POINTER_CAST(Node.children) - OldNodePointer));
						if (Node.PS_Greater)
							Node.PS_Greater = (node_data *)(NewNodePointer + (POINTER_CAST(Node.PS_Greater) - OldNodePointer));
						if (Node.PS_Less)
							Node.PS_Less = (node_data *)(NewNodePointer + (POINTER_CAST(Node.PS_Less) - OldNodePointer));
						if (Node.PS_Shared)
							Node.PS_Shared = (node_data *)(NewNodePointer + (POINTER_CAST(Node.PS_Shared) - OldNodePointer));
					}
					
					// Edit parent-node pointer also
					parent =  &Nodes.front() + ParentIndex;

					// CB: Find the node reference again, the old one may point to stale memory
					for (node_reference= &parent->children;
							*node_reference && (*node_reference)->polygon_index!=polygon_index;
							node_reference= &(*node_reference)->siblings)
						;
				}
				node = &Nodes[Length];		// The length here is the "old" length
				
				*node_reference= node;
				INITIALIZE_NODE(node, polygon_index, 0, parent, node_reference);
				
				// Place new node in tree if it has gotten rooted
				if (Length > 0)
				{
				node_data *CurrNode = &Nodes.front();
				while(true)
				{
					long PolyDiff = long(polygon_index) - long(CurrNode->polygon_index);
					if (PolyDiff > 0)
					{
						node_data *NextNode = CurrNode->PS_Greater;
						if (NextNode)
							// Advance
							CurrNode = NextNode;
						else
						{
							// Attach to end
							CurrNode->PS_Greater = node;
							break;
						}
					}
					else if (PolyDiff < 0)
					{
						node_data *NextNode = CurrNode->PS_Less;
						if (NextNode)
							// Advance
							CurrNode = NextNode;
						else
						{
							// Attach to end
							CurrNode->PS_Less = node;
							break;
						}
					}
					else // Equal
					{
						node_data *NextNode = CurrNode->PS_Shared;
						if (NextNode)
							// Splice node into shared-polygon chain
							node->PS_Shared = NextNode;
						CurrNode->PS_Shared = node;
						break;
					}
				}
				}
			}

			/* update the line clipping information, if necessary, for this node (donÕt add
				duplicates */
			if (clipping_line_index!=NONE)
			{
				short i;
				
				if (!TEST_RENDER_FLAG(clipping_line_index, _line_has_clip_data))
					calculate_line_clipping_information(clipping_line_index, clip_flags);
				clipping_line_index= line_clip_indexes[clipping_line_index];
				
				for (i=0;
						i<node->clipping_line_count&&node->clipping_lines[i]!=clipping_line_index;
						++i)
					;
				if (i==node->clipping_line_count)
				{
					assert(node->clipping_line_count<MAXIMUM_CLIPPING_LINES_PER_NODE);
					node->clipping_lines[node->clipping_line_count++]= clipping_line_index;
				}
			}
			
			/* update endpoint clipping information for this node if we have a valid endpoint with clip */
			if (clipping_endpoint_index!=NONE && (clip_flags&(_clip_left|_clip_right)))
			{
				clipping_endpoint_index= calculate_endpoint_clipping_information(clipping_endpoint_index, clip_flags);
				
				// Be sure it's valid
				if (clipping_endpoint_index != NONE)
				{
					if (node->clipping_endpoint_count<MAXIMUM_CLIPPING_ENDPOINTS_PER_NODE)
						node->clipping_endpoints[node->clipping_endpoint_count++]= clipping_endpoint_index;
				}
			}
			
			parent= node;
			// LP: keep in sync!
			ParentIndex = static_cast<int>(parent - &Nodes.front());
		}
	}
	while (polygon_index!=NONE);
}