After a lot of attempts, this is it. I'm using cubes to mark the vertices and then use radial picking to determine what vertex is selected. Note that when two vertices are not on the same surface, they don't stick together. In a newer version, I will update the connect type
;------------------------------------------------------------------------------------------------------- ; globals ;------------------------------------------------------------------------------------------------------- Type piv Field mesh Field index Field surf End Type Dim indexedpiv.piv(50, 8000) Const DragMenu = 30 Const DotScale# = 0.01 Const DotPickRadius# = 0.03 Global campiv ;central pivot for camera Global camera ;camera Global plane ;plane used for picking Global mesh ;mesh in editor Global selsurf ;selected surface Global selvert ;selected vertex Global dot ;dot image (selected dot) Global UpdateNeeded ;flag for redrawing interface Global light Global orgpiv ;connects two vertices (with the same coords) Type Connect Field surf Field v1 Field v2 End Type Dim Cursor_Down(2) ;------------------------------------------------------------------------------------------------------- ; setup graphics ;------------------------------------------------------------------------------------------------------- Graphics3D 1024, 768, 0, 2 SetBuffer BackBuffer() ;create dot images CreateDots orgpiv = CreateCube() ScaleMesh orgpiv, dotscale, dotscale, dotscale EntityColor orgpiv, 255, 0, 0 TFormFilter 0 buffer = CreateImage(GraphicsWidth(), GraphicsHeight()) ;setup camera and plane Setup3DWorld ;make GUI MakeGUI ;WireFrame True ;------------------------------------------------------------------------------------------------------- ; main loop ;------------------------------------------------------------------------------------------------------- OpenMesh Global Cursor_X, Cursor_Y Repeat For i = 1 To 2 Cursor_Down(i) = MouseDown(i) Next Cursor_X = MouseX() Cursor_Y = MouseY() ;cursor keys If KeyDown(203) Then Turn +1 If KeyDown(205) Then Turn -1 If KeyDown(200) Then Zoom +1/5.0 If KeyDown(208) Then Zoom -1/5.0 If KeyDown(44) Then Turn 0, -1 If KeyDown(30) Then Turn 0, +1 ;if mouse is down If Cursor_Down(1) Then ;get coords CameraPick camera, Cursor_X, Cursor_Y ;ctrl If KeyDown(29) Then If selsurf <> 0 Then surf = GetSurface(mesh, selsurf) TFormPoint VertexX(surf, selvert), VertexY(surf, selvert), VertexZ(surf, selvert), mesh, 0 MoveVertex selsurf, selvert, TFormedX(), TFormedY(), PickedY() - TFormedY() outline$ = (PickedY() - TFormedY()) End If Else ;move selected vertex MoveVertex selsurf, selvert, PickedX(), PickedY(), PickedZ() End If End If ;render if flag is set If UpdateNeeded Then RenderWorld() GrabImage buffer, 0, 0 Else DrawBlock buffer, 0, 0 End If ;draw vertices DrawVertices(camera, mesh) ;reset flag UpdateNeeded = False ; ;draw and handle GUI ; HandleGUI DrawGui$() Color 255,255,255 Text 0, 0, "Use cursor keys to rotate" Text 0, 20, "Drag vertices with mouse" Text 0, 40, "Number of surfaces:" + CountSurfaces(mesh) Flip If KeyHit(16) Then SetMesh CreateCube() If KeyHit(17) Then SetMesh CreateCone() If KeyHit(18) Then SetMesh CreateCylinder() If KeyHit(19) Then SetMesh CreateSphere() Until KeyHit(1) End ;------------------------------------------------------------------------------------------------------- ; MakeGUI() ;------------------------------------------------------------------------------------------------------- ;creates G.U.I. Function MakeGUI() End Function ;------------------------------------------------------------------------------------------------------- ; Setup3DWorld() ;------------------------------------------------------------------------------------------------------- ;creates 3d world Function Setup3DWorld() ;create camera campiv = CreatePivot() camera = CreateCamera(campiv) CameraZoom camera, 2.4 PositionEntity camera, 0, 0, -15 ;create plane plane = CreatePlane(1, campiv) RotateEntity plane, -90, 0, 0 EntityPickMode plane, 2 EntityAlpha plane, 0.0 ;create light light = CreateLight() LightColor light, 128, 128, 128;64, 64, 64 TurnEntity light, 0, 10, 0 ;AmbientLight 0, 0, 0 End Function ;------------------------------------------------------------------------------------------------------- ; DrawVertices() ;------------------------------------------------------------------------------------------------------- ;project all vertices of a mesh Function DrawVertices(cam, mesh) Local i% Local j% Local surf% Local maxafstand# = 10000.0 Local dist# Local px# Local py# ; If KeyDown(203) Or KeyDown(205) Then Return ;if there is a mesh and no vertices are drawn allready If (mesh <> 0) And (Not Cursor_Down(1)) Then EntityPickMode plane, 0 EntityPickMode mesh, 2 For pv.piv = Each piv EntityPickMode pv\mesh, 1 Next CameraPick camera, MouseX(), MouseY() selvert = 0 selsurf = 0 If PickedEntity() <> 0 Then If PickedEntity() <> mesh Then For pv.piv = Each piv If PickedEntity() = pv\mesh Then selvert = pv\index selsurf = pv\surf End If Next End If End If For pv.piv = Each piv EntityPickMode pv\mesh, 0 Next EntityPickMode mesh, 0 EntityPickMode plane, 2 End If If mesh = 0 Then Return If selsurf < 1 Then Return ;get selected surface surf = GetSurface(mesh, selsurf) ;project selected vertex coords onto camera CameraProject cam, VertexX(surf, selvert), VertexY(surf, selvert), VertexZ(surf, selvert) px# = ProjectedX() py# = ProjectedY() ;draw a dot at the coords DrawImage dot, px, py ;position plane on the Z of this vertex TFormPoint VertexX(surf, selvert), VertexY(surf, selvert), VertexZ(surf, selvert), mesh, campiv PositionEntity plane, 0, 0, TFormedZ() End Function ;------------------------------------------------------------------------------------------------------- ; Turn() ;------------------------------------------------------------------------------------------------------- ;turn editor Function Turn(yw#, rl# = 0) ;turn camera TurnEntity campiv, rl#, yw#, 0 TurnEntity light, rl#, yw, 0 ;set flag for redrawing UpdateNeeded = True End Function ;------------------------------------------------------------------------------------------------------- ; Zoom() ;------------------------------------------------------------------------------------------------------- ;zooms camera in/out Function Zoom(z#) ;if camera is not entirely zoomed in If EntityZ(camera) +z < 0 Then ;change camera zoom MoveEntity camera, 0, 0, z# ;set flag for redrawing UpdateNeeded = True End If End Function ;------------------------------------------------------------------------------------------------------- ; VDist() ;------------------------------------------------------------------------------------------------------- ;return distance (x1,y1)-(x2,y2) Function VDist(x1#, y1#, x2#, y2#) ;get distance and return it Return Sqr(dB(x2 - x1) + dB(y2 - y1)) End Function ;------------------------------------------------------------------------------------------------------- ; dB() ;------------------------------------------------------------------------------------------------------- ;returns x^2 Function dB#(x#) Return x * x End Function ;------------------------------------------------------------------------------------------------------- ; MoveVertex() ;------------------------------------------------------------------------------------------------------- ;move a single vertex Function MoveVertex(surf, vert, x#, y#, z#) If surf < 1 Then Return ;get surface isurf = GetSurface(mesh, surf) ;set vertex coords iVertexCoords surf, vert, x, y, z ;look for connected vertices For c.Connect = Each Connect If c\surf = surf Then ;move them along If c\v1 = vert Then iVertexCoords surf, c\v2, x, y, z If c\v2 = vert Then iVertexCoords surf, c\v1, x, y, z End If Next ;set flag for redrawing UpdateNeeded = True ;calculate new normals MeshNormals mesh End Function Function iVertexCoords(surf, vert, x#, y#, z#) VertexCoords GetSurface(mesh, surf), vert, x, y, z If indexedpiv(surf, vert) <> Null Then PositionEntity indexedpiv(surf, vert)\mesh, x, y, z End Function ;------------------------------------------------------------------------------------------------------- ; CreateDots() ;------------------------------------------------------------------------------------------------------- ;create images for dots Function CreateDots() dot = CreateImage(10, 10) Cls Color 0, 0, 255 Rect 0, 0, 10, 10 Color 255, 255, 255 Rect 2, 2, 6, 6 GrabImage dot, 0, 0 MidHandle dot End Function ;------------------------------------------------------------------------------------------------------- ; ScanMesh() ;------------------------------------------------------------------------------------------------------- ;scan mesh for overlapping vertices Function ScanMesh(mesh) ;delete each connection type Delete Each Connect ;return if there is no mesh If mesh = 0 Then Return ;scan all surfaces For i = 1 To CountSurfaces(mesh) surf = GetSurface(mesh, i) ;scan all vertices on surface For j = 0 To CountVertices(surf) - 1 ;get coords vx1# = VertexX(surf, j) vy1# = VertexY(surf, j) vz1# = VertexZ(surf, j) ;scan all other vertices (with higher index) For k = j + 1 To CountVertices(surf) - 1 ;get coords vx2# = VertexX(surf, k) vy2# = VertexY(surf, k) vz2# = VertexZ(surf, k) ;if coords are the same If Cmp(vx1, vx2) And Cmp(vy1, vy2) And Cmp(vz1, vz2) Then ;store these two vertices c.Connect = New Connect c\surf = i c\v1 = j c\v2 = k End If Next Next Next End Function ;------------------------------------------------------------------------------------------------------- ; InitVars() ;------------------------------------------------------------------------------------------------------- ;initialize variables that need resetting Function InitVars() selsurf = 0 selvert = 0 UpdateNeeded = True Delete Each Connect If mesh <> 0 Then FreeEntity mesh End Function ;------------------------------------------------------------------------------------------------------- ; SetMesh() ;------------------------------------------------------------------------------------------------------- ;accepts a new mesh Function SetMesh(imesh) For pv.piv = Each piv If pv\mesh <> 0 Then FreeEntity pv\mesh Delete pv Next If imesh = 0 Then Return InitVars ;rescale If MeshWidth(imesh) <> 0 Then If MeshHeight(imesh) <> 0 Then If MeshDepth(imesh) <> 0 Then FitMesh imesh, -1, -1, -1, 2, 2, 2, 1 End If End If End If mesh = imesh EntityFX mesh, 16 EntityShininess mesh, 2 MeshUnweld (mesh) MeshNormals mesh ; UpdateNormals mesh ScanMesh mesh For su = 1 To CountSurfaces(mesh) surf = GetSurface(mesh, su) For i = 0 To CountVertices(surf) - 1 pv.piv = New piv pv\index = i pv\surf = su indexedpiv(su, i) = pv pv\mesh = CopyEntity(orgpiv);CreatePivot() TFormPoint VertexX(surf, i), VertexY(surf, i), VertexZ(surf, i), mesh, 0 PositionEntity pv\mesh, TFormedX(), TFormedY(), TFormedZ() EntityRadius pv\mesh, DotPickRadius# Next Next PositionEntity camera, 0, 0, -MeshDepth(mesh) * 3 End Function ;------------------------------------------------------------------------------------------------------- ; OpenMesh() ;------------------------------------------------------------------------------------------------------- ;show dialog and load mesh Function OpenMesh() If mesh <> 0 Then FreeEntity mesh SetMesh CreateSphere() End Function ;------------------------------------------------------------------------------------------------------- ; HandleGUI() ;------------------------------------------------------------------------------------------------------- ;handles gui activity Function HandleGUI(button$) If button$ = "Load" Then OpenMesh() End Function ;------------------------------------------------------------------------------------------------------- ; Compare() ;------------------------------------------------------------------------------------------------------- ;determine which vertex is closer to the camera Function Compare(s1, i1, s2, i2) surf1 = GetSurface(mesh, s1) surf2 = GetSurface(mesh, s2) TFormPoint VertexX(surf1, i1), VertexY(surf1, i1), VertexZ(surf1, i1), mesh, campiv z1# = TFormedZ() TFormPoint VertexX(surf2, i2), VertexY(surf2, i2), VertexZ(surf2, i2), mesh, campiv z2# = TFormedZ() Return (z1 > z2) End Function Function Cmp(x#, y#) If Abs(x) < 0.001 Then x = 0 If Abs(y) < 0.001 Then y = 0 xx% = Floor(x * 100) yy% = Floor(y * 100) Return (xx = yy) End Function ;by Stevie G Function MESHnormals( mesh ) For l = 1 To CountSurfaces(mesh ) s = GetSurface( mesh , l ) ;calculate normals for flatshading For t = 0 To CountTriangles( s )-1 v0 = TriangleVertex( s, t, 0 ) v1 = TriangleVertex( s, t, 1 ) v2 = TriangleVertex( s, t, 2 ) ax# = VertexX( s, v1 ) - VertexX( s, v0 ) ay# = VertexY( s, v1 ) - VertexY( s, v0 ) az# = VertexZ( s, v1 ) - VertexZ( s, v0 ) bx# = VertexX( s, v2 ) - VertexX( s, v1 ) by# = VertexY( s, v2 ) - VertexY( s, v1 ) bz# = VertexZ( s, v2 ) - VertexZ( s, v1 ) Nx# = ( ay * bz ) - ( az * by ) Ny# = ( az * bx ) - ( ax * bz ) Nz# = ( ax * by ) - ( ay * bx ) Ns# = Sqr( Nx * Nx + Ny*Ny + Nz*Nz ) Nx = Nx / Ns Ny = Ny / Ns Nz = Nz / Ns For v = v0 To v2 VertexNormal s, v, Nx, Ny, Nz Next Next Next End Function Function MESHunweld( Mesh ) Copy = CreateMesh() For su = 1 To CountSurfaces( Mesh ) s = GetSurface( Mesh , su ) ns = CreateSurface( Copy ) For t = 0 To CountTriangles( s ) - 1 v0 = TriangleVertex( s, t, 0 ) v1 = TriangleVertex( s, t, 1 ) v2 = TriangleVertex( s, t, 2 ) Nv0 = AddVertex( ns , VertexX( s , v0 ) , VertexY( s, v0 ) , VertexZ( s, v0 ) ) Nv1 = AddVertex( ns , VertexX( s , v1 ) , VertexY( s, v1 ) , VertexZ( s, v1 ) ) Nv2 = AddVertex( ns , VertexX( s , v2 ) , VertexY( s, v2 ) , VertexZ( s, v2 ) ) VertexTexCoords ns, nv0, VertexU(s, v0), VertexV(s, v0), VertexW(s, v0) VertexTexCoords ns, nv1, VertexU(s, v1), VertexV(s, v1), VertexW(s, v1) VertexTexCoords ns, nv2, VertexU(s, v2), VertexV(s, v2), VertexW(s, v2) AddTriangle ns , Nv0 , Nv1 , Nv2 Next ClearSurface s For t = 0 To CountTriangles( ns ) - 1 v0 = TriangleVertex( ns, t, 0 ) v1 = TriangleVertex( ns, t, 1 ) v2 = TriangleVertex( ns, t, 2 ) Nv0 = AddVertex( s , VertexX( ns , v0 ) , VertexY( ns, v0 ) , VertexZ( ns, v0 ) ) Nv1 = AddVertex( s , VertexX( ns , v1 ) , VertexY( ns, v1 ) , VertexZ( ns, v1 ) ) Nv2 = AddVertex( s , VertexX( ns , v2 ) , VertexY( ns, v2 ) , VertexZ( ns, v2 ) ) VertexTexCoords s, nv0, VertexU(ns, v0), VertexV(ns, v0), VertexW(ns, v0) VertexTexCoords s, nv1, VertexU(ns, v1), VertexV(ns, v1), VertexW(ns, v1) VertexTexCoords s, nv2, VertexU(ns, v2), VertexV(ns, v2), VertexW(ns, v2) AddTriangle s , Nv0 , Nv1 , Nv2 Next Next FreeEntity Copy Return Mesh End Function