/// \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)); }
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; }
// Get a transformed copy of this frustum Frustum Frustum::getTransformedBy(const Matrix4& matrix) const { // greebo: DR's Plane3 is seriuosly hampered by its internal representation // which is nx,ny,nz,dist instead of a,b,c,d. This causes a lot of confusion // and makes it necessary to invert the dist() member each time before // applying a transformation matrix. Plane3 rightTemp = Plane3(right.normal(), -right.dist()).transform(matrix); Plane3 leftTemp = Plane3(left.normal(), -left.dist()).transform(matrix); Plane3 topTemp = Plane3(top.normal(), -top.dist()).transform(matrix); Plane3 bottomTemp = Plane3(bottom.normal(), -bottom.dist()).transform(matrix); Plane3 backTemp = Plane3(back.normal(), -back.dist()).transform(matrix); Plane3 frontTemp = Plane3(front.normal(), -front.dist()).transform(matrix); rightTemp.dist() = -rightTemp.dist(); leftTemp.dist() = -leftTemp.dist(); topTemp.dist() = -topTemp.dist(); bottomTemp.dist() = -bottomTemp.dist(); backTemp.dist() = -backTemp.dist(); frontTemp.dist() = -frontTemp.dist(); return Frustum( rightTemp, leftTemp, bottomTemp, topTemp, backTemp, frontTemp ); }
/// \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; }
inline double plane3_distance_to_point(const Plane3& plane, const Vector3& point) { return vector3_dot(point, plane.normal()) - plane.dist(); }