Code archives/3D Graphics - Mesh/ClusterizeMesh Revisited

This code has been declared by its author to be Public Domain code.

Download source code

ClusterizeMesh Revisited by RifRaf2005
Original author was JFK, his entry is below in the archives. I made several changes and additions to the routine.
I call it chunkterrain as i use it mainly for mesh terrains made with FLE and the likes. but you can use it on anything
Unlike JKFs original version, with this version you are not limited to any spacial area. You can also tell the function how many times to divide each axis. so if you call ChunkTerrain (mesh,2,2,2) it will divide each axis by 2, and give you 2x2x2 cube chunks. (2 meaning (meshsize/2)).

theres a update_chunks() function is there if you want to use it.. wich hides chunks out of range.

Aside from the original function modifications, other functions created to make it all work were RemoveSurface() NeareastPower() and ChunkDistance(). Nearestpower just snaps any number to the nearest X multiplier. and allows the function to put triangles into cube chunks regardless of mesh size or position.

This will also work on scaled meshes. with scalemesh or even ScaleEntity.
Type remove_surf
	Field id
	End Type

Type Cluster
	Field XC#, YC#, ZC#
	Field Mesh, Surf[200]
	End Type

Function ChunkTerrain(mesh,xsize=50,ysize=1,zsize=50)
	Delete Each Cluster
    Delete Each Remove_surf 
	; First we'll need to get the original terrain scale for matching scale after the chunking
    vx# = GetMatElement#(Mesh, 0, 0)
	vy# = GetMatElement#(Mesh, 0, 1)
	vz# = GetMatElement#(Mesh, 0, 2)
	XScale# = Sqr(vx# * vx# + vy# * vy# + vz# * vz#)
	vx# = GetMatElement#(Mesh, 1, 0)
	vy# = GetMatElement#(Mesh, 1, 1)
	vz# = GetMatElement#(Mesh, 1, 2)
	YScale# = Sqr(vx# * vx# + vy# * vy# + vz# * vz#)
	vx# = GetMatElement#(Mesh, 2, 0)
	vy# = GetMatElement#(Mesh, 2, 1)
	vz# = GetMatElement#(Mesh, 2, 2)
	ZScale# = Sqr(vx# * vx# + vy# * vy# + vz# * vz#)

	cx# = Int((MeshWidth#(Mesh)) / xsize)
	cy# = Int((MeshHeight#(Mesh)) / ysize)
	cz# = Int((MeshDepth#(Mesh)) / zsize)

	; Let the chunking begin
	sos = CountSurfaces(mesh)
	For s = 1 To sos
		surf = GetSurface(mesh, s)
		brush = GetSurfaceBrush(surf)

		For t = 0 To CountTriangles(surf) - 1
			x0#  = VertexX#(surf, TriangleVertex(surf, t, 0))
			y0#  = VertexY#(surf, TriangleVertex(surf, t, 0))
			z0#  = VertexZ#(surf, TriangleVertex(surf, t, 0))
			nx0# = VertexNX#(surf, TriangleVertex(surf, t, 0))
			ny0# = VertexNY#(surf, TriangleVertex(surf, t, 0))
			nz0# = VertexNZ#(surf, TriangleVertex(surf, t, 0))
			al0# = VertexAlpha#(surf, TriangleVertex(surf, t, 0))
			cr0# = VertexRed#(surf, TriangleVertex(surf, t, 0))
			cg0# = VertexGreen#(surf, TriangleVertex(surf, t, 0))
			cb0# = VertexBlue#(surf, TriangleVertex(surf, t, 0))
			x1#  = VertexX#(surf, TriangleVertex(surf, t, 1))
			y1#  = VertexY#(surf, TriangleVertex(surf, t, 1))
			z1#  = VertexZ#(surf, TriangleVertex(surf, t, 1))
			nx1# = VertexNX#(surf, TriangleVertex(surf, t, 1))
			ny1# = VertexNY#(surf, TriangleVertex(surf, t, 1))
			nz1# = VertexNZ#(surf, TriangleVertex(surf, t, 1))
			al1# = VertexAlpha#(surf, TriangleVertex(surf, t, 1))
			cr1# = VertexRed#(surf, TriangleVertex(surf, t, 1))
			cg1# = VertexGreen#(surf, TriangleVertex(surf, t, 1))
			cb1# = VertexBlue#(surf, TriangleVertex(surf, t, 1))
			x2#  = VertexX#(surf, TriangleVertex(surf, t, 2))
			y2#  = VertexY#(surf, TriangleVertex(surf, t, 2))
			z2#  = VertexZ#(surf, TriangleVertex(surf, t, 2))
			u0a# = VertexU#(surf, TriangleVertex(surf, t, 0), 0)
			v0a# = VertexV#(surf, TriangleVertex(surf, t, 0), 0)
			u1a# = VertexU#(surf, TriangleVertex(surf, t, 1), 0)
			v1a# = VertexV#(surf, TriangleVertex(surf, t, 1), 0)
			u2a# = VertexU#(surf, TriangleVertex(surf, t, 2), 0)
			v2a# = VertexV#(surf, TriangleVertex(surf, t, 2), 0)
			nx2# = VertexNX#(surf, TriangleVertex(surf, t, 2))
			ny2# = VertexNY#(surf, TriangleVertex(surf, t, 2))
			nz2# = VertexNZ#(surf, TriangleVertex(surf, t, 2))
			al2# = VertexAlpha#(surf, TriangleVertex(surf, t, 2))
			cr2# = VertexRed#(surf, TriangleVertex(surf, t, 2))
			cg2# = VertexGreen#(surf, TriangleVertex(surf, t, 2))
			cb2# = VertexBlue#(surf, TriangleVertex(surf, t, 2))

			; Let's see which chunk we'll assign this vert to
			x_c# = NearestPower(VertexX#(surf, TriangleVertex(surf, t, 0)), CX)
			y_c# = NearestPower(VertexY#(surf, TriangleVertex(surf, t, 0)), CY)
			z_c# = NearestPower(VertexZ#(surf, TriangleVertex(surf, t, 0)), CZ)
			Found = False
			For cl.cluster = Each cluster
				If x_c = cl\xc And y_c = cl\yc And z_c = cl\zc
					If cl\surf[s] <> 0
						Found = True
						v0 = AddVertex(cl\surf[s], x0, y0, z0)
						VertexTexCoords cl\surf[s], v0, u0a, v0a, 0
						VertexColor cl\surf[s], v0, cr0, cg0, cb0, al0
						VertexNormal cl\surf[s], v0, nx0, ny0, nz0
						v1 = AddVertex(cl\surf[s], x1, y1, z1)
						VertexTexCoords cl\surf[s], v1, u1a, v1a, 0
						VertexColor cl\surf[s], v1, cr1, cg1, cb1, al1
						VertexNormal cl\surf[s], v1, nx1, ny1, nz1
						v2 = AddVertex(cl\surf[s], x2, y2, z2)
						VertexTexCoords cl\surf[s], v2, u2a, v2a, 0
						VertexColor cl\surf[s], v2, cr2, cg2, cb2, al2
						VertexNormal cl\surf[s], v2, nx2, ny2, nz2
						nope = AddTriangle(cl\surf[s], v0, v1, v2)
						Exit
					EndIf
				EndIf
			Next

			; If there was no chunk for that area, we'll make it here
			If Found = False
				cl.cluster = New cluster
				nsegs = nsegs + 1
				cl\xc# = x_c
				cl\yc# = y_c
				cl\zc# = z_c
				cl\mesh = CreateMesh()
				For ss = 1 To sos
					cl\surf[ss] = CreateSurface(cl\mesh)
					surf2 = GetSurface(mesh, ss) 
					brush = GetSurfaceBrush(surf2)
                    PaintSurface cl\surf[ss], brush
				Next
				v0 = AddVertex(cl\surf[s], x0, y0, z0)
				VertexTexCoords cl\surf[s], v0, u0a, v0a, 0
				VertexColor cl\surf[s], v0, cr0, cg0, cb0, al0
				VertexNormal cl\surf[s], v0, nx0, ny0, nz0
				v1 = AddVertex(cl\surf[s], x1, y1, z1)
				VertexTexCoords cl\surf[s], v1, u1a, v1a, 0
				VertexColor cl\surf[s], v1, cr1, cg1, cb1, al1
				VertexNormal cl\surf[s], v1, nx1, ny1, nz1
				v2 = AddVertex(cl\surf[s], x2, y2, z2)
				VertexTexCoords cl\surf[s], v2, u2a, v2a, 0
				VertexColor cl\surf[s], v2, cr2, cg2, cb2, al2
				VertexNormal cl\surf[s], v2, nx2, ny2, nz2
				nope = AddTriangle(cl\surf[s], v0, v1, v2)
			EndIf
		Next
	Next

