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