Guest User

Untitled

a guest
Mar 9th, 2019
908
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 47.66 KB | None | 0 0
  1. //---------------------------------------------------------------------------
  2. #ifndef UModelH
  3. #define UModelH
  4. //---------------------------------------------------------------------------
  5. #include <Ray.h>
  6. #include <Documents.h>
  7. #include <DocNodes.h>
  8. #include <Pair.h>
  9. //---------------------------------------------------------------------------
  10. // Forward class declarations
  11. class CTexture;
  12. //---------------------------------------------------------------------------
  13. // Radius for a vertex sphere used by ray hit checks
  14. #define VERTEX_RADIUS 0.06f
  15. //---------------------------------------------------------------------------
  16. // Selection mode
  17. enum ESelectionMode
  18. {
  19.     SM_VERTEX,
  20.     SM_FACE,
  21.     SM_OBJECT
  22. };
  23. //---------------------------------------------------------------------------
  24. // Selection action
  25. enum ESelectionAction
  26. {
  27.     SA_SELECT,
  28.     SA_DESELECT,
  29.     SA_TOGGLE
  30. };
  31. //---------------------------------------------------------------------------
  32. // Coordinate restriction for operations
  33. enum ECoordinateRestriction
  34. {
  35.     CR_NONE,        // Do not restrict
  36.     CR_XAXIS,       // Restrict to X axis
  37.     CR_YAXIS,       // Restrict to Y axis
  38.     CR_ZAXIS        // Restrict to Z axis
  39. };
  40. //---------------------------------------------------------------------------
  41. // Geometries available for adding to a model
  42. enum EGeometry
  43. {
  44.     G_PLANE,
  45.     G_CUBE,
  46.     G_OCTAGON,
  47.     G_CONE,
  48.     G_CYLINDER,
  49.     G_SPHERE,
  50.     G_ISOSPHERE
  51. };
  52. //---------------------------------------------------------------------------
  53. // A single vertex for a mesh
  54. struct SVertex
  55. {
  56.     AVector     P;
  57.     AVector     N;
  58.     float       S, T;
  59.     bool        Selected:1;
  60.     bool        Marked:1;
  61.     bool        Mask:1;
  62.  
  63.     // Empty constructor
  64.     inline SVertex()
  65.         : P(0.0f, 0.0f, 0.0f)
  66.         , N(0.0f, 0.0f, 0.0f)
  67.         , S(0.0f)
  68.         , T(0.0f)
  69.         , Selected(false)
  70.         , Marked(false)
  71.         , Mask(false)
  72.     {
  73.     }
  74.     // Copy constructor
  75.     inline SVertex(const SVertex& src)
  76.     {
  77.         operator=(src);
  78.     }
  79.     // Full values constructor
  80.     inline SVertex(const AVector& p, const AVector& n, float s, float t)
  81.         : P(p)
  82.         , N(n)
  83.         , S(s)
  84.         , T(t)
  85.         , Selected(false)
  86.         , Marked(false)
  87.         , Mask(false)
  88.     {
  89.     }
  90.  
  91.     // Assignment operator
  92.     inline const SVertex& operator=(const SVertex& rhs)
  93.     {
  94.         if (&rhs != this) {
  95.             P = rhs.P;
  96.             N = rhs.N;
  97.             S = rhs.S;
  98.             T = rhs.T;
  99.             Selected = rhs.Selected;
  100.             Marked = rhs.Marked;
  101.             Mask = rhs.Mask;
  102.         }
  103.         return *this;
  104.     }
  105.  
  106.     // Equality operator (needed for TDynArray usage)
  107.     inline bool operator==(const SVertex& rhs) const
  108.     {
  109.         return P==rhs.P && N==rhs.N && S==rhs.S && T==rhs.T;
  110.     }
  111.     // Inequality operator
  112.     inline bool operator!=(const SVertex& rhs) const
  113.     {
  114.         return P!=rhs.P || N!=rhs.N || S!=rhs.S || T!=rhs.T;
  115.     }
  116. };
  117. //---------------------------------------------------------------------------
  118. // A single face for a mesh
  119. struct SFace
  120. {
  121.     unsigned    A, B, C;    // Vertex indices
  122.     bool        Selected;
  123.  
  124.     // Empty constructor
  125.     inline SFace()
  126.         : Selected(false)
  127.     {
  128.     }
  129.     // Copy constructor
  130.     inline SFace(const SFace& src)
  131.         : A(src.A), B(src.B), C(src.C)
  132.         , Selected(false)
  133.     {
  134.     }
  135.     // Full values constructor
  136.     inline SFace(unsigned a, unsigned b, unsigned c)
  137.         : A(a), B(b), C(c)
  138.         , Selected(false)
  139.     {
  140.     }
  141.  
  142.     // Assignment operator
  143.     inline const SFace& operator=(const SFace& rhs)
  144.     {
  145.         if (&rhs != this) {
  146.             A = rhs.A;
  147.             B = rhs.B;
  148.             C = rhs.C;
  149.             Selected = rhs.Selected;
  150.         }
  151.         return *this;
  152.     }
  153.  
  154.     // Equality operator (needed for TDynArray usage)
  155.     inline bool operator==(const SFace& rhs) const
  156.     {
  157.         return A==rhs.A && B==rhs.B && C==rhs.C;
  158.     }
  159.     // Inequality operator
  160.     inline bool operator!=(const SFace& rhs) const
  161.     {
  162.         return A!=rhs.A || B!=rhs.B || C!=rhs.C;
  163.     }
  164. };
  165. //---------------------------------------------------------------------------
  166. // A mesh in the model
  167. class CMesh : public CDocNode
  168. {
  169. public:
  170.     CMesh();
  171.     virtual ~CMesh();
  172.     // Adds a new vertex to this mesh and returns its index
  173.     unsigned AddVertex(const SVertex& v);
  174.     // Removes the vertex at the given index in the vertex array any faces that
  175.     // refer to that vertex
  176.     void RemoveVertex(unsigned idx);
  177.     // Removes all vertices and faces from this mesh
  178.     void RemoveAll();
  179.     // Searches for the index of a vertex in the vertex array that matches the
  180.     // given one and returns true if the vertex was found
  181.     bool FindVertex(const SVertex& v, unsigned& index) const;
  182.     // Searches for the index of a vertex in the vertex array that is at the
  183.     // given position and returns true if the vertex was found
  184.     bool FindVertexAt(const AVector& p, unsigned& index) const;
  185.     // Searches for the vertices near the given position fills the given array
  186.     // with the vertex indices, returns false if no vertices were found
  187.     bool FindVerticesNear(const AVector& p, float distance, TDynArray<unsigned>& indices) const;
  188.     // Returns the face indices using the given vertex, returns false if the
  189.     // vertex has no faces associated with it
  190.     bool FindVertexUsers(unsigned vidx, TDynArray<unsigned>& fidx) const;
  191.     // Adds the given new face and returns the index in the faces array
  192.     unsigned AddFace(const SFace& face);
  193.     // Removes the face at the given index
  194.     void RemoveFace(unsigned idx);
  195.     // Returns true if the given ray hits a vertex while treating each vertex
  196.     // as sphere with the given radius and fills the vertex index and
  197.     // intersection point if so
  198.     bool RayVertexHit(const ARay& ray, float radius, unsigned& vidx, AVector& ip) const;
  199.     // Returns true if the given ray hits a face and fills the face index and
  200.     // intersection point if so
  201.     bool RayFaceHit(const ARay& ray, unsigned& fidx, AVector& ip) const;
  202.     // Merge nearby selected vertices in this mesh
  203.     void MergeVertices(float distance, bool maskOnly);
  204.     // Clear the mask flag from all vertices
  205.     void ClearMask();
  206.     // Set the selected flag
  207.     inline void SetSelected(bool selected) { m_selected = selected; }
  208.     // Returns the texture this mesh is using
  209.     inline const CTexture* GetTexture() const { return m_texture; }
  210.     // Returns the vertices in this mesh
  211.     inline TDynArray<SVertex>& GetVertices() { return m_vertices; }
  212.     // Returns the faces in this mesh
  213.     inline TDynArray<SFace>& GetFaces() { return m_faces; }
  214.     // Returns true if this mesh is selected
  215.     inline bool IsSelected() const { return m_selected; }
  216. private:
  217.     TDynArray<SVertex>  m_vertices; // Mesh vertices
  218.     TDynArray<SFace>    m_faces;    // Mesh faces
  219.     CTexture*           m_texture;  // Mesh texture
  220.     bool                m_selected; // The mesh is selected
  221. };
  222. //---------------------------------------------------------------------------
  223. // Model document class, contains the data for the edited model
  224. class CModel : public CDocument, public CDocRootNode
  225. {
  226. public:
  227.     CModel();
  228.     virtual ~CModel();
  229.     // Creates a new mesh in this model
  230.     CMesh* CreateMesh();
  231.     // Returns true if the given ray hits a node and fills the node and
  232.     // intersection point if so
  233.     bool RayNodeHit(const ARay& ray, CDocNode*& node, AVector& ip) const;
  234.     // Set the selection mode
  235.     void SetSelectionMode(ESelectionMode selectionMode);
  236.     // Clear the current selection
  237.     void ClearSelection();
  238.     // Select an element using the given ray
  239.     void SelectByRay(const ARay& ray, ESelectionAction& action);
  240.     // Select everything
  241.     void SelectAll();
  242.     // Collect pointers to selected vertices
  243.     void CollectSelectedVertices(TDynArray< TPair<CMesh*,unsigned> >& vertices) const;
  244.     // Clear the target mesh for new geometry
  245.     void ClearTargetMesh();
  246.     // Set the target mesh from the selection, returns false on empty selection
  247.     bool SetTargetMeshFromSelection();
  248.     // Returns the target mesh used to add new geometry
  249.     CMesh* GetTargetMesh(bool createNewIfNone);
  250.     // Set the 3D cursor
  251.     void SetCursor(const AVector& cursor);
  252.     // Set the 3D cursor from the selection, returns false on invalid selection
  253.     bool SetCursorFromSelection();
  254.     // Set the lockplane to the given plane
  255.     void SetLockPlane(const APlane& plane);
  256.     // Set the lockplane from the selection, returns false on invalid selection
  257.     bool SetLockPlaneFromSelection();
  258.     // Clear the lockplane
  259.     void ClearLockPlane();
  260.     // Set the coordinate restriction
  261.     void SetCoordinateRestriction(ECoordinateRestriction coordRestrict);
  262.     // Searches for the vertices near the given position fills the given array
  263.     // with the mesh and vertex index pairs, returns false if no vertices were
  264.     // found
  265.     bool FindVerticesNear(const AVector& p, float distance, TDynArray< TPair<CMesh*,unsigned> >& vertices) const;
  266.     // Weld (move at the same spot) selected vertices
  267.     void WeldVertices(float distance);
  268.     // Merge nearby selected vertices in all selected meshes
  269.     void MergeVertices(float distance);
  270.     // Split the selected vertices so that no selected face shares vertices
  271.     // with another face
  272.     void SplitVertices();
  273.     // Flip the selected faces
  274.     void FlipFaces();
  275.     // Flip the selected vertex normals
  276.     void FlipNormals();
  277.     // Recalculate the normals for the selected vertices
  278.     void RecalcNormals();
  279.     // Select the vertices that are nearby to the already selected vertices
  280.     void SelectNearbyVertices(float distance);
  281.     // Add the given geometry either as a new mesh or as geometry to the
  282.     // current target mesh (use ClearTargetMesh to force a new mesh), returns
  283.     // the mesh that was used for the new geometry
  284.     CMesh* AddGeometry(EGeometry geo);
  285.     // Delete the selection
  286.     void DeleteSelection();
  287.     // Delete the selected faces only
  288.     void DeleteSelectedFaces();
  289.     // Returns the current selection mode
  290.     inline ESelectionMode GetSelectionMode() const { return m_selectionMode; }
  291.     // Returns the 3D cursor
  292.     inline const AVector& GetCursor() const { return m_cursor; }
  293.     // Returns the lockplane
  294.     inline const APlane& GetLockPlane() const { return m_lockPlane; }
  295.     // Returns true if there is a lockplane
  296.     inline bool HasLockPlane() const { return m_lockPlane != APlane(0.0f, 0.0f, 0.0f, 0.0f); }
  297.     // Returns the current coordinate restriction
  298.     inline ECoordinateRestriction GetCoordinateRestriction() const { return m_coordRestrict; }
  299. private:
  300.     TDynArray< TPair<CDocNode*,unsigned> >  m_selection;        // Currently selected elements
  301.     ESelectionMode                          m_selectionMode;    // Current selection mode
  302.     CMesh*                                  m_targetMesh;       // Mesh to use as a target for new geometry
  303.     AVector                                 m_cursor;           // 3D cursor
  304.     APlane                                  m_lockPlane;        // Lockplane (used by tools)
  305.     ECoordinateRestriction                  m_coordRestrict;    // Current coordinate restriction
  306. protected:
  307.     // CDocument
  308.     virtual CDocView* CreateView(int);
  309. protected:
  310.     // CNode
  311.     virtual void OnChildRemoved(CNode* node);
  312. };
  313. //---------------------------------------------------------------------------
  314. #endif
  315.  
  316. //---------------------------------------------------------------------------
  317. #pragma hdrstop
  318. #include <HashMap.h>
  319. #include "UModelView.h"
  320. #include "UModel.h"
  321. #include "UTools.h"
  322. //---------------------------------------------------------------------------
  323. // Mesh data used for primitives
  324. #include "MeshData.inc"
  325. //---------------------------------------------------------------------------
  326. // CMesh implementation
  327. CMesh::CMesh()
  328.     : m_texture(NULL)
  329.     , m_selected(false)
  330. {
  331. }
  332. //---------------------------------------------------------------------------
  333. CMesh::~CMesh()
  334. {
  335.     GTool->ObjectDestroyed(this);
  336. }
  337. //---------------------------------------------------------------------------
  338. unsigned CMesh::AddVertex(const SVertex& v)
  339. {
  340.     m_vertices.Add(v);
  341.     MarkModified();
  342.     return m_vertices.GetSize() - 1;
  343. }
  344. //---------------------------------------------------------------------------
  345. void CMesh::RemoveVertex(unsigned idx)
  346. {
  347.     DEBUG_ASSERT(idx < m_vertices.GetSize(), "invalid vertex index");
  348.     m_vertices.RemoveAt(idx);
  349.     // Remove any faces that refer to this index
  350.     if (m_faces.HasItems())
  351.     {
  352.         for (unsigned i=m_faces.GetSize() - 1;;i--)
  353.         {
  354.             if (m_faces[i].A == idx || m_faces[i].B == idx || m_faces[i].C == idx)
  355.             {
  356.                 m_faces.RemoveAt(i);
  357.             }
  358.             if (!i) break;
  359.         }
  360.         // Adjust remaining indices
  361.         for (unsigned i=0; i < m_faces.GetSize(); ++i)
  362.         {
  363.             if (m_faces[i].A > idx) m_faces[i].A--;
  364.             if (m_faces[i].B > idx) m_faces[i].B--;
  365.             if (m_faces[i].C > idx) m_faces[i].C--;
  366.         }
  367.     }
  368.     MarkModified();
  369. }
  370. //---------------------------------------------------------------------------
  371. void CMesh::RemoveFace(unsigned idx)
  372. {
  373.     DEBUG_ASSERT(idx < m_faces.GetSize(), "invalid face index");
  374.     m_faces.RemoveAt(idx);
  375.     MarkModified();
  376. }
  377. //---------------------------------------------------------------------------
  378. void CMesh::RemoveAll()
  379. {
  380.     m_vertices.Clear();
  381.     m_faces.Clear();
  382.     MarkModified();
  383. }
  384. //---------------------------------------------------------------------------
  385. bool CMesh::FindVertex(const SVertex& v, unsigned& index) const
  386. {
  387.     for (unsigned i=0; i < m_vertices.GetSize(); ++i)
  388.     {
  389.         if (v == m_vertices[i])
  390.         {
  391.             index = i;
  392.             return true;
  393.         }
  394.     }
  395.     return false;
  396. }
  397. //---------------------------------------------------------------------------
  398. bool CMesh::FindVertexAt(const AVector& p, unsigned& index) const
  399. {
  400.     for (unsigned i=0; i < m_vertices.GetSize(); ++i)
  401.     {
  402.         if (p == m_vertices[i].P)
  403.         {
  404.             index = i;
  405.             return true;
  406.         }
  407.     }
  408.     return false;
  409. }
  410. //---------------------------------------------------------------------------
  411. bool CMesh::FindVerticesNear(const AVector& p, float distance, TDynArray<unsigned>& indices) const
  412. {
  413.     unsigned start = indices.GetSize();
  414.     distance = distance*distance;
  415.     for (unsigned i=0; i < m_vertices.GetSize(); ++i)
  416.     {
  417.         if (NVector::TDistanceSquared3D(p, m_vertices[i].P) <= distance)
  418.         {
  419.             indices.AddUnique(i);
  420.         }
  421.     }
  422.     return start < indices.GetSize();
  423. }
  424. //---------------------------------------------------------------------------
  425. bool CMesh::FindVertexUsers(unsigned vidx, TDynArray<unsigned>& fidx) const
  426. {
  427.     unsigned start = fidx.GetSize();
  428.     for (unsigned i=0; i < m_faces.GetSize(); ++i)
  429.     {
  430.         if (m_faces[i].A == vidx) fidx.Add(i);
  431.         if (m_faces[i].B == vidx) fidx.Add(i);
  432.         if (m_faces[i].C == vidx) fidx.Add(i);
  433.     }
  434.     return start < fidx.GetSize();
  435. }
  436. //---------------------------------------------------------------------------
  437. unsigned CMesh::AddFace(const SFace& face)
  438. {
  439.     DEBUG_ASSERT(face.A < m_vertices.GetSize(), "invalid A vertex index");
  440.     DEBUG_ASSERT(face.B < m_vertices.GetSize(), "invalid B vertex index");
  441.     DEBUG_ASSERT(face.C < m_vertices.GetSize(), "invalid C vertex index");
  442.     m_faces.Add(face);
  443.     return m_faces.GetSize() - 1;
  444. }
  445. //---------------------------------------------------------------------------
  446. bool CMesh::RayVertexHit(const ARay& ray, float radius, unsigned& vidx, AVector& ip) const
  447. {
  448.     AVector tmpIP;
  449.     float distance, bestDistance = 0xFFFFFFFF;
  450.     vidx = -1;
  451.     for (unsigned i=0; i < m_vertices.GetSize(); ++i)
  452.     {
  453.         if (NRay::TSphereHit3D(ray, m_vertices[i].P, radius, tmpIP))
  454.         {
  455.             distance = NVector::TDistanceSquared3D(ray.O, tmpIP);
  456.             if (vidx == -1 || distance < bestDistance)
  457.             {
  458.                 bestDistance = distance;
  459.                 ip = tmpIP;
  460.                 vidx = i;
  461.             }
  462.         }
  463.     }
  464.     return vidx != -1;
  465. }
  466. //---------------------------------------------------------------------------
  467. bool CMesh::RayFaceHit(const ARay& ray, unsigned& fidx, AVector& ip) const
  468. {
  469.     AVector tmpIP;
  470.     float distance, bestDistance = 0xFFFFFFFF;
  471.     fidx = -1;
  472.     for (unsigned i=0; i < m_faces.GetSize(); ++i)
  473.     {
  474.         const SFace& face = m_faces[i];
  475.         if (NRay::TTriangleHit3D(ray,
  476.             m_vertices[face.A].P, m_vertices[face.B].P, m_vertices[face.C].P, tmpIP))
  477.         {
  478.             distance = NVector::TDistanceSquared3D(ray.O, tmpIP);
  479.             if (fidx == -1 || distance < bestDistance)
  480.             {
  481.                 bestDistance = distance;
  482.                 ip = tmpIP;
  483.                 fidx = i;
  484.             }
  485.         }
  486.     }
  487.     return fidx != -1;
  488. }
  489. //---------------------------------------------------------------------------
  490. void CMesh::MergeVertices(float distance, bool maskOnly)
  491. {
  492.     TDynArray<unsigned> toDelete;
  493.     if (m_vertices.GetSize() == 0) return;
  494.     for (unsigned i=m_vertices.GetSize() - 1;; --i)
  495.     {
  496.         if (maskOnly && !m_vertices[i].Mask)
  497.         {
  498.             if (!i) break;
  499.             continue;
  500.         }
  501.         if (!toDelete.Contains(i))
  502.         {
  503.             unsigned base = toDelete.GetSize();
  504.             FindVerticesNear(m_vertices[i].P, distance, toDelete);
  505.             toDelete.Remove(i);
  506.             if (maskOnly && toDelete.HasItems())
  507.             {
  508.                 for (unsigned j=toDelete.GetSize() - 1;; --j)
  509.                 {
  510.                     if (!m_vertices[toDelete[j]].Mask) toDelete.RemoveAt(j);
  511.                     if (!j) break;
  512.                 }
  513.             }
  514.             for (unsigned j=0; j < m_faces.GetSize(); ++j)
  515.             {
  516.                 SFace& face = m_faces[j];
  517.                 for (unsigned k=base; k < toDelete.GetSize(); ++k)
  518.                 {
  519.                     if (face.A == toDelete[k]) face.A = i;
  520.                     if (face.B == toDelete[k]) face.B = i;
  521.                     if (face.C == toDelete[k]) face.C = i;
  522.                 }
  523.             }
  524.         }
  525.         if (!i) break;
  526.     }
  527.     toDelete.Sort(NDynArray::TDescending);
  528.     if (toDelete.HasItems())
  529.     {
  530.         for (unsigned i=0; i < toDelete.GetSize(); ++i)
  531.             RemoveVertex(toDelete[i]);
  532.         MarkModified();
  533.     }
  534. }
  535. //---------------------------------------------------------------------------
  536. void CMesh::ClearMask()
  537. {
  538.     for (unsigned i=0; i < m_vertices.GetSize(); ++i) m_vertices[i].Mask = false;
  539. }
  540. //---------------------------------------------------------------------------
  541. // CModel implementation
  542. CModel::CModel()
  543.     : CDocument()
  544.     , CDocRootNode(this)
  545.     , m_selectionMode(SM_FACE)
  546.     , m_targetMesh(NULL)
  547.     , m_cursor(0, 0, 0)
  548.     , m_lockPlane(0, 0, 0, 0)
  549.     , m_coordRestrict(CR_NONE)
  550. {
  551. }
  552. //---------------------------------------------------------------------------
  553. CModel::~CModel()
  554. {
  555.     GTool->ObjectDestroyed(this);
  556. }
  557. //---------------------------------------------------------------------------
  558. CMesh* CModel::CreateMesh()
  559. {
  560.     DEBUG_ASSERT(CanModify(), "Tried to create a mesh in an unmodifiable model");
  561.     CMesh* mesh = new CMesh();
  562.     AddChild(mesh);
  563.     CDocument::MarkModified();
  564.     return mesh;
  565. }
  566. //---------------------------------------------------------------------------
  567. void CModel::SetSelectionMode(ESelectionMode selectionMode)
  568. {
  569.     TDynArray< TPair<CMesh*,unsigned> > vertices;
  570.     if (m_selectionMode == selectionMode) return;
  571.     CollectSelectedVertices(vertices);
  572.     ClearSelection();
  573.     m_selectionMode = selectionMode;
  574.     if (vertices.HasItems())
  575.     {
  576.         unsigned i;
  577.         switch (selectionMode)
  578.         {
  579.         case SM_VERTEX:
  580.             for (i=0; i < vertices.GetSize(); ++i)
  581.             {
  582.                 vertices[i].First->GetVertices()[vertices[i].Second].Selected = true;
  583.                 m_selection.Add(TPair<CDocNode*,unsigned>(vertices[i].First, vertices[i].Second));
  584.             }
  585.             break;
  586.         case SM_FACE:
  587.             for (i=0; i < vertices.GetSize(); ++i)
  588.             {
  589.                 vertices[i].First->GetVertices()[vertices[i].Second].Mask = true;
  590.             }
  591.             for (i=0; i < GetChildCount(); ++i)
  592.             {
  593.                 CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  594.                 if (!mesh) continue;
  595.                 TDynArray<SFace>& faces = mesh->GetFaces();
  596.                 for (unsigned j=0; j < faces.GetSize(); ++j)
  597.                 {
  598.                     if (mesh->GetVertices()[faces[j].A].Mask &&
  599.                         mesh->GetVertices()[faces[j].B].Mask &&
  600.                         mesh->GetVertices()[faces[j].C].Mask)
  601.                     {
  602.                         faces[j].Selected = true;
  603.                         m_selection.Add(TPair<CDocNode*,unsigned>(mesh, j));
  604.                     }
  605.                 }
  606.             }
  607.             for (i=0; i < vertices.GetSize(); ++i)
  608.             {
  609.                 vertices[i].First->GetVertices()[vertices[i].Second].Mask = false;
  610.             }
  611.             break;
  612.         case SM_OBJECT:
  613.             {} // TODO
  614.         }
  615.     }
  616.     InvalidateViews();
  617. }
  618. //---------------------------------------------------------------------------
  619. void CModel::ClearSelection()
  620. {
  621.     unsigned i;
  622.     switch (m_selectionMode)
  623.     {
  624.     case SM_VERTEX:
  625.         for (i=0; i < m_selection.GetSize(); ++i)
  626.         {
  627.             DEBUG_ASSERT(dynamic_cast<CMesh*>(m_selection[i].First), "Selected vertex is not associated with a mesh");
  628.             static_cast<CMesh*>(m_selection[i].First)->GetVertices()[m_selection[i].Second].Selected = false;
  629.         }
  630.         break;
  631.     case SM_FACE:
  632.         for (i=0; i < m_selection.GetSize(); ++i)
  633.         {
  634.             DEBUG_ASSERT(dynamic_cast<CMesh*>(m_selection[i].First), "Selected face is not associated with a mesh");
  635.             static_cast<CMesh*>(m_selection[i].First)->GetFaces()[m_selection[i].Second].Selected = false;
  636.         }
  637.         break;
  638.     case SM_OBJECT:
  639.         for (i=0; i < m_selection.GetSize(); ++i)
  640.         {
  641.             CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  642.             if (!mesh) continue;
  643.             mesh->SetSelected(false);
  644.         }
  645.         break;
  646.     }
  647.     m_selection.Clear();
  648.     InvalidateViews();
  649. }
  650. //---------------------------------------------------------------------------
  651. bool CModel::RayNodeHit(const ARay& ray, CDocNode*& node, AVector& ip) const
  652. {
  653.     AVector tmpIP;
  654.     float distance, bestDistance = 0xFFFFFFFF;
  655.     unsigned index;
  656.     node = NULL;
  657.     for (unsigned i=0; i < GetChildCount(); ++i)
  658.     {
  659.         CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  660.         if (!mesh) continue;
  661.         if (mesh->RayFaceHit(ray, index, tmpIP))
  662.         {
  663.             distance = NVector::TDistanceSquared3D(ray.O, tmpIP);
  664.             if (!node || bestDistance > distance)
  665.             {
  666.                 bestDistance = distance;
  667.                 node = mesh;
  668.                 ip = tmpIP;
  669.             }
  670.         }
  671.     }
  672.     if (!node)
  673.     {
  674.         for (unsigned i=0; i < GetChildCount(); ++i)
  675.         {
  676.             CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  677.             if (!mesh) continue;
  678.             if (mesh->RayVertexHit(ray, VERTEX_RADIUS, index, tmpIP))
  679.             {
  680.                 distance = NVector::TDistanceSquared3D(ray.O, tmpIP);
  681.                 if (!node || bestDistance > distance)
  682.                 {
  683.                     bestDistance = distance;
  684.                     node = mesh;
  685.                     ip = tmpIP;
  686.                 }
  687.             }
  688.         }
  689.     }
  690.     return node != NULL;
  691. }
  692. //---------------------------------------------------------------------------
  693. void CModel::SelectByRay(const ARay& ray, ESelectionAction& action)
  694. {
  695.     CDocNode* node;
  696.     CMesh* mesh;
  697.     AVector ip;
  698.     unsigned index;
  699.     if (!RayNodeHit(ray, node, ip)) return;
  700.     mesh = dynamic_cast<CMesh*>(node);
  701.     if (!mesh) return;
  702.     switch (m_selectionMode)
  703.     {
  704.     case SM_VERTEX:
  705.         if (!mesh->RayVertexHit(ray, VERTEX_RADIUS, index, ip)) return;
  706.         if (action == SA_TOGGLE)
  707.             action = mesh->GetVertices()[index].Selected ? SA_DESELECT : SA_SELECT;
  708.         if (action == SA_SELECT)
  709.         {
  710.             m_selection.AddUnique(TPair<CDocNode*,unsigned>(mesh, index));
  711.             mesh->GetVertices()[index].Selected = true;
  712.         }
  713.         else
  714.         {
  715.             m_selection.Remove(TPair<CDocNode*,unsigned>(mesh, index));
  716.             mesh->GetVertices()[index].Selected = false;
  717.         }
  718.         if (!m_targetMesh) m_targetMesh = mesh;
  719.         break;
  720.     case SM_FACE:
  721.         if (!mesh->RayFaceHit(ray, index, ip)) return;
  722.         if (action == SA_TOGGLE)
  723.             action = mesh->GetFaces()[index].Selected ? SA_DESELECT : SA_SELECT;
  724.         if (action == SA_SELECT)
  725.         {
  726.             m_selection.AddUnique(TPair<CDocNode*,unsigned>(mesh, index));
  727.             mesh->GetFaces()[index].Selected = true;
  728.         }
  729.         else
  730.         {
  731.             m_selection.Remove(TPair<CDocNode*,unsigned>(mesh, index));
  732.             mesh->GetFaces()[index].Selected = false;
  733.         }
  734.         if (!m_targetMesh) m_targetMesh = mesh;
  735.         break;
  736.     case SM_OBJECT:
  737.         if (action == SA_TOGGLE)
  738.             action = mesh->IsSelected() ? SA_DESELECT : SA_SELECT;
  739.         if (action == SA_SELECT)
  740.         {
  741.             m_selection.AddUnique(TPair<CDocNode*,unsigned>(mesh, 0));
  742.             mesh->SetSelected(true);
  743.         }
  744.         else
  745.         {
  746.             m_selection.Remove(TPair<CDocNode*,unsigned>(mesh, 0));
  747.             mesh->SetSelected(false);
  748.         }
  749.         if (!m_targetMesh) m_targetMesh = mesh;
  750.         break;
  751.     default:
  752.         DEBUG_FAIL("Invalid selection mode");
  753.     }
  754.     InvalidateViews();
  755. }
  756. //---------------------------------------------------------------------------
  757. void CModel::SelectAll()
  758. {
  759.     unsigned i, j;
  760.     ClearSelection();
  761.     switch (m_selectionMode)
  762.     {
  763.     case SM_VERTEX:
  764.         for (i=0; i < GetChildCount(); ++i)
  765.         {
  766.             CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  767.             if (!mesh) continue;
  768.             for (j=0; j < mesh->GetVertices().GetSize(); ++j)
  769.             {
  770.                 mesh->GetVertices()[j].Selected = true;
  771.                 m_selection.Add(TPair<CDocNode*,unsigned>(mesh, j));
  772.             }
  773.         }
  774.         break;
  775.     case SM_FACE:
  776.         for (i=0; i < GetChildCount(); ++i)
  777.         {
  778.             CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  779.             if (!mesh) continue;
  780.             for (j=0; j < mesh->GetFaces().GetSize(); ++j)
  781.             {
  782.                 mesh->GetFaces()[j].Selected = true;
  783.                 m_selection.Add(TPair<CDocNode*,unsigned>(mesh, j));
  784.             }
  785.         }
  786.         break;
  787.     case SM_OBJECT:
  788.         for (i=0; i < GetChildCount(); ++i)
  789.         {
  790.             CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  791.             if (!mesh) continue;
  792.             mesh->SetSelected(true);
  793.             m_selection.Add(TPair<CDocNode*,unsigned>(mesh, 0));
  794.         }
  795.         break;
  796.     }
  797.     InvalidateViews();
  798. }
  799. //---------------------------------------------------------------------------
  800. void CModel::CollectSelectedVertices(TDynArray< TPair<CMesh*,unsigned> >& vertices) const
  801. {
  802.     // NOTE: it might be a good idea to update the selected flag in vertices
  803.     // regardless of selection mode so that this method only has to go through
  804.     // all vertices once instead
  805.     unsigned i;
  806.     switch (m_selectionMode)
  807.     {
  808.     case SM_VERTEX:
  809.         vertices.SetCapacity(m_selection.GetSize());
  810.         for (i=0; i < m_selection.GetSize(); ++i)
  811.         {
  812.             vertices.Add(TPair<CMesh*,unsigned>(
  813.                 static_cast<CMesh*>(m_selection[i].First),
  814.                 m_selection[i].Second));
  815.         }
  816.         break;
  817.     case SM_FACE:
  818.         vertices.SetCapacity(m_selection.GetSize()*3);
  819.         for (i=0; i < m_selection.GetSize(); ++i)
  820.         {
  821.             CMesh* mesh = static_cast<CMesh*>(m_selection[i].First);
  822.             const SFace& face = mesh->GetFaces()[m_selection[i].Second];
  823.             vertices.AddUnique(TPair<CMesh*,unsigned>(mesh, face.A));
  824.             vertices.AddUnique(TPair<CMesh*,unsigned>(mesh, face.B));
  825.             vertices.AddUnique(TPair<CMesh*,unsigned>(mesh, face.C));
  826.         }
  827.         break;
  828.     case SM_OBJECT:
  829.         for (i=0; i < m_selection.GetSize(); ++i)
  830.         {
  831.             CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  832.             if (!mesh) continue;
  833.             for (unsigned j=0; j < mesh->GetVertices().GetSize(); ++j)
  834.                 vertices.Add(TPair<CMesh*,unsigned>(mesh, j));
  835.         }
  836.         break;
  837.     }
  838. }
  839. //---------------------------------------------------------------------------
  840. void CModel::ClearTargetMesh()
  841. {
  842.     if (!m_targetMesh) return;
  843.     m_targetMesh = NULL;
  844.     InvalidateViews();
  845. }
  846. //---------------------------------------------------------------------------
  847. bool CModel::SetTargetMeshFromSelection()
  848. {
  849.     if (m_selection.IsEmpty()) return false;
  850.     CMesh* targetMesh = dynamic_cast<CMesh*>(m_selection[0].First);
  851.     if (!targetMesh) return false;
  852.     if (targetMesh != m_targetMesh)
  853.     {
  854.         m_targetMesh = targetMesh;
  855.         InvalidateViews();
  856.     }
  857.     return true;
  858. }
  859. //---------------------------------------------------------------------------
  860. CMesh* CModel::GetTargetMesh(bool createNewIfNone)
  861. {
  862.     if (m_targetMesh) return m_targetMesh;
  863.     if (createNewIfNone)
  864.     {
  865.         m_targetMesh = CreateMesh();
  866.         InvalidateViews();
  867.         return m_targetMesh;
  868.     }
  869.     return NULL;
  870. }
  871. //---------------------------------------------------------------------------
  872. void CModel::SetCursor(const AVector& cursor)
  873. {
  874.     if (cursor == m_cursor) return;
  875.     m_cursor = cursor;
  876.     InvalidateViews();
  877. }
  878. //---------------------------------------------------------------------------
  879. bool CModel::SetCursorFromSelection()
  880. {
  881.     if (m_selection.IsEmpty()) return false;
  882.     TDynArray< TPair<CMesh*,unsigned> > vertices;
  883.     CollectSelectedVertices(vertices);
  884.     ABox box;
  885.     box.Min = box.Max = vertices[0].First->GetVertices()[vertices[0].Second].P;
  886.     for (unsigned i=1; i < vertices.GetSize(); ++i)
  887.     {
  888.         box.Include(vertices[i].First->GetVertices()[vertices[i].Second].P);
  889.     }
  890.     SetCursor(box.GetCenter3D());
  891.     return true;
  892. }
  893. //---------------------------------------------------------------------------
  894. void CModel::SetLockPlane(const APlane& plane)
  895. {
  896.     m_lockPlane = plane;
  897. }
  898. //---------------------------------------------------------------------------
  899. bool CModel::SetLockPlaneFromSelection()
  900. {
  901.     if (m_selection.IsEmpty()) return false;
  902.     switch (m_selectionMode)
  903.     {
  904.     case SM_VERTEX:
  905.         if (m_selection.GetSize() < 3) return false;
  906.         SetLockPlane(APlane(
  907.             static_cast<CMesh*>(m_selection[0].First)->GetVertices()[m_selection[0].Second].P,
  908.             static_cast<CMesh*>(m_selection[1].First)->GetVertices()[m_selection[1].Second].P,
  909.             static_cast<CMesh*>(m_selection[2].First)->GetVertices()[m_selection[2].Second].P));
  910.         break;
  911.     case SM_FACE:
  912.         if (m_selection.GetSize() < 1) return false;
  913.         {
  914.             const SFace& face = static_cast<CMesh*>(m_selection[0].First)->GetFaces()[m_selection[0].Second];
  915.             SetLockPlane(APlane(
  916.                 static_cast<CMesh*>(m_selection[0].First)->GetVertices()[face.A].P,
  917.                 static_cast<CMesh*>(m_selection[0].First)->GetVertices()[face.B].P,
  918.                 static_cast<CMesh*>(m_selection[0].First)->GetVertices()[face.C].P));
  919.         }
  920.         break;
  921.     case SM_OBJECT:
  922.         return false;
  923.     }
  924.     return true;
  925. }
  926. //---------------------------------------------------------------------------
  927. void CModel::ClearLockPlane()
  928. {
  929.     m_lockPlane.X = m_lockPlane.Y = m_lockPlane.Z = m_lockPlane.W = 0.0f;
  930. }
  931. //---------------------------------------------------------------------------
  932. void CModel::SetCoordinateRestriction(ECoordinateRestriction coordRestrict)
  933. {
  934.     if (coordRestrict == m_coordRestrict) return;
  935.     m_coordRestrict = coordRestrict;
  936.     InvalidateViews();
  937. }
  938. //---------------------------------------------------------------------------
  939. bool CModel::FindVerticesNear(const AVector& p, float distance, TDynArray< TPair<CMesh*,unsigned> >& vertices) const
  940. {
  941.     unsigned start = vertices.GetSize();
  942.     for (unsigned i=0; i < GetChildCount(); ++i)
  943.     {
  944.         CMesh* mesh = dynamic_cast<CMesh*>(GetChild(i));
  945.         if (!mesh) continue;
  946.         TDynArray<unsigned> indices;
  947.         if (mesh->FindVerticesNear(p, distance, indices))
  948.         {
  949.             for (unsigned j=0; j < indices.GetSize(); ++j)
  950.             {
  951.                 vertices.Add(TPair<CMesh*,unsigned>(mesh, indices[j]));
  952.             }
  953.         }
  954.     }
  955.     return start < vertices.GetSize();
  956. }
  957. //---------------------------------------------------------------------------
  958. void CModel::WeldVertices(float distance)
  959. {
  960.     TDynArray< TPair<CMesh*,unsigned> > vertices, cluster;
  961.     bool modified = false;
  962.     CollectSelectedVertices(vertices);
  963.     if (!vertices.HasItems()) return;
  964.     distance = distance*distance;
  965.     for (unsigned i=0; i < vertices.GetSize(); ++i)
  966.     {
  967.         SVertex& vtx = vertices[i].First->GetVertices()[vertices[i].Second];
  968.         if (!vtx.Mask)
  969.         {
  970.             TVector<double> avg(NVector::ToDouble(vtx.P));
  971.             cluster.Reset();
  972.             vtx.Mask = true;
  973.             for (unsigned j=i + 1; j < vertices.GetSize(); ++j)
  974.             {
  975.                 SVertex& ovtx = vertices[j].First->GetVertices()[vertices[j].Second];
  976.                 if (!ovtx.Mask && NVector::TDistanceSquared3D(vtx.P, ovtx.P) <= distance)
  977.                 {
  978.                     cluster.Add(vertices[j]);
  979.                     avg += NVector::ToDouble(ovtx.P);
  980.                     ovtx.Mask = true;
  981.                 }
  982.             }
  983.             if (cluster.HasItems())
  984.             {
  985.                 double scale = 1.0/(cluster.GetSize() + 1);
  986.                 avg *= scale;
  987.                 AVector avgf = NVector::ToSingle(avg);
  988.                 vtx.P = avgf;
  989.                 for (unsigned j=0; j < cluster.GetSize(); ++j)
  990.                 {
  991.                     cluster[j].First->GetVertices()[cluster[j].Second].P = avgf;
  992.                 }
  993.                 modified = true;
  994.             }
  995.         }
  996.     }
  997.     for (unsigned i=0; i < vertices.GetSize(); ++i)
  998.     {
  999.         vertices[i].First->GetVertices()[vertices[i].Second].Mask = false;
  1000.     }
  1001.     if (modified)
  1002.     {
  1003.         CDocument::MarkModified();
  1004.         InvalidateViews();
  1005.     }
  1006. }
  1007. //---------------------------------------------------------------------------
  1008. void CModel::MergeVertices(float distance)
  1009. {
  1010.     TDynArray<CMesh*> meshes;
  1011.     unsigned i;
  1012.     ESelectionMode oldMode = m_selectionMode;
  1013.     switch (m_selectionMode)
  1014.     {
  1015.     case SM_VERTEX:
  1016.         for (i=0; i < m_selection.GetSize(); ++i)
  1017.         {
  1018.             CMesh* mesh = static_cast<CMesh*>(m_selection[i].First);
  1019.             meshes.AddUnique(mesh);
  1020.             mesh->GetVertices()[m_selection[i].Second].Mask = true;
  1021.         }
  1022.         break;
  1023.     case SM_FACE:
  1024.         for (i=0; i < m_selection.GetSize(); ++i)
  1025.         {
  1026.             CMesh* mesh = static_cast<CMesh*>(m_selection[i].First);
  1027.             meshes.AddUnique(mesh);
  1028.             const SFace& face = mesh->GetFaces()[m_selection[i].Second];
  1029.             mesh->GetVertices()[face.A].Mask = true;
  1030.             mesh->GetVertices()[face.B].Mask = true;
  1031.             mesh->GetVertices()[face.C].Mask = true;
  1032.         }
  1033.         break;
  1034.     case SM_OBJECT:
  1035.         for (i=0; i < m_selection.GetSize(); ++i)
  1036.         {
  1037.             CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  1038.             if (mesh)
  1039.             {
  1040.                 for (unsigned j=0; j < mesh->GetVertices().GetSize(); ++j)
  1041.                 {
  1042.                     mesh->GetVertices()[j].Mask = true;
  1043.                 }
  1044.                 meshes.AddUnique(mesh);
  1045.             }
  1046.         }
  1047.         break;
  1048.     }
  1049.     ClearSelection();
  1050.     SetSelectionMode(SM_VERTEX);
  1051.     for (unsigned i=0; i < meshes.GetSize(); ++i)
  1052.     {
  1053.         CMesh* mesh = meshes[i];
  1054.         mesh->MergeVertices(distance, m_selectionMode != SM_OBJECT);
  1055.         for (unsigned j=0; j < mesh->GetVertices().GetSize(); ++j)
  1056.         {
  1057.             if (mesh->GetVertices()[j].Mask)
  1058.             {
  1059.                 mesh->GetVertices()[j].Mask = false;
  1060.                 mesh->GetVertices()[j].Selected = true;
  1061.                 m_selection.Add(TPair<CDocNode*,unsigned>(mesh, j));
  1062.             }
  1063.         }
  1064.     }
  1065.     SetSelectionMode(oldMode);
  1066. }
  1067. //---------------------------------------------------------------------------
  1068. void CModel::SplitVertices()
  1069. {
  1070.     DEBUG_ASSERT(m_selectionMode == SM_FACE, "Can only split vertices in face mode");
  1071.     TDynArray<unsigned> fidx;
  1072.     for (unsigned i=0; i < m_selection.GetSize(); ++i)
  1073.     {
  1074.         CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  1075.         if (!mesh) continue;
  1076.         SFace& face = mesh->GetFaces()[m_selection[i].Second];
  1077.         // Split vertex A if needed
  1078.         fidx.Reset();
  1079.         mesh->FindVertexUsers(face.A, fidx);
  1080.         if (fidx.GetSize() > 1)
  1081.         {
  1082.             face.A = mesh->AddVertex(mesh->GetVertices()[face.A]);
  1083.         }        
  1084.         // Split vertex B if needed
  1085.         fidx.Reset();
  1086.         mesh->FindVertexUsers(face.B, fidx);
  1087.         if (fidx.GetSize() > 1)
  1088.         {
  1089.             face.B = mesh->AddVertex(mesh->GetVertices()[face.B]);
  1090.         }
  1091.         // Split vertex C if needed
  1092.         fidx.Reset();
  1093.         mesh->FindVertexUsers(face.C, fidx);
  1094.         if (fidx.GetSize() > 1)
  1095.         {
  1096.             face.C = mesh->AddVertex(mesh->GetVertices()[face.C]);
  1097.         }
  1098.     }
  1099. }
  1100. //---------------------------------------------------------------------------
  1101. void CModel::FlipFaces()
  1102. {
  1103.     DEBUG_ASSERT(m_selectionMode == SM_FACE, "Can only flip faces in face mode");
  1104.     if (!m_selection.HasItems()) return;
  1105.     for (unsigned i=0; i < m_selection.GetSize(); ++i)
  1106.     {
  1107.         CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  1108.         if (!mesh) continue;
  1109.         SFace& face = mesh->GetFaces()[m_selection[i].Second];
  1110.         TSwap(face.B, face.C);
  1111.     }
  1112.     CDocument::MarkModified();
  1113.     InvalidateViews();
  1114. }
  1115. //---------------------------------------------------------------------------
  1116. void CModel::FlipNormals()
  1117. {
  1118.     TDynArray< TPair<CMesh*,unsigned> > vertices;
  1119.     CollectSelectedVertices(vertices);
  1120.     if (!vertices.HasItems()) return;
  1121.     for (unsigned i=0; i < vertices.GetSize(); ++i)
  1122.     {                        
  1123.         vertices[i].First->GetVertices()[vertices[i].Second].N = -vertices[i].First->GetVertices()[vertices[i].Second].N;
  1124.     }
  1125.     CDocument::MarkModified();
  1126.     InvalidateViews();
  1127. }
  1128. //---------------------------------------------------------------------------
  1129. void CModel::RecalcNormals()
  1130. {
  1131.     TDynArray< TPair<CMesh*,unsigned> > vertices, cluster;
  1132.     TDynArray<unsigned> fidx;
  1133.     bool modified = false;
  1134.     CollectSelectedVertices(vertices);
  1135.     if (!vertices.HasItems()) return;
  1136.     for (unsigned i=0; i < vertices.GetSize(); ++i)
  1137.     {
  1138.         CMesh* mesh = vertices[i].First;
  1139.         fidx.Reset();
  1140.         if (mesh->FindVertexUsers(vertices[i].Second, fidx))
  1141.         {
  1142.             SVertex& vtx = mesh->GetVertices()[vertices[i].Second];
  1143.             AVector vn(0, 0, 0);
  1144.             for (unsigned j=0; j < fidx.GetSize(); ++j)
  1145.             {
  1146.                 const SFace& face = mesh->GetFaces()[fidx[j]];
  1147.                 vn += NVector::TCalcTriangleNormal3D(
  1148.                     mesh->GetVertices()[face.A].P,
  1149.                     mesh->GetVertices()[face.B].P,
  1150.                     mesh->GetVertices()[face.C].P);
  1151.             }
  1152.             vtx.N = vn.GetNormalized3D();
  1153.             modified = true;
  1154.         }
  1155.     }
  1156.     if (modified)
  1157.     {
  1158.         CDocument::MarkModified();
  1159.         InvalidateViews();
  1160.     }
  1161. }
  1162. //---------------------------------------------------------------------------
  1163. void CModel::SelectNearbyVertices(float distance)
  1164. {
  1165.     TDynArray< TPair<CMesh*,unsigned> > vertices;
  1166.     DEBUG_ASSERT(m_selectionMode == SM_VERTEX, "Can only select vertices in vertex mode");
  1167.     for (unsigned i=0; i < m_selection.GetSize(); ++i)
  1168.     {
  1169.         CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  1170.         if (!mesh) continue;
  1171.         FindVerticesNear(mesh->GetVertices()[m_selection[i].Second].P, distance, vertices);
  1172.     }
  1173.     if (!vertices.HasItems()) return;
  1174.     for (unsigned i=0; i < vertices.GetSize(); ++i)
  1175.     {
  1176.         if (!vertices[i].First->GetVertices()[vertices[i].Second].Selected)
  1177.         {
  1178.             vertices[i].First->GetVertices()[vertices[i].Second].Selected = true;
  1179.             m_selection.Add(TPair<CDocNode*,unsigned>(vertices[i].First, vertices[i].Second));            
  1180.         }
  1181.     }
  1182.     InvalidateViews();
  1183. }
  1184. //---------------------------------------------------------------------------
  1185. CMesh* CModel::AddGeometry(EGeometry geo)
  1186. {
  1187.     const float* data;
  1188.     size_t count;
  1189.     switch (geo)
  1190.     {
  1191.     case G_PLANE:
  1192.         data = LPlane;
  1193.         count = sizeof(LPlane)/sizeof(LPlane[0]);
  1194.         break;
  1195.     case G_CUBE:
  1196.         data = LCube;
  1197.         count = sizeof(LCube)/sizeof(LCube[0]);
  1198.         break;
  1199.     case G_OCTAGON:
  1200.         data = LOctagon;
  1201.         count = sizeof(LOctagon)/sizeof(LOctagon[0]);
  1202.         break;
  1203.     case G_CONE:
  1204.         data = LCone;
  1205.         count = sizeof(LCone)/sizeof(LCone[0]);
  1206.         break;
  1207.     case G_CYLINDER:
  1208.         data = LCylinder;
  1209.         count = sizeof(LCylinder)/sizeof(LCylinder[0]);
  1210.         break;
  1211.     case G_SPHERE:
  1212.         data = LSphere;
  1213.         count = sizeof(LSphere)/sizeof(LSphere[0]);
  1214.         break;
  1215.     case G_ISOSPHERE:
  1216.         data = LIsosphere;
  1217.         count = sizeof(LIsosphere)/sizeof(LIsosphere[0]);
  1218.         break;
  1219.     default:
  1220.         DEBUG_FAIL("Invalid parameter passed for geometry");
  1221.     }
  1222.     CMesh* target = m_targetMesh ? m_targetMesh : CreateMesh();
  1223.     AMatrix m = NMatrix::GetRotation(-90*3.1415/180.0, AVector(1, 0, 0));
  1224.     for (size_t i=0; i < count; i += 9)
  1225.     {
  1226.         AVector va(data[i], data[i + 1], data[i + 2]);
  1227.         AVector vb(data[i + 3], data[i + 4], data[i + 5]);
  1228.         AVector vc(data[i + 6], data[i + 7], data[i + 8]);
  1229.         va = m.Transform3D(va);
  1230.         vb = m.Transform3D(vb);
  1231.         vc = m.Transform3D(vc);
  1232.         AVector n(NVector::TCalcTriangleNormal3D(va, vb, vc));
  1233.         int a = target->AddVertex(SVertex(va, n, 0, 0));
  1234.         int b = target->AddVertex(SVertex(vb, n, 0, 0));
  1235.         int c = target->AddVertex(SVertex(vc, n, 0, 0));
  1236.         target->AddFace(SFace(a, b, c));
  1237.     }
  1238.     if (!m_targetMesh) m_targetMesh = target;
  1239.     CDocument::MarkModified();
  1240.     InvalidateViews();
  1241.     return target;
  1242. }
  1243. //---------------------------------------------------------------------------
  1244. void CModel::DeleteSelection()
  1245. {
  1246.     unsigned i;
  1247.     THashMap< CMesh*,TDynArray<unsigned> > mvMap;
  1248.     TDynArray<CMesh*> meshes;
  1249.     switch (m_selectionMode)
  1250.     {
  1251.     case SM_VERTEX:
  1252.         for (i=0; i < m_selection.GetSize(); ++i)
  1253.         {
  1254.             DEBUG_ASSERT(dynamic_cast<CMesh*>(m_selection[i].First), "Selected vertex is not associated with a mesh");
  1255.             mvMap[static_cast<CMesh*>(m_selection[i].First)].Add(m_selection[i].Second);
  1256.         }
  1257.         ClearSelection();
  1258.         mvMap.GetKeys(meshes);
  1259.         for (i=0; i < meshes.GetSize(); ++i)
  1260.         {
  1261.             TDynArray<unsigned>& indices = mvMap[meshes[i]];
  1262.             indices.Sort(NDynArray::TDescending);
  1263.             for (unsigned j=0; j < indices.GetSize(); ++j)
  1264.             {
  1265.                 meshes[i]->RemoveVertex(indices[j]);
  1266.             }
  1267.         }
  1268.         break;
  1269.     case SM_FACE:
  1270.         for (i=0; i < m_selection.GetSize(); ++i)
  1271.         {
  1272.             DEBUG_ASSERT(dynamic_cast<CMesh*>(m_selection[i].First), "Selected face is not associated with a mesh");
  1273.             CMesh* mesh = static_cast<CMesh*>(m_selection[i].First);
  1274.             mvMap[mesh].Add(mesh->GetFaces()[m_selection[i].Second].A);
  1275.             mvMap[mesh].Add(mesh->GetFaces()[m_selection[i].Second].B);
  1276.             mvMap[mesh].Add(mesh->GetFaces()[m_selection[i].Second].C);
  1277.         }
  1278.         ClearSelection();
  1279.         mvMap.GetKeys(meshes);
  1280.         for (i=0; i < meshes.GetSize(); ++i)
  1281.         {
  1282.             TDynArray<unsigned>& indices = mvMap[meshes[i]];
  1283.             indices.Sort(NDynArray::TDescending);
  1284.             for (unsigned j=0; j < indices.GetSize(); ++j)
  1285.             {
  1286.                 meshes[i]->RemoveVertex(indices[j]);
  1287.             }
  1288.         }
  1289.         break;
  1290.     case SM_OBJECT:
  1291.         // TODO
  1292.         break;
  1293.     }
  1294.     InvalidateViews();
  1295. }
  1296. //---------------------------------------------------------------------------
  1297. void CModel::DeleteSelectedFaces()
  1298. {
  1299.     TDynArray<unsigned> faces;
  1300.     TDynArray<CMesh*> meshes;
  1301.     THashMap< CMesh*,TDynArray<unsigned> > mvMap;
  1302.     unsigned i;
  1303.     switch (m_selectionMode)
  1304.     {
  1305.     case SM_VERTEX:
  1306.         for (i=0; i < m_selection.GetSize(); ++i)
  1307.         {
  1308.             DEBUG_ASSERT(dynamic_cast<CMesh*>(m_selection[i].First), "Selected vertex is not associated with a mesh");
  1309.             meshes.AddUnique(static_cast<CMesh*>(m_selection[i].First));
  1310.         }
  1311.         for (i=0; i < meshes.GetSize(); ++i)
  1312.         {
  1313.             if (!meshes[i]->GetFaces().HasItems()) continue;
  1314.             faces.Reset();
  1315.             for (unsigned j=meshes[i]->GetFaces().GetSize() - 1;; --j)
  1316.             {
  1317.                 if (meshes[i]->GetVertices()[meshes[i]->GetFaces()[j].A].Selected &&
  1318.                     meshes[i]->GetVertices()[meshes[i]->GetFaces()[j].B].Selected &&
  1319.                     meshes[i]->GetVertices()[meshes[i]->GetFaces()[j].C].Selected)
  1320.                 {
  1321.                     faces.Add(j);
  1322.                 }
  1323.                 if (!j) break;
  1324.             }
  1325.             for (unsigned j=0; j < faces.GetSize(); ++j)
  1326.             {
  1327.                 meshes[i]->RemoveFace(faces[j]);
  1328.             }
  1329.         }
  1330.         ClearSelection();
  1331.         break;
  1332.     case SM_FACE:
  1333.         for (i=0; i < m_selection.GetSize(); ++i)
  1334.         {
  1335.             DEBUG_ASSERT(dynamic_cast<CMesh*>(m_selection[i].First), "Selected face is not associated with a mesh");
  1336.             mvMap[static_cast<CMesh*>(m_selection[i].First)].Add(m_selection[i].Second);
  1337.         }
  1338.         ClearSelection();
  1339.         mvMap.GetKeys(meshes);
  1340.         for (i=0; i < meshes.GetSize(); ++i)
  1341.         {
  1342.             TDynArray<unsigned>& indices = mvMap[meshes[i]];
  1343.             indices.Sort(NDynArray::TDescending);
  1344.             for (unsigned j=0; j < indices.GetSize(); ++j)
  1345.             {
  1346.                 meshes[i]->RemoveFace(indices[j]);
  1347.             }
  1348.         }
  1349.         break;
  1350.     case SM_OBJECT:
  1351.         for (i=0; i < m_selection.GetSize(); ++i)
  1352.         {
  1353.             CMesh* mesh = dynamic_cast<CMesh*>(m_selection[i].First);
  1354.             if (!mesh) continue;
  1355.             mesh->GetFaces().Clear();
  1356.         }
  1357.         ClearSelection();
  1358.         CDocument::MarkModified();
  1359.         break;
  1360.     }
  1361.     InvalidateViews();
  1362. }
  1363. //---------------------------------------------------------------------------
  1364. CDocView* CModel::CreateView(int)
  1365. {
  1366.     return CModelViewCreator::Create(this);
  1367. }
  1368. //---------------------------------------------------------------------------
  1369. void CModel::OnChildRemoved(CNode* node)
  1370. {
  1371.     if (node == m_targetMesh) m_targetMesh = NULL;
  1372. }
  1373. //---------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment