Ultimate Tricky Mesh Question of the Week

Blitz3D Forums/Blitz3D Programming/Ultimate Tricky Mesh Question of the Week

ok, major progress here (i think). I've implemented some really useful things from the code archives, and I am SOOOO close to getting this to be exactly as it should be, at least for really simple cases.

Here's how it's working now:

For each triangles, I evaluate all of the potential intersections of each segment with the segments of the other triangle. This ends up being 15 cases, and works splendidly. Each of these intersections are exactly as they should be.

Now that I have these intersections, I need to mesh them. Therein lies the trouble. They are evaluated arbitrarily, and therefore I cannot intelligently mesh them. In the code posted below I'm trying to use FredBorg's awesome tesselation code to accomplish this, but it isn't working correctly.

Any ideas how to proceed? There are a couple of paths that would seem to solve these problems. I can:

1. figure out how to check the intersections in the correct order to order the verts in the proper fashion so that they form the right tris,

2. implement a new tesselation algo to try to make tris out of these arbitrarily arranged verts

3. figure out why it's not working right with FredBorg's code

any ideas?

thanks,
roland

here's my working code. I apologize for the extra stuff in here (camera projections and 2d ops to draw the interesections -- these no longer work because they are before the updateworld() and renderworld() but i've been too lazy to take them out).


Graphics3D 800,600,0,2
SeedRnd MilliSecs()

Const VERTEXLIMIT	= 999

Const DEGENERATE	= 0
Const CONCAVE		= 1
Const CONVEX		= 2

Type tessVert
	Field x#,y#,z#,u#,v#,n
End Type

Type tessSurf
	Field v0.tessVert[VERTEXLIMIT]
	Field v1.tessVert[VERTEXLIMIT]
	Field v2.tessVert[VERTEXLIMIT]
	Field n_tris
End Type

Dim tsv.tessVert(0)

Global mE0x#,mE0y#,mE0z#	
Global mE1x#,mE1y#,mE1z#				
Global mNx#,mNy#,mNz#,mA#
Global tessNx#,tessNy#,tessNz#


pivot = CreatePivot()
cam = CreateCamera(pivot)
PositionEntity cam,0,0,30
PointEntity cam,pivot

tri1 = CreateMesh()
tri1surf = CreateSurface(tri1)
tri1angle# = 45
tri1x# = -15
tri1y# = 10
tri1width# = 15
tri1length# = 20
EntityFX tri1,2+32+1

tri2 = CreateMesh()
tri2surf = CreateSurface(tri2)
tri2angle# = -45
tri2x# = 15
tri2y# = 10
tri2width# = 15
tri2length# = 20

EntityColor tri2,150,150,150

Global intersectx#
Global intersecty#


mesh = CreateMesh()
surf = CreateSurface(mesh)
EntityColor mesh,0,0,255


While Not KeyHit(1)

ClearSurface tri1surf

	If KeyHit(57)
		wire = Not wire
		WireFrame wire
	End If


If KeyDown(203) Then tri1x = tri1x+.2
If KeyDown(205) Then tri1x = tri1x-.2
If KeyDown(200) Then tri1y = tri1y+.2
If KeyDown(208) Then tri1y = tri1y-.2

If KeyDown(30) Then tri1angle = tri1angle+1
If KeyDown(44) Then tri1angle = tri1angle-1


;update first triangle
;ClearSurface tri1surf

dx# = Sin(tri1angle-tri1width)*tri1length
dy# = -Cos(tri1angle-tri1width)*tri1length

dx2# = Sin(tri1angle+tri1width)*tri1length
dy2# = -Cos(tri1angle+tri1width)*tri1length

tri1v0 = AddVertex(tri1surf,tri1x,tri1y,0)
tri1v1 = AddVertex(tri1surf,tri1x+dx,tri1y+dy,0)
tri1v2 = AddVertex(tri1surf,tri1x+dx2,tri1y+dy2,0)


VertexColor tri1surf,tri1v0,255,0,0,.5
VertexColor tri1surf,tri1v1,0,255,0,.5
VertexColor tri1surf,tri1v2,0,0,255,.5

AddTriangle tri1surf,tri1v0,tri1v1,tri1v2

UpdateNormals tri1

;update second triangle
ClearSurface tri2surf

t2dx# = Sin(tri2angle-tri2width)*tri2length
t2dy# = -Cos(tri2angle-tri2width)*tri2length

t2dx2# = Sin(tri2angle+tri2width)*tri2length
t2dy2# = -Cos(tri2angle+tri2width)*tri2length

