is vertex visible ?

Blitz3D Forums/Blitz3D Programming/is vertex visible ?

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