void ForestTechniqueManager::createTreeList(osg::Node* terrain,const osg::Vec3& origin, const osg::Vec3& size,unsigned int numTreesToCreate,TreeList& trees) { float max_TreeHeight = sqrtf(size.length2()/(float)numTreesToCreate); float max_TreeWidth = max_TreeHeight*0.5f; float min_TreeHeight = max_TreeHeight*0.3f; float min_TreeWidth = min_TreeHeight*0.5f; trees.reserve(trees.size()+numTreesToCreate); for(unsigned int i=0;i<numTreesToCreate;++i) { Tree* tree = new Tree; tree->_position.set(random(origin.x(),origin.x()+size.x()),random(origin.y(),origin.y()+size.y()),origin.z()); tree->_color.set(random(128,255),random(128,255),random(128,255),255); tree->_width = random(min_TreeWidth,max_TreeWidth); tree->_height = random(min_TreeHeight,max_TreeHeight); tree->_type = 0; if (terrain) { osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(tree->_position,tree->_position+osg::Vec3(0.0f,0.0f,size.z())); osgUtil::IntersectionVisitor iv(intersector.get()); terrain->accept(iv); if (intersector->containsIntersections()) { osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections(); for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = intersections.begin(); itr != intersections.end(); ++itr) { const osgUtil::LineSegmentIntersector::Intersection& intersection = *itr; tree->_position = intersection.getWorldIntersectPoint(); } } } trees.push_back(tree); } }
void ForestTechniqueManager::Cell::bin() { // put trees in appropriate cells. TreeList treesNotAssigned; for(TreeList::iterator titr=_trees.begin(); titr!=_trees.end(); ++titr) { Tree* tree = titr->get(); bool assigned = false; for(CellList::iterator citr=_cells.begin(); citr!=_cells.end() && !assigned; ++citr) { if ((*citr)->contains(tree->_position)) { (*citr)->addTree(tree); assigned = true; } } if (!assigned) treesNotAssigned.push_back(tree); } // put the unassigned trees back into the original local tree list. _trees.swap(treesNotAssigned); // prune empty cells. CellList cellsNotEmpty; for(CellList::iterator citr=_cells.begin(); citr!=_cells.end(); ++citr) { if (!((*citr)->_trees.empty())) { cellsNotEmpty.push_back(*citr); } } _cells.swap(cellsNotEmpty); }
RearrangeNodesCommand::RearrangeNodesCommand(const std::list<boost::shared_ptr<NodeGui> >& nodes, QUndoCommand *parent) : QUndoCommand(parent) , _nodes() { ///1) Separate the nodes in trees they belong to, once a node has been "used" by a tree, mark it ///and don't try to reposition it for another tree ///2) For all trees : recursively position each nodes so that each input of a node is positionned as following: /// a) The first non mask input is positionned above the node /// b) All others non mask inputs are positionned on the left of the node, each one separated by the space of half a node /// c) All masks are positionned on the right of the node, each one separated by the space of half a node ///3) Move all trees so that they are next to each other and their "top level" node ///(the input that is at the highest position in the Y coordinate) is at the same ///Y level (node centers have the same Y) std::list<NodeGui*> usedNodes; ///A list of Tree ///Each tree is a lit of nodes with a boolean indicating if it was already positionned( "used" ) by another tree, if set to ///true we don't do anything /// Each node that doesn't have any output is a potential tree. TreeList trees; for (std::list<boost::shared_ptr<NodeGui> >::const_iterator it = nodes.begin(); it!=nodes.end(); ++it) { const std::list<boost::shared_ptr<Natron::Node> >& outputs = (*it)->getNode()->getOutputs(); if (outputs.empty()) { boost::shared_ptr<Tree> newTree(new Tree); newTree->buildTree(*it, usedNodes); trees.push_back(newTree); } } ///For all trees find out which one has the top most level node QPointF topLevelPos(0,INT_MAX); for (TreeList::iterator it = trees.begin(); it!=trees.end(); ++it) { const QPointF& treeTop = (*it)->getTopLevelNodeCenter(); if (treeTop.y() < topLevelPos.y()) { topLevelPos = treeTop; } } ///now offset all trees to be top aligned at the same level for (TreeList::iterator it = trees.begin(); it!=trees.end(); ++it) { const QPointF& treeTop = (*it)->getTopLevelNodeCenter(); QPointF delta(0,topLevelPos.y() - treeTop.y()); if (delta.x() != 0 || delta.y() != 0) { (*it)->moveAllTree(delta); } ///and insert the final result into the _nodes list const std::list<TreeNode>& treeNodes = (*it)->getNodes(); for (std::list<TreeNode>::const_iterator it2 = treeNodes.begin(); it2!=treeNodes.end(); ++it2) { NodeToRearrange n; n.node = it2->first; QSize size = n.node->getSize(); n.newPos = it2->second - QPointF(size.width() / 2.,size.height() / 2.); n.oldPos = n.node->pos(); _nodes.push_back(n); } } }