Beispiel #1
0
/// \brief Keep the value of \p infinity as small as possible to improve precision in Winding_Clip.
void Winding_createInfinite(FixedWinding& winding, const Plane3& plane, double infinity)
{
  double max = -infinity;
  int x = -1;
  for (int i=0 ; i<3; i++)
  {
    double d = fabs(plane.normal()[i]);
    if (d > max)
    {
      x = i;
      max = d;
    }
  }
  if(x == -1)
  {
    globalErrorStream() << "invalid plane\n";
    return;
  }
    
  DoubleVector3 vup = g_vector3_identity;  
  switch (x)
  {
  case 0:
  case 1:
    vup[2] = 1;
    break;    
  case 2:
    vup[0] = 1;
    break;    
  }


  vector3_add(vup, vector3_scaled(plane.normal(), -vector3_dot(vup, plane.normal())));
  vector3_normalise(vup);
    
  DoubleVector3 org = vector3_scaled(plane.normal(), plane.dist());
  
  DoubleVector3 vright = vector3_cross(vup, plane.normal());
  
  vector3_scale(vup, infinity);
  vector3_scale(vright, infinity);

  // project a really big  axis aligned box onto the plane
  
  DoubleLine r1, r2, r3, r4;
  r1.origin = vector3_added(vector3_subtracted(org, vright), vup);
  r1.direction = vector3_normalised(vright);
  winding.push_back(FixedWindingVertex(r1.origin, r1, c_brush_maxFaces));
  r2.origin = vector3_added(vector3_added(org, vright), vup);
  r2.direction = vector3_normalised(vector3_negated(vup));
  winding.push_back(FixedWindingVertex(r2.origin, r2, c_brush_maxFaces));
  r3.origin = vector3_subtracted(vector3_added(org, vright), vup);
  r3.direction = vector3_normalised(vector3_negated(vright));
  winding.push_back(FixedWindingVertex(r3.origin, r3, c_brush_maxFaces));
  r4.origin = vector3_subtracted(vector3_subtracted(org, vright), vup);
  r4.direction = vector3_normalised(vup);
  winding.push_back(FixedWindingVertex(r4.origin, r4, c_brush_maxFaces));
}
Beispiel #2
0
void TextureProjection::transformLocked (std::size_t width, std::size_t height, const Plane3& plane,
		const Matrix4& identity2transformed)
{

	Vector3 normalTransformed(matrix4_transformed_direction(identity2transformed, plane.normal()));

	// identity: identity space
	// transformed: transformation
	// stIdentity: base st projection space before transformation
	// stTransformed: base st projection space after transformation
	// stOriginal: original texdef space

	// stTransformed2stOriginal = stTransformed -> transformed -> identity -> stIdentity -> stOriginal

	Matrix4 identity2stIdentity;
	basisForNormal(plane.normal(), identity2stIdentity);

	Matrix4 transformed2stTransformed;
	basisForNormal(normalTransformed, transformed2stTransformed);

	Matrix4 stTransformed2identity(matrix4_affine_inverse(matrix4_multiplied_by_matrix4(transformed2stTransformed,
			identity2transformed)));

	Vector3 originalProjectionAxis(matrix4_affine_inverse(identity2stIdentity).z().getVector3());

	Vector3 transformedProjectionAxis(stTransformed2identity.z().getVector3());

	Matrix4 stIdentity2stOriginal = m_texdef.getTransform((float) width, (float) height);
	Matrix4 identity2stOriginal(matrix4_multiplied_by_matrix4(stIdentity2stOriginal, identity2stIdentity));

	double dot = originalProjectionAxis.dot(transformedProjectionAxis);
	if (dot == 0) {
		// The projection axis chosen for the transformed normal is at 90 degrees
		// to the transformed projection axis chosen for the original normal.
		// This happens when the projection axis is ambiguous - e.g. for the plane
		// 'X == Y' the projection axis could be either X or Y.

		Matrix4 identityCorrected = matrix4_reflection_for_plane45(plane, originalProjectionAxis,
				transformedProjectionAxis);

		identity2stOriginal = matrix4_multiplied_by_matrix4(identity2stOriginal, identityCorrected);
	}

	Matrix4 stTransformed2stOriginal = matrix4_multiplied_by_matrix4(identity2stOriginal, stTransformed2identity);

	setTransform((float) width, (float) height, stTransformed2stOriginal);
	m_texdef.normalise((float) width, (float) height);
}
Beispiel #3
0
Vector3 Winding::centroid(const Plane3& plane) const
{
	Vector3 centroid(0,0,0);

	float area2 = 0, x_sum = 0, y_sum = 0;
	const ProjectionAxis axis = projectionaxis_for_normal(plane.normal());
	const indexremap_t remap = indexremap_for_projectionaxis(axis);

	for (std::size_t i = size() - 1, j = 0; j < size(); i = j, ++j)
	{
		const float ai = (*this)[i].vertex[remap.x]
				* (*this)[j].vertex[remap.y] - (*this)[j].vertex[remap.x]
				* (*this)[i].vertex[remap.y];

		area2 += ai;

		x_sum += ((*this)[j].vertex[remap.x] + (*this)[i].vertex[remap.x]) * ai;
		y_sum += ((*this)[j].vertex[remap.y] + (*this)[i].vertex[remap.y]) * ai;
	}

	centroid[remap.x] = x_sum / (3 * area2);
	centroid[remap.y] = y_sum / (3 * area2);
	{
		Ray ray(Vector3(0, 0, 0), Vector3(0, 0, 0));
		ray.origin[remap.x] = centroid[remap.x];
		ray.origin[remap.y] = centroid[remap.y];
		ray.direction[remap.z] = 1;
		centroid[remap.z] = ray.getDistance(plane);
	}

	return centroid;
}
Beispiel #4
0
/// \brief Returns the point at which \p line intersects \p plane, or an undefined value if there is no intersection.
inline DoubleVector3 line_intersect_plane(const DoubleLine& line, const Plane3& plane)
{
  return line.origin + vector3_scaled(
    line.direction,
    -plane3_distance_to_point(plane, line.origin)
    / vector3_dot(line.direction, plane.normal())
  );
}
Beispiel #5
0
/// \brief Calculate the \p centroid of the polygon defined by \p winding which lies on plane \p plane.
void Winding_Centroid(const Winding& winding, const Plane3& plane, Vector3& centroid)
{
  double area2 = 0, x_sum = 0, y_sum = 0;
  const ProjectionAxis axis = projectionaxis_for_normal(plane.normal());
  const indexremap_t remap = indexremap_for_projectionaxis(axis);
  for(std::size_t i = winding.numpoints-1, j = 0; j < winding.numpoints; i = j, ++j)
  {
    const double ai = winding[i].vertex[remap.x] * winding[j].vertex[remap.y] - winding[j].vertex[remap.x] * winding[i].vertex[remap.y];
    area2 += ai;
    x_sum += (winding[j].vertex[remap.x] + winding[i].vertex[remap.x]) * ai;
    y_sum += (winding[j].vertex[remap.y] + winding[i].vertex[remap.y]) * ai;
  }

  centroid[remap.x] = static_cast<float>(x_sum / (3 * area2));
  centroid[remap.y] = static_cast<float>(y_sum / (3 * area2));
  {
    Ray ray(Vector3(0, 0, 0), Vector3(0, 0, 0));
    ray.origin[remap.x] = centroid[remap.x];
    ray.origin[remap.y] = centroid[remap.y];
    ray.direction[remap.z] = 1;
    centroid[remap.z] = static_cast<float>(ray_distance_to_plane(ray, plane));
  }
}
scene::INodePtr BrushDef3Parser::parse(parser::DefTokeniser& tok) const
{
	// Create a new brush
	scene::INodePtr node = GlobalBrushCreator().createBrush();

	// Cast the node, this must succeed
	IBrushNodePtr brushNode = boost::dynamic_pointer_cast<IBrushNode>(node);
	assert(brushNode != NULL);

	IBrush& brush = brushNode->getIBrush();

	tok.assertNextToken("{");

	// Parse face tokens until a closing brace is encountered
	while (1)
	{
		std::string token = tok.nextToken();

		// Token should be either a "(" (start of face) or "}" (end of brush)
		if (token == "}")
		{
			break; // end of brush
		}
		else if (token == "(") // FACE
		{
			// Construct a plane and parse its values
			Plane3 plane;

			plane.normal().x() = string::to_float(tok.nextToken());
			plane.normal().y() = string::to_float(tok.nextToken());
			plane.normal().z() = string::to_float(tok.nextToken());
			plane.dist() = -string::to_float(tok.nextToken()); // negate d

			tok.assertNextToken(")");

			// Parse TexDef
			Matrix4 texdef;
			tok.assertNextToken("(");

			tok.assertNextToken("(");
			texdef.xx() = string::to_float(tok.nextToken());
			texdef.yx() = string::to_float(tok.nextToken());
			texdef.tx() = string::to_float(tok.nextToken());
			tok.assertNextToken(")");

			tok.assertNextToken("(");
			texdef.xy() = string::to_float(tok.nextToken());
			texdef.yy() = string::to_float(tok.nextToken());
			texdef.ty() = string::to_float(tok.nextToken());
			tok.assertNextToken(")");

			tok.assertNextToken(")");

			// Parse Shader
			std::string shader = tok.nextToken();

			// Parse Flags (usually each brush has all faces detail or all faces structural)
			IBrush::DetailFlag flag = static_cast<IBrush::DetailFlag>(
				string::convert<std::size_t>(tok.nextToken(), IBrush::Structural));
			brush.setDetailFlag(flag);

			// Ignore the other two flags
			tok.skipTokens(2);

			// Finally, add the new face to the brush
			/*IFace& face = */brush.addFace(plane, texdef, shader);
		}
		else {
			std::string text = (boost::format(_("BrushDef3Parser: invalid token '%s'")) % token).str();
			throw parser::ParseException(text);
		}
	}

	// Final outer "}"
	tok.assertNextToken("}");

	return node;
}
Beispiel #7
0
/// \brief Returns the infinite line that is the intersection of \p plane and \p other.
inline DoubleLine plane3_intersect_plane3(const Plane3& plane, const Plane3& other)
{
  DoubleLine line;
  line.direction = vector3_cross(plane.normal(), other.normal());
  switch(vector3_largest_absolute_component_index(line.direction))
  {
  case 0:
    line.origin.x() = 0;
    line.origin.y() = (-other.dist() * plane.normal().z() - -plane.dist() * other.normal().z()) / line.direction.x();
    line.origin.z() = (-plane.dist() * other.normal().y() - -other.dist() * plane.normal().y()) / line.direction.x();
    break;
  case 1:
    line.origin.x() = (-plane.dist() * other.normal().z() - -other.dist() * plane.normal().z()) / line.direction.y();
    line.origin.y() = 0;
    line.origin.z() = (-other.dist() * plane.normal().x() - -plane.dist() * other.normal().x()) / line.direction.y();
    break;
  case 2:
    line.origin.x() = (-other.dist() * plane.normal().y() - -plane.dist() * other.normal().y()) / line.direction.z();
    line.origin.y() = (-plane.dist() * other.normal().x() - -other.dist() * plane.normal().x()) / line.direction.z();
    line.origin.z() = 0;
    break;
  default:
    break;
  }

  return line;
}
Beispiel #8
0
inline double plane3_distance_to_point(const Plane3& plane, const Vector3& point)
{
  return vector3_dot(point, plane.normal()) - plane.dist();
}