is vertex visible ?

Blitz3D Forums/Blitz3D Programming/is vertex visible ?

Is there a way to determine if a vertex is visible ? I want to highlight the vertices that are on the camera's side of the entity.
I thought it could be possible by reading the normals of the vertex. My line of thought is, that if the normal points towards the camera, the vertex would be in view. However, I'm not sure if that is true and I don't know how to do that.

You need CameraProject I think...no scrap that idea.

Thinking more about it, you could cycle through each triangle of the mesh testing the normals, if the triangles normal points toward you then its vertices are all visible.

Thanks, the method works, but I find it difficult to determine if a vector is pointing towards the camera.
 	;setup graphics
	Graphics3D 800, 600, 0, 2
	SetBuffer BackBuffer()
	
	WireFrame 1

	camera = CreateCamera()
	MoveEntity camera, 0, 0, -15
	
	campiv = CreatePivot()
	EntityParent camera, campiv
	
	cube = CreateCube()
	UpdateNormals cube
	surf = GetSurface(cube, 1)
	
	Repeat
		
		;turn camera
		TurnEntity campiv, 0, 1, 0
		RenderWorld
		
		;loop through all vertices	
		For i = 0 To CountVertices(surf) - 1


			TFormPoint VertexNX(surf, i), VertexNY(surf, i), VertexNZ(surf, i), cube, 0
			nx# = TFormedX() - EntityX(cube, 1) + EntityX(camera, 1)
			ny# = TFormedY() - EntityY(cube, 1) + EntityY(camera, 1)
			nz# = TFormedZ() - EntityZ(cube, 1) + EntityZ(camera, 1)
			TFormPoint nx, ny, nz, 0, camera
			
			test = TFormedZ() <= 0
			
			If test Then
							
				;draw normals
				TFormPoint VertexX(surf, i), VertexY(surf, i), VertexZ(surf, i), cube, 0
				CameraProject camera, TFormedX(), TFormedY(), TFormedZ()
				
				;project vertex position			
				vx# = ProjectedX()
				vy# = ProjectedY()
				TFormPoint VertexX(surf, i) + VertexNX(surf, i), VertexY(surf, i) + VertexNY(surf, i), VertexZ(surf, i) + VertexNZ(surf, i), cube, 0
	
				;project normal direction from vertex position
				CameraProject camera, TFormedX(), TFormedY(), TFormedZ()				
				nx# = ProjectedX()
				ny# = ProjectedY()
				
				;draw normal			
				Color 255, 0, 0
				Line vx, vy, nx, ny
				
			End If
							
		Next
								
		Flip
		
	Until KeyHit(1)
	
	End

When I turned on WireFrame modus, I realised the common culling is done by checking if a triangle is either clockwise or counter-clockwise. So I think I should give that a try.

Sorry for double-posting, but I found an algo in the archive (by birdie) that determines CW/CCW for a 2d triangle. And it works:
 	;setup graphics
	Graphics3D 800, 600, 0, 2
	SetBuffer BackBuffer()
	
	;enable wireframe	
	WireFrame 1

	;create camera	
	camera = CreateCamera()
	MoveEntity camera, 0, 0, -5
	
	;create pivot for camera	
	campiv = CreatePivot()
	EntityParent camera, campiv
	
	;create cube	
	cube = CreateCube()
	UpdateNormals cube
	surf = GetSurface(cube, 1)
	
	Repeat
		
		;turn camera
		TurnEntity campiv, 0, 1, 0
		RenderWorld
		
		;loop through all triangles		
		For i = 0 To CountTriangles(surf) - 1
		
			;get vertices from triangle			
			v0 = TriangleVertex(surf, i, 0)		
			v1 = TriangleVertex(surf, i, 1)
			v2 = TriangleVertex(surf, i, 2)
			
			;get coordinates from vertices
			v0x# = VertexX(surf, v0)
			v0y# = VertexY(surf, v0)
			v0z# = VertexZ(surf, v0)
			
			v1x# = VertexX(surf, v1)
			v1y# = VertexY(surf, v1)
			v1z# = VertexZ(surf, v1)
			
			v2x# = VertexX(surf, v2)
			v2y# = VertexY(surf, v2)
			v2z# = VertexZ(surf, v2)
			
			;project vertices to screen			
			CameraProject camera, v0x, v0y, v0z
			v0x# = ProjectedX()
			v0y# = ProjectedY()
							
			CameraProject camera, v1x, v1y, v1z
			v1x# = ProjectedX()
			v1y# = ProjectedY()
							
			CameraProject camera, v2x, v2y, v2z
			v2x# = ProjectedX()
			v2y# = ProjectedY()
			
			;check if triangle is CW			
			If ((v0x - v1x) * (v2y - v1y) - (v0y - v1y) * (v2x - v1x)) < 0 Then
				
				;if it is, draw vertices
				Color 255, 0, 0
				Oval v0x - 1, v0y - 1, 3, 3
				Oval v1x - 1, v1y - 1, 3, 3
				Oval v2x - 1, v2y - 1, 3, 3
				
			End If
			
		Next
							
		Flip
		
	Until KeyHit(1)
	
	End


