示例#1
0
static unsigned long
xspirograph_draw (Display *dpy, Window window, void *closure)
{
  struct state *st = (struct state *) closure;
  Bool free_color = False;
  Bool flip_p = (st->counter & 1);
  int i;

  switch (st->drawstate) {
    case ERASE1:
      /* 5 sec delay before starting the erase */
      st->drawstate = ERASE2;
      /* shouldn't this use the configured long_delay value??? */
      return (st->long_delay == 0 ? 0 : 5000000);

    case ERASE2:
      /* erase, delaying 1/50th sec between frames */
      st->eraser = erase_window(st->dpy, st->window, st->eraser);
      if (st->eraser)
	/* shouldn't this be a configured pause??? */
	return 20000;
      st->drawstate = NEW_LAYER;
      /* just finished erasing -- leave screen black for 1 sec */
      return (st->long_delay == 0 ? 0 : 1000000);

    case DRAW:
      /* most common case put in front */
      for (i = 0; i < 1000; i++) {
        if (go(st, st->radius1, (flip_p ? st->radius2 : -st->radius2),
	       st->distance)) {
	  st->drawstate = NEW_LAYER;
	  break;
	}
      }
      /* Next draw is delayed sleep_time (initialized value)*/
      return st->sub_sleep_time;

    case NEW_LAYER:
      /* Increment counter */
      st->counter++;
      if (st->counter > (2 * st->num_layers)) {
	/* reset to zero, free, and erase next time through */
	st->counter = 0;
	if (free_color)
	  XFreeColors (st->dpy, st->xgwa.colormap, &st->color.pixel, 1, 0);
	st->drawstate = ERASE1;
      } else {
	/* first, third, fifth, ... time through */
	if (!flip_p)
	  pick_new (st);

	new_colors (st);
	st->drawstate = DRAW;
      }
      /* No delay to the next draw */
      return 0;

    default:
      /* OOPS!! */
      fprintf(stderr, "%s: invalid state\n", progname);
      exit(1);
  }

  return st->sub_sleep_time;
  /* notreached */
}
示例#2
0
void MeshWithConnectivity::LoopSubdivision() {
	// generate new (odd) vertices

	// visited edge -> vertex position information
	// Note that this is different from the one in computeConnectivity()
	typedef std::map<std::pair<int, int>, int> edgemap_t;
	edgemap_t new_vertices;

	// The new data must be doublebuffered or otherwise some of the calculations below would
	// not read the original positions but the newly changed ones, which is slightly wrong.
	std::vector<Vec3f> new_positions(positions.size());
	std::vector<Vec3f> new_normals(normals.size());
	std::vector<Vec3f> new_colors(colors.size());

	for (size_t i = 0; i < indices.size(); ++i)
		for (int j = 0; j < 3; ++j) {
			int v0 = indices[i][j];
			int v1 = indices[i][(j+1)%3];

			// Map the edge endpoint indices to new vertex index.
			// We use min and max because the edge direction does not matter when we finally
			// rebuild the new faces (R3); this is how we always get unique indices for the map.
			auto edge = std::make_pair(min(v0, v1), max(v0, v1));

			// With naive iteration, we would find each edge twice, because each is part of two triangles
			// (if the mesh does not have any holes/empty borders). Thus, we keep track of the already
			// visited edges in the new_vertices map. That requires the small R3 task below in the 'if' block.
			if (new_vertices.find(edge) == new_vertices.end()) {
				// YOUR CODE HERE (R4): compute the position for odd (= new) vertex.
				Vec3f pos, col, norm;
				int leftvertex, rightvertex;
				// You will need to use the neighbor information to find the correct vertices.
				// Be careful with indexing!
				// No need to worry about boundaries, though (except for the extra credit!).

				// Then, use the correct weights for each four corner vertex.
				// This default implementation just puts the new vertex at the edge midpoint.
				if (j == 0)
					leftvertex = indices[i][2];
				else if (j == 1)
					leftvertex = indices[i][0];
				else
					leftvertex = indices[i][1];
				Vec3i neigh = neighborTris[i];
				bool found = false;
				for (int k = 0; k < 3; k++)
				{
					int kms = neigh[k];

					if (kms == -1)
						continue;

					int x = indices[kms][0], y= indices[kms][1], z = indices[kms][2];
					if ((indices[kms][0] == v0 || indices[kms][1] == v0 || indices[kms][2] == v0) && (indices[kms][0] == v1 || indices[kms][1] == v1 || indices[kms][2] == v1))
					{
						if ((x == v0 && y == v1) || (x == v1 && y == v0))
							rightvertex = z;
						else if ((y == v0 && z == v1) || (z == v0 && y == v1))
							rightvertex = x;
						else
							rightvertex = y;
						found = true;
						break;
					}
				}
				if (found){
					pos = ((3.0f * (positions[v0] + positions[v1])) + (positions[leftvertex] + positions[rightvertex])) / 8.0f;
					col = ((3.0f * (colors[v0] + colors[v1])) + (colors[leftvertex] + colors[rightvertex])) / 8.0f;
					norm = ((3.0f * (normals[v0] + normals[v1])) + (normals[leftvertex] + normals[rightvertex])) / 8.0f;
				}

				else {
					pos = 0.5f * (positions[v0] + positions[v1]);
					col = 0.5f * (colors[v0] + colors[v1]);
					norm = 0.5f * (normals[v0] + normals[v1]);
				}
				new_positions.push_back(pos);
				new_colors.push_back(col);
				new_normals.push_back(norm);

				// YOUR CODE HERE (R3):
				// Map the edge to the correct vertex index.
				new_vertices[edge] = new_positions.size() - 1;
				// This is just one line! Use new_vertices and the index of the just added position.
			}
		}
		// compute positions for even (old) vertices
		std::vector<bool> vertexComputed(new_positions.size(), false);

		for (int i = 0; i < (int)indices.size(); ++i) {
			for (int j = 0; j < 3; ++j) {
				int v0 = indices[i][j];

				// don't redo if this one is already done
				if (vertexComputed[v0])
					continue;

				vertexComputed[v0] = true;

				Vec3f pos, col, norm;
				std::vector<int> neighbors;
				// YOUR CODE HERE (R5): reposition the old vertices

				// This default implementation just passes the data through unchanged.
				// You need to replace these three lines with the loop over the 1-ring
				// around vertex v0, and compute the new position as a weighted average
				// of the other vertices as described in the handout.
				for (int k = 0; k < indices.size(); k++){
					for (int l = 0; l < 3; l++){
						if (indices[k][l] == v0){
							neighbors.push_back(indices[k][(l + 1) % 3]);
							neighbors.push_back(indices[k][(l + 2) % 3]);
						}
					}
				}
				sort(neighbors.begin(), neighbors.end());
				neighbors.erase(std::unique(neighbors.begin(),neighbors.end()), neighbors.end());

				int n = neighbors.size();
				float b;
				if (n>3)
					b = 3.0f / (8.0f * n);
				else if (n == 3)
					b = 3.0f / 16.0f;
				else
					b = 0.0f;
				Vec3f rightsum1, rightsum2, rightsum3;
				for (int k = 0; k < neighbors.size(); k++){
					rightsum1 += positions[neighbors[k]];
					rightsum2 += colors[neighbors[k]];
					rightsum3 += normals[neighbors[k]];
				}
				rightsum1 *= (float)b;
				rightsum2 *= (float)b;
				rightsum3 *= (float)b;
				float ks = 1.0f - (float)n*(float)b;
				rightsum1 += ks * positions[v0];
				rightsum2 += ks * colors[v0];
				rightsum3 += ks * normals[v0];
				pos = rightsum1;
				col = rightsum2;
				norm = rightsum3;

				new_positions[v0] = pos;
				new_colors[v0] = col;
				new_normals[v0] = norm;
			}
		}
		// and then, finally, regenerate topology
		// every triangle turns into four new ones
		std::vector<Vec3i> new_indices;
		new_indices.reserve(indices.size()*4);
		for (size_t i = 0; i < indices.size(); ++i) {
			Vec3i even = indices[i]; // start vertices of e_0, e_1, e_2

			// YOUR CODE HERE (R3):
			// fill in X and Y (it's the same for both)
			auto edge_a = std::make_pair(min(even.x, even.y), max(even.x, even.y));
			auto edge_b = std::make_pair(min(even.z, even.y), max(even.z, even.y));
			auto edge_c = std::make_pair(min(even.x, even.z), max(even.x, even.z));

			// The edges edge_a, edge_b and edge_c now define the vertex indices via new_vertices.
			// (The mapping is done in the loop above.)
			// The indices define the smaller triangle inside the indices defined by "even", in order.
			// Read the vertex indices out of new_vertices to build the small triangle "odd"
			int a, b, c;
			a = new_vertices[edge_a];
			b = new_vertices[edge_b];
			c = new_vertices[edge_c];
			// Vec3i odd = ...
			new_indices.push_back(Vec3i(a,b,c));
			new_indices.push_back(Vec3i(a, b, even[1]));
			new_indices.push_back(Vec3i(a,c, even[0]));
			new_indices.push_back(Vec3i(b, c, even[2]));
			// Then, construct the four smaller triangles from the surrounding big triangle  "even"
			// and the inner one, "odd". Push them to "new_indices".

			// NOTE: REMOVE the following line after you're done with the new triangles.
			// This just keeps the mesh intact and serves as an example on how to add new triangles.
			//new_indices.push_back( Vec3i( even[0], even[1], even[2] ) );
		}

		// ADD THESE LINES when R3 is finished. Replace the originals with the repositioned data.
		indices = std::move(new_indices);
		positions = std::move(new_positions);
		normals = std::move(new_normals);
		colors = std::move(new_colors);
		neighborTris.size();
}