Exemple #1
0
void Brush_ConstructCuboid(Brush& brush, const AABB& bounds, const std::string& shader, const TextureProjection& projection)
{
  const unsigned char box[3][2] = { { 0, 1 }, { 2, 0 }, { 1, 2 } };
  Vector3 mins(bounds.origin - bounds.extents);
  Vector3 maxs(bounds.origin + bounds.extents);

  brush.clear();
  brush.reserve(6);

  {
    for(int i=0; i < 3; ++i)
    {
      Vector3 planepts1(maxs);
      Vector3 planepts2(maxs);
      planepts2[box[i][0]] = mins[box[i][0]];
      planepts1[box[i][1]] = mins[box[i][1]];

      brush.addPlane(maxs, planepts1, planepts2, shader, projection);
    }
  }
  {
    for(int i=0; i < 3; ++i)
    {
      Vector3 planepts1(mins);
      Vector3 planepts2(mins);
      planepts1[box[i][0]] = maxs[box[i][0]];
      planepts2[box[i][1]] = maxs[box[i][1]];

      brush.addPlane(mins, planepts1, planepts2, shader, projection);
    }
  }
}
Exemple #2
0
	void Cone::generate (Brush& brush, const AABB& bounds, std::size_t sides, const TextureProjection& projection,
			const std::string& shader)
	{
		if (sides < _minSides) {
			gtkutil::errorDialog(_("Too few sides for constructing the prism, minimum is 3"));
			return;
		}
		if (sides > _maxSides) {
			gtkutil::errorDialog(_("Too many sides for constructing the prism, maximum is 32"));
			return;
		}

		brush.clear();
		brush.reserve(sides + 1);

		Vector3 mins(bounds.origin - bounds.extents);
		Vector3 maxs(bounds.origin + bounds.extents);

		float radius = maxExtent(bounds.extents);
		const Vector3& mid = bounds.origin;
		Vector3 planepts[3];

		planepts[0][0] = mins[0];
		planepts[0][1] = mins[1];
		planepts[0][2] = mins[2];
		planepts[1][0] = maxs[0];
		planepts[1][1] = mins[1];
		planepts[1][2] = mins[2];
		planepts[2][0] = maxs[0];
		planepts[2][1] = maxs[1];
		planepts[2][2] = mins[2];

		brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);

		for (std::size_t i = 0; i < sides; ++i) {
			double sv = sin(i * 3.14159265 * 2 / sides);
			double cv = cos(i * 3.14159265 * 2 / sides);

			planepts[0][0] = static_cast<float> (floor(mid[0] + radius * cv + 0.5));
			planepts[0][1] = static_cast<float> (floor(mid[1] + radius * sv + 0.5));
			planepts[0][2] = mins[2];

			planepts[1][0] = mid[0];
			planepts[1][1] = mid[1];
			planepts[1][2] = maxs[2];

			planepts[2][0] = static_cast<float> (floor(planepts[0][0] - radius * sv + 0.5));
			planepts[2][1] = static_cast<float> (floor(planepts[0][1] + radius * cv + 0.5));
			planepts[2][2] = maxs[2];

			brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
		}
	}
