Weld and unwrap meshes

Blitz3D Forums/Blitz3D Programming/Weld and unwrap meshes

JoshK(Posted 2003) [#1]
This code divides meshes up into surfaces by triangle normals. It creates a list of all triangle normals, merging faces that have normals within a specified limit, then rebuilds the mesh so that each surface contains only triangles within a certain range of normals. The same routine can be used to split a single-surface mesh up into coplanar surfaces (for lightmapping, BSP, and CSG), or it can merge a mesh into a single surface.

Graphics3D 800,600,16,2

cam=CreateCamera()
CameraClsColor cam,255,255,255
TurnEntity cam,45,45,0
MoveEntity cam,0,0,-15

m=LoadMesh("box.3ds")
ScaleMesh m,.1,.1,.1
os=CountSurfaces(m)
EntityColor m,255,0,0
result=WeldMesh(m,0.1)
FreeEntity m

While Not KeyHit(1)
	TurnEntity result,0,1,1
	RenderWorld
	Color 0,0,0
	Text 0,0,os+" surfaces split into "+CountSurfaces(result)+" surfaces."
	Flip
	Wend


End

Function WeldMesh(mesh,limit#=0.1)
facebank=CreateBank()
result=CreateMesh()
For s=1 To CountSurfaces(mesh)
	surf=GetSurface(mesh,s)
	For t=0 To CountTriangles(surf)-1
		A=TriangleVertex(surf,t,0)
		B=TriangleVertex(surf,t,1)
		C=TriangleVertex(surf,t,2)
		TriangleNormal VertexX(surf,A),VertexY(surf,A),VertexZ(surf,A),VertexX(surf,B),VertexY(surf,B),VertexZ(surf,B),VertexX(surf,C),VertexY(surf,C),VertexZ(surf,C)
		nx#=VectorX()
		ny#=VectorY()
		nz#=VectorZ()
		face=FaceExists(facebank,nx,ny,nz,limit)
		If face>-1
			trislist=PeekInt(facebank,16*face+12)
			appendint trislist,surf
			appendint trislist,t
			Else
			appendfloat facebank,nx
			appendfloat facebank,ny
			appendfloat facebank,nz
			trislist=CreateBank()
			appendint facebank,trislist
			appendint trislist,surf
			appendint trislist,t
			EndIf
		Next
	Next
For n=0 To BankSize(facebank)/16-1
	newsurf=CreateSurface(result)
	b=CreateBrush()
 	BrushColor b,Rand(255),Rand(255),Rand(255)
	PaintSurface newsurf,b
	FreeBrush b
	trislist=PeekInt(facebank,16*n+12)
	For t=0 To BankSize(trislist)/8-1
		surf=PeekInt(trislist,t*8)
		ti=PeekInt(trislist,t*8+4)
		A=TriangleVertex(surf,ti,0)
		B=TriangleVertex(surf,ti,1)
		C=TriangleVertex(surf,ti,2)
		A=VertexExists(newsurf,VertexX(surf,A),VertexY(surf,A),VertexZ(surf,A))
		B=VertexExists(newsurf,VertexX(surf,B),VertexY(surf,B),VertexZ(surf,B))
		C=VertexExists(newsurf,VertexX(surf,C),VertexY(surf,C),VertexZ(surf,C))
		AddTriangle newsurf,A,B,C
		Next
	Next
FreeBank facebank
Return result
End Function

Function VertexExists(surf,x#,y#,z#,accuracy#=0.00001)
For v=0 To CountVertices(surf)-1
	If PointDistance(x,y,z,VertexX(surf,v),VertexY(surf,v),VertexZ(surf,v))<=accuracy Return v
	Next
Return AddVertex(surf,x,y,z)
End Function

Function FaceExists(bank,x#,y#,z#,limit#)
For n=0 To BankSize(bank)/16-1
	nx#=PeekFloat(bank,n*16)
	ny#=PeekFloat(bank,n*16+4)
	nz#=PeekFloat(bank,n*16+8)
	SubVector x,y,z,nx,ny,nz
	If Magnitude(VectorX(),VectorY(),VectorZ())<=limit Return n
	Next
Return -1
End Function

Function appendint(buffer,value)
ResizeBank buffer,BankSize(buffer)+4
PokeInt buffer,BankSize(buffer)-4,value
End Function

Function appendfloat(buffer,value#)
ResizeBank buffer,BankSize(buffer)+4
PokeFloat buffer,BankSize(buffer)-4,value
End Function



BlitzSupport(Posted 2003) [#2]
Halo, I'm getting 'userlib function not found' here:

If PointDistance(x,y,z,VertexX(surf,v),VertexY(surf,v),VertexZ(surf,v))<=accuracy Return v


Re-arranging things shows that PointDistance is the culprit, but it *is* recognised as a command (just downloaded your latest 3d libs, BTW) if you place it into a blank program, so I'm a little stumped -- could possibly be a Blitz problem...

Anyone else get this?

BTW Good work on that plane-split thing!


JoshK(Posted 2003) [#3]
My bad. I messed up the title of the PointDistance function. The libs are updated now, same download.