Code archives/3D Graphics - Mesh/ClusterizeMesh Revisited
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| 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
| ||
| Sweet, just a week too late! :P (made my own) However, this will come in handy :D |
| ||
| Good to see somebody is using it. Well done. |
Code Archives Forum