1. Swyter
  2. cartographer


Swyter  committed 6593929

*Compute the maximum _absolute_ axis when checking axis reversal
*Compute normals using "Weighting By Surface Area" as shown in this excellent page by ByteHazard

That basically means that when averaging connected faces
to each vertex the size of each face is important, As our mate Barf/Scruples likes to say.

This smart technique gives excellent results without even using smoothing groups.

  • Participants
  • Parent commits 73b707e
  • Branches revamp

Comments (0)

Files changed (1)

File mab-map.lua

View file
  • Ignore whitespace
      return U:cross(V):normalized()
+function mab.map:computearea(triangle)
+     local a,b,c=
+     mab.map.vtx[triangle[1]],
+     mab.map.vtx[triangle[2]],
+     mab.map.vtx[triangle[3]]
+     local sqrt=math.sqrt
+     local D1=(a-b):len() --magnitudes
+     local D2=(b-c):len()
+     local D3=(c-a):len()
+     local H = (D1 + D2 + D3) * 0.5
+     return sqrt(H * (H - D1) * (H - D2) * (H - D3))
 function mab.map:saveobj(file,reversed_mode)
   print("@--Exporting OBJ..."); local start=os.clock(); local lastmat=-1;
 function mab.map:softnormal()
   local vtxi={}
-  mab.map.fcn,mab.map.vtn={},{}
+  mab.map.fcn,mab.map.cfa,mab.map.vtn={},{},{}
   for i=1,fcs do --get a list of triangle membership for any vertex
     local vta,vtb,vtc=mab.map.fcs[i][1],mab.map.fcs[i][2],mab.map.fcs[i][3]
-    --compute per-face normals using cross-product
+    --compute per-face normals using cross-product, don't ask me why putting this in its own loop halves the processing time, cool optimizations!
+    --compute area of this triangle/face, so we can average proportionally depending on sizes <http://www.bytehazard.com/code/vertnorm.html>
+    mab.map.cfa[i]=mab.map:computearea(mab.map.fcs[i])
   for i=1,#vtxi do --average between all the per-face normals to get a smooth aproximation
     local thingie=vector.new(0,0,0)
       for u=1, #vtxi[i] do
           local currface=vtxi[i][u]
-          thingie=thingie+mab.map.fcn[currface]
+          thingie=thingie+mab.map.fcn[currface]*mab.map.cfa[currface] --small polygons will have little influence, large polygons have large influence
-      mab.map.vtn[i]=thingie/#vtxi[i]
+      mab.map.vtn[i]=(thingie/#vtxi[i]):normalized()
 function mab.map:aretheaxisreversed()
   if mab.map.vtx and mab.map.fcs then --if we have map
   local max=math.max
+  local abs=math.abs
   local ly,lz=0,0
     for i=1,#mab.map.fcs do --go across all the faces in the map and compare y/z of the second vertex
-      ly=max(ly,mab.map.vtx[mab.map.fcs[i][2]].y)
-      lz=max(lz,mab.map.vtx[mab.map.fcs[i][2]].z)
+      ly=max(ly,abs(mab.map.vtx[mab.map.fcs[i][2]].y))
+      lz=max(lz,abs(mab.map.vtx[mab.map.fcs[i][2]].z))
     --if lz wins then the imported model has less height(ly) than width(lz), and probably, if we're dealing with