;remove blank surfaces from chunk
	For cl.Cluster = Each Cluster
        For rems.remove_surf=Each remove_surf
             Delete rems
               Next
	    For scn=1 To CountSurfaces(cl\mesh)
            sf=GetSurface(cl\mesh,scn)
 			vn=CountVertices(sf)-1
            If vn=<0 Then 
               rems.Remove_surf=New remove_surf
               rems\id=scn	
               EndIf
               Next
            fb=fb*-1
            cl\mesh=removesurface(cl\mesh)
            EntityPickMode cl\mesh,2,True
			Next


;free the original large mesh         
	FreeEntity Mesh

End Function


Function NearestPower(N#, Snapper#)

	Return Float#(Int(Abs(N#) / Snapper#)) * Snapper# * Sgn(N#)

End Function

Function uPdate_clusters(ent,maxdist#=500)
For C.CLUSTER=Each CLUSTER
				dist# = chunk_distance(ent,c\mesh)
				If dist>maxdist# Then 
 				  HideEntity c\mesh 
                 Else
                   ShowEntity c\mesh
                  EndIf 
				Next
				End Function
				

Function Chunk_distance(entity1,entity2)
	s=GetSurface(entity2,1)
	Return Sqr#((EntityX#(entity1,1) - VertexX#(s,1))^2 + (EntityZ#(entity1,1) - VertexZ(s,1))^2)
    End Function

Function removesurface(ent)
DebugLog "testing removal"
;ok we need to rebuild the mesh
DebugLog "creating mesh target"
 newmesh=CreateMesh()
 ns=CountSurfaces(ent)
DebugLog ns+" original surfaces"

For i=1 To ns
nogo=0
For rems.remove_surf=Each remove_surf
  If i=rems\id Then nogo=1
  Next
 If nogo=0  Then
    DebugLog "making surf"
 	  surf=GetSurface(ent,i)	
	  newsurf=CreateSurface(newmesh)
  	  brush = GetSurfaceBrush(surf)

		tc=CountTriangles(surf)
             For tri=0 To tc-1
			    v_r1#=VertexRed(surf,TriangleVertex(Surf,tri,0) )
			    v_g1#=VertexGreen(surf,TriangleVertex(Surf,tri,0)) 
			    v_b1#=VertexBlue(surf,TriangleVertex(Surf,tri,0) )
			    v_r2#=VertexRed(surf,TriangleVertex(Surf,tri,1) )
			    v_g2#=VertexGreen(surf,TriangleVertex(Surf,tri,1)) 
			    v_b2#=VertexBlue(surf,TriangleVertex(Surf,tri,1) )
			    v_r3#=VertexRed(surf,TriangleVertex(Surf,tri,2) )
			    v_g3#=VertexGreen(surf,TriangleVertex(Surf,tri,2)) 
			    v_b3#=VertexBlue(surf,TriangleVertex(Surf,tri,2) )

			    v_x0#=VertexX(surf,TriangleVertex(surf,tri,0))
			    v_x1#=VertexX(surf,TriangleVertex(surf,tri,1))
			    v_x2#=VertexX(surf,TriangleVertex(surf,tri,2))

			    v_y0#=VertexY(surf,TriangleVertex(surf,tri,0))
			    v_y1#=VertexY(surf,TriangleVertex(surf,tri,1))
			    v_y2#=VertexY(surf,TriangleVertex(surf,tri,2))

			    v_z0#=VertexZ(surf,TriangleVertex(surf,tri,0))
			    v_z1#=VertexZ(surf,TriangleVertex(surf,tri,1))
			    v_z2#=VertexZ(surf,TriangleVertex(surf,tri,2))

			    v_u0#=VertexU(surf,TriangleVertex(surf,tri,0))
			    v_u1#=VertexU(surf,TriangleVertex(surf,tri,1))
			    v_u2#=VertexU(surf,TriangleVertex(surf,tri,2))

			    v_v0#=VertexV(surf,TriangleVertex(surf,tri,0))
			    v_v1#=VertexV(surf,TriangleVertex(surf,tri,1))
			    v_v2#=VertexV(surf,TriangleVertex(surf,tri,2))

			    v_a0#=VertexAlpha(surf,TriangleVertex(surf,tri,0))
 		        v_a1#=VertexAlpha(surf,TriangleVertex(surf,tri,1))
			    v_a2#=VertexAlpha(surf,TriangleVertex(surf,tri,2))

                 v0=AddVertex(newsurf,v_x0,v_y0,v_z0,v_u0,v_v0)
			     v1=AddVertex(newsurf,v_x1,v_y1,v_z1,v_u1,v_v1)
			     v2=AddVertex(newsurf,v_x2,v_y2,v_z2,v_u2,v_v2)
			     AddTriangle(newsurf,v0,v1,v2)

			    VertexColor newsurf, v0,v_r1,v_g1,v_b1,v_a0
			    VertexColor newsurf, v1,v_r2,v_g2,v_b2,v_a1
			    VertexColor newsurf, v2,v_r3,v_g3,v_b3,v_a2
              Next 
             PaintSurface newsurf,brush
             UpdateNormals newmesh
       EndIf 
       Next
;free the old mesh
FreeEntity ent
;return the updated mesh
Return newmesh
End Function

Comments

Damien Sturdy2005
Sweet, just a week too late! :P (made my own)
However, this will come in handy :D


jfk EO-111102005
Good to see somebody is using it. Well done.


Code Archives Forum