[bb] Polygon Reduction by John J. [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:42

Previous topic - Next topic

BlitzBot

Title : Polygon Reduction
Author : John J.
Posted : 1+ years ago

Description : This polygon reduction function is based on the Blitz3D example at "examplesirdielodmesh" by David Bird.

Using the reduction function is extremely simple. Just call the MeshPolygonsReduce function, with the mesh and reduction amount.

Example:
MeshPolygonsReduce(ent,500) ;Reduce 500 polygons from 'ent'

For example code and media, download <a href="http://www.alsbonsai.com/john/PolygonReduction.zip" target="_blank">PolygonReduction.zip (11KB)</a> [/i]

Code :
Code (blitzbasic) Select
;=========================================================================
;Polygon Reduction Function - Based on the Blitz3D example at "examplesirdielodmesh" by David Bird
;-------------------------------------------------------------------------
;
;Using the reduction function is extremely simple. Just call the
;MeshPolygonsReduce Function, with the mesh and reduction amount. Example:
;
;MeshPolygonsReduce(ent,500) ;Reduce 500 polygons from 'ent'
;
;=========================================================================

;**** Internal data ****
Const MAXTRIS=100000

Dim PR_TriVisible(MAXTRIS)
Dim PR_TriCost#(MAXTRIS)
Dim PR_TriVert(MAXTRIS,3)
Dim PR_TriConnect(MAXTRIS,2)

Global PR_TriangleCount=0,PR_VertexCount=0
Global PR_CurrentSurface



;============================== Main Function ============================
;MeshPolygonsReduce (mesh, n)
;  inputmesh: The mesh to reduce
;  n: The amount of polygons to reduce from the inputmesh
Function MeshPolygonsReduce(mesh,n)
;Make sure "mesh" is really a mesh
If EntityClass$(mesh)<>"Mesh" Then
RuntimeError "Can't reduce polygons of a "+Lower$(EntityClass$(mesh))
Return
End If

If n<=0 Then Return ;Don't need to do anything

;Divide n by the surface count
n=n/CountSurfaces(mesh)
If n<1 Then n=1 ;Don't do nothing

;For every surface
For surf=1 To CountSurfaces(mesh)
;Get surface
PR_CurrentSurface=GetSurface(mesh,surf)

;Calculate surface data
CalculateMeshData(mesh)

;Remove n lowest cost polys from mesh
For i=1 To n
tri=LeastNeededTriangle()
If tri<>-1 Then RemoveTriangle(tri)
Next

;Clear the surface's triangles
ClearSurface PR_CurrentSurface,False,True

;Regenerate the mesh with the new level of detail
For i=0 To PR_TriangleCount
If PR_TriVisible(i) Then
AddTriangle PR_CurrentSurface,PR_TriVert(i,0),PR_TriVert(i,1),PR_TriVert(i,2)
End If
Next
Next

;Update the new mesh's normals
UpdateNormals mesh
End Function
;-------------------------------------------------------------------------



;********* Internal Functions *********
Function CalculateMeshData(mesh)
;Clear data
PR_TriangleCount=0
PR_VertexCount=0

;Get vertex count
PR_VertexCount=CountVertices(PR_CurrentSurface)

;Initialise triangles
PR_TriangleCount=CountTriangles(PR_CurrentSurface)-1
For triindex=0 To PR_TriangleCount
For i=0 To 2
PR_TriVert(triindex,i)=TriangleVertex(PR_CurrentSurface,triindex,i)
Next
PR_TriVisible(triindex)=True
Next

;Process triangles
For triindex=0 To PR_TriangleCount
CalculateTriangleCost#(triindex) ;Calculate the triangle's importance
Next
End Function

Function LeastNeededTriangle()
;Find minimum cost
minimumcost#=1000000
triindex=-1
For i=0 To PR_TriangleCount
If PR_TriVisible(i) Then
If PR_TriCost(i)<minimumcost Then
triindex=i
minimumcost=PR_TriCost(i)
End If
End If
Next
;Return lowest triangle
Return triindex
End Function

Function RemoveTriangle(tri)
PR_TriVisible(tri)=False

;Re-attach vertices
oldvert=PR_TriVert(tri,PR_TriConnect(tri,0))
newvert=PR_TriVert(tri,PR_TriConnect(tri,1))
For i=0 To PR_TriangleCount
changed=False
If PR_TriVert(i,0)=oldvert Then PR_TriVert(i,0)=newvert:changed=True
If PR_TriVert(i,1)=oldvert Then PR_TriVert(i,1)=newvert:changed=True
If PR_TriVert(i,2)=oldvert Then PR_TriVert(i,2)=newvert:changed=True
If changed Then ;Recalculate triangle cost if the triangle has been re-attached
CalculateTriangleCost(i)
End If
Next
End Function

Function CalculateTriangleCost#(tri)
;Calculate the edge sizes of the triangle
x0#=VertexX(PR_CurrentSurface,PR_TriVert(tri,0)):y0#=VertexY(PR_CurrentSurface,PR_TriVert(tri,0)):z0#=VertexZ(PR_CurrentSurface,PR_TriVert(tri,0))
x1#=VertexX(PR_CurrentSurface,PR_TriVert(tri,1)):y1#=VertexY(PR_CurrentSurface,PR_TriVert(tri,1)):z1#=VertexZ(PR_CurrentSurface,PR_TriVert(tri,1))
x2#=VertexX(PR_CurrentSurface,PR_TriVert(tri,2)):y2#=VertexY(PR_CurrentSurface,PR_TriVert(tri,2)):z2#=VertexZ(PR_CurrentSurface,PR_TriVert(tri,2))
coord0#=Sqr((x0-x1)^2+(y0-y1)^2+(z0-z1)^2)
coord1#=Sqr((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)
coord2#=Sqr((x2-x0)^2+(y2-y0)^2+(z2-z0)^2)

;Pick the best vertice to use when removing the triangle
If coord0<coord1 And coord0<coord2 Then n=1
If coord1<coord0 And coord1<coord2 Then n=2
If coord2<coord0 And coord2<coord1 Then n=3

Select n
Case 0
PR_TriConnect(tri,0)=1:PR_TriConnect(tri,1)=0
Case 1
PR_TriConnect(tri,0)=1:PR_TriConnect(tri,1)=0
Case 2
PR_TriConnect(tri,0)=2:PR_TriConnect(tri,1)=1
Case 3
PR_TriConnect(tri,0)=0:PR_TriConnect(tri,1)=2
End Select

;Set the cost to the sum of the triangle's edges
PR_TriCost#(tri)=coord0+coord1+coord2
End Function


Comments :


jfk EO-11110(Posted 1+ years ago)

 this is cool.


Barliesque(Posted 1+ years ago)

 Superb!  Thanks for posting.  :)


BlitzSupport(Posted 1+ years ago)

 Excellent.


Panno(Posted 1+ years ago)

 wow....


WildStorm(Posted 1+ years ago)

 so cool


Neochrome(Posted 1+ years ago)

 Perfect 10


slenkar(Posted 1+ years ago)

 nice,I tried it with a mesh of a man, it took the head off and removed the front of the chest,I wonder if there is a way to fix this.. it could be a great tool.