mav on renderworld()

Blitz3D Forums/Blitz3D Programming/mav on renderworld()

In my texpaint program, I get an error on RenderWorld()
So I wrote a small test version using different methods, but it keeps giving the same error.
Is there something I'm doing wrong ?
I would appreciate it if someone could try to run this code and tell me if the bug occurs on their machine. It takes a minute for the bug to appear.
Has someone experienced the same problem ? I've read a few posts on this error, but in that cases people made too many triangles on a surface.
; PickedTri type
; Necessary for the PickedU(), PickedV(), and PickedW() commands
Type PickedTri
	Field ent,surf,tri				;picked entity, surface and triangle
	Field px#,py#,pz#			    ;picked xyz
	Field pu#[1],  pv#[1]  ,pw#[1]  ;picked uvw x 2
	
	Field vx#[2],  vy#[2]  ,vz#[2]  ;vertex xyz
	Field vnx#[2], vny#[2] ,vnz#[2] ;vertex normals
	Field vu#[5],  vv#[5]  ,vw#[5]  ;vertex uvw x 2
End Type

Global ptri.pickedtri = New pickedtri



;-----------------------------------------------------------------------------------------------------
;
;-----------------------------------------------------------------------------------------------------
	
	Graphics3D 1024, 768, 0, 2
	SetBuffer BackBuffer()
		
	;Include "pickeduv.bb"

	ShowPointer()
	
	;show opendialog	
	f$ = "C:\Program Files\Blitz3D\help\commands\3d_examples\media\makbot\mak_running.x"
	
	If FileType(f$) <> 1 Then End

	camera% = CreateCamera()
	CameraZoom camera%, 2.4
		
	mesh% = LoadMesh(f$)
	
	ww# = MeshWidth(mesh%)
	hh# = MeshHeight(mesh%)
	dd# = MeshDepth(mesh%)
	
	ScaleEntity mesh%, 0.05, 0.05, 0.05
	PositionEntity camera%, 0, 1, -7
	
	EntityPickMode mesh%, 2

	tel = 0
	
	Repeat
	
		RotateEntity mesh, 0, -tel, 0
		
		tel = tel + 1
		
		elaps# = tel * 30
			
		y# = Sin((elaps) * 0.200) * 100
		MoveMouse 512, y + 390
	
		If KeyDown(203) Then TurnEntity mesh, 0, +1, 0
		If KeyDown(205) Then TurnEntity mesh, 0, -1, 0
	
		RenderWorld
		
		CameraPick camera, MouseX(), MouseY()
		Text 0, 20, PickedSurface()
		
		;(PickedSurface() <> olds) And 
		
		If (PickedSurface()<>0) Then  
			surf% = PickedSurface()
			If surf <> 0 Then
				brush% = GetSurfaceBrush(surf%)
				If brush <> 0 Then
					tex% = GetBrushTexture(brush%)
					If tex <> 0 Then
						s$ = TextureName$(tex%)
						SetBuffer TextureBuffer(tex%)
						If GraphicsBuffer() = TextureBuffer(tex%) Then
						Color 255, 0, 0
						xx# = PickedU() * TextureWidth(tex%)
						yy# = PickedV() * TextureHeight(tex%)
						;Plot xx, yy
						If xx > 20 And yy > 20 Then
							If xx < TextureWidth(tex) - 20 And yy < TextureHeight(tex) - 20 Then
			
								Oval xx - 5, yy - 5, 11, 11
							
							End If
						End If
						SetBuffer BackBuffer()
						End If
					PaintSurface PickedSurface(), brush
					FreeTexture tex
				End If
				If brush <> 0 Then FreeBrush brush%
			End If
		End If
End If
			
		Text 0, 40, s$ + "<"
		Text 0, 0, tel
		
		Flip False
	
	Until KeyHit(1)
	
	End
	
	
	
	
	
; ID: 515
; Author: fredborg
; Date: 2002-11-30 11:51:35
; Title: PickedU(), PickedV(), PickedW()
; Description: Returns the U,V, and W coordinates of the last successful pick command!

