void CurveCreateTool::PickPosition(int x, int y, Vector3 &position) { FrustumLinePickVisitor pick (m_Scene->GetViewport()->GetCamera(), x, y); // pick in the world m_PickWorld.Raise( PickArgs( &pick ) ); bool set = false; if (s_SurfaceSnap || s_ObjectSnap) { V_PickHitSmartPtr sorted; PickHit::Sort(m_Scene->GetViewport()->GetCamera(), pick.GetHits(), sorted, PickSortTypes::Intersection); V_PickHitSmartPtr::const_iterator itr = sorted.begin(); V_PickHitSmartPtr::const_iterator end = sorted.end(); for ( ; itr != end; ++itr ) { // don't snap if we are surface snapping with no normal if ( s_SurfaceSnap && !(*itr)->HasNormal() ) { continue; } if ( (*itr)->GetHitObject() != m_Instance ) { SceneGraph::HierarchyNode* node = Reflect::SafeCast<SceneGraph::HierarchyNode>( (*itr)->GetHitObject() ); if ( s_ObjectSnap ) { Vector4 v = node->GetTransform()->GetGlobalTransform().t; position.x = v.x; position.y = v.y; position.z = v.z; } else { position = (*itr)->GetIntersection(); } set = true; break; } } } if (!set) { // place the object on the camera plane m_Scene->GetViewport()->GetCamera()->ViewportToPlaneVertex( (float32_t)x, (float32_t)y, SceneGraph::CreateTool::s_PlaneSnap, position); } }
bool CurveEditTool::MouseDown( const MouseButtonInput& e ) { bool success = true; if ( GetEditMode() == CurveEditModes::Modify ) { success = m_ControlPointManipulator->MouseDown( e ); } else { Curve* curve = NULL; { FrustumLinePickVisitor pick (m_Scene->GetViewport()->GetCamera(), e.GetPosition().x, e.GetPosition().y); m_Scene->Pick( &pick ); V_PickHitSmartPtr sorted; PickHit::Sort(m_Scene->GetViewport()->GetCamera(), pick.GetHits(), sorted, PickSortTypes::Intersection); for ( V_PickHitSmartPtr::const_iterator itr = sorted.begin(), end = sorted.end(); itr != end; ++itr ) { if ( curve = Reflect::SafeCast<Curve>( (*itr)->GetHitObject() ) ) { break; } } } if ( !curve || !m_Scene->IsEditable() ) { return false; } LinePickVisitor pick (m_Scene->GetViewport()->GetCamera(), e.GetPosition().x, e.GetPosition().y); switch ( GetEditMode() ) { case CurveEditModes::Insert: { std::pair<uint32_t, uint32_t> points; if ( !curve->ClosestControlPoints( &pick, points ) ) { return false; } CurveControlPoint* p0 = curve->GetControlPointByIndex( points.first ); CurveControlPoint* p1 = curve->GetControlPointByIndex( points.second ); Vector3 a( p0->GetPosition() ); Vector3 b( p1->GetPosition() ); Vector3 p; if ( curve->GetCurveType() == CurveType::Linear ) { float mu; if ( !pick.GetPickSpaceLine().IntersectsSegment( a, b, -1.0f, &mu ) ) { return false; } p = a * ( 1.0f - mu ) + b * mu; } else { p = ( a + b ) * 0.5f; } uint32_t index = points.first > points.second ? points.first : points.second; CurveControlPointPtr point = new CurveControlPoint(); point->SetOwner( curve->GetOwner() ); point->Initialize(); curve->GetOwner()->Push( curve->InsertControlPointAtIndex( index, point ) ); break; } case CurveEditModes::Remove: { int32_t index = curve->ClosestControlPoint( &pick ); if ( index < 0 ) { return false; } curve->GetOwner()->Push( curve->RemoveControlPointAtIndex( index ) ); break; } } curve->Dirty(); m_Scene->Execute( false ); } return success || Base::MouseDown( e ); }
void PickHit::Sort(Editor::Camera* camera, const V_PickHitSmartPtr& hits, V_PickHitSmartPtr& sorted, PickSortType sortType) { // early out if we have no hits if (hits.empty()) return; // get our camera distance Vector3 cameraPosition; camera->GetPosition(cameraPosition); V_SortKey sortKeys; // for each hit object for ( V_PickHitSmartPtr::const_iterator itr = hits.begin(), end = hits.end(); itr != end; ++itr ) { PickHitPtr hit = *itr; Vector3 intersection; float32_t pickDistance; switch (sortType) { case PickSortTypes::Intersection: case PickSortTypes::Surface: { if (!hit->HasIntersection()) { continue; } intersection = hit->GetIntersection(); pickDistance = hit->GetIntersectionDistance(); break; } case PickSortTypes::Vertex: { if (!hit->HasVertex()) { continue; } intersection = hit->GetVertex(); pickDistance = hit->GetVertexDistance(); break; } } float32_t cameraDistance = (cameraPosition - intersection).LengthSquared(); sortKeys.push_back( SortKey (hit, cameraDistance, pickDistance) ); } switch ( sortType ) { case PickSortTypes::Intersection: { std::sort( sortKeys.begin(), sortKeys.end(), &CompareCameraDistance ); break; } case PickSortTypes::Surface: { std::sort( sortKeys.begin(), sortKeys.end(), &ComparePickDistanceThenCameraDistance ); break; } case PickSortTypes::Vertex: { std::sort( sortKeys.begin(), sortKeys.end(), &ComparePickDistance ); break; } default: { HELIUM_BREAK(); break; } } // clear sorted.clear(); // reserve data for our result sorted.reserve(sortKeys.size()); // dump V_SortKey::const_iterator itr = sortKeys.begin(); V_SortKey::const_iterator end = sortKeys.end(); for( ;itr != end; ++itr ) { sorted.push_back(itr->m_Hit); } }
bool CreateTool::DetermineTranslationAndNormal( PickVisitor& pick, Vector3& t, Vector3& n ) { // pick in the world PickArgs args ( &pick ); m_PickWorld.Raise( args ); bool set = false; if ( s_SurfaceSnap || s_ObjectSnap ) { // process results V_PickHitSmartPtr sorted; PickHit::Sort( m_Scene->GetViewport()->GetCamera(), pick.GetHits(), sorted, PickSortTypes::Intersection ); V_PickHitSmartPtr::const_iterator itr = sorted.begin(); V_PickHitSmartPtr::const_iterator end = sorted.end(); for ( ; itr != end; ++itr ) { Editor::HierarchyNode* node = Reflect::SafeCast<Editor::HierarchyNode>( (*itr)->GetHitObject() ); // don't snap against what we are placing if ( node == m_Instance ) { continue; } // eliminate nodes that are not live when we are live snapping if ( s_LiveObjectsOnly && !node->IsLive() ) { continue; } // don't snap if we are surface snapping with no normal if ( s_SurfaceSnap && !(*itr)->HasNormal() ) { continue; } // don't snap if we don't have an intersection if ( !(*itr)->HasIntersection() ) { continue; } if ( s_ObjectSnap ) { Vector4 v = node->GetTransform()->GetGlobalTransform().t; t.x = v.x; t.y = v.y; t.z = v.z; set = true; } else { t = (*itr)->GetIntersection(); } if ( s_NormalSnap && (*itr)->HasNormal() ) { n = (*itr)->GetNormal(); } set = true; break; } } return set; }