Still, it is not exactly what I want. I think I should try projecting every triangle, and then checking if the projected vertex coordinate is behind any of the triangles from the cameras view.

This is how I would do it - slightly different from your versions. Note that one issue you may have is using updatenormals on the cube as this command averages the normals of shared verts. In this case as the normals are the same for each vertice in the triangle it's probably quicker to just loop throught the triangles rather than the verts.

	;setup graphics
	Graphics3D 800, 600, 0, 2
	SetBuffer BackBuffer()
	
	;enable wireframe	
	WireFrame 1

	;create camera	
	camera = CreateCamera()
	MoveEntity camera, 0, 0, -5
	
	;create pivot for camera	
	campiv = CreatePivot()
	EntityParent camera, campiv
	
	;create cube	
	cube = CreateCube()
	
	;Omit this Line as UpdateNormals averages cooexistent vertices
	;UpdateNormals cube
	s = GetSurface(cube, 1)
	
	Repeat
		
		;turn camera
		TurnEntity campiv, 0, 1, 0
		RenderWorld
		
		;loop through all triangles		
		For v = 0 To CountVertices( s ) - 1
		
			;get global vertex position
			TFormPoint VertexX( s, v ) , VertexY( s, v ), VertexZ( s, v ) , cube, 0
			;get direction vector from camera to vertex
			Cx# = TFormedX() - EntityX( camera, 1 )
			Cy# = TFormedY() - EntityY( Camera, 1 )
			Cz# = TFormedZ() - EntityZ( camera, 1 )
			;tform normal into Global coords 
			TFormNormal VertexNX( s, v ) , VertexNY( s, v ) , VertexNZ( s, v ), cube, 0
			;dot product
			Dot# = Cx * TFormedX() + Cy * TFormedY() + Cz * TFormedZ()
			
			If Dot< 0 			
				TFormPoint VertexX( s, v ) , VertexY( s, v) , VertexZ( s, v ), cube, 0
				CameraProject camera, TFormedX(), TFormedY(), TFormedZ() 
				Color 255,0,0
				Oval ProjectedX()-1, ProjectedY()-1, 3, 3
			End If
			
		Next
							
		Flip
		
	Until KeyHit(1)
	
	End


Stevie

dot product=math<>bram=thank you! I see what you mean with the UpdateNormals() problem. But for that, I can calculate face normals I suppose? Thanks again.

No problem. I use this function to re-calculate polygon normals rather than vertex normals .. the updatenormals function sucks in my opinion. You'll probably have to ensure the mesh has no shared verts before you use this .. but I have an unweld function if you need it.

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