;
; PickedU(), PickedV(), PickedW() commands 
;
; Created by Mikkel Fredborg
; 
; Use as you please, but please include a thank you :)
;

;

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedU#(coordset = 0)
	 
	; if something new has been picked then calculate the new uvw coordinates
	If (PickedX()<>ptri\px) Or (PickedY()<>ptri\py) Or (PickedZ()<>ptri\pz) Or (PickedSurface()<>ptri\surf)
		PickedUVW()
	End If
	
	Return ptri\pu[coordset]
	
End Function

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedV#(coordset = 0)
	
	; if something new has been picked then calculate the new uvw coordinates
	If (PickedX()<>ptri\px) Or (PickedY()<>ptri\py) Or (PickedZ()<>ptri\pz) Or (PickedSurface()<>ptri\surf)
		PickedUVW()
	End If
	
	Return ptri\pv[coordset]
	
End Function

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedW#(coordset = 0)
	
	; if something new has been picked then calculate the new uvw coordinates
	If (PickedX()<>ptri\px) Or (PickedY()<>ptri\py) Or (PickedZ()<>ptri\pz) Or (PickedSurface()<>ptri\surf)
		PickedUVW()
	End If
	
	Return ptri\pw[coordset]
	
End Function

;
; Calculates the UVW coordinates of a pick
; Do not call this by yourself, as PickedU(), PickedV(), and PickedW()
; takes care of calling it when nescessary
Function PickedUVW()

	If PickedSurface()
		ptri\ent  = PickedEntity()
		ptri\surf = PickedSurface()
		ptri\tri  = PickedTriangle()
			
		ptri\px = PickedX()
		ptri\py = PickedY()
		ptri\pz = PickedZ()
		
		For i = 0 To 2
			TFormPoint VertexX(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),VertexY(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),VertexZ(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),ptri\ent,0

			ptri\vx[i] = TFormedX()
			ptri\vy[i] = TFormedY()
			ptri\vz[i] = TFormedZ()

			ptri\vnx[i] = VertexNX(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
			ptri\vny[i] = VertexNY(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
			ptri\vnz[i] = VertexNZ(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
					
			ptri\vu[i+0] = VertexU(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)
			ptri\vv[i+0] = VertexV(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)
			ptri\vw[i+0] = VertexW(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)

			ptri\vu[i+3] = VertexU(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
			ptri\vv[i+3] = VertexV(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
			ptri\vw[i+3] = VertexW(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
		Next

		; Select which component of xyz coordinates to ignore
		Local coords = 3

		If Abs(PickedNX()) > Abs(PickedNY())
			If Abs(PickedNX())>Abs(PickedNZ()) Then coords = 1
		Else
			If Abs(PickedNY())>Abs(PickedNZ()) Then coords = 2
		EndIf
		
		Local a0#,a1#,b0#,b1#,c0#,c1#
		
		; xy components
		If (coords = 3)
			; edge 0
			a0# = ptri\vx[1] - ptri\vx[0]
			a1# = ptri\vy[1] - ptri\vy[0]
		
			; edge 1
			b0# = ptri\vx[2] - ptri\vx[0]
			b1# = ptri\vy[2] - ptri\vy[0]

			; picked offset from triangle vertex 0
			c0# = PickedX() - ptri\vx[0]
			c1# = PickedY() - ptri\vy[0]
		Else		
			; xz components
			If (coords = 2)
				; edge 0
				a0# = ptri\vx[1] - ptri\vx[0]
				a1# = ptri\vz[1] - ptri\vz[0]
		
				; edge 1
				b0# = ptri\vx[2] - ptri\vx[0]
				b1# = ptri\vz[2] - ptri\vz[0]

				; picked offset from triangle vertex 0
				c0# = PickedX() - ptri\vx[0]
				c1# = PickedZ() - ptri\vz[0]
			Else
				; yz components

				; edge 0
				a0# = ptri\vy[1] - ptri\vy[0]
				a1# = ptri\vz[1] - ptri\vz[0]
		
				; edge 1
				b0# = ptri\vy[2] - ptri\vy[0]
				b1# = ptri\vz[2] - ptri\vz[0]

				; picked offset from triangle vertex 0
				c0# = PickedY() - ptri\vy[0]
				c1# = PickedZ() - ptri\vz[0]
			End If
		End If
						
		;
		; u and v are offsets from vertex 0 along edge 0 and edge 1
		; using these it is possible to calculate the Texture UVW coordinates
		; of the picked XYZ location
		;
		; a0*u + b0*v = c0
		; a1*u + b1*v = c1
		;
		; solve equation (standard equation with 2 unknown quantities)
		; check a math book to see why the following is true
		;
		Local u# = (c0*b1 - b0*c1) / (a0*b1 - b0*a1)
		Local v# = (a0*c1 - c0*a1) / (a0*b1 - b0*a1)
		
		; If either u or v is out of range then the
		; picked entity was not a mesh, and therefore
		; the uvw coordinates cannot be calculated
		If (u<0.0 Or u>1.0) Or (v<0.0 Or v>1.0)
			Return 
		End If
		
		; Calculate picked uvw's for coordset 0 (and modulate them to be in the range of 0-1 nescessary)
		ptri\pu[0] = (ptri\vu[0] + ((ptri\vu[1] - ptri\vu[0]) * u) + ((ptri\vu[2] - ptri\vu[0]) * v)) Mod 1
		ptri\pv[0] = (ptri\vv[0] + ((ptri\vv[1] - ptri\vv[0]) * u) + ((ptri\vv[2] - ptri\vv[0]) * v)) Mod 1
		ptri\pw[0] = (ptri\vw[0] + ((ptri\vw[1] - ptri\vw[0]) * u) + ((ptri\vw[2] - ptri\vw[0]) * v)) Mod 1
		
		; If any of the coords are negative
		If ptri\pu[0]<0.0 Then ptri\pu[0] = 1.0 + ptri\pu[0]
		If ptri\pv[0]<0.0 Then ptri\pv[0] = 1.0 + ptri\pv[0]
		If ptri\pw[0]<0.0 Then ptri\pw[0] = 1.0 + ptri\pw[0]
		
		; Calculate picked uvw's for coordset 1 (and modulate them to be in the range of 0-1 nescessary)
		ptri\pu[1] = (ptri\vu[3] + ((ptri\vu[4] - ptri\vu[3]) * u) + ((ptri\vu[5] - ptri\vu[3]) * v)) Mod 1
		ptri\pv[1] = (ptri\vv[3] + ((ptri\vv[4] - ptri\vv[3]) * u) + ((ptri\vv[5] - ptri\vv[3]) * v)) Mod 1
		ptri\pw[1] = (ptri\vw[3] + ((ptri\vw[4] - ptri\vw[3]) * u) + ((ptri\vw[5] - ptri\vw[3]) * v)) Mod 1

		; If any of the coords are negative
		If ptri\pu[1]<0.0 Then ptri\pu[1] = 1.0 + ptri\pu[1]
		If ptri\pv[1]<0.0 Then ptri\pv[1] = 1.0 + ptri\pv[1]
		If ptri\pw[1]<0.0 Then ptri\pw[1] = 1.0 + ptri\pw[1]
	End If

End Function

When I made a version that handles single surface meshes, there is no bug. Same goes for the original texpaint by birdie. So I think the problem could have something to do with using PickedSurface().

Works fine for me.

Thanks skidraces, I appreciate it.
The trouble with this bug is that is takes really a while for it to appear.
I've traced the bug using a counter and speeded the example up using "Flip False".
When counter reaches 1995, the bug appears.

If there is a chance a texture is missing you probably want to test if tex%=0 before you go and lock / setbuffer the texture, if that doesn't help comment out the call to oval, if that fixes it it sounds very much like a driver bug...

If still no, then can you remove the millisecs() dependency and use an incrementing variable and repost so I am running the same test with the same numbers as yourself.

I think it is strange that I've had this similair problem in two versions. I tested it on another PC, and there it gives an error, too.
Removing the oval did solve the problem! Also when I removed the two 'SetBuffer' commands: no error.

The bug appears after a fixed number of frames.
PC1:2330 PC2:3200
It doesn't matter where I enter the 'loop'. Maybe it is a problem with releasing something ?

All other bugs with RenderWorld() involved some kind of memory leak, for instance too much triangles on a surface.

GetSurfaceBrush creates a new brush, but the texture applied to it, is it a copy too ? I checked if the handle of this returned texture is the same as the original handle, and it is the same.

I still think it is a bug. Sigh .. I will find a workaround.

it is not crashing to me, but sometimes blitz' renderworld crashes on to many triangles!

Hmm. Thanks for testing it, oh child of the devil. I think Skidracer is right then, about it being a driver problem. I have a NVidia board on both my pc's. Thanks again Skid and sorry I had my doubts. I can avoid the error by creating a new texture and draw on that.
; PickedTri type
; Necessary for the PickedU(), PickedV(), and PickedW() commands
Type PickedTri
	Field ent,surf,tri				;picked entity, surface and triangle
	Field px#,py#,pz#			    ;picked xyz
	Field pu#[1],  pv#[1]  ,pw#[1]  ;picked uvw x 2
	
	Field vx#[2],  vy#[2]  ,vz#[2]  ;vertex xyz
	Field vnx#[2], vny#[2] ,vnz#[2] ;vertex normals
	Field vu#[5],  vv#[5]  ,vw#[5]  ;vertex uvw x 2
End Type

Global ptri.pickedtri = New pickedtri



;-----------------------------------------------------------------------------------------------------
;
;-----------------------------------------------------------------------------------------------------
	
	Graphics3D 1024, 768, 0, 2
	SetBuffer BackBuffer()
		
	;Include "pickeduv.bb"

	ShowPointer()
	
	;show opendialog	
	f$ = "c:\_xfiles\mak_running.x"
	
	If FileType(f$) <> 1 Then End

	camera% = CreateCamera()
	CameraZoom camera%, 2.4
		
	mesh% = LoadMesh(f$)
	
	Dim ibrush%(CountSurfaces(mesh))
	Dim isurf%(CountSurfaces(mesh))
	Dim itex%(CountSurfaces(mesh))
	Dim col%(CountSurfaces(mesh))

	For i% = 1 To CountSurfaces(mesh)
		
		surf% = GetSurface(mesh, i)
		ibrush%(i) = CreateBrush(255, 255, 255)
		isurf%(i) = surf%
		itex%(i) = CreateTexture(512, 512)
		col%(i) = Rand($FFFFFF)
		BrushTexture ibrush(i), itex(i)
		PaintSurface surf, ibrush%(i)
		
	Next
	
	ww# = MeshWidth(mesh%)
	hh# = MeshHeight(mesh%)
	dd# = MeshDepth(mesh%)
	
	ScaleEntity mesh%, 0.05, 0.05, 0.05
	PositionEntity camera%, 0, 1, -7
	
	SetPickMode(mesh)
		
	tel = 0
	
	Repeat	
			
		If KeyDown(203) Then TurnEntity mesh, 0, +1, 0
		If KeyDown(205) Then TurnEntity mesh, 0, -1, 0
	
		RenderWorld
		
		CameraPick camera, MouseX(), MouseY()
		Text 0, 20, PickedSurface()
		
		;(PickedSurface() <> olds) And 
		
		If (PickedSurface()<>0) Then  			
		
			surf% = PickedSurface()
			
			sel% = 0
			For i = 1 To CountSurfaces(mesh)
				
				If isurf(i) = surf Then sel = i: tex = itex%(i)
				
			Next
			
			If sel > 0 Then
			
				SetBuffer TextureBuffer(tex%)
				Color 0, 0, col%(sel)
				xx# = PickedU() * TextureWidth(tex%)
				yy# = PickedV() * TextureHeight(tex%)
				Oval xx - 5, yy - 5, 11, 11
				SetBuffer BackBuffer()
				
			End If
							
		End If
			
		Text 0, 40, s$ + "<"
		Text 0, 0, tel
		
		Flip False
	
	Until KeyHit(1)
	
	End
	
	
	
	
	
; ID: 515
; Author: fredborg
; Date: 2002-11-30 11:51:35
; Title: PickedU(), PickedV(), PickedW()
; Description: Returns the U,V, and W coordinates of the last successful pick command!

;
; PickedU(), PickedV(), PickedW() commands 
;
; Created by Mikkel Fredborg
; 
; Use as you please, but please include a thank you :)
;

;

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedU#(coordset = 0)
	
	; if something new has been picked then calculate the new uvw coordinates
	If (PickedX()<>ptri\px) Or (PickedY()<>ptri\py) Or (PickedZ()<>ptri\pz) Or (PickedSurface()<>ptri\surf)
		PickedUVW()
	End If
	
	Return ptri\pu[coordset]
	
End Function

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedV#(coordset = 0)
	
	; if something new has been picked then calculate the new uvw coordinates
	If (PickedX()<>ptri\px) Or (PickedY()<>ptri\py) Or (PickedZ()<>ptri\pz) Or (PickedSurface()<>ptri\surf)
		PickedUVW()
	End If
	
	Return ptri\pv[coordset]
	
End Function

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedW#(coordset = 0)
	
	; if something new has been picked then calculate the new uvw coordinates
	If (PickedX()<>ptri\px) Or (PickedY()<>ptri\py) Or (PickedZ()<>ptri\pz) Or (PickedSurface()<>ptri\surf)
		PickedUVW()
	End If
	
	Return ptri\pw[coordset]
	
End Function

;
; Calculates the UVW coordinates of a pick
; Do not call this by yourself, as PickedU(), PickedV(), and PickedW()
; takes care of calling it when nescessary
Function PickedUVW()

	If PickedSurface()
		ptri\ent  = PickedEntity()
		ptri\surf = PickedSurface()
		ptri\tri  = PickedTriangle()
			
		ptri\px = PickedX()
		ptri\py = PickedY()
		ptri\pz = PickedZ()
		
		For i = 0 To 2
			TFormPoint VertexX(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),VertexY(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),VertexZ(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),ptri\ent,0

			ptri\vx[i] = TFormedX()
			ptri\vy[i] = TFormedY()
			ptri\vz[i] = TFormedZ()

			ptri\vnx[i] = VertexNX(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
			ptri\vny[i] = VertexNY(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
			ptri\vnz[i] = VertexNZ(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
					
			ptri\vu[i+0] = VertexU(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)
			ptri\vv[i+0] = VertexV(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)
			ptri\vw[i+0] = VertexW(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)

			ptri\vu[i+3] = VertexU(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
			ptri\vv[i+3] = VertexV(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
			ptri\vw[i+3] = VertexW(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
		Next

		; Select which component of xyz coordinates to ignore
		Local coords = 3

		If Abs(PickedNX()) > Abs(PickedNY())
			If Abs(PickedNX())>Abs(PickedNZ()) Then coords = 1
		Else
			If Abs(PickedNY())>Abs(PickedNZ()) Then coords = 2
		EndIf
		
		Local a0#,a1#,b0#,b1#,c0#,c1#
		
		; xy components
		If (coords = 3)
			; edge 0
			a0# = ptri\vx[1] - ptri\vx[0]
			a1# = ptri\vy[1] - ptri\vy[0]
		
			; edge 1
			b0# = ptri\vx[2] - ptri\vx[0]
			b1# = ptri\vy[2] - ptri\vy[0]

			; picked offset from triangle vertex 0
			c0# = PickedX() - ptri\vx[0]
			c1# = PickedY() - ptri\vy[0]
		Else		
			; xz components
			If (coords = 2)
				; edge 0
				a0# = ptri\vx[1] - ptri\vx[0]
				a1# = ptri\vz[1] - ptri\vz[0]
		
				; edge 1
				b0# = ptri\vx[2] - ptri\vx[0]
				b1# = ptri\vz[2] - ptri\vz[0]

				; picked offset from triangle vertex 0
				c0# = PickedX() - ptri\vx[0]
				c1# = PickedZ() - ptri\vz[0]
			Else
				; yz components

				; edge 0
				a0# = ptri\vy[1] - ptri\vy[0]
				a1# = ptri\vz[1] - ptri\vz[0]
		
				; edge 1
				b0# = ptri\vy[2] - ptri\vy[0]
				b1# = ptri\vz[2] - ptri\vz[0]

				; picked offset from triangle vertex 0
				c0# = PickedY() - ptri\vy[0]
				c1# = PickedZ() - ptri\vz[0]
			End If
		End If
						
		;
		; u and v are offsets from vertex 0 along edge 0 and edge 1
		; using these it is possible to calculate the Texture UVW coordinates
		; of the picked XYZ location
		;
		; a0*u + b0*v = c0
		; a1*u + b1*v = c1
		;
		; solve equation (standard equation with 2 unknown quantities)
		; check a math book to see why the following is true
		;
		Local u# = (c0*b1 - b0*c1) / (a0*b1 - b0*a1)
		Local v# = (a0*c1 - c0*a1) / (a0*b1 - b0*a1)
		
		; If either u or v is out of range then the
		; picked entity was not a mesh, and therefore
		; the uvw coordinates cannot be calculated
		If (u<0.0 Or u>1.0) Or (v<0.0 Or v>1.0)
			Return 
		End If
		
		; Calculate picked uvw's for coordset 0 (and modulate them to be in the range of 0-1 nescessary)
		ptri\pu[0] = (ptri\vu[0] + ((ptri\vu[1] - ptri\vu[0]) * u) + ((ptri\vu[2] - ptri\vu[0]) * v)) Mod 1
		ptri\pv[0] = (ptri\vv[0] + ((ptri\vv[1] - ptri\vv[0]) * u) + ((ptri\vv[2] - ptri\vv[0]) * v)) Mod 1
		ptri\pw[0] = (ptri\vw[0] + ((ptri\vw[1] - ptri\vw[0]) * u) + ((ptri\vw[2] - ptri\vw[0]) * v)) Mod 1
		
		; If any of the coords are negative
		If ptri\pu[0]<0.0 Then ptri\pu[0] = 1.0 + ptri\pu[0]
		If ptri\pv[0]<0.0 Then ptri\pv[0] = 1.0 + ptri\pv[0]
		If ptri\pw[0]<0.0 Then ptri\pw[0] = 1.0 + ptri\pw[0]
		
		; Calculate picked uvw's for coordset 1 (and modulate them to be in the range of 0-1 nescessary)
		ptri\pu[1] = (ptri\vu[3] + ((ptri\vu[4] - ptri\vu[3]) * u) + ((ptri\vu[5] - ptri\vu[3]) * v)) Mod 1
		ptri\pv[1] = (ptri\vv[3] + ((ptri\vv[4] - ptri\vv[3]) * u) + ((ptri\vv[5] - ptri\vv[3]) * v)) Mod 1
		ptri\pw[1] = (ptri\vw[3] + ((ptri\vw[4] - ptri\vw[3]) * u) + ((ptri\vw[5] - ptri\vw[3]) * v)) Mod 1

		; If any of the coords are negative
		If ptri\pu[1]<0.0 Then ptri\pu[1] = 1.0 + ptri\pu[1]
		If ptri\pv[1]<0.0 Then ptri\pv[1] = 1.0 + ptri\pv[1]
		If ptri\pw[1]<0.0 Then ptri\pw[1] = 1.0 + ptri\pw[1]
	End If

End Function

Function SetPickMode(mesh%)

	EntityPickMode mesh, 2
	If CountChildren(mesh) < 1 Then Return
	
	For i = 1 To CountChildren(mesh)
		ef% = GetChild(mesh, i)
		SetPickMode(ef)
	Next
	
End Function