-- About:
-- MarbleCLAY Script to find single bad quad (and remove it) in the selected object.
-- Bad quads are quads (4 vert objects) and not flat, ie the quad verts are not on the same plane, or not Coplanar.

-- copied mostly from Flip.lua example

-- Instructions:
-- Put file in MarbleCLAY\Script\ run via Option->script->Execute Script or via the script window.
-- just enter script name (without .lau) and hit enter or double click the script name in the script window to rerun.

-- MC Dev docs:
-- https://web.archive.org/web/20160612052732/http://homepage3.nifty.com/escargot/DownLoadFrm.html (MarbleSDK beta5.6)

-- If you uncomment the following line, you can run it faster (possibly), 
-- but you can't stop it in the middle
 mc.debugmode(false)


 --  local start = os.time()

   local doc = mc.GetDocument()
   if doc then
 
     -- create a proxy object for the operation
     -- Create outside the loop to save memory
     local poly = mc.polygon_proxy()
	 local vertex1 = mc.vertex_proxy()
	 local vertex2 = mc.vertex_proxy()
	 local vertex3 = mc.vertex_proxy()
	 local vertex4 = mc.vertex_proxy()
	 
     local vtxs = {-1,-1,-1,-1} --Array for specifying vertices. (Note that Lua arrays start at 1)
     local uvs = {-1,-1,-1,-1} --Array for specifying UV vertices. (Note that Lua arrays start at 1)
    
     local i = 0
     repeat
       local obj = mc.GetActiveMesh(doc,i)
       if obj then
         -- get number of faces
         local cnt = mc.GetPolygonCount(obj)
		 
        --print("Object has PolygonCount=",cnt)
         -- Create a History object to record editing operations
         local his = mc.CreateHistory(doc,obj,CW_HISTORY_MODIFY_GEOMETRY,"QTestByLua")

         -- start editing
         mc.BeginModify(obj,his)
       -- --print("1 test")
		
         -- scan all faces
         for j = 0,cnt-1 do
		-- --print("2 test")
           if mc.GetPolygonProxy(obj,j,poly) then -- get the information of the jth face to the polygon proxy
        --  --print("3 test")
             -- Find faces that do not contain INVALID in the tag field and contain SELECT
             if (not mc.tag_contains(poly, CWBIT_TAG_INVALID))
             and (mc.tag_contains(poly, CWBIT_TAG_SELECT) and poly.n == 4 ) then
               -- Create an array with reversed face vertices
              
			--   --print("4 test")
               -- for k = 1,n do
                 -- vtxs[k] = poly["v"..(n-k)] -- vertex numbers are stored in poly[v0~v3]
                 -- uvs[k] = poly["u"..(n-k)] --UV vertex numbers are stored in poly[u0~u3]
               -- end
                  --print("Object ",j, " has points ", poly.n)
				
				
					 --print("here")
					vtxs[1] = poly.v0 -- vertex numbers are stored in poly[v0~v3]
					--print("vtxs1[1] ", vtxs[1] )
					vtxs[2] = poly["v1"]
					--print("vtxs1[2] ", vtxs[2] )
					vtxs[3] = poly["v2"]
					--print("vtxs1[3] ", vtxs[3] )
					vtxs[4] = poly["v3"]
					--print("vtxs1[4] ", vtxs[4] )
					 --print(table.concat(vtxs,", "))
					----print(table.concat(poly.v0,", "))
					 --print("1 here vtxs[1] " , vtxs[1])
					 -- // bool_value, vertex = GetVertexProxy(obj, index)
					--  --print(table.concat(mc.GetVertexProxy(obj,14,vertex1),", "))
					-- test, vertex1 = mc.GetVertexProxy(obj,14)
					mc.GetVertexProxy(obj,vtxs[1],vertex1)
					
					--print("vertex1 x ", vertex1.x)
					--print("vertex1 y ", vertex1.y)
					--print("vertex1 z ", vertex1.z)
					
					mc.GetVertexProxy(obj,vtxs[2],vertex2)
					
					--print("vertex2 x ", vertex2.x)
					--print("vertex2 y ", vertex2.y)
					--print("vertex2 z ", vertex2.z)
					
					
					mc.GetVertexProxy(obj,vtxs[3],vertex3)
					
					--print("vertex3 x ", vertex3.x)
					--print("vertex3 y ", vertex3.y)
					--print("vertex3 z ", vertex3.z)
					
					
					mc.GetVertexProxy(obj,vtxs[4],vertex4)
					
					--print("vertex4 x ", vertex4.x)
					--print("vertex4 y ", vertex4.y)
					--print("vertex4 z ", vertex4.z)				
					
				 
				 --print("Object ",j, " has points ", poly.n)
				  
				 -- from: https://www.geeksforgeeks.org/program-to-check-whether-4-points-in-a-3-d-plane-are-coplanar/
				  --print("start..")
				  
					local x1 = vertex2.x
					local y1 = vertex2.y
					local z1 = vertex2.z
					local x2 = vertex3.x
					local y2 = vertex3.y
					local z2 = vertex3.z
					local x3 = vertex4.x
					local y3 = vertex4.y
					local z3 = vertex4.z
					local x = vertex1.x
					local y = vertex1.y
					local z = vertex1.z
	
					--print("prim set...")
				    local a1 = x2 - x1 
					local b1 = y2 - y1 
					local c1 = z2 - z1 
					local a2 = x3 - x1 
					local b2 = y3 - y1 
					local c2 = z3 - z1 
					
					--print("prim set 2...")
					
					local a = b1 * c2 - b2 * c1 
					local b = a2 * c1 - a1 * c2 
					local c = a1 * b2 - b1 * a2 

					local d = (- a * x1 - b * y1 - c * z1) 
					   --print("prim set3...")
					   
					--// equation of plane is: a*x + b*y + c*z = 0 #
					   
					--// checking if the 4th point satisfies
					--// the above equation
					local res = a * x + b * y + c * z + d
					if(res == 0) then
						 --print("face is Coplanar!") 
					else 
						print("face NOT Coplanar, removed and exiting!") 
						mc.RemovePolygon(obj, j, false, true, his)
						break
					end
					
					--print("finished") 
               -- delete original face
              -- mc.RemovePolygon(obj, j, false, true, his)
               -- Create a new face. (The data in the proxy is still valid if the face has just been deleted.)
              -- mc.AddPolygon(obj, poly.mat, poly.n, vtxs, uvs, poly.grp, his)
             end
			-- --print("5 test")
           end
		  -- --print("6 test")
         end
		-- --print("7 test")
        
         -- Finish editing
         mc.EndModify(obj,CWBIT_TAG_SELECT or CWBIT_TAG_MAKE,0,his)
       else
         break
       end
       i = i + 1
     until (false)

     -- screen update
     mc.RefreshView(doc, CW_VIEW_ALL)
    
     --print("done.")
   end
  
   --print("time=",os.time()-start)
   
   