Example #1
0
void CellularAutomata::onSimulation(double currentSampleCount, double sampleDelta) {
    SimTime deltaTime = float(sampleDelta) / m_sampleRate;
    m_displayInterpolationFactor = slew(m_displayInterpolationFactor, m_displayMode, deltaTime, 0.8f);
    if (m_paused) {
        m_currentTime = floor(m_currentTime / stepTime())*stepTime();
        return;
    }
    int oldBeatNum = beatNum();
    m_currentTime += deltaTime;
    int newBeatNum = beatNum();
    if (newBeatNum != oldBeatNum) {
        step();
    }
    for (const HeadWallCollision& c : m_wallCollisions) {
        int index = isVert(c.d) ? c.pos.x : c.pos.y;
        Synthesizer::global->queueSound(m_soundBank[index]);
    }
}
Example #2
0
void CellularAutomata::draw(RenderDevice* rd, const Ray& mouseRay, const Color3& color) {

    int numSegments = 100;

    for (int i = 0; i < m_width; ++i) {
        float alpha = float(i)/(m_width - 1.0f);
        drawSegmentedLine(rd, color, Vector2(alpha, 0), Vector2(alpha, 1), 81);
    }

    for (int i = 0; i < m_height; ++i) {
        float alpha = float(i)/(m_height - 1.0f);
        drawSegmentedLine(rd, color, Vector2(0, alpha), Vector2(1, alpha), 81);

    }
    for (auto collision : m_wallCollisions) {
        if (isVert(collision.d)) {
            int i = collision.pos.x;
            float alpha = float(i) / (m_width - 1.0f);
            drawSegmentedLine(rd, color * 1.5f, Vector2(alpha, 0), Vector2(alpha, 1), 81);
        } else {
            int i = collision.pos.y;
            float alpha = float(i) / (m_height - 1.0f);
            drawSegmentedLine(rd, color * 1.5f, Vector2(0, alpha), Vector2(1, alpha), 81);
        }
    } 
  
    for (auto collision : m_headCollisions) {
        const Vector2int16 pos = collision.pos;
  

        Vector2 normalizedCoord = Vector2(pos) * Vector2(1.0f/(m_width - 1.0f), 1.0f/(m_height - 1.0f));

        Vector3 center = normCoordTo3DPoint(normalizedCoord);

        Vector3 radius(0.01f, 0.01f, 0.01f);
        Draw::box(AABox(center - radius, center + radius), rd, color*3.5f, Color4::clear());
    }
  
  
    Color4 clear = Color4::clear();
    const float sAlpha = stepAlpha();
    /*  debugPrintf("Step Alpha %f\n", sAlpha);
    debugPrintf("Time %f\n", m_currentTime);
    debugPrintf("Beat %d : %f\n", beatNum());*/
    bool showTransientPlayhead = m_paused;
    for (auto head : m_playhead) {

        const Vector2int16 pos = head.position;
  
        Vector2 unnormalizedCoord = (Vector2(pos.x, pos.y) + Vector2(vecFromDir(head.direction)) * sAlpha);

        Vector2 normalizedCoord = unnormalizedCoord * Vector2(1.0f/(m_width - 1.0f), 1.0f/(m_height - 1.0f));

        Vector3 center = normCoordTo3DPoint(normalizedCoord);

        if (m_paused) { 
            float colorMultiplier = 1.0f;
            if (pos == m_transientPlayhead.position) {
                showTransientPlayhead = false;
                colorMultiplier = 1.5f;
            }
            Draw::arrow(center, (normCoordTo3DPoint(normalizedCoord + Vector2(vecFromDir(head.direction))) - center)*0.02f, rd, color*colorMultiplier, 0.5f);
        } else {
            float maxDimension = max(m_width - 1.0f, m_height - 1.0f);
            float r = 0.0007f*maxDimension;
            Vector3 radius(r, r, r);
            Draw::box(AABox(center - radius, center + radius), rd, color*3.5f, Color4::clear());
        }
    }
    if (showTransientPlayhead && m_transientPlayhead.position.x >= 0) {
        Point2 normalizedCoord = Point2(m_transientPlayhead.position) * Vector2(1.0f / (m_width - 1.0f), 1.0f / (m_height - 1.0f));
        const Point3& center = normCoordTo3DPoint(normalizedCoord);
        Draw::arrow(center, (normCoordTo3DPoint(normalizedCoord + Vector2(vecFromDir(m_transientPlayhead.direction))) - center)*0.02f, rd, Color4(color, 0.5f), 0.5f);
    }

    m_wallCollisions.fastClear();
    m_headCollisions.fastClear();

}
Example #3
0
void find_holes(Seg_t segs[], int nsegs, int **pholesizes, int *pnholes) {
  int *xorder, *yorder, found;
  int nx, ny, i,j,k, y1, y2, x1, x2, t, x, y, *queue, head, tail, qlen;
  char *array;
  int hole_total;

  xorder = malloc(2*nsegs*sizeof(xorder[0])); assert(xorder);
  yorder = malloc(2*nsegs*sizeof(yorder[0])); assert(yorder);

  for( i = 0, j = 0, k = 0; i < nsegs; i++ ) {
    xorder[j++] = segs[i].p1.x;
    xorder[j++] = segs[i].p2.x;
    yorder[k++] = segs[i].p1.y;
    yorder[k++] = segs[i].p2.y;
  }

  qsort(xorder, j, sizeof(*xorder), int_cmp);
  qsort(yorder, k, sizeof(*yorder), int_cmp);

  /* uniqify the arrays xorder and yorder. */
  for( i = 1, j = 0; i < nsegs*2; /* nil */ )
    if( xorder[i] != xorder[j] ) xorder[++j] = xorder[i++]; else i++;

  nx = j + 1;

  for( i = 1, j = 0; i < nsegs*2; /* nil */ )
    if( yorder[i] != yorder[j] ) yorder[++j] = yorder[i++]; else i++;

  ny = j + 1;

  /* now allocate our happy array. */
  array = calloc( (2*nx+1) * (2*ny+1) , sizeof(*array) );
  
  for( i = 0; i < nsegs; i++ ) {
    if( isVert(segs[i])) {
      x = y1 = y2 = -1;
      for( j = 0; j < ny; j++ ) {
	if( segs[i].p1.y == yorder[j] ) y1 = j;
	if( segs[i].p2.y == yorder[j] ) y2 = j;
      }
      for( j = 0; j < nx; j++ ) if( segs[i].p1.x == xorder[j] ) x  = j;
      /* assert(y1 != -1 && y2 != -1 && x != -1);*/
      if( y1 > y2 ) swap(y1,y2,t);
      
      x = x*2 + 1;
      for( j = 2*y1+1; j <= 2*y2+1; j ++ ) {
	a(x,j) = '*';
      }
      
    } else if( isHorz(segs[i])) {
      y = x1 = x2 = -1;
      for( j = 0; j < nx; j++ ) {
	if( segs[i].p1.x == xorder[j] ) x1 = j;
	if( segs[i].p2.x == xorder[j] ) x2 = j;
      }
      for( j = 0; j < ny; j++ ) if( segs[i].p1.y == yorder[j] ) y  = j;
      /* assert(x1 != -1 && x2 != -1 && y != -1); */
      if( x1 > x2 ) swap(x1,x2,t);
      y = y * 2 + 1;
      for( j = 2*x1+1; j <= 2*x2+1; j ++ ) {
	a(j,y) = '*';
      }
    } else {
      assert(0); /* must be either horizontal or vertical. */
    }
  }
  if( debug ) dump_array(array, nx, ny);

  /* now the array is filled in with the segment boundaries */
  /* flood fill from the outside. */
  
  /* well, first set up the bfs queue. */

  /* this should be quite big enough. I claim that 2 * ... would
   * be enough. */
  /* the entries of the queue are encoded as:
   * x<<16 | y */
  qlen = 4 * ( (2*nx+1) + (2*ny+1));
  queue = malloc(qlen*sizeof(queue[0])); assert(queue);

  head = tail = 0;
  queue[tail++] = 0;
  a(0,0) = 1; /* visited is marked 1. */

  while( head != tail ) {
    x = queue[head]; 
    head = (head + 1) % qlen;
    y = x & 0xffff; x >>= 16;

    for( t = 0; t < 4; t++ ) {
      switch(t) {
      case 0: i = x-1; j = y  ; break;
      case 1: i = x  ; j = y-1; break;
      case 2: i = x+1; j = y  ; break;
      case 3: i = x  ; j = y+1; break;
      default:
      }

      if( i >= 0 && i <= 2*nx && j >= 0 && j <= 2*ny && !a(i,j) ) {
	queue[tail] = i << 16 | j;
	tail = (tail + 1) % qlen;
	a(i,j) = 1;
      }
    }
  }

  if(debug) dump_array(array, nx, ny);

  /* now the array has been flooded from the outside. condense
   * adjacent holes by dissolving the boundaries between them. */

  /* the bounds of these for loops are shrunk by one because
   * by construction the entire array has boundaries 1 now,
   * so we don't need to check them. */
  for( i = 1; i < 2*nx; i++ ) {
    for( j = 1; j < 2*ny; j++ ) {
      if( a(i,j) == '*' &&
	((a(i-1,j) == 0 && a(i+1,j) == 0) || (a(i,j-1) == 0 && a(i,j+1) == 0)))
	a(i,j) = 0;
    }
  }
  if(debug) dump_array(array, nx, ny);

  /* now while there is a still an element of the array with coordinates
   * of form (2k,2m) set to zero, flood fill and measure the area. */
  *pholesizes = NULL; *pnholes = 0;
  do {
    found = 0;
    for( i = 2; i <= 2*nx; i += 2 ) {
      for( j = 2; j <= 2*ny; j += 2 ) {
	if( ! a(i,j) ) { found = 1; goto zero_found; }
      }
    }
    /* ! found */ break;
    
  zero_found:
    hole_total = head = tail = 0;
    queue[tail++] = i << 16 | j;
    a(i,j) = 1; /* visited is marked 1. */
    
    while( head != tail ) {
      x = queue[head]; 
      head = (head + 1) % qlen;
      y = x & 0xffff; x >>= 16;
      if( !(x&1) && !(y&1) ) {
	/* an even-coordinate square. that means, measure it. */
	hole_total += 
	  (xorder[x/2] - xorder[(x/2)-1]) * (yorder[y/2] - yorder[(y/2)-1]);
      }
      /* and enqueue its neigbours. */
      for( t = 0; t < 4; t++ ) {
	switch(t) {
	case 0: i = x-1; j = y  ; break;
	case 1: i = x  ; j = y-1; break;
	case 2: i = x+1; j = y  ; break;
	case 3: i = x  ; j = y+1; break;
	default:
	}
	if( i >= 0 && i <= 2*nx && j >= 0 && j <= 2*ny && !a(i,j) ) {
	  queue[tail] = i << 16 | j;
	  tail = (tail + 1) % qlen;
	  a(i,j) = 1;
	}
      }
    } /* end loop bfs flood filling this hole */
    
    if( *pholesizes == NULL ) {
      *pholesizes = malloc((*pnholes + 1) * sizeof((*pholesizes)[0]));
      assert(*pholesizes);
    } else {
      *pholesizes = realloc( *pholesizes, 
			     (*pnholes + 1) * sizeof((*pholesizes)[0]));
      assert(*pholesizes);
    }
    (*pholesizes)[(*pnholes)++] = hole_total;
  } while(1); /* broken when zero elements are exhausted. */
  free(queue); free(array); free(xorder); free(yorder);
}

int main() {
  int i,x1,y1,x2,y2,nsegs, *holes, nholes;
  Seg_t *segs;

  segs = NULL; nsegs = 0;

  while(scanf("%d %d %d %d", &x1, &y1, &x2, &y2) == 4 ){
    segs = segs 
      ? realloc(segs, ++nsegs * sizeof(segs[0])) 
      : malloc(++nsegs * sizeof(segs[0]));
    
    segs[nsegs-1].p1.x = x1; segs[nsegs-1].p1.y = y1;
    segs[nsegs-1].p2.x = x2; segs[nsegs-1].p2.y = y2;
  }

  find_holes(segs, nsegs, &holes, &nholes);
  printf("There are %d holes.\n", nholes);

  for( i = 0; i < nholes; i++ )
    printf("Hole of size %d\n", holes[i]);
  return 0;
}