void Brush_ConstructSphere(Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection)
{
  if(sides < c_brushSphere_minSides)
  {
    globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " << Unsigned(c_brushSphere_minSides) << "\n";
    return;
  }
  if(sides > c_brushSphere_maxSides)
  {
    globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " << Unsigned(c_brushSphere_maxSides) << "\n";
    return;
  }

  brush.undoSave();
  brush.clear();
  brush.reserve(sides*sides);

  float radius = max_extent(bounds.extents);
  const Vector3& mid = bounds.origin;
  Vector3 planepts[3];

  double dt = 2 * c_pi / sides;
  double dp = c_pi / sides;
  for(std::size_t i=0; i < sides; i++)
  {
    for(std::size_t j=0;j < sides-1; j++)
    {
      double t = i * dt;
      double p = float(j * dp - c_pi / 2);

      planepts[0] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p), radius));
      planepts[1] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p + dp), radius));
      planepts[2] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius));

      brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
    }
  }

  {
    double p = (sides - 1) * dp - c_pi / 2;
    for(std::size_t i = 0; i < sides; i++)
    {
      double t = i * dt;

      planepts[0] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p), radius));
      planepts[1] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius));
      planepts[2] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p), radius));

      brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
    }
  }
}
void Brush_ConstructCone(Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection)
{
  if(sides < c_brushCone_minSides)
  {
    globalErrorStream() << c_brushCone_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " << Unsigned(c_brushCone_minSides) << "\n";
    return;
  }
  if(sides > c_brushCone_maxSides)
  {
    globalErrorStream() << c_brushCone_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " << Unsigned(c_brushCone_maxSides) << "\n";
    return;
  }

  brush.undoSave();
  brush.clear();
  brush.reserve(sides+1);

  Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents));
  Vector3 maxs(vector3_added(bounds.origin, bounds.extents));

  float radius = max_extent(bounds.extents);
  const Vector3& mid = bounds.origin;
  Vector3 planepts[3];

  planepts[0][0] = mins[0];planepts[0][1] = mins[1];planepts[0][2] = mins[2];
  planepts[1][0] = maxs[0];planepts[1][1] = mins[1];planepts[1][2] = mins[2];
  planepts[2][0] = maxs[0];planepts[2][1] = maxs[1];planepts[2][2] = mins[2];

  brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);

  for (std::size_t i=0 ; i<sides ; ++i)
  {
    double sv = sin (i*3.14159265*2/sides);
    double cv = cos (i*3.14159265*2/sides);

    planepts[0][0] = static_cast<float>(floor(mid[0]+radius*cv+0.5));
    planepts[0][1] = static_cast<float>(floor(mid[1]+radius*sv+0.5));
    planepts[0][2] = mins[2];

    planepts[1][0] = mid[0];
    planepts[1][1] = mid[1];
    planepts[1][2] = maxs[2];

    planepts[2][0] = static_cast<float>(floor(planepts[0][0] - radius * sv + 0.5));
    planepts[2][1] = static_cast<float>(floor(planepts[0][1] + radius * cv + 0.5));
    planepts[2][2] = maxs[2];

    brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
  }
}
Exemple #5
0
void Sphere::generate (Brush& brush, const AABB& bounds, std::size_t sides, const TextureProjection& projection,
                       const std::string& shader)
{
    if (sides < _minSides) {
        gtkutil::errorDialog(_("Too few sides for constructing the sphere, minimum is 3"));
        return;
    }
    if (sides > _maxSides) {
        gtkutil::errorDialog(_("Too many sides for constructing the sphere, maximum is 31"));
        return;
    }

    brush.clear();
    brush.reserve(sides * sides);

    float radius = maxExtent(bounds.extents);
    const Vector3& mid = bounds.origin;
    Vector3 planepts[3];

    double dt = 2 * c_pi / sides;
    double dp = c_pi / sides;
    for (std::size_t i = 0; i < sides; i++) {
        for (std::size_t j = 0; j < sides - 1; j++) {
            double t = i * dt;
            double p = float(j * dp - c_pi / 2);

            planepts[0] = mid + vector3_for_spherical(t, p) * radius;
            planepts[1] = mid + vector3_for_spherical(t, p + dp) * radius;
            planepts[2] = mid + vector3_for_spherical(t + dt, p + dp) * radius;

            brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
        }
    }

    {
        double p = (sides - 1) * dp - c_pi / 2;
        for (std::size_t i = 0; i < sides; i++) {
            double t = i * dt;

            planepts[0] = mid + vector3_for_spherical(t, p) * radius;
            planepts[1] = mid + vector3_for_spherical(t + dt, p + dp) * radius;
            planepts[2] = mid + vector3_for_spherical(t + dt, p) * radius;

            brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
        }
    }
}
Exemple #6
0
void Brush_ConstructPrism(Brush& brush, const AABB& bounds, std::size_t sides, int axis, const std::string& shader, const TextureProjection& projection)
{
  if(sides < c_brushPrism_minSides)
  {
    globalErrorStream() << c_brushPrism_name << ": sides " << sides << ": too few sides, minimum is " << c_brushPrism_minSides << "\n";
    return;
  }
  if(sides > c_brushPrism_maxSides)
  {
    globalErrorStream() << c_brushPrism_name << ": sides " << sides << ": too many sides, maximum is " << c_brushPrism_maxSides << "\n";
    return;
  }

  brush.clear();
  brush.reserve(sides+2);

  Vector3 mins(bounds.origin - bounds.extents);
  Vector3 maxs(bounds.origin + bounds.extents);

  float radius = max_extent_2d(bounds.extents, axis);
  const Vector3& mid = bounds.origin;
  Vector3 planepts[3];

  planepts[2][(axis+1)%3] = mins[(axis+1)%3];
  planepts[2][(axis+2)%3] = mins[(axis+2)%3];
  planepts[2][axis] = maxs[axis];
  planepts[1][(axis+1)%3] = maxs[(axis+1)%3];
  planepts[1][(axis+2)%3] = mins[(axis+2)%3];
  planepts[1][axis] = maxs[axis];
  planepts[0][(axis+1)%3] = maxs[(axis+1)%3];
  planepts[0][(axis+2)%3] = maxs[(axis+2)%3];
  planepts[0][axis] = maxs[axis];

  brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);

  planepts[0][(axis+1)%3] = mins[(axis+1)%3];
  planepts[0][(axis+2)%3] = mins[(axis+2)%3];
  planepts[0][axis] = mins[axis];
  planepts[1][(axis+1)%3] = maxs[(axis+1)%3];
  planepts[1][(axis+2)%3] = mins[(axis+2)%3];
  planepts[1][axis] = mins[axis];
  planepts[2][(axis+1)%3] = maxs[(axis+1)%3];
  planepts[2][(axis+2)%3] = maxs[(axis+2)%3];
  planepts[2][axis] = mins[axis];

  brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
 
  for (std::size_t i=0 ; i<sides ; ++i)
  {
    double sv = sin (i*3.14159265*2/sides);
    double cv = cos (i*3.14159265*2/sides);

    planepts[0][(axis+1)%3] = static_cast<float>(floor(mid[(axis+1)%3]+radius*cv+0.5));
    planepts[0][(axis+2)%3] = static_cast<float>(floor(mid[(axis+2)%3]+radius*sv+0.5));
    planepts[0][axis] = mins[axis];

    planepts[1][(axis+1)%3] = planepts[0][(axis+1)%3];
    planepts[1][(axis+2)%3] = planepts[0][(axis+2)%3];
    planepts[1][axis] = maxs[axis];

    planepts[2][(axis+1)%3] = static_cast<float>(floor(planepts[0][(axis+1)%3] - radius*sv + 0.5));
    planepts[2][(axis+2)%3] = static_cast<float>(floor(planepts[0][(axis+2)%3] + radius*cv + 0.5));
    planepts[2][axis] = maxs[axis];

    brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection);
  }
}
Exemple #7
0
void BrushByPlaneClipper::visit(const scene::INodePtr& node) const {
	// Don't clip invisible nodes
	if (!node->visible()) {
		return;
	}

	// Try to cast the instance onto a brush
	Brush* brush = Node_getBrush(node);

	// Return if not brush
	if (brush == NULL) {
		return;
	}

	Plane3 plane(_p0, _p1, _p2);
	if (!plane.isValid()) {
		return;
	}

	// greebo: Analyse the brush to find out which shader is the most used one
	getMostUsedTexturing(brush);

	BrushSplitType split = Brush_classifyPlane(*brush, _split == eFront ? -plane : plane);

	if (split.counts[ePlaneBack] && split.counts[ePlaneFront]) {
		// the plane intersects this brush
		if (_split == eFrontAndBack) {
			scene::INodePtr brushNode = GlobalBrushCreator().createBrush();

			assert(brushNode != NULL);

			Brush* fragment = Node_getBrush(brushNode);
			assert(fragment != NULL);
			fragment->copy(*brush);

			FacePtr newFace = fragment->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection);

			if (newFace != NULL && _split != eFront) {
				newFace->flipWinding();
			}

			fragment->removeEmptyFaces();
			ASSERT_MESSAGE(!fragment->empty(), "brush left with no faces after split");

			// Mark this brush for insertion
			_insertList.insert(InsertMap::value_type(brushNode, node->getParent()));
		}

		FacePtr newFace = brush->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection);

		if (newFace != NULL && _split == eFront) {
			newFace->flipWinding();
		}

		brush->removeEmptyFaces();
		ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after split");
	}
	// the plane does not intersect this brush
	else if (_split != eFrontAndBack && split.counts[ePlaneBack] != 0) {
		// the brush is "behind" the plane
		_deleteList.insert(node);
	}
}
void BrushByPlaneClipper::split(const BrushPtrVector& brushes)
{
	Plane3 plane(_p0, _p1, _p2);

	if (!plane.isValid())
	{
		return;
	}

	for (BrushPtrVector::const_iterator i = brushes.begin(); i != brushes.end(); ++i)
	{
		const BrushNodePtr& node = *i;

		// Don't clip invisible nodes
		if (!node->visible())
		{
			continue;
		}

		Brush& brush = node->getBrush();

		scene::INodePtr parent = node->getParent();

		if (!parent)
		{
			continue;
		}

		// greebo: Analyse the brush to find out which shader is the most used one
		getMostUsedTexturing(brush);

		BrushSplitType split = Brush_classifyPlane(brush, _split == eFront ? -plane : plane);

		if (split.counts[ePlaneBack] && split.counts[ePlaneFront])
		{
			// the plane intersects this brush
			if (_split == eFrontAndBack)
			{
				scene::INodePtr fragmentNode = GlobalBrushCreator().createBrush();

				assert(fragmentNode != NULL);

				// Put the fragment in the same layer as the brush it was clipped from
				// Do this before adding the fragment to the parent, since there is an
				// update algorithm setting the visibility of the fragment right there.
				scene::assignNodeToLayers(fragmentNode, node->getLayers());

				// greebo: For copying the texture scale the new node needs to be inserted in the scene
				// otherwise the shaders cannot be captured and the scale is off

				// Insert the child into the designated parent
				scene::addNodeToContainer(fragmentNode, parent);

				// Select the child
				Node_setSelected(fragmentNode, true);

				Brush* fragment = Node_getBrush(fragmentNode);
				assert(fragment != NULL);
				fragment->copy(brush);

				FacePtr newFace = fragment->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection);

				if (newFace != NULL && _split != eFront)
				{
					newFace->flipWinding();
				}

				fragment->removeEmptyFaces();
				ASSERT_MESSAGE(!fragment->empty(), "brush left with no faces after split");
			}

			FacePtr newFace = brush.addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection);

			if (newFace != NULL && _split == eFront) {
				newFace->flipWinding();
			}

			brush.removeEmptyFaces();
			ASSERT_MESSAGE(!brush.empty(), "brush left with no faces after split");
		}
		// the plane does not intersect this brush
		else if (_split != eFrontAndBack && split.counts[ePlaneBack] != 0)
		{
			// the brush is "behind" the plane
			// Remove the node from the scene
			scene::removeNodeFromParent(node);
		}
	}
}