void Brush::rebuildGeometry() { delete m_geometry; m_geometry = new BrushGeometry(m_worldBounds); // sort the faces by the weight of their plane normals like QBSP does Model::FaceList sortedFaces = m_faces; std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Planef::WeightOrder(true))); std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Planef::WeightOrder(false))); FaceSet droppedFaces; bool success = m_geometry->addFaces(sortedFaces, droppedFaces); assert(success); for (FaceSet::iterator it = droppedFaces.begin(); it != droppedFaces.end(); ++it) { Face* face = *it; face->setBrush(NULL); m_faces.erase(std::remove(m_faces.begin(), m_faces.end(), face), m_faces.end()); delete face; } for (FaceList::iterator it = m_faces.begin(); it != m_faces.end(); ++it) { Face* face = *it; face->invalidateTexAxes(); face->invalidateVertexCache(); } if (m_entity != NULL) m_entity->invalidateGeometry(); }
SplitFacesCommand::SplitFacesCommand(Model::MapDocument& document, const wxString& name, const Model::FaceList& faces, const Vec3f& delta) : SnapshotCommand(Command::MoveVertices, document, name), m_delta(delta) { Model::FaceList::const_iterator it, end; for (it = faces.begin(), end = faces.end(); it != end; ++it) { const Model::Face& face = **it; Model::FaceInfo faceInfo = face.faceInfo(); Model::Brush* brush = face.brush(); BrushFaceMapInsertResult result = m_brushFaces.insert(BrushFaceMapEntry(brush, faceInfo)); assert(result.second); m_brushes.push_back(brush); } }
Model::Brush* MapParser::parseBrush(const BBox& worldBounds, Utility::ProgressIndicator* indicator) { Token token = m_tokenizer.nextToken(); if (token.type() == TokenType::Eof) return NULL; expect(TokenType::OBrace | TokenType::CBrace, token); if (token.type() == TokenType::CBrace) return NULL; const size_t firstLine = token.line(); Model::FaceList faces; while ((token = m_tokenizer.nextToken()).type() != TokenType::Eof) { switch (token.type()) { case TokenType::OParenthesis: { m_tokenizer.pushToken(token); Model::Face* face = parseFace(worldBounds); if (face != NULL) faces.push_back(face); break; } case TokenType::CBrace: { if (indicator != NULL) indicator->update(static_cast<int>(token.position())); Model::Brush* brush = new Model::Brush(worldBounds); // sort the faces by the weight of their plane normals like QBSP does Model::FaceList sortedFaces = faces; std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Plane::WeightOrder(true))); std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Plane::WeightOrder(false))); Model::FaceList::iterator faceIt = sortedFaces.begin(); Model::FaceList::iterator faceEnd = sortedFaces.end(); while (faceIt != faceEnd) { Model::Face* face = *faceIt++; if (!brush->addFace(face)) { m_console.warn("Skipping malformed brush at line %i", firstLine); delete brush; brush = NULL; break; } } // if something went wrong, we must delete all faces that have not been added to the brush yet if (faceIt != faceEnd) Utility::deleteAll(sortedFaces, faceIt); if (brush != NULL) { brush->setFilePosition(firstLine, token.line() - firstLine); if (!brush->closed()) m_console.warn("Non-closed brush at line %i", firstLine); } return brush; } default: { Utility::deleteAll(faces); throw MapParserException(token, TokenType::OParenthesis | TokenType::CParenthesis); } } } return NULL; }