Exemplo n.º 1
0
/** Returns the data used for the scaler shader for the given pixel. It is a 8-bit bitmask. The bits stand for the 8
    neighbouring pixels in this order:
	  1 2 3
	  4 . 5
	  6 7 8
	... and denote whether the pixels belongs to the same group as this pixel.
	*/
int C4LandscapeRenderGL::CalculateScalerBitmask(int x, int y, C4Rect To, C4Landscape *pSource)
{
	int pixel = pSource->_GetPix(To.x+x, To.y+y);
	int placement = pSource->_GetPlacement(To.x+x, To.y+y);

	int neighbours[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	if(To.y+y > 0)
	{
		if(To.x+x > 0)
			neighbours[0] = pSource->_GetPix(To.x+x-1, To.y+y-1);
		neighbours[1] = pSource->_GetPix(To.x+x, To.y+y-1);
		if(To.x+x < iWidth-1)
			neighbours[2] = pSource->_GetPix(To.x+x+1, To.y+y-1);
	}
	if(To.x+x > 0)
		neighbours[3] = pSource->_GetPix(To.x+x-1, To.y+y);
	if(To.x+x < iWidth-1)
		neighbours[4] = pSource->_GetPix(To.x+x+1, To.y+y);
	if(To.y+y < iHeight-1)
	{
		if(To.x+x > 0)
			neighbours[5] = pSource->_GetPix(To.x+x-1, To.y+y+1);
		neighbours[6] = pSource->_GetPix(To.x+x, To.y+y+1);
		if(To.x+x < iWidth-1)
			neighbours[7] = pSource->_GetPix(To.x+x+1, To.y+y+1);
	}

	// Look for highest-placement material in our surroundings
	int maxPixel = pixel, maxPlacement = placement;
	for(int i = 0; i < 8; i++)
	{
		int tempPlacement = MatPlacement(PixCol2Mat(neighbours[i]));
		if(tempPlacement > maxPlacement || (tempPlacement == maxPlacement && neighbours[i] > maxPixel) )
		{
			maxPixel = neighbours[i];
			maxPlacement = tempPlacement;
		}
	}

	// Scaler calculation depends on whether this is the highest-placement material around
	int scaler = 0;
	if(maxPixel == pixel)
	{
		// If yes, we consider all other materials as "other"
		for(int i = 0; i < 8; i++)
			if(neighbours[i] == pixel)
				scaler += (1<<i);

	} else {

		// Otherwise, we *only* consider the highest-placement material as "other"
		for(int i = 0; i < 8; i++)
			if(neighbours[i] != maxPixel)
				scaler += (1<<i);
	}
	return scaler;
}
void C4Landscape::UpdatePixMaps() // Copied from C4Landscape.cpp
{
	int32_t i;
	for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Mat[i] = PixCol2Mat(i);
	for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Dens[i] = MatDensity(Pix2Mat[i]);
	for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Place[i] = MatValid(Pix2Mat[i]) ? ::MaterialMap.Map[Pix2Mat[i]].Placement : 0;
	for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Light[i] = MatValid(Pix2Mat[i]) && (::MaterialMap.Map[Pix2Mat[i]].Light>0);
	Pix2Place[0] = 0;
	// clear bridge mat conversion buffers
	for (int32_t i = 0; i < C4M_MaxTexIndex; ++i)
	{
		delete [] BridgeMatConversion[i];
		BridgeMatConversion[i] = NULL;
	}
}
Exemplo n.º 3
0
BOOL C4Shape::Attach(int32_t &cx, int32_t &cy, BYTE cnat_pos) {
  // Adjust given position to one pixel before contact
  // at vertices matching CNAT request.

  BOOL fAttached = FALSE;

#ifdef C4ENGINE

  int32_t vtx, xcnt, ycnt, xcrng, ycrng, xcd, ycd;
  int32_t motion_x = 0;
  BYTE cpix;

  // reset attached material
  AttachMat = MNone;

  // New attachment behaviour in CE:
  // Before, attachment was done by searching through all vertices,
  // and doing attachment to any vertex with a matching CNAT.
  // While this worked well for normal Clonk attachment, it caused nonsense
  // behaviour if multiple vertices matched the same CNAT. In effect, attachment
  // was then done to the last vertex only, usually stucking the object sooner
  // or later.
  // For instance, the scaling procedure of regular Clonks uses two CNAT_Left-
  // vertices (shoulder+belly), which "block" each other in situations like
  // scaling up battlements of towers. That way, the 2px-overhang of the
  // battlement is sufficient for keeping out scaling Clonks. The drawback is
  // that sometimes Clonks get stuck scaling in very sharp edges or single
  // floating material pixels; occuring quite often in Caverace, or maps where
  // you blast Granite and many single pixels remain.
  //
  // Until a better solution for designing battlements is found, the old-style
  // behaviour will be used for Clonks.	Both code variants should behave equally
  // for objects with only one matching vertex to cnat_pos.
  if (!(cnat_pos & CNAT_MultiAttach)) {
    // old-style attachment
    for (vtx = 0; vtx < VtxNum; vtx++)
      if (VtxCNAT[vtx] & cnat_pos) {
        xcd = ycd = 0;
        switch (cnat_pos & (~CNAT_Flags)) {
          case CNAT_Top:
            ycd = -1;
            break;
          case CNAT_Bottom:
            ycd = +1;
            break;
          case CNAT_Left:
            xcd = -1;
            break;
          case CNAT_Right:
            xcd = +1;
            break;
        }
        xcrng = AttachRange * xcd * (-1);
        ycrng = AttachRange * ycd * (-1);
        for (xcnt = xcrng, ycnt = ycrng; (xcnt != -xcrng) || (ycnt != -ycrng);
             xcnt += xcd, ycnt += ycd) {
          int32_t ax = cx + VtxX[vtx] + xcnt + xcd,
                  ay = cy + VtxY[vtx] + ycnt + ycd;
          if (GBackDensity(ax, ay) >= ContactDensity && ax >= 0 &&
              ax < GBackWdt) {
            cpix = GBackPix(ax, ay);
            AttachMat = PixCol2Mat(cpix);
            iAttachX = ax;
            iAttachY = ay;
            iAttachVtx = vtx;
            cx += xcnt;
            cy += ycnt;
            fAttached = 1;
            break;
          }
        }
      }
  } else  // CNAT_MultiAttach
  {
    // new-style attachment
    // determine attachment direction
    xcd = ycd = 0;
    switch (cnat_pos & (~CNAT_Flags)) {
      case CNAT_Top:
        ycd = -1;
        break;
      case CNAT_Bottom:
        ycd = +1;
        break;
      case CNAT_Left:
        xcd = -1;
        break;
      case CNAT_Right:
        xcd = +1;
        break;
    }
    // check within attachment range
    xcrng = AttachRange * xcd * (-1);
    ycrng = AttachRange * ycd * (-1);
    for (xcnt = xcrng, ycnt = ycrng; (xcnt != -xcrng) || (ycnt != -ycrng);
         xcnt += xcd, ycnt += ycd)
      // check all vertices with matching CNAT
      for (vtx = 0; vtx < VtxNum; vtx++)
        if (VtxCNAT[vtx] & cnat_pos) {
          // get new vertex pos
          int32_t ax = cx + VtxX[vtx] + xcnt + xcd,
                  ay = cy + VtxY[vtx] + ycnt + ycd;
          // can attach here?
          cpix = GBackPix(ax, ay);
          if (MatDensity(PixCol2Mat(cpix)) >= ContactDensity && ax >= 0 &&
              ax < GBackWdt) {
            // store attachment material
            AttachMat = PixCol2Mat(cpix);
            // store absolute attachment position
            iAttachX = ax;
            iAttachY = ay;
            iAttachVtx = vtx;
            // move position here
            cx += xcnt;
            cy += ycnt;
            // mark attachment
            fAttached = 1;
            // break both looops
            xcnt = -xcrng - xcd;
            ycnt = -ycrng - ycd;
            break;
          }
        }
  }
  // both attachments: apply motion done by SolidMasks
  if (motion_x) cx += BoundBy<int32_t>(motion_x, -1, 1);

#endif

  return fAttached;
}