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
|