tri2v0 = AddVertex(tri2surf,tri2x,tri2y,0)
tri2v1 = AddVertex(tri2surf,tri2x+t2dx,tri2y+t2dy,0)
tri2v2 = AddVertex(tri2surf,tri2x+t2dx2,tri2y+t2dy2,0)


AddTriangle tri2surf,tri2v0,tri2v1,tri2v2

UpdateNormals tri2


;all necessary checks to determine triangle to triangle intersection points

;t1 rightside against t2 rightside
If linesIntersect(tri1x,tri1y,tri1x+dx,tri1y+dy,tri2x,tri2y,tri2x+t2dx,tri2y+t2dy) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)

EndIf

;t1 leftside against t2 rightside
If linesIntersect(tri1x,tri1y,tri1x+dx2,tri1y+dy2,tri2x,tri2y,tri2x+t2dx,tri2y+t2dy) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 leftside against t2 leftside
If linesIntersect(tri1x,tri1y,tri1x+dx2,tri1y+dy2,tri2x,tri2y,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 rightside against t2 leftside
If linesIntersect(tri1x,tri1y,tri1x+dx,tri1y+dy,tri2x,tri2y,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 end against t2 end
If linesIntersect(tri1x+dx2,tri1y+dy2,tri1x+dx,tri1y+dy,tri2x+t2dx,tri2y+t2dy,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 end against t2 rightside
If linesIntersect(tri1x+dx2,tri1y+dy2,tri1x+dx,tri1y+dy,tri2x,tri2y,tri2x+t2dx,tri2y+t2dy) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 end against t2 leftside
If linesIntersect(tri1x+dx2,tri1y+dy2,tri1x+dx,tri1y+dy,tri2x,tri2y,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 rightside against t2 end
If linesIntersect(tri1x,tri1y,tri1x+dx,tri1y+dy,tri2x+t2dx,tri2y+t2dy,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf

;t1 leftside against t2 end
If linesIntersect(tri1x,tri1y,tri1x+dx2,tri1y+dy2,tri2x+t2dx,tri2y+t2dy,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,intersectx,intersecty,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(intersectx,intersecty,.5)
EndIf


;test if tri1's verts are inside tri2:
If InTriangle(tri1x,tri1y,tri2x,tri2y,tri2x+t2dx,tri2y+t2dy,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,tri1x,tri1y,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(tri1x,tri1y,.5)
EndIf

If InTriangle(tri1x+dx,tri1y+dy,tri2x,tri2y,tri2x+t2dx,tri2y+t2dy,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,tri1x+dx,tri1y+dy,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(tri1x+dx,tri1y+dy,.5)
EndIf

If InTriangle(tri1x+dx2,tri1y+dy2,tri2x,tri2y,tri2x+t2dx,tri2y+t2dy,tri2x+t2dx2,tri2y+t2dy2) = True
	CameraProject cam,tri1x+dx2,tri1y+dy2,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(tri1x+dx2,tri1y+dy2,.5)
EndIf


;test if tri2's verts are inside tri1:
If InTriangle(tri2x,tri2y,tri1x,tri1y,tri1x+dx,tri1y+dy,tri1x+dx2,tri1y+dy2) = True
	CameraProject cam,tri2x,tri2y,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(tri2x,tri2y,.5)
EndIf

If InTriangle(tri2x+t2dx,tri2y+t2dy,tri1x,tri1y,tri1x+dx,tri1y+dy,tri1x+dx2,tri1y+dy2) = True
	CameraProject cam,tri2x+t2dx,tri2y+t2dy,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(tri2x+t2dx,tri2y+t2dy,.5)
EndIf

If InTriangle(tri2x+t2dx2,tri2y+t2dy2,tri1x,tri1y,tri1x+dx,tri1y+dy,tri1x+dx2,tri1y+dy2) = True
	CameraProject cam,tri2x+t2dx2,tri2y+t2dy2,0
	Oval ProjectedX(),ProjectedY(),3,3

	tess_AddVert(tri2x+t2dx2,tri2y+t2dy2,.5)
EndIf



		tris = tess_Triangulate()
	
		;
		; Build a real 3D surface from the tessSurf
		ClearSurface surf
		For tessVert.TessVert = Each TessVert
			AddVertex surf,tessVert\x,tessVert\y,tessVert\z
		Next
		tessSurf.TessSurf = First TessSurf
		For t = 0 To tessSurf\n_tris-1
			AddTriangle surf,tessSurf\v0[t]\n,tessSurf\v1[t]\n,tessSurf\v2[t]\n
		Next		
		UpdateNormals mesh
		
		;
		; Clean up :)
		tess_Clean()

	FreeEntity meshcopy
	meshcopy = CopyMesh(mesh)
	EntityColor meshcopy,0,0,255
	FlipMesh meshcopy
	

UpdateWorld()
RenderWorld()

;Text 320,  0,"Tris - "+tris+" | Time - "+ms+" ms",True


Flip



Wend



Function linesIntersect(x1#,y1#, x2#,y2#, x3#,y3#, x4#,y4#)

	numeratorA#  = (x4-x3)*(y1-y3)-(y4-y3)*(x1-x3)
	numeratorB#  = (x2-x1)*(y1-y3)-(y2-y1)*(x1-x3)
	denominator# = (y4-y3)*(x2-x1)-(x4-x3)*(y2-y1)

	If denominator = 0.0 Then
		Return False
	Else
		Ua# = numeratorA/denominator
		Ub# = numeratorB/denominator
		range1# = Ua >= 0.0 And Ua <= 1.0
		range2# = Ub >= 0.0 And Ub <= 1.0
		If range1 And range2 Then
			intersectX# = (x1 + Ua*(x2-x1))
			intersectY# = (y1 + Ua*(y2-y1))
			Return True
		Else
			Return False
		End If
    End If
End Function


;x0, y0 = point, others are triangle verts.
Function InTriangle(x0#,y0#,x1#,y1#,x2#,y2#,x3#,y3#)

	b0# =  (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)
	b1# = ((x2 - x0) * (y3 - y0) - (x3 - x0) * (y2 - y0)) / b0 
	If b1 <= 0 Then Return False
	
	b2# = ((x3 - x0) * (y1 - y0) - (x1 - x0) * (y3 - y0)) / b0
	If b2 <= 0 Then Return False

	b3# = ((x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0)) / b0 
	If b3 <= 0 Then Return False
	
	Return True
	
End Function


Function tess_Clean()
	
	Delete Each tessVert
	Delete Each tessSurf
	
End Function

Function tess_AddVert(x#,y#,z#=0.0,u#=0.0,v#=0.0)
	
	p.tessVert = Last tessVert
	If (p = Null)
		n = 0
	Else
		n = p\n+1
	End If
		
	p.tessVert = New tessVert
	p\x		= x
	p\y		= y
	p\z		= z
	p\u		= u
	p\v		= v
	p\n		= n
	
End Function

Function tess_ComputeNormal()

	tessNx# = 0.0
	tessNy# = 0.0
	tessNz# = 0.0

	For a.tessVert = Each tessVert
		b.tessVert = After a
		If b = Null Then Exit
		
        tessNx = tessNx + ((a\y - b\y ) * ( a\z + b\z))
        tessNy = tessNy + ((a\z - b\z ) * ( a\x + b\x))
        tessNz = tessNz + ((a\x - b\x ) * ( a\y + b\y))
	Next
	
	; Normalize it, not really nescessary
	; just nicer to look at :)
	Local d# = Sqr(tessNx*tessNx + tessNy*tessNy + tessNz*tessNz)
	If d>0.0
		tessNx = tessNx/d
		tessNy = tessNy/d
		tessNz = tessNz/d
	End If

End Function

Function tess_Triangulate()

	Local n_tris = 0
	Local n_verts = 0
	Local noErrors = True

	; Close the polygon, by adding the first vert after the last
	p.tessVert = First tessVert
	If Not (p=Null)
		tess_AddVert(p\x,p\y,p\z,p\u,p\v)
	End If

	; Get the normal of the entire polygon
	tess_ComputeNormal()

	; Count number of vertices
	n_verts = -1
	For p.tessVert = Each tessVert
		n_verts = n_verts + 1
	Next

	; Index the vertices
	Dim tsv(n_verts)
	n = 0
	For p.tessVert = Each tessVert
		tsv(n) = p
		n = n + 1
	Next

	; Prepare a TessSurf
	surf.TessSurf	= New TessSurf
	surf\n_tris		= 0

	; Now it gets funny
	While n_verts=>3 And noErrors = True
	
		noErrors = False
		
		i = 0
		j = 1
		k = 2
		While k<(n_verts+3)
			If n_verts=0 Then Exit

			ib = i Mod n_verts
			jb = j Mod n_verts
			kb = k Mod n_verts
		
			Select tess_TriangleArea(ib,jb,kb)
				Case CONVEX:
					If tess_IsAnyPointInside(ib,jb,kb,n_verts) 
						; Triangle is ok, but it cross another part of the polygon
						i = j
						j = k
						k = k + 1
					Else
						; Triangle is ok, so build it
						tess_AddTriangle(surf,ib,jb,kb)
						n_tris   = n_tris + 1
						n_verts  = tess_RemoveVertex(jb,n_verts)
						noErrors = True
					End If
					
				Case CONCAVE:
					; Triangle faces the wrong way
					i = j
					j = k
					k = k + 1
				
				Case DEGENERATE:
					; Bad triangle (zero area)
					n_verts  = tess_RemoveVertex(jb,n_verts)
					noErrors = True
		
			End Select
		Wend
		
	Wend
	
	Return n_tris
	
End Function

Function tess_TriangleArea(i,j,k)
	
	Local v0.tessVert = tsv(i)
	Local v1.tessVert = tsv(j)
	Local v2.tessVert = tsv(k)

	mE0x# = v0\x-v2\x
	mE0y# = v0\y-v2\y
	mE0z# = v0\z-v2\z
	
	mE1x# = v1\x-v2\x
	mE1y# = v1\y-v2\y
	mE1z# = v1\z-v2\z				

	mNx# = mE0y * mE1z - mE0z * mE1y
	mNy# = mE0z * mE1x - mE0x * mE1z
	mNz# = mE0x * mE1y - mE0y * mE1x
		
	mA# = (mNx*mNx + mNy*mNy + mNz*mNz)

	If Abs(mA) < 0.000001
		Return DEGENERATE
	End If
	
	If (mNx#*tessNx# + mNy#*tessNy# + mNz#*tessNz#) < 0.0
		Return CONCAVE
	Else
		Return CONVEX
	End If
	
End Function

Function tess_RemoveVertex(j,n_verts)

	For i = j+1 To n_verts
		tsv(i-1)=tsv(i)
	Next
	Return n_verts-1
		
End Function

Function tess_AddTriangle(surf.tessSurf,i,j,k)

	surf\v0[ surf\n_tris ] = tsv(i)
	surf\v1[ surf\n_tris ] = tsv(j)
	surf\v2[ surf\n_tris ] = tsv(k)
	surf\n_tris = surf\n_tris + 1
	Return surf\n_tris
	
End Function

Function tess_IsAnyPointInside(i,j,k,n_verts)

	For ip=0 To n_verts
    	If (ip<i) Or (ip>k)
			If tess_IsPointInside(tsv(ip),tsv(k))
				Return True
			End If
		End If
	Next

	Return False
	
End Function

Function tess_IsPointInside(point.tessVert,q2.tessVert)

	Local pmq2x# = point\x - q2\x
	Local pmq2y# = point\y - q2\y
	Local pmq2z# = point\z - q2\z		
	
	Local ntmpx# = 0.0
	Local ntmpy# = 0.0
	Local ntmpz# = 0.0
	
	Local b0# = 0.0
	Local b1# = 0.0

	ntmpx# = pmq2y * mE1z - pmq2z * mE1y
	ntmpy# = pmq2z * mE1x - pmq2x * mE1z
	ntmpz# = pmq2x * mE1y - pmq2y * mE1x
	b0# = mNx*ntmpx + mNy*ntmpy + mNz*ntmpz
	If b0 <= 0.0 Then Return False
	
	ntmpx# = mE0y * pmq2z - mE0z * pmq2y
	ntmpy# = mE0z * pmq2x - mE0x * pmq2z
	ntmpz# = mE0x * pmq2y - mE0y * pmq2x
	b1# = mNx*ntmpx + mNy*ntmpy + mNz*ntmpz
	If b1 <= 0.0 Then Return False
	
    If (mA-B0-B1)>0.0
		Return True
	Else
		Return False
	End If

End Function

Function tess_TriNormal(v0x#,v0y#,v0z#,v1x#,v1y#,v1z#,v2x#,v2y#,v2z#)
	
	ax#=v1x-v0x
	ay#=v1y-v0y
	az#=v1z-v0z
	
	bx#=v2x-v1x
	by#=v2y-v1y
	bz#=v2z-v1z
	
	tessNx#=(ay#*bz#)-(az#*by#)
	tessNy#=(az#*bx#)-(ax#*bz#)
	tessNz#=(ax#*by#)-(ay#*bx#)

End Function