Thanks Stevie! The flat shading looks a lot better. I could use that for my "extrude" editor as well, if that's allright. Here, look, I'll show what I am making:
;-------------------------------------------------------------------------------------------------------
;											   globals
;-------------------------------------------------------------------------------------------------------

	Const 	DragMenu = 30

	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	dot2					;dot image 2 (unselected dot)
	Global	UpdateNeeded			;flag for redrawing interface
	Global 	light
	
	;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()
	
	buffer = CreateImage(GraphicsWidth(), GraphicsHeight())
	 	
	;create dot images	
	CreateDots
	
	;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 mouse is down
			If Cursor_Down(1) Then
				;get coords
				CameraPick camera, Cursor_X, Cursor_Y
				;move selected vertex
				MoveVertex selsurf, selvert, PickedX(), PickedY(), PickedZ()
			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"

		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 there is a mesh and no vertices are drawn allready
	If (mesh <> 0) And (Not Cursor_Down(1)) Then

		;scan all surfaces	
		For i = 1 To CountSurfaces(mesh)
			
			surf = GetSurface(mesh, i)

			;by Stevie G
			;loop through all triangles		
			Color 255,0,0
			For v = 0 To CountVertices( surf ) - 1
			
				;get global vertex position
				TFormPoint VertexX( surf, v ) , VertexY( surf, v ), VertexZ( surf, v ) , cube, 0
				;get direction vector from camera to vertex
				Cx# = TFormedX() - EntityX( camera, 1 )
				Cy# = TFormedY() - EntityY( Camera, 1 )
				Cz# = TFormedZ() - EntityZ( camera, 1 )
				;tform normal into Global coords 
				TFormNormal VertexNX( surf, v ) , VertexNY( surf, v ) , VertexNZ( surf, v ), cube, 0
				;dot product
				iDot# = Cx * TFormedX() + Cy * TFormedY() + Cz * TFormedZ()
				
				If iDot< 0 			
					TFormPoint VertexX( surf, v ) , VertexY( surf, v) , VertexZ( surf, v ), cube, 0
					CameraProject camera, TFormedX(), TFormedY(), TFormedZ() 
					DrawBlock dot2, ProjectedX()-2, ProjectedY()-2
														
					dist# = VDist(ProjectedX(), ProjectedY(), Cursor_X, Cursor_Y)
					If dist < maxafstand Then 
								
						;select the vertex
						maxafstand = dist
						selsurf = i
						selvert = v
		
					End If
					
				End If
					
			Next
													
		Next
		
	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#)
	
	;turn camera
	TurnEntity 		campiv, 0, yw#, 0
	TurnEntity 		light, 0, 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
	VertexCoords isurf, 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 VertexCoords isurf, c\v2, x, y, z
			If c\v2 = vert Then VertexCoords isurf, c\v1, x, y, z
		End If
	Next
	
	;set flag for redrawing
	UpdateNeeded 	= True
	;calculate new normals
	MeshNormals 	mesh
	
End Function

;-------------------------------------------------------------------------------------------------------
;												CreateDots()
;-------------------------------------------------------------------------------------------------------
;create images for dots
Function CreateDots()

	dot = CreateImage(10, 10)
	dot2 = CreateImage(5, 5)
	
	Cls
	Color 0, 0, 255
	Rect 0, 0, 10, 10
	Color 255, 255, 255
	Rect 2, 2, 6, 6
	GrabImage dot, 0, 0
	
	Cls
	Color 255, 0, 0
	Rect 0, 0, 5, 5, 0
	GrabImage dot2, 0, 0
	
	MidHandle dot
	MidHandle dot2
				
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)
	
	If imesh = 0 Then Return
	InitVars
	mesh = imesh
	;FitMesh mesh, -1, -1, -1, 2, 2, 2, 1
	EntityFX mesh, 16
	EntityShininess mesh, 2
	Unweld mesh
	MeshNormals mesh
	ScanMesh mesh

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


; ID: 422
; Author: starfox
; Date: 2002-09-09 14:16:20
; Title: Unweld
; Description: This function unwelds all the points

Function Unweld(mesh)
;Unweld a mesh, retaining all of its textures coords and textures
For surfcount = 1 To CountSurfaces(mesh)
	surf = GetSurface(mesh,surfcount)

	count = CountTriangles(surf)
	bank = CreateBank((15*count)*4)
	For tricount = 0 To count-1
	off = (tricount*15)*4
	in = TriangleVertex(surf,tricount,0)
	x# = VertexX(surf,in):y#=VertexY(surf,in):z#=VertexZ(surf,in)
	u# = VertexU(surf,in):v#=VertexV(surf,in)
	PokeFloat(bank,off,x)
	PokeFloat(bank,off+4,y)
	PokeFloat(bank,off+8,z)
	PokeFloat(bank,off+12,u)
	PokeFloat(bank,off+16,v)

	in = TriangleVertex(surf,tricount,1)
	x# = VertexX(surf,in):y#=VertexY(surf,in):z#=VertexZ(surf,in)
	u# = VertexU(surf,in):v#=VertexV(surf,in)
	PokeFloat(bank,off+20,x)
	PokeFloat(bank,off+24,y)
	PokeFloat(bank,off+28,z)
	PokeFloat(bank,off+32,u)
	PokeFloat(bank,off+36,v)

	in = TriangleVertex(surf,tricount,2)
	x# = VertexX(surf,in):y#=VertexY(surf,in):z#=VertexZ(surf,in)
	u# = VertexU(surf,in):v#=VertexV(surf,in)
	PokeFloat(bank,off+40,x)
	PokeFloat(bank,off+44,y)
	PokeFloat(bank,off+48,z)
	PokeFloat(bank,off+52,u)
	PokeFloat(bank,off+56,v)

	Next
	
	ClearSurface(surf,True,True)
	
	For tricount = 0 To count-1
	off = (tricount*15)*4
	x# = PeekFloat(bank,off)
	y# = PeekFloat(bank,off+4)
	z# = PeekFloat(bank,off+8)
	u# = PeekFloat(bank,off+12)
	v# = PeekFloat(bank,off+16)
	a = AddVertex(surf,x,y,z,u,v)
	x# = PeekFloat(bank,off+20)
	y# = PeekFloat(bank,off+24)
	z# = PeekFloat(bank,off+28)
	u# = PeekFloat(bank,off+32)
	v# = PeekFloat(bank,off+36)
	b = AddVertex(surf,x,y,z,u,v)
	x# = PeekFloat(bank,off+40)
	y# = PeekFloat(bank,off+44)
	z# = PeekFloat(bank,off+48)
	u# = PeekFloat(bank,off+52)
	v# = PeekFloat(bank,off+56)
	c = AddVertex(surf,x,y,z,u,v)
	AddTriangle(surf,a,b,c)
	Next
	FreeBank bank
Next
UpdateNormals mesh
Return mesh
End Function

It is an editor, where you can drag vertices of meshes.
Drawing/hiding the vertices is working allright, however I would like to try and make it more strict. Maybe I could use small (3d) sprites to mark the vertices? Strange thing would be that the dots become very big when you zoom. :)

Excellent, I'm sure I could make use of this!

Here's my unweld function .. no banks but free's the existing and returns the new mesh. Incase you're interested ..

unction MESHunweld( Mesh )

	Copy = CreateMesh()
	ns = CreateSurface( Copy )
	For su = 1 To CountSurfaces( Mesh )
		s = GetSurface( Mesh , su )
		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 ) )
			VertexColor ns, Nv0 , VertexRed( s, v0 ) , VertexGreen( s, v0 ) , VertexBlue( s, v0 )
			VertexColor ns, Nv1 , VertexRed( s, v1 ) , VertexGreen( s, v1 ) , VertexBlue( s, v1 )
			VertexColor ns, Nv2 , VertexRed( s, v2 ) , VertexGreen( s, v2 ) , VertexBlue( s, v2 )
			AddTriangle ns , Nv0 , Nv1 , Nv2
		Next
	Next
	FreeEntity mesh
	Return Copy

End Function	



For the points, just Rescale the sprites based on distance to camera should sort your dot size. That's assuming you're using the camera z pos to zoom else scale based on the zoom factor.

I'll keep an eye on this.

Stevie

Thanks! I tried the sprites and I even tried painting the vertices on the texture. Sprites were too slow and painting on the texture doesn't look too good. And when I use the these methods, I would still have to find out what vertices are in view. I think the best thing to do now it to write a function that checks if the vertex is behind any triangles.

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