Example #1
0
int AStar(){
  int i;
  double tftheta, cost;
  double center_x1, center_y1, center_x2, center_y2;
  int grid_x, grid_y, grid_theta;
  int norm_x, norm_y, norm_theta;
  struct node_t temp;
  geometry_msgs::Pose pose, tfpose;
  
  // x1,y1: right circle
  CalcCenter(&center_x1, &center_y1, &center_x2, &center_y2);


  Astar_count++;
  //std::cout << Astar_count << std::endl;
  //std::cout << "openlist size: " << openlist.size() << std::endl;
  

  /* calculate tf point */
  tftheta = current_theta - origin_yaw;
  tftheta = ChangeTheta(tftheta);
  current_theta = ChangeTheta(current_theta);
  //if (tftheta < 0 || tftheta >= 2*M_PI) {std::cout << "ERROR!!" << std::endl;}
  tfpose.position.x = current_x; tfpose.position.y = current_y; tfpose.position.z = 0.0;
  tf::Vector3 tfpoint = TransformPoint(tfpose);

  /* current grid cell */
  norm_x = (int)(tfpoint.getX()*10); norm_y = (int)(tfpoint.getY()*10);
  norm_theta = (int)(tftheta/THETA);

  /// skip closed?
  //if (map[norm_y][norm_x].status == CLOSED){
  //  openlist.pop();
  //  if(openlist.empty()) {return 1;}
  //  temp = openlist.top();
  //  x = temp.x;  y = temp.y;  theta = temp.theta;
  //  return -1;
  //}
  ///

  map[norm_y][norm_x][norm_theta].status = CLOSED;
  //closelist.push_back(openlist.top()); //is this necessary?
  openlist.pop();


  /* for visualization */
  //posestamped.header.frame_id = PATH_FRAME;
  tf::Quaternion quat;
  quat.setEuler(0.0,0.0,map[norm_y][norm_x][norm_theta].theta);//setEulerZYX?
  pose.orientation.x = quat.getX();
  pose.orientation.y = quat.getY();
  pose.orientation.z = quat.getZ();
  pose.orientation.w = quat.getW();
  pose.position.x = map[norm_y][norm_x][norm_theta].x;
  pose.position.y = map[norm_y][norm_x][norm_theta].y;
  pose.position.z = 0.0;
  //posestamped.orientation.w = 1.0;
  plan_poses.poses.push_back(pose);
  ///////////


  // search for 6 states //
  for (i = 0; i < 6; i++){
    switch (i){
    case 0:// forward //
      //continue;
      if (map[norm_y][norm_x][norm_theta].steering == 1) {continue;}
      temp.x = current_x + ARC*cos(current_theta);
      temp.y = current_y + ARC*sin(current_theta);
      temp.theta = current_theta;
      cost = ARC*W_STRAIGHT;
      break;
    case 1:// backward //
      //continue;
      if (map[norm_y][norm_x][norm_theta].steering == 0) {continue;}
      temp.x = current_x + ARC*cos(current_theta+M_PI);
      temp.y = current_y + ARC*sin(current_theta+M_PI);
      temp.theta = current_theta;
      cost = ARC*W_STRAIGHT;
      break;
    case 2:// left forward //
      //continue;
      if (map[norm_y][norm_x][norm_theta].steering == 3 ||
	  map[norm_y][norm_x][norm_theta].steering == 4) {continue;}
      temp.x = (ARC/THETA)*cos(current_theta + 3*M_PI/2 + THETA) + center_x2;
      temp.y = (ARC/THETA)*sin(current_theta + 3*M_PI/2 + THETA) + center_y2;
      temp.theta = current_theta + THETA;
      cost = ARC*W_CURVE;
      break;
    case 3:// left backward //
      //continue;
      if (map[norm_y][norm_x][norm_theta].steering == 2 ||
	  map[norm_y][norm_x][norm_theta].steering == 5) {continue;}
      temp.x = (ARC/THETA)*cos(current_theta + 3*M_PI/2 - THETA) + center_x2;
      temp.y = (ARC/THETA)*sin(current_theta + 3*M_PI/2 - THETA) + center_y2;
      temp.theta = current_theta - THETA;
      cost = ARC*W_CURVE;
      break;
    case 4:// right forward //
      //continue;
      if (map[norm_y][norm_x][norm_theta].steering == 5 ||
	  map[norm_y][norm_x][norm_theta].steering == 2) {continue;}
      temp.x = (ARC/THETA)*cos(current_theta + M_PI/2 - THETA) + center_x1;
      temp.y = (ARC/THETA)*sin(current_theta + M_PI/2 - THETA) + center_y1;
      temp.theta = current_theta - THETA;
      cost = ARC*W_CURVE;
      break;
    case 5:// right backward //
      //continue;
      if (map[norm_y][norm_x][norm_theta].steering == 4 ||
	  map[norm_y][norm_x][norm_theta].steering == 3) {continue;}
      temp.x = (ARC/THETA)*cos(current_theta + M_PI/2 + THETA) + center_x1;
      temp.y = (ARC/THETA)*sin(current_theta + M_PI/2 + THETA) + center_y1;
      temp.theta = current_theta + THETA;
      cost = ARC*W_CURVE;
      break;
    }


    // calculate grid cell in each state
    tftheta = temp.theta - origin_yaw;
    tftheta = ChangeTheta(tftheta);
    if (tftheta < 0 || tftheta >= 2*M_PI) {std::cout << "ERROR!!" << std::endl;}///
    tfpose.position.x = temp.x; tfpose.position.y = temp.y; tfpose.position.z = 0.0;
    tfpoint = TransformPoint(tfpose);

    grid_x = (int)(tfpoint.getX()*10); grid_y = (int)(tfpoint.getY()*10);
    grid_theta = (int)(tftheta/THETA);

    /* process for Astar search */
    if (grid_x < 0 || grid_x >= SIZE_X ||
	grid_y < 0 || grid_y >= SIZE_Y){
      continue;
    } else if(Collide(tfpoint.getX(), tfpoint.getY(), tftheta)){
      continue;
    } else if (map[grid_y][grid_x][grid_theta].goal &&
	       GoalAngle(temp.theta)){ //current node is GOAL
      std::cout << Astar_count << std::endl;
      map[grid_y][grid_x][grid_theta].x = temp.x;
      map[grid_y][grid_x][grid_theta].y = temp.y;
      map[grid_y][grid_x][grid_theta].theta = temp.theta;
      map[grid_y][grid_x][grid_theta].parent = &map[norm_y][norm_x][norm_theta];
      map[grid_y][grid_x][grid_theta].steering = i;
      gx = grid_x;  gy = grid_y;
      gtheta = grid_theta;
      return 0;
    } else if (map[grid_y][grid_x][grid_theta].status == OPEN){
      if (map[norm_y][norm_x][norm_theta].gc+cost < 
	  map[grid_y][grid_x][grid_theta].gc){
	map[grid_y][grid_x][grid_theta].x = temp.x;
	map[grid_y][grid_x][grid_theta].y = temp.y;
	map[grid_y][grid_x][grid_theta].theta = temp.theta;
	map[grid_y][grid_x][grid_theta].gc = map[norm_y][norm_x][norm_theta].gc+cost;
	//map[grid_y][grid_x][grid_theta].hc = W_HC * hypot(dgx-temp.x, dgy-temp.y);
	map[grid_y][grid_x][grid_theta].parent = &map[norm_y][norm_x][norm_theta];
	map[grid_y][grid_x][grid_theta].steering = i;
	openlist.push(map[grid_y][grid_x][grid_theta]); // can't erase old node?
      }
    } else if (map[grid_y][grid_x][grid_theta].status == CLOSED){
      if (map[norm_y][norm_x][norm_theta].gc+cost < 
	  map[grid_y][grid_x][grid_theta].gc){
	map[grid_y][grid_x][grid_theta].x = temp.x;
	map[grid_y][grid_x][grid_theta].y = temp.y;
	map[grid_y][grid_x][grid_theta].theta = temp.theta;
	map[grid_y][grid_x][grid_theta].gc = map[norm_y][norm_x][norm_theta].gc+cost;
	//map[grid_y][grid_x][grid_theta].hc = W_HC * hypot(dgx-temp.x, dgy-temp.y);
	map[grid_y][grid_x][grid_theta].parent = &map[norm_y][norm_x][norm_theta];
	map[grid_y][grid_x][grid_theta].steering = i;
	openlist.push(map[grid_y][grid_x][grid_theta]);
      }
    } else {
      map[grid_y][grid_x][grid_theta].x = temp.x; 
      map[grid_y][grid_x][grid_theta].y = temp.y;
      map[grid_y][grid_x][grid_theta].theta = temp.theta;
      map[grid_y][grid_x][grid_theta].status = OPEN;
      map[grid_y][grid_x][grid_theta].gc = map[norm_y][norm_x][norm_theta].gc+cost;
      //map[grid_y][grid_x][grid_theta].hc = W_HC * hypot(dgx-temp.x, dgy-temp.y);
      map[grid_y][grid_x][grid_theta].parent = &map[norm_y][norm_x][norm_theta];
      map[grid_y][grid_x][grid_theta].steering = i;
      openlist.push(map[grid_y][grid_x][grid_theta]);
    }

    //std::cout << "openlist size: " << openlist.size() << std::endl;
  }


  // if opnelist is empty, failed
  if (openlist.empty()){
    std::cout << "EMPTY!!" << std::endl;
    return 1;
  }


  // set next start point
  temp = openlist.top();
  current_x = temp.x;  current_y = temp.y;
  current_theta = temp.theta;

  // terminate search
  if (Astar_count == SEARCH_LIMIT)
    return 1;

  return -1;//for loop

}
Example #2
0
bool CMine::CalcDeltaLights (double fLightScale, int force, int recursion_depth) 
{
	// initialize totals
CDSegment *srcseg, *childseg;
int source_segnum, child_segnum;
double effect[4];

GameInfo ().delta_lights.count = 0;
GameInfo ().dl_indices.count = 0;
bool bWall, bD2XLights = (level_version >= 15) && (GameInfo ().fileinfo_version >= 34);

fLightScale = 1.0; ///= 100.0;
for (source_segnum = 0, srcseg = Segments (); 
	  source_segnum < SegCount (); 
	  source_segnum++, srcseg++) {
	// skip if not marked unless we are automatically saving
	if  (!(srcseg->wall_bitmask & MARKED_MASK) && !force) 
		continue;
	// loop on all sides
	int source_sidenum;
	for (source_sidenum = 0; source_sidenum < 6; source_sidenum++) {
		INT16 tmapnum = srcseg->sides [source_sidenum].nBaseTex & 0x3fff;
		INT16 tmapnum2 = srcseg->sides [source_sidenum].nOvlTex & 0x3fff;
		INT16 trignum;
		bool bl1 = (bool) (IsLight (tmapnum) != -1);
		bool bl2 = (bool) (IsLight (tmapnum2) != -1);
		if (!(bl1 || bl2))
			continue;	// no lights on this side
		bool bCalcDeltas = false;
		// if the current side is a wall and has a light and is the target of a trigger
		// than can make the wall appear/disappear, calculate delta lights for it
		if ((bWall = (FindWall (source_segnum, source_sidenum) != NULL)) &&
			 ((trignum = FindTriggerTarget (0, source_segnum, source_sidenum)) >= 0)) {
			INT8 trigtype = Triggers (trignum)->type;
			bCalcDeltas =
				(trigtype == TT_ILLUSION_OFF) ||
				(trigtype == TT_ILLUSION_ON) ||
				(trigtype == TT_CLOSE_WALL) ||
				(trigtype == TT_OPEN_WALL) ||
				(trigtype == TT_LIGHT_OFF) ||
				(trigtype == TT_LIGHT_ON);
				 
			}
		if (!bCalcDeltas)
			bCalcDeltas = IsFlickeringLight (source_segnum, source_sidenum);
		if (!bCalcDeltas) {
			bool bb1 = IsBlastableLight (tmapnum);
			bool bb2 = IsBlastableLight (tmapnum2);
			if (bb1 == bb2)
				bCalcDeltas = bb1;	// both lights blastable or not
			else if (!(bb1 ? bl2 : bl1))	// i.e. one light blastable and the other texture not a non-blastable light 
				bCalcDeltas = true;
			}
		if (!bCalcDeltas) {	//check if light is target of a "light on/off" trigger
			int trignum = FindTriggerTarget (0, source_segnum, source_sidenum);
			if ((trignum >= 0) && (Triggers (trignum)->type >= TT_LIGHT_OFF))
				bCalcDeltas = true;
			}
		if (!bCalcDeltas)
			continue;
		// only set lights for textures which have a nOvlTex
		//if (tmapnum2 == 0)
		//	continue;

		INT16 srcwall = srcseg->sides [source_sidenum].nWall;
		if ((srcseg->children [source_sidenum] != -1) &&
			 ((srcwall >= GameInfo ().walls.count) || (Walls (srcwall)->type == WALL_OPEN)))
			continue;

//		if ((IsLight (tmapnum) == -1) && (IsLight (tmapnum2) == -1))
//			continue;
		if (GameInfo ().dl_indices.count >= MAX_DL_INDICES) {
			char szMsg [256];
			sprintf (szMsg, " Light tool: Too many dynamic lights at render depth %d", recursion_depth);
			DEBUGMSG (szMsg);
			return false;
			}

		vms_vector A,source_center;

		// get index number and increment total number of dl_indices
		int dl_index_num = (int)GameInfo ().dl_indices.count++;
		dl_index *pdli = DLIndex (dl_index_num);
		if (bD2XLights) {
			pdli->d2x.segnum = source_segnum;
			pdli->d2x.sidenum = source_sidenum;
			pdli->d2x.count = 0; // will be incremented below
			}
		else {
			pdli->d2.segnum = source_segnum;
			pdli->d2.sidenum = source_sidenum;
			pdli->d2.count = 0; // will be incremented below
			}
		pdli->d2.index = (INT16)GameInfo ().delta_lights.count;

		// find orthogonal angle of source segment
		CalcOrthoVector(A,source_segnum,source_sidenum);
		// remember to flip the sign since we want it to point inward
		A.x = -A.x;
		A.y = -A.y;
		A.z = -A.z;

		// calculate the center of the source segment
		CalcCenter(source_center,source_segnum,source_sidenum);

		// mark those Segments () within N children of current cube
		//(note: this is done once per light instead of once per segment
		//       even though some Segments () have multiple lights.
		//       This actually reduces the number of calls since most
		//       Segments () do not have lights)

		int h;
		for (h = 0; h < SegCount (); h++)
			Segments (h)->seg_number = -1;
		SetSegmentChildNum (srcseg, source_segnum, recursion_depth);
		srcseg->seg_number = recursion_depth;

		// setup source corner vertex for length calculation later
		vms_vector source_corner[4];
		int j;
		for (j = 0; j < 4; j++) {
			UINT8 vertnum = side_vert[source_sidenum][j];
			int h = srcseg->verts[vertnum];
			source_corner[j].x = Vertices (h)->x;
			source_corner[j].y = Vertices (h)->y;
			source_corner[j].z = Vertices (h)->z;
			}

		// loop on child Segments ()
		for (child_segnum = 0, childseg = Segments ();
			  child_segnum < SegCount ();
			  child_segnum++, childseg++) {
			if (childseg->seg_number < 0)
				continue;
			// loop on child sides
			int child_sidenum;
			for (child_sidenum = 0; child_sidenum < 6; child_sidenum++) {
				// if texture has a child..
#ifdef _DEBUG
			CBRK (source_segnum == 6 && source_sidenum == 2 &&
				child_segnum == 10 && child_sidenum == 1);
#endif
				if (childseg->children[child_sidenum] >= 0) {
					UINT16 nWall = childseg->sides[child_sidenum].nWall;
					// .. if there is no wall ..
					if (nWall >= GameInfo ().walls.count)
						continue;
					// .. or its not a door ..
					if (Walls (nWall)->type == WALL_OPEN) 
						continue; // don't put light because there is no texture here
					}
				// don't affect non-flickering light emitting textures (e.g. lava)
				tmapnum = childseg->sides [child_sidenum].nBaseTex;
				tmapnum2 = childseg->sides [child_sidenum].nOvlTex & 0x3fff;
				if (m_nNoLightDeltas == 1) {
					if (((IsLight (tmapnum) >= 0) || (IsLight (tmapnum2) >= 0))
						 && !IsFlickeringLight (child_segnum, child_sidenum))
						continue;
					}
				else if ((m_nNoLightDeltas == 2) && (IsLava (tmapnum) || IsLava (tmapnum2)))
					continue;
				// if the child side is the same as the source side, then set light and continue
				if (child_sidenum == source_sidenum && child_segnum == source_segnum) {
					if ((GameInfo ().delta_lights.count >= MAX_DELTA_LIGHTS) || 
						 (bD2XLights ? pdli->d2x.count == 8191 : pdli->d2.count == 255)) {
						char szMsg [256];
						sprintf (szMsg, " Light tool: Too many dynamic lights at render depth %d", recursion_depth);
						DEBUGMSG (szMsg);
						return false;
						}
					delta_light *dl = DeltaLights (GameInfo ().delta_lights.count++);
					dl->segnum = child_segnum;
					dl->sidenum = child_sidenum;
					dl->dummy = 0;
					dl->vert_light [0] =
					dl->vert_light [1] =
					dl->vert_light [2] =
					dl->vert_light [3] = (UINT8) min (32, 32 * fLightScale);
					if (bD2XLights)
						pdli->d2x.count++;
					else
						pdli->d2.count++;
					continue;
					}

				// calculate vector between center of source segment and center of child
#ifdef _DEBUG
					CBRK (child_segnum == qqq1 && child_sidenum == qqq2);
#endif
					if (CalcSideLights (child_segnum, child_sidenum, source_center, source_corner, A, effect, fLightScale, bWall)) {
						theApp.SetModified (TRUE);
						if ((GameInfo ().delta_lights.count >= MAX_DELTA_LIGHTS) || 
							 (bD2XLights ? pdli->d2x.count == 8191 : pdli->d2.count == 255)) {
							char szMsg [256];
							sprintf (szMsg, " Light tool: Too many dynamic lights at render depth %d", recursion_depth);
							DEBUGMSG (szMsg);
							return false;
							}
						delta_light *dl = DeltaLights (GameInfo ().delta_lights.count++);
						dl->segnum = child_segnum;
						dl->sidenum = child_sidenum;
						dl->dummy = 0;
						int iCorner;
						for (iCorner = 0; iCorner < 4; iCorner++)
							dl->vert_light [iCorner] = (UINT8) min(32, effect [iCorner]);
						if (bD2XLights)
							pdli->d2x.count++;
						else
							pdli->d2.count++;
						}
					}
				}
//			}
		}
	}
return true;
}
Example #3
0
bool CMine::CalcSideLights (int segnum, int sidenum, vms_vector& source_center, 
									 vms_vector *source_corner, vms_vector& A, double *effect,
									 double fLightScale, bool bIgnoreAngle)
{
	CDSegment *seg = Segments (segnum);
// calculate vector between center of source segment and center of child
vms_vector B,center;
CalcCenter (center,segnum,sidenum);
B.x = center.x - source_center.x;
B.y = center.y - source_center.y;
B.z = center.z - source_center.z;

// calculate angle between vectors (use dot product equation)
if (!bIgnoreAngle) {
	double ratio,angle;
	double A_dot_B = (double)A.x * (double)B.x
						+ (double)A.y * (double)B.y
						+ (double)A.z * (double)B.z;
	double mag_A = my_sqrt( (double)A.x*(double)A.x
						+(double)A.y*(double)A.y
						+(double)A.z*(double)A.z);
	double mag_B = my_sqrt( (double)B.x*(double)B.x
						+(double)B.y*(double)B.y
						+(double)B.z*(double)B.z);
	if (mag_A == 0 || mag_B == 0)
		angle = (200.0 * M_PI)/180.0; // force a failure
	else {
		ratio = A_dot_B/(mag_A * mag_B);
		ratio = ((double)((int)(ratio*1000.0))) / 1000.0;
		if (ratio < -1.0 || ratio > (double)1.0)
			angle = (199.0 * M_PI)/180.0;  // force a failure
		else
			angle = acos(ratio);
		}
	// if angle is less than 110 degrees
	// then we found a match
	if (angle >= (180.0 * M_PI)/180.0)
		return false;
	}
int i, j;
for (j = 0; j < 4; j++) {
	vms_vector corner;
	int vertnum = side_vert[sidenum][j];
	int h = seg->verts[vertnum];
	corner.x = Vertices (h)->x;
	corner.y = Vertices (h)->y;
	corner.z = Vertices (h)->z;
	double length = 20.0 * m_lightRenderDepth;
	for (i = 0; i < 4; i++)
		length = min (length, CalcLength (source_corner + i, &corner) / F1_0);
	length /= 10.0 * m_lightRenderDepth / 6.0; // divide by 1/2 a cubes length so opposite side
	// light is recuded by 1/4
	effect [j] = 32;
	if (length > 1.0)//if (length < 20.0 * m_lightRenderDepth) // (roughly 4 standard cube lengths)
		effect [j] /= (length * length);
	effect [j] *= fLightScale;
//	else
//		effect [j] = 0;
	}
// if any of the effects are > 0, then increment the
// light for that side
return (effect [0] != 0 || effect [1] != 0 || effect [2] != 0 || effect [3] != 0);
}
Example #4
0
void CMine::Illuminate (
	INT16 source_segnum, 
	INT16 source_sidenum, 
	UINT32 brightness, 
	double fLightScale, 
	bool bAll, bool 
	bCopyTexLights) 
{
CDSegment	*seg = Segments ();
CDSegment	*child_seg;
double		effect[4];
// find orthogonal angle of source segment
vms_vector A;

//fLightScale /= 100.0;
CalcOrthoVector (A,source_segnum,source_sidenum);
// remember to flip the sign since we want it to point inward
A.x = -A.x;
A.y = -A.y;
A.z = -A.z;

// calculate the center of the source segment
vms_vector source_center;
CalcCenter (source_center,source_segnum,source_sidenum);
if ((source_segnum == 911) && (source_sidenum == 3))
	A = A;
// mark those Segments () within N children of current cube

// set child numbers
//Segments ()[source_segnum].seg_number = m_lightRenderDepth;
int i;
for (i = SegCount (); i; i--, seg++)
	seg->seg_number = -1;
SetSegmentChildNum (NULL, source_segnum, m_lightRenderDepth);
CDColor *plc = LightColor (source_segnum, source_sidenum);
if (!plc->index) {
	plc->index = 255;
	plc->color.r =
	plc->color.g =
	plc->color.b = 1.0;
	}
if (UseTexColors () && bCopyTexLights) {
	CDColor	*psc = LightColor (source_segnum, source_sidenum, false);
	*psc = *plc;
	}
seg = Segments (source_segnum);
seg->seg_number = m_lightRenderDepth;
bool bWall = false; //FindWall (source_segnum, source_sidenum) != NULL;
// loop on child Segments ()
int child_segnum;
for (child_segnum=0, child_seg = Segments ();child_segnum<SegCount ();child_segnum++, child_seg++) {
	// skip if this is not viewable
	if (child_seg->seg_number < 0) 
		continue;
	// skip if not marked
//	if (!(bAll || (child_seg->wall_bitmask & MARKED_MASK)))
//		continue;
	// setup source corner vertex for length calculation later
	vms_vector source_corner[4];
	int j;
	for (j = 0; j < 4; j++) {
		int vertnum = side_vert [source_sidenum][j];
		int h = seg->verts [vertnum];
		source_corner[j].x = Vertices (h)->x;
		source_corner[j].y = Vertices (h)->y;
		source_corner[j].z = Vertices (h)->z;
		}
	// loop on child sides
	int child_sidenum;
	for (child_sidenum = 0; child_sidenum < 6; child_sidenum++) {
		// if side has a child..
		if (!(bAll || SideIsMarked (child_segnum, child_sidenum)))
			continue;
		if (child_seg->children[child_sidenum] >= 0) {
			UINT16 nWall = child_seg->sides[child_sidenum].nWall;
			// .. but there is no wall ..
			if (nWall >= GameInfo ().walls.count)
				continue;
				// .. or its not a door ..
			if (Walls (nWall)->type == WALL_OPEN)
				continue;
			}

//		CBRK (psc->index > 0);
		// if the child side is the same as the source side, then set light and continue
#ifdef _DEBUG
		CBRK (child_segnum == qqq1 && child_sidenum == qqq2);
#endif
		if (child_sidenum == source_sidenum && child_segnum == source_segnum) {
			uvl		*uvlP = child_seg->sides [child_sidenum].uvls;
			UINT32	vBr, lBr;

			theApp.SetModified (TRUE);
			int j;
			for (j = 0; j < 4; j++, uvlP++) {
				CDColor *pvc = VertexColors (child_seg->verts [side_vert [child_sidenum][j]]);
				vBr = (UINT16) uvlP->l;
				lBr = (UINT32) (brightness * fLightScale);
				BlendColors (plc, pvc, lBr, vBr);
				vBr += lBr;
				vBr = min (0x8000, vBr);
				uvlP->l = (UINT16) vBr;
				}
			continue;
			}

		// calculate vector between center of source segment and center of child
//		CBRK (child_segnum == 1 && child_sidenum == 2);
		if (CalcSideLights (child_segnum, child_sidenum, source_center, source_corner, A, effect, fLightScale, bWall)) {
				UINT32	vBr, lBr;	//vertex brightness, light brightness
				uvl		*uvlP = child_seg->sides [child_sidenum].uvls;

			theApp.SetModified (TRUE);
			int j;
			for (j = 0; j < 4; j++, uvlP++) {
				CDColor *pvc = VertexColors (child_seg->verts [side_vert [child_sidenum][j]]);
				if (child_seg->verts [side_vert [child_sidenum][j]] == 2368)
					j = j;
				vBr = (UINT16) uvlP->l;
				lBr = (UINT16) (brightness * effect [j] / 32);
				BlendColors (plc, pvc, lBr, vBr);
				vBr += lBr;
				vBr = min (0x8000, vBr);
				uvlP->l = (UINT16) vBr;
				}
			}
		}
	}
}
void ribi::trim::SetWindingHorizontal(std::vector<boost::shared_ptr<Edge>>& edges,const Winding winding)
{
  assert(CalcWindingHorizontal(AddConst(edges)) != winding);
  switch(winding)
  {
    case Winding::indeterminate:
    {
      edges[1]->Reverse();
    }
    break;
    case Winding::clockwise:
    {
      assert(edges.size() == 3 && "Otherwise I am not sure this will work");
      const Coordinat3D center { CalcCenter(edges) };
      const int n_edges { static_cast<int>(edges.size()) };
      for (int i=0; i!=n_edges; ++i)
      {
        //Fix winding
        if (!IsClockwiseHorizontal(edges[i],center)) { edges[i]->Reverse(); }
        assert(IsClockwiseHorizontal(edges[i],center));
        //Fix ordering of elements
        if (edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo()) continue;
        //Try to swap the next element's order
        assert(i + 1 < n_edges);
        if (edges[i+1]->GetFrom() != edges[i]->GetTo()) { edges[i+1]->Reverse(); }
        if (edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo()) continue;
        //Swap the next and its next elements
        assert(i + 2 < n_edges);
        if (edges[i+1]->GetFrom() != edges[i]->GetTo()) { std::swap(edges[i+1],edges[i+2]); }
        if (edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo()) continue;
        //Try to swap the next element's order
        if (edges[i+1]->GetFrom() != edges[i]->GetTo()) { edges[i+1]->Reverse(); }
        assert(edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo());
      }
    }
    break;
    case Winding::counter_clockwise:
    {
      assert(edges.size() == 3 && "Otherwise I am not sure this will work");
      const Coordinat3D center { CalcCenter(edges) };
      const int n_edges { static_cast<int>(edges.size()) };
      for (int i=0; i!=n_edges; ++i)
      {
        //Fix winding
        if (IsClockwiseHorizontal(edges[i],center)) { edges[i]->Reverse(); }
        assert(!IsClockwiseHorizontal(edges[i],center));
        //Fix ordering of elements
        if (edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo()) continue;
        //Try to swap the next element's order
        assert(i + 1 < n_edges);
        if (edges[i+1]->GetFrom() != edges[i]->GetTo()) { edges[i+1]->Reverse(); }
        if (edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo()) continue;
        //Swap the next and its next elements
        assert(i + 2 < n_edges);
        if (edges[i+1]->GetFrom() != edges[i]->GetTo()) { std::swap(edges[i+1],edges[i+2]); }
        if (edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo()) continue;
        //Try to swap the next element's order
        if (edges[i+1]->GetFrom() != edges[i]->GetTo()) { edges[i+1]->Reverse(); }
        assert(edges[(i+1) % n_edges]->GetFrom() == edges[i]->GetTo());
      }
    }
    break;
  }
  assert(CalcWindingHorizontal(AddConst(edges)) == winding);
}