local empty = {}
local vBufferSize = 16000
local vBufferN = 0

local vBuffer1
local vBuffer2

local vData 
local vPointer

if useData then 
  ffi.cdef ([[
    typedef struct { 
      float x,  y,  z, w;
      float u,  v;
      float r,  g,  b, a;
      float nx, ny, nz;
    } vertex;
  ]])
  print("bufsize",(ffi.sizeof("vertex")*vBufferSize)/(1024),"kb")
  if LOVE then 
		vData 	    = love.data.newByteData(ffi.sizeof("vertex")*vBufferSize)
	  vPointer    = vData:getPointer()
	  vBuffer1    = ffi.cast("vertex*",vPointer)
	  vBuffer2    = ffi.cast("vertex*",love.data.newByteData(ffi.sizeof("vertex")*vBufferSize):getPointer())
	else
		vBuffer1 = ffi.new("vertex[?]",vBufferSize)
		vBuffer2 = ffi.new("vertex[?]",vBufferSize)
		vData = vBuffer1
	end
else
	vBuffer1 =  {} for i=1,vBufferSize,1 do vBuffer1[i] = { 0,0,0,0, 0,0, 0,0,0,0, 0,0,0} end
	vBuffer2 =  {} for i=1,vBufferSize,1 do vBuffer2[i] = { 0,0,0,0, 0,0, 0,0,0,0, 0,0,0} end
end

local vBufferStart = 0
local tempTerrain={tris={}}
local vBuf
local tv1,tv2,tv3,tv4 = vec2(),vec2(),vec2(),vec2()
local tmpPt1, tmpPt2, tmpPt3 = vec3(),vec3(),vec3()
local tempBase = {0,0,0,0}
local tempColor = {1,1,1}
local tempHeights = {0,0}
local tempHeights2 = {0,0,0,0}
local tempFaceRemovals = {false,false,false,false}
local cos,sin,sqrt = math.cos,math.sin,math.sqrt

local totalSteps = 0 
local currentStep = 0


local function unpackColor(c)
	return c[1],c[2],c[3],1, 0,0,0, c[4]
end

local function colorTable(color)
	return color.r and {color.r,color.g,color.b, color.pattern, color.scale, color.rotation} or {r=color[1],g=color[2],b=color[3]}
end

local function setTable2(t,...)
	for i=1,#t,1 do 
		t[i] = arg[i]
	end
	return t
end

local function startVerts(alt) 
	vBuf = alt and vBuffer2 or vBuffer1
	vBufferN = useData and -1 or 0
	vBufferStart=vBufferN+1
	for k,v in pairs(tempTerrain) do tempTerrain[k]=nil end
end

local function setValues (t,v1,v2,v3,v4)
  t[1],t[2],t[3],t[4]=v1,v2,v3,v4
	return t
end

local function setValues2(a,b)
	a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15],a[16]=
	b[1],b[2],b[3],b[4],b[5],b[6],b[7],b[8],b[9],b[10],b[11],b[12],b[13],b[14],b[15],b[16]
end

local function insertValues (t,n,v1,v2,v3,v4)
	t[n]=t[n] or {}
	setValues(t[n],v1,v2,v3,v4)
end

local function vRange()
	return {vBufferStart,vBufferN}
end

local vBufInsert = useData and 
function(v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15)
  vBufferN=vBufferN+1

  vBuf[vBufferN].x  = v0  
	vBuf[vBufferN].y  = v1  
	vBuf[vBufferN].z  = v2  
	vBuf[vBufferN].w  = v3  
	vBuf[vBufferN].u  = v4  
	vBuf[vBufferN].v  = v5  
	vBuf[vBufferN].r  = v6  
	vBuf[vBufferN].g  = v7  
	vBuf[vBufferN].b  = v8  
	vBuf[vBufferN].a  = v9  
	vBuf[vBufferN].nx = 0 
	vBuf[vBufferN].ny = 0 
	vBuf[vBufferN].nz = 0 

	
end
or
function(v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v16)
  vBufferN=vBufferN+1

  vBuf[vBufferN][1 ]=v1  
  vBuf[vBufferN][2 ]=v2  
  vBuf[vBufferN][3 ]=v3  
  vBuf[vBufferN][4 ]=v4  
  vBuf[vBufferN][5 ]=v5  
  vBuf[vBufferN][6 ]=v6  
  vBuf[vBufferN][7 ]=v7  
  vBuf[vBufferN][8 ]=v8  
  vBuf[vBufferN][9 ]=v9  
  vBuf[vBufferN][10]=v10 
  vBuf[vBufferN][11]=v11 
  vBuf[vBufferN][12]=v12 
  vBuf[vBufferN][13]=v13 

end

local slice = {}
local function setVerticesFromTableSlice(mesh,table,first,last)
	local v=1
  if useData then 
    mesh:setVertices(vData)
  else 
  	for i=first,last do 
  		slice[v] = table[i]
  		v = v+1
  	end
  	for i=v,#slice,1 do 
  		slice[i]=nil
  	end
    mesh:setVertices(slice)
  end
end

-- local function cloneBuffer()
-- 	for i=1,vBufferSize,1 do 
-- 		setValues2(vBuffer2[i],vBuffer[i])
-- 	end
-- end

local lineV1,lineV2,lineV3,lineV4 = vec2(),vec2(),vec2(),vec2()
local tempLine,tempLineN = {},0
local lineCross,lineDir = vec3(),vec3()
local tempVert = vec3()

local function specialWave(t)
	if t<0.11 then 
		return sin(t*10)
	elseif t<0.75 then 
		return cos(t)
	else
		return t 
	end
end
local baluster = {height=0,width=0}
local function insertThickLine(p1,p2,width,color,style,keepShape,keepAngle)
	local style   			= style or empty
	local segs 					= style.segs or 8
	local steps 				= style.steps or 1
	local wave  				= style.wave 
	local length 				= vec3.dist(p1,p2)
	local line 					= tempLine
	local w,pw 					= width
	local v1,v2,v3,v4 	= lineV1,lineV2,lineV3,lineV4
	local vertical = false--(p1.x==p2.x) and (p1.z==p2.z)
	if not keepShape then 
		local j,n = 0,0
		if vertical then -- MODEL
			if not baluster.verts then 
				baluster.verts = obj.load("models/architecture/balusters/baluster1.obj")
				for v=1,#baluster.verts,1 do 
					baluster.height=baluster.verts[v][2]<baluster.height and baluster.verts[v][2] or baluster.height
					baluster.width=baluster.verts[v][1]<baluster.width and baluster.verts[v][1] or baluster.width
				end
			end
			local sx,sy,sz = (width/baluster.width), (length/math.abs(baluster.height))
			n = #baluster.verts

			if style.roll then 
				local c = cos(style.roll)
				local s = sin(style.roll)
				local x 
				local y 
				for i=n, 1,-1 do 
					x = baluster.verts[i][1]*sx
					y = baluster.verts[i][3]*sx
					insertValues(line,i, c*x-s*y, baluster.verts[i][2]*sy, s*x+c*y)
				end
			else
				for i=1, n do 
					insertValues(line,i,baluster.verts[i][1]*sx,baluster.verts[i][2]*sy,baluster.verts[i][3]*sx)
				end
			end
		else
			pw = wave and wave(0)*width or width
			for s=1,steps,1 do 
				local y1,y2 = (s-1)*(-length/steps),s*(-length/steps)
				if wave then 
					 w = wave((s/steps))*width
				end 
				for i=1,segs,1 do 
					j = i==segs and 1 or i+1
					v1:set(vec2.from_cartesian2(pw/2,(i/segs)*pi*2))
					v2:set(vec2.from_cartesian2(pw/2,(j/segs)*pi*2))
					v3:set(vec2.from_cartesian2(w/2,(i/segs)*pi*2))
					v4:set(vec2.from_cartesian2(w/2,(j/segs)*pi*2))

					n=n+1; insertValues(line,n, v1.x,y1,v1.y )
					n=n+1; insertValues(line,n, v4.x,y2,v4.y )
					n=n+1; insertValues(line,n, v3.x,y2,v3.y )
					n=n+1; insertValues(line,n, v1.x,y1,v1.y )
					n=n+1; insertValues(line,n, v2.x,y1,v2.y )
					n=n+1; insertValues(line,n, v4.x,y2,v4.y )
				end
				pw = w
			end
		end
		tempLineN = n
	end
	if (not vertical) and (not keepAngle) then 
		-- local angle = axes.y:dot(lineDir) 
		-- lineDir:set(vec3.sub2(p2,p1))
		-- lineCross:set(vec3.cross2(lineDir,axes.y))
		-- for i=1, tempLineN do 
		-- 	tempVert:set(line[i][1],line[i][2],line[i][3])
		-- 	line[i][1],line[i][2],line[i][3] = tempVert:rotate2(pi/2,lineCross)
		-- end
	end
	for i=1, tempLineN do 
		vBufInsert(p1.x+line[i][1],p1.y+line[i][2],p1.z+line[i][3],1,1,1,unpackColor(color))
	end
end

local white = {1,1,1}

local function insertWallVerts(base,y,color,remove,rc)
	local rc     = rc or 0
	local remove = remove or empty
	local outer  = color and (type(color[1])=="table" and color[1] or color) or white
	local inner  = color and (type(color[2])=="table" and color[2] or color) or outer
	local r0,g0,b0 = inner[1],inner[2],inner[3]
	local r1,g1,b1 = outer[1],outer[2],outer[3]
	local r2,g2,b2 = rc==0 and r0 or outer[1],rc==0 and g0 or outer[2],rc==0 and b0 or outer[3]
	local r3,g3,b3 = rc==3 and r0 or outer[1],rc==3 and g0 or outer[2],rc==3 and b0 or outer[3]
	local r4,g4,b4 = rc==4 and r0 or outer[1],rc==4 and g0 or outer[2],rc==4 and b0 or outer[3]
	local y1,y2,y3,y4 = y[1],y[2],y[3] or y[1],y[4] or y[2] 

	vBufInsert( base[1].x,	y1,	base[1].y, 1, 1,1, r1,g1,b1,1, 0,0,0) 
	vBufInsert( base[2].x,	y3,	base[2].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
	vBufInsert( base[1].x,	y2,	base[1].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
	vBufInsert( base[2].x,	y3,	base[2].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
	vBufInsert( base[2].x,	y4,	base[2].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
	vBufInsert( base[1].x,	y2,	base[1].y, 1, 1,1, r1,g1,b1,1, 0,0,0) 

	vBufInsert( base[3].x,	y2,	base[3].y, 1, 1,1, r2,g2,b2,1, 0,0,0)
	vBufInsert( base[4].x,	y3,	base[4].y, 1, 1,1, r2,g2,b2,1, 0,0,0)
	vBufInsert( base[3].x,	y1,	base[3].y, 1, 1,1, r2,g2,b2,1, 0,0,0) 
	vBufInsert( base[3].x,	y2,	base[3].y, 1, 1,1, r2,g2,b2,1, 0,0,0) 
	vBufInsert( base[4].x,	y4,	base[4].y, 1, 1,1, r2,g2,b2,1, 0,0,0)
	vBufInsert( base[4].x,	y3,	base[4].y, 1, 1,1, r2,g2,b2,1, 0,0,0)

	if not remove[1]then
		vBufInsert( base[4].x,	y4,	base[4].y, 1, 1,1, r1,g1,b1,1, 0,0,0) -- right / remove 1
		vBufInsert( base[2].x,	y4,	base[2].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[2].x,	y3,	base[2].y, 1, 1,1, r1,g1,b1,1, 0,0,0) 
		vBufInsert( base[2].x,	y3,	base[2].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[4].x,	y3,	base[4].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[4].x,	y4,	base[4].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
	end

	if not remove[2]then
		vBufInsert( base[1].x,	y1,	base[1].y, 1, 1,1, r1,g1,b1,1, 0,0,0) -- left / remove 2
		vBufInsert( base[1].x,	y2,	base[1].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[3].x,	y2,	base[3].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[3].x,	y2,	base[3].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[3].x,	y1,	base[3].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
		vBufInsert( base[1].x,	y1,	base[1].y, 1, 1,1, r1,g1,b1,1, 0,0,0)
	end

	if not remove[3]then
		vBufInsert( base[3].x,	y1,	base[3].y, 1, 1,1, r3,g3,b3,1, 0,0,0) -- bottom / remove 3
		vBufInsert( base[2].x,	y3,	base[2].y, 1, 1,1, r3,g3,b3,1, 0,0,0)
		vBufInsert( base[1].x,	y1,	base[1].y, 1, 1,1, r3,g3,b3,1, 0,0,0) 
		vBufInsert( base[3].x,	y1,	base[3].y, 1, 1,1, r3,g3,b3,1, 0,0,0)
		vBufInsert( base[4].x,	y3,	base[4].y, 1, 1,1, r3,g3,b3,1, 0,0,0)
		vBufInsert( base[2].x,	y3,	base[2].y, 1, 1,1, r3,g3,b3,1, 0,0,0)
	end

	if not remove[4]then
		vBufInsert( base[1].x,	y2,	base[1].y, 1, 1,1, r4,g4,b4,1, 0,0,0) -- top / remove 4
		vBufInsert( base[2].x,	y4,	base[2].y, 1, 1,1, r4,g4,b4,1, 0,0,0)
		vBufInsert( base[3].x,	y2,	base[3].y, 1, 1,1, r4,g4,b4,1, 0,0,0)
		vBufInsert( base[3].x,	y2,	base[3].y, 1, 1,1, r4,g4,b4,1, 0,0,0)
		vBufInsert( base[2].x,	y4,	base[2].y, 1, 1,1, r4,g4,b4,1, 0,0,0)
		vBufInsert( base[4].x,	y4,	base[4].y, 1, 1,1, r4,g4,b4,1, 0,0,0)
	end
end

local edges = {}
local edge= {0,0,0,0}
local edgeVec = vec2()
local edgeNorm = vec2()
local edgeNum = 0
for i=1,1000,1 do 
	edges[i] = {
		0,0,0,0,
		norm 	= vec2(),
		p1 	 	= vec2(),
		p2 		= vec2()
	}
end
local function getEdge()
	edgeNum = edgeNum+1
	return edges[edgeNum]
end 
local function insertEdge(edges,x1,y1,x2,y2)
	local edge = getEdge()
	setValues(edge,x1,y1,x2,y2)
	edgeVec:set(edge[3]-edge[1],edge[4]-edge[2])
	edgeVec.x,edgeVec.y = -edgeVec.y,edgeVec.x
	edgeNorm:set(vec2.normalize2(edgeVec))
	edgeVec = edgeNorm*(edgeInset or 0)
	setValues(edge,edge[1]+edgeVec.x,edge[2]+edgeVec.y,edge[3]+edgeVec.x,edge[4]+edgeVec.y)
	edge.p1:set(edge[1],edge[2])
	edge.p2:set(edge[3],edge[4])
	edge.norm:set(edgeNorm)
	table.insert(edges,edge)
end

local smoothPairs,smoothGroups,smoothN = {{},{}},{},1
local vertsTaken
local function getSharedVerts(verts)
	local new = false 
	for i=#smoothPairs[1],1,-1 do 
		local v,w =inTable(verts,smoothPairs[1][i]),inTable(verts,smoothPairs[2][i])
		if v or w then 
			if not v then table.insert(verts,smoothPairs[1][i]) end
			if not w then table.insert(verts,smoothPairs[2][i]) end
			table.remove(smoothPairs[1],i)
			table.remove(smoothPairs[2],i)
			new = true
		end
	end
	return verts,new
end

local function averageNormals(verts,smooth,first,last)
	local smooth,first,last = smooth or 0.5,first or (useData and 0 or 1),last or #verts  
	local abs = math.abs
	local sqrt = math.sqrt

	for v=first,last,1 do 
		for w=first,last,1 do 
			if v~=w
				 and abs(verts[w][1]-verts[v][1])<1  
				 and abs(verts[w][2]-verts[v][2])<1  
				 and abs(verts[w][3]-verts[v][3])<1 
				 and verts[v][11]*verts[w][11] +  verts[v][12]*verts[w][12] +  verts[v][13]*verts[w][13]>smooth then 
					smoothPairs[1][smoothN] = v
					smoothPairs[2][smoothN] = w
				 	smoothN=smoothN+1
			end
		end
	end
	-- print("\npairs")
	-- print(inspect(smoothPairs))
	local shared,new
	local retry 
	while #smoothPairs[1]>0 do
		if not retry then 
			shared = getSharedVerts({smoothPairs[1][#smoothPairs[2]],smoothPairs[2][#smoothPairs[2]]})
			if #shared>0 then 
				retry=true 
			end
		else
			shared,new = getSharedVerts(shared)
			if not new then 
				table.insert(smoothGroups,shared)
				retry=false
			end	
		end
	end

	if #smoothGroups>0 then 
		-- print("\ngroups")
		-- print(inspect(smoothGroups))
		for g=1,#smoothGroups,1 do 
			local nx,ny,nz  = 0,0,0
			for i=1,#smoothGroups[g],1 do 
				local v = smoothGroups[g][i]
				nx,ny,nz = nx+verts[v][11],  ny+verts[v][12],  nz+verts[v][13]
			end
			local l = sqrt(nx*nx+ny*ny+nz*nz)
			nx,ny,nz =nx/l,ny/l,nz/l 
			for i=1,#smoothGroups[g],1 do 
				local v = smoothGroups[g][i]
			  verts[v][11],verts[v][12],verts[v][13] = nx,ny,nz
			end
		end
	end
end



local nx,ny,nz,ba,ca = 0,0,0,vec3(),vec3()
local function calcVertNormals(verts,tris,first,last,smooth,offset)
  -- print( "normals" )
	local t,l = 0
	local first,last = first or (type(verts)=="cdata" and 0 or 1),last or #verts
	local sqrt = math.sqrt
	smoothPairs = smooth and {{},{}} or smoothPairs
	smoothGroups = smooth and {} or smoothGroups
	vertsTaken = smooth and {} or vertsTaken
	smoothN = 1

  if type(verts)=="cdata" then 
  	-- if type(verts)=="table" then 
  	-- 	print_info(levels)
  	-- end
		for v=first,last-2,3 do 
	  	
			ba.x,ba.y,ba.z = verts[v+1].x - verts[v].x,verts[v+1].y - verts[v].y,verts[v+1].z - verts[v].z
			ca.x,ca.y,ca.z = verts[v+2].x - verts[v].x,verts[v+2].y - verts[v].y,verts[v+2].z - verts[v].z

			nx,ny,nz =  ba.y * ca.z - ba.z * ca.y,
									ba.z * ca.x - ba.x * ca.z,
									ba.x * ca.y - ba.y * ca.x

			l = sqrt(nx*nx+ny*ny+nz*nz)
			nx,ny,nz =nx/l,ny/l,nz/l 
			-- print(nx,ny,nz)
	  	  verts[v].nx,  verts[v].ny,  verts[v].nz = nx,ny,nz
			verts[v+1].nx,verts[v+1].ny,verts[v+1].nz = nx,ny,nz
			verts[v+2].nx,verts[v+2].ny,verts[v+2].nz = nx,ny,nz
	  end
  else
		local offset = offset or 11
		local x,y,z = offset,offset+1,offset+2
		for v=first,last-2,3 do 
			ba.x,ba.y,ba.z = verts[v+1][1] - verts[v][1],verts[v+1][2] - verts[v][2],verts[v+1][3] - verts[v][3]
			ca.x,ca.y,ca.z = verts[v+2][1] - verts[v][1],verts[v+2][2] - verts[v][2],verts[v+2][3] - verts[v][3]

			nx,ny,nz =  ba.y * ca.z - ba.z * ca.y,
									ba.z * ca.x - ba.x * ca.z,
									ba.x * ca.y - ba.y * ca.x

			l = sqrt(nx*nx+ny*ny+nz*nz)
			nx,ny,nz =nx/l,ny/l,nz/l 

	  	  verts[v][x],  verts[v][y],  verts[v][z] = nx,ny,nz
			verts[v+1][x],verts[v+1][y],verts[v+1][z] = nx,ny,nz
			verts[v+2][x],verts[v+2][y],verts[v+2][z] = nx,ny,nz
	  end
	end

  if not editingLevel and smooth then
  	-- averageNormals(verts,smooth,first,last)
	end
end
scene.calcVertNormals = calcVertNormals
local useBuffer    
local verts        
local first, last  
local range        
local function insertTerrain(entity,t)
	bench.push("insert")
  bench.push("5something")
	local t = t or tempTerrain
	useBuffer    = not t.verts
	verts        = t.verts or vBuf 
	first, last  = useBuffer and vBufferStart or 1, useBuffer and vBufferN or #verts
	range        = last-first+1
	
	local model,insert 
	for k,v in pairs(entity.terrain.models) do 
		if v.isFloor == t.isFloor and 
			 v.isRoof == t.isRoof and 
			 v.isEdge == t.isEdge and 
			 v.isWall == t.isWall and 
			 v.index  == t.index and
			 v.id 		 == t.id then 
			model,insert = v,k
		end
	end
  bench.pop("5something")

	bench.push("6normals")
	t.tris = t.tris or {}
	calcVertNormals(verts,t.tris,first,last,t.smooth)

	-- print("shared",sharedFound)
	bench.pop("6normals")
	local makeNew = false

	bench.push("7mesh")
	if insert and entity.terrain.models[insert] then 
		if range==0 then 
		  if entity.terrain.models[insert].mesh then 
		  	entity.terrain.models[insert].mesh:release()
			  entity.terrain.models[insert].mesh = nil
		  end
			table.insert(entity.terrainRemovals,insert)
		else
			if entity.terrain.models[insert].mesh and entity.terrain.models[insert].nverts ==  range then 
				setVerticesFromTableSlice(entity.terrain.models[insert].mesh, verts, first, last)
			else 
				if entity.terrain.models[insert].mesh then 
					entity.terrain.models[insert].mesh:release()
				end
				entity.terrain.models[insert].mesh = gfx.newMesh(zformat,range,t.triMode or "triangles",editingLevel and "stream" or "static")
				setVerticesFromTableSlice(entity.terrain.models[insert].mesh, verts, first, last)
			end
		end
	else 
		if range>0 then 
			makeNew = true 
		end
	end
	bench.pop("7mesh")

	bench.push("8new")
	if makeNew then 
		table.insert(entity.terrain.models,{
			mesh 			= gfx.newMesh(zformat, range,t.triMode or "triangles",editingLevel and "stream" or "static")
		})
		setVerticesFromTableSlice(entity.terrain.models[#entity.terrain.models].mesh, verts, first, last)
	end
	bench.pop("8new")
	terrainVerts= terrainVerts+range

	local index = insert or (makeNew and #entity.terrain.models or 0)

	bench.push("9stuff")
	if entity.terrain.models[index] then 
		for k,v in pairs(t) do
			if k~="verts" then 
				entity.terrain.models[index][k]=v
			end
		end
		if t.texture then 
			t.texture:setWrap("repeat","repeat")
		end
		if entity.terrain.models[index].mesh then
			-- gfx.setTexture(entity.terrain.models[index].mesh,patterns.atlas)
		end
		entity.terrain.models[index].nverts = range
		entity.terrain.models[index].newbb = true
		entity.terrain.models[index].isTerrain=true
		-- entity.terrain.models[index].bbox = entity.terrain.models[index].bbox or calcBBOX2(t.tris)
	end


	bench.pop("9stuff")
	bench.pop("insert")
end

local function dc (path,inherit)
	local copy = deepcopy(path.color) 
	copy.inherit = inherit
	return copy
end

local function defaultColors (path,parts)
	local color = path.colors
	path.inner,path.outer = (path.inner or deepcopy(path.color)),(path.outer or deepcopy(path.color))
	color.color = colorTable(path.color)
	color.inner = colorTable(path.inner)
	color.outer = colorTable(path.outer)
	for p,part in ipairs(parts) do  
		path[part].color  = path[part].color or dc(path)
		path[part].inner  = path[part].inner or dc(path)
		path[part].outer  = path[part].outer or dc(path)
		color[part]       = color[part] or {}
		color[part].color =  colorTable(path[part].color)
		color[part].outer =  colorTable(path[part].outer)
		color[part].inner =  colorTable(path[part].inner)
	end
	return color
end



local function lerp(a,b,t) return (1-t)*a + t*b end
local function gradientStep(steps,gradient,color)
  currentStep=currentStep+1
  totalSteps=totalSteps+1
    setValues(
      color.ramp,
      lerp(gradient[1].floor.inner[1],gradient[2].floor.inner[1],currentStep/steps),
      lerp(gradient[1].floor.inner[2],gradient[2].floor.inner[2],currentStep/steps),
      lerp(gradient[1].floor.inner[3],gradient[2].floor.inner[3],currentStep/steps)
    )
end

function checkSnap (floor,startPoint,endPoint)
  local index = select(2,lume.match(floor,
    function(x) 
      return x.id==(startPoint and startPoint.snapPoint.id or endPoint.snapPoint.id) 
    end ))
  return floor[index].moved or floor[index==#floor and 1 or index+1].moved
end

------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------



local vp1,vp2 = vec3(),vec3()
local nextPoint,prevPoint
local midPoint = vec2()
local sines,cosines = {},{}
local lPoints,rPoints = {},{}
local ilPoints,irPoints = {},{}
local blPoints,brPoints = {},{}
local midPoints = {}
local angs,dists = {},{}
local summedInner,summedOuter = {},{}

local bar,bar2 = {},{}
local railOffset = vec3()
local railInset= vec2()
local railSet = vec2()
local railv1,railv2 = vec3(),vec3()
local post1,post2= vec3(),vec3()
local wallOffset = vec2()
local floors = {}
local ramps = {}

function scene.addFloors(entity)
	edgeNum=0
   -- if true then return end
	local removals = {}
	bench.push("floors")
  floors = toArray(entity.floors, floors)
  for _=1,#floors,1 do 
    local floor = floors[_]
    local f = floor.id

		if   scene.time==0
			or (pathsPanel and pathsPanel.changed and pathsPanel.changed[1]=="floors" and pathsPanel.changed[2]==floor.id)  
			or (pathsPanel and pathsPanel.cutting and pathsPanel.cutTarget[2] == floor.id)
			or editor.debug.force_build
			 then 

			bench.push("1")

			local y 			= floor.points[1].y
			floor.isFloor = true
			floor.shape 	= {}
			floor.shape2 	= {}
			floor.edges 	= {nocopy = true}
			floor.group 	= #room.nextPlanes + 1

			local dist,ang,ang0
			local edgeVerts,wallVerts,wallVerts2 = {},{},{}
			local midLerp = vec3()
			

			floor.wall 		= floor.wall 			or  {height=0.3,enabled=false} 
			floor.roof 		= floor.roof 			or  {height=0.3,enabled=false} 
			floor.floor 	= floor.floor 		or  {enabled=true					 } 
			floor.cornice = floor.cornice 	or  {style=1, 	enabled=false} 
			floor.railing = floor.railing 	or  {count=0.3,width=5,rails={enabled=false,count=1},enabled=false} 
			floor.railing.rails = floor.railing.rails or {enabled=false,count=1}
			floor.railing.width = floor.railing.width or 5
			floor.thick = true
			floor.thickness = 8

			local color = defaultColors(floor,{"floor","wall","roof"})
			local wallHeight = floor.wall.height
			local makeThick = floor.enabled and floor.thick

			bench.pop("1")

			bench.push("2")

			local inter,inter2,sect,sect2
			for p,point in ipairs(floor.points) do 
		  	point.index = p 

				prevPoint = floor.points[p==1 and #floor.points or p-1]
				nextPoint = floor.points[p==#floor.points and 1 or p+1]

				point.dist = math.dist(point.x,point.z,nextPoint.x,nextPoint.z)
				dist = math.dist(prevPoint.x,prevPoint.z,nextPoint.x,nextPoint.z)
				ang0 = math.angle(point.x,point.z,nextPoint.x,nextPoint.z)
				ang = ang0+pi/2

				angs[p] = ang
				dists[p] = math.dist(point.x,point.z,nextPoint.x,nextPoint.z)
				sines[p] = math.sin(ang-pi/2)
				cosines[p]=math.cos(ang-pi/2)
				summedOuter[p]=(p>1 and summedOuter[p-1]+dists[p-1] or 0)

				if not midPoints[p] then midPoints[p]=vec2() end
				if not rPoints[p]   then rPoints[p]=vec2() end
				if not lPoints[p]   then lPoints[p]=vec2() end
				if not irPoints[p]  then irPoints[p]=vec2() end
				if not ilPoints[p]  then ilPoints[p]=vec2() end
				if not brPoints[p]  then brPoints[p]=vec2() end
				if not blPoints[p]  then blPoints[p]=vec2() end

				-- OUTER
				midLerp:set(vec3.lerp2(point,nextPoint,0.5))
				midPoints[p]:set(midLerp.x+math.cos(ang)*floor.thickness*0.5,	midLerp.z+math.sin(ang)*floor.thickness*0.5)
				midPoint:set(midLerp.x+math.cos(ang)*floor.thickness,	midLerp.z+math.sin(ang)*floor.thickness)

				rPoints[p]:set(midPoint:add2(vec2.from_cartesian2(dist,ang-pi/2)))
				lPoints[p]:set(midPoint:sub2(vec2.from_cartesian2(dist,ang-pi/2)))
				
				if lPoints[p-1] and rPoints[p-1] then 
					inter,sect = math.intersect(lPoints[p],rPoints[p],lPoints[p-1],rPoints[p-1])
					if inter then 
						lPoints[p]:set(sect)
						rPoints[p-1]:set(sect)
					end
				end

				if p==#floor.points then 
					inter,sect = math.intersect(lPoints[p],rPoints[p],lPoints[1],rPoints[1])
					if inter then 
						rPoints[p]:set(sect)
						lPoints[1]:set(sect)
					end
				end


				-- INNER
				midLerp:set(vec3.lerp2(point,nextPoint,0.5))
				midPoint:set(midLerp.x+math.cos(ang)*0,	midLerp.z+math.sin(ang)*0)

				ilPoints[p]:set(midPoint:sub2(vec2.from_cartesian2(dist,ang-pi/2)))
				irPoints[p]:set(midPoint:add2(vec2.from_cartesian2(dist,ang-pi/2)))
				
				if ilPoints[p-1] and irPoints[p-1] then 
					inter,sect = math.intersect(ilPoints[p],irPoints[p],ilPoints[p-1],irPoints[p-1])
					inter2,sect2 = math.intersect(ilPoints[p],irPoints[p],lPoints[p-1],rPoints[p-1])
					if inter then 
						ilPoints[p]:set(sect)
						irPoints[p-1]:set(sect)
					end
					if inter2 then 
						blPoints[p]:set(sect2)
						brPoints[p-1]:set(sect2)
					end
				end

				if p==#floor.points then 
					inter,sect = math.intersect(ilPoints[p],irPoints[p],ilPoints[1],irPoints[1])
					if inter then 
						irPoints[p]:set(sect)
						ilPoints[1]:set(sect)
					end
				end

				summedInner[p]=(p>1 and summedInner[p-1]+vec2.dist(ilPoints[p-1],irPoints[p-1]) or 0)
			end

			bench.pop("2")

			bench.push("3")
			for p,point in ipairs(floor.points) do 
				table.insert(floor.shape,point.x)
				table.insert(floor.shape,point.z)
				table.insert(floor.shape2,point.x)
				table.insert(floor.shape2,point.z)

				prevPoint = floor.points[p==1 and #floor.points or p-1]
				nextPoint = floor.points[p==#floor.points and 1 or p+1]

				vp1.x,vp1.y,vp1.z = point.x,point.y,point.z
				vp2.x,vp2.y,vp2.z = nextPoint.x,nextPoint.y,nextPoint.z

				local wall = floor.walled=="closed" or (floor.walled=="gaps" and (point.walled==true or type(point.walled)=="nil"))
				
				if wall  then 
					insertEdge(floor.edges,point.x,point.z,nextPoint.x,nextPoint.z)
				end

				local wallCornice

				if  editingLevel or floor.wall.enabled then 

					bench.push("3.1")
					if floor.wall.enabled and not floor.railing.enabled and wall  then 
						table.insert(floor.shape2,midPoints[p].x)
						table.insert(floor.shape2,midPoints[p].y)
					end

					if editingLevel then 
						startVerts()
            local r,g,b = unpackColor(color.floor.inner)
						vBufInsert(ilPoints[p].x,	y-0.25,	ilPoints[p].y, 1,1,1, r,g,b,1) 
						vBufInsert(irPoints[p].x,	y-0.25,	irPoints[p].y, 1,1,1, r,g,b,1)
						vBufInsert(rPoints[p].x,	y-0.25,	rPoints[p].y,  1,1,1, r,g,b,1)
						vBufInsert(lPoints[p].x,	y-0.25,	lPoints[p].y,  1,1,1, r,g,b,1) 

						local edgeVisible = not (floor.wall.enabled and wall and not floor.railing.enabled)
						-- {floor.color.r*1.1,floor.color.g*1.1,floor.color.b*1.1,1}
					  
						insertTerrain(entity,{
							isEdge  	= true,
							mode 			= "floors",
							visible  	= edgeVisible,
							triMode  	= "fan",
							index   	= p,
							id 				= floor.id,
							layer   	= -2
						})
					end
					bench.pop("3.1")

					startVerts()
					if  floor.wall.enabled and wall then 
						
						bench.push("3.2")
						local isPrevWalled = floor.walled=="closed" or (floor.walled=="gaps" and (prevPoint.walled==true or prevPoint.walled==nil))
						local isNextWalled = floor.walled=="closed" or (floor.walled=="gaps" and (nextPoint.walled==true or nextPoint.walled==nil))

						local cutWall,anyCuts = scene.cutWall(floor,point)
						local success
						local triangulated
						local offset = wallOffset 

						if floor.railing.enabled or makeThick then 
							offset:set(vec2.from_cartesian2(floor.thickness, angs[p]))
						end

						bench.pop("3.2")

						if anyCuts then 
							bench.push("cut walls")
							local ang0 = math.angle(point.x,point.z,nextPoint.x,nextPoint.z)
							local sinA,cosA = math.sin(ang0),math.cos(ang0)
							local first = vBufferN+1

              local r,g,b = unpackColor(color.floor.outer)
							for c,cut in ipairs(cutWall) do 
								success,triangulated = pcall(mth.triangulate,cut)
								if  success then 
									for t,tri in ipairs(triangulated) do 
							     	vBufInsert( point.x+cosA*tri[1], point.y-tri[2], point.z+sinA*tri[1], 1 ,0,0, r,g,b,1)
							     	vBufInsert( point.x+cosA*tri[3], point.y-tri[4], point.z+sinA*tri[3], 1 ,0,0, r,g,b,1)
							     	vBufInsert( point.x+cosA*tri[5], point.y-tri[6], point.z+sinA*tri[5], 1 ,0,0, r,g,b,1)
							    end
								end
							end
							
							local last = vBufferN

							if makeThick then 
                local r,g,b = unpackColor(color.wall.inner) 
                if useData then 
                  for v=first,last,3 do 
                    vBufInsert( vBuffer1[v+2].x+offset.x,vBuffer1[v+2].y,vBuffer1[v+2].z + offset.y,1,0,0, r,g,b,1)
                    vBufInsert( vBuffer1[v+1].x+offset.x,vBuffer1[v+1].y,vBuffer1[v+1].z + offset.y,1,0,0, r,g,b,1)
                    vBufInsert( vBuffer1[v  ].x+offset.x,vBuffer1[v  ].y,vBuffer1[v  ].z + offset.y,1,0,0, r,g,b,1)
                  end
                else
    							for v=first,last,3 do 
    								vBufInsert( vBuffer1[v+2][1]+offset.x,vBuffer1[v+2][2],vBuffer1[v+2][3] +offset.y,1,0,0, r,g,b,1)
    								vBufInsert( vBuffer1[v+1][1]+offset.x,vBuffer1[v+1][2],vBuffer1[v+1][3] +offset.y,1,0,0, r,g,b,1)
    								vBufInsert( vBuffer1[v  ][1]+offset.x,vBuffer1[v  ][2],vBuffer1[v  ][3] +offset.y,1,0,0, r,g,b,1)
    							end
                end

                local r,g,b = unpackColor(color.wall.outer) 
								for c,cut in ipairs(cutWall) do 
									for v=1,#cut,2 do
										vn = v==#cut-1 and 1 or v+2
										vBufInsert( point.x+cosA*cut[v]+offset.x, 	point.y-cut[v+1], 	point.z+sinA*cut[v]+offset.y, 	1 ,0,0 	, r,g,b,1)
										vBufInsert( point.x+cosA*cut[vn], 					point.y-cut[vn+1], 	point.z+sinA*cut[vn], 					1 ,0,0 	, r,g,b,1)
										vBufInsert( point.x+cosA*cut[v], 						point.y-cut[v+1], 	point.z+sinA*cut[v], 						1 ,0,0 	, r,g,b,1)

										vBufInsert( point.x+cosA*cut[v]+offset.x, 	point.y-cut[v+1], 	point.z+sinA*cut[v]+offset.y, 	1 ,0,0 	, r,g,b,1)
										vBufInsert( point.x+cosA*cut[vn]+offset.x, 	point.y-cut[vn+1], 	point.z+sinA*cut[vn]+offset.y, 	1 ,0,0 	, r,g,b,1)
										vBufInsert( point.x+cosA*cut[vn], 					point.y-cut[vn+1], 	point.z+sinA*cut[vn], 					1 ,0,0 	, r,g,b,1)
									end 
								end
							end

							bench.pop("cut walls")
						else 
							if floor.railing.enabled then 
								bench.push("railing")
								
								local segs= 8
								local v1,v2 = railv1,railv2
								local bars = mf((dists[p]/25)*(floor.railing.count))+1
								local i,j = 1/bars
								post1:set((ilPoints[p].x+lPoints[p].x)/2,vp1.y,(ilPoints[p].y+lPoints[p].y)/2)
								post2:set((irPoints[p].x+rPoints[p].x)/2,vp1.y,(irPoints[p].y+rPoints[p].y)/2)

								railInset:set(vec2.from_cartesian2(floor.railing.width,angs[p]))
								floor.railing.width = floor.railing.width or floor.thickness
								for b=0,bars,1 do 
									j = b*i 
									if j==0 then 
										railOffset:set(post1)
										railSet:set(0,0)
									elseif j==1 then 
										railOffset:set(post2)
										railSet:set(0,0)
									else 
										railOffset:set(vec3.lerp2(vp1, vp2, j))
										railSet:set(railInset)
									end
									v1:set(railOffset.x+railSet.x,railOffset.y,railOffset.z+railSet.y)
									v2:set(railOffset.x+railSet.x,railOffset.y-wallHeight,railOffset.z+railSet.y)
									insertThickLine(v1,v2,floor.railing.width,color.wall.outer, {roll=angs[p]})
								end

								if not floor.roof.enabled then 
									local b = 5
									insertWallVerts(
										{ilPoints[p],irPoints[p],lPoints[p],rPoints[p]},
										{y-wallHeight,y-wallHeight-b},
										{color.inner,color.inner}
									)
								end
								if  floor.railing.rails.enabled then 
									floor.railing.rails.width = floor.railing.rails.width or 5
									local mr = lume.round(floor.railing.rails.count)
									local step = wallHeight/(mr+1)
									for m=1,mr,1 do 
										local yShift = step*m
										v1:set(post1.x,post1.y-yShift,post1.z)
										v2:set(post2.x,post2.y-yShift,post2.z)
										insertThickLine(v1,v2,floor.railing.rails.width,color.wall.outer)
									end
								end
								bench.pop("railing")
							elseif makeThick then
								bench.push("3.2.2.4") 
								insertWallVerts(
									{ilPoints[p],irPoints[p],lPoints[p],rPoints[p]},
									{y,y-wallHeight},
									{color.wall.outer,color.wall.inner},
									{isNextWalled,isPrevWalled,floor.floor.enabled,floor.roof.enabled}
								)
								bench.pop("3.2.2.4") 
							else  
								bench.push("3.2.2.5") 
                local r,g,b = unpackColor(color.wall.color) 
								vBufInsert(point.x,			y,	point.z, 								1,0,0 ,r,g,b,1)
								vBufInsert(nextPoint.x,	y,	nextPoint.z, 						1,0,0 ,r,g,b,1)
								vBufInsert(point.x,		  y-wallHeight,	point.z,	 		1,1,1 ,r,g,b,1)
								vBufInsert(nextPoint.x,	y-wallHeight,	nextPoint.z, 	1,1,1 ,r,g,b,1)
								bench.pop("3.2.2.5") 
							end
						end
						
						
						if not floor.railing.enabled then 
							cornice = cornice or {}
							cornice.height=cornice.height or 0
							cornice.width=cornice.width or 0
							cornice.depth=cornice.depth or 0
							cornice.dists = cornice.dists or {}
							
							if not cornice.verts then 
								local sqrt = math.sqrt
								cornice.verts =  obj.load("models/architecture/cornices/cornice_11.obj")
								for v=1,#cornice.verts,1 do 
									cornice.verts[v][1]=-cornice.verts[v][1]
									cornice.verts[v][2]=-cornice.verts[v][2]
									--cornice.verts[v][3]=-cornice.verts[v][3]
									cornice.width=cornice.verts[v][1]<cornice.width and cornice.verts[v][1] or cornice.width
									cornice.height=cornice.verts[v][2]<cornice.height and cornice.verts[v][2] or cornice.height
									cornice.depth=cornice.verts[v][3]<cornice.depth and cornice.verts[v][3] or cornice.depth
								end

								cornice.width = math.abs(cornice.width)
								cornice.height = math.abs(cornice.height)
								cornice.depth = math.abs(cornice.depth)

								for v=1,#cornice.verts,1 do 
									cornice.verts[v][1]=cornice.verts[v][1]+cornice.width
									cornice.verts[v][2]=cornice.verts[v][2]+cornice.height
									cornice.verts[v][3]=cornice.verts[v][3]+cornice.depth+floor.thickness
								end
								calcVertNormals(cornice.verts,nil,nil,nil)--,0.5)
								cornice.mesh=gfx.newMesh(zformat,cornice.verts,"triangles")
							end

							bench.push("3.3.1")
							if floor.cornice.enabled then 
								wallCornice =  {
									posL=vec3(point.x,point.y-wallHeight,point.z),
									posR=vec3(nextPoint.x,point.y-wallHeight,nextPoint.z),
									dir = vec3(math.cos(angs[p]+pi/2),0,math.sin(angs[p]+pi/2)),
									model=cornice,
									ang=angs[p],
									dist=dists[p],
									color = {unpackColor(color.inner)},
									lslice=vec2.sub(ilPoints[p],lPoints[p]):rotate(pi/2),
									rslice=vec2.sub(irPoints[p],rPoints[p]):rotate(-pi/2)
								} 
								wallCornice.vec=wallCornice.dir*wallCornice.model.width
							end
							bench.pop("3.3.1")

							bench.push("3.3.2")
							-- if     (floor.wall.inner.pattern and floor.wall.inner.pattern>0) 
							-- 		or (floor.wall.outer.pattern and floor.wall.outer.pattern>0)  then 
							-- 	for v=vBufferStart,vBufferN,1 do 
							-- 		-- print(vBuffer[v][14])
							-- 		if  floor.wall.inner.pattern>0 and (useData and vBuffer1[v].pi or vBuffer1[v][14]) == floor.wall.inner.pattern then 
							-- 			local x,y,w,h = unpack(patterns.size[floor.wall.inner.pattern])
							-- 			local s = 10
       --              if useData then 
  					-- 					vBuffer1[v].u=((summedInner[p]+math.dist(vBuffer1[v].x,vBuffer1[v].z,point.x,point.z)))/(w/s)
  					-- 					vBuffer1[v].v=((-vBuffer1[v].y))/(h/s)
       --              else
       --                vBuffer1[v][5]=((summedInner[p]+math.dist(vBuffer1[v][1],vBuffer1[v][3],point.x,point.z)))/(w/s)
       --                vBuffer1[v][6]=((-vBuffer1[v][2]))/(h/s)
       --              end
							-- 			-- vBuffer[v][5],vBuffer[v][6] = vec2(vBuffer[v][5],vBuffer[v][6]):rotate(pi/3):unpack()
							-- 		end
							-- 	end
							-- end
							bench.pop("3.3.2")
						end

						local makeNew = false
						
						terrainVerts = terrainVerts+vBufferN-vBufferStart+1
					end

					insertTerrain(entity,{
				  	isWall  	= true,
				  	mode 			= "floors",
				  	index   	= p,
				  	id 				= floor.id,
				  	smooth    = 0.4,
				  	cornice 	= wallCornice,
				  })
				 
				end
			end
      bench.pop("3")

			bench.push("trifloor")
			table.insert(room.nextPlanes, floor)

			local tris 	= {}
			local thicc = floor.thickness
			local triangulated = mth.triangulate(floor.shape)
			local triangulated2 = triangulated
			local tried,tris2 = pcall(mth.triangulate,floor.shape2)
			if tried then triangulated2 = tris2 end

      bench.pop("trifloor")
			
			-- FLOOR 
			bench.push("4")
			startVerts() 
			if floor.floor.enabled then
		    for t,tri in ipairs(triangulated2) do 
		     	vBufInsert( 	 tri[1], y, tri[2], 1 ,0,0, unpackColor(color.floor.inner))
		     	vBufInsert( 	 tri[3], y, tri[4], 1 ,0,0, unpackColor(color.floor.inner))
		     	vBufInsert( 	 tri[5], y, tri[6], 1 ,0,0, unpackColor(color.floor.inner))
		    end

			  if  makeThick then 
			  	for t,tri in ipairs(triangulated) do 
			     	vBufInsert( 	 tri[5], y+thicc, tri[6], 1 ,0,0, unpackColor(color.floor.outer) )
			     	vBufInsert( 	 tri[3], y+thicc, tri[4], 1 ,0,0, unpackColor(color.floor.outer) )
			     	vBufInsert( 	 tri[1], y+thicc, tri[2], 1 ,0,0, unpackColor(color.floor.outer) )
			    end
			    for p,point in ipairs(floor.points) do 
			    	nextPoint   =  floor.points[p==#floor.points and 1 or p+1] 
			     	vBufInsert( 	 point.x,			point.y+thicc, 	point.z, 1 			,0,0, unpackColor(color.floor.outer))
			     	vBufInsert( 	 nextPoint.x,	nextPoint.y, 		nextPoint.z, 1 	,0,0, unpackColor(color.floor.outer))
			    	vBufInsert( 	 point.x,			point.y, 				point.z, 1 			,0,0, unpackColor(color.floor.outer))

			     	vBufInsert( 	 point.x,			point.y+thicc, 			point.z, 1 			,0,0, unpackColor(color.floor.outer))
			     	vBufInsert( 	 nextPoint.x,	nextPoint.y+thicc, 	nextPoint.z, 1 	,0,0, unpackColor(color.floor.outer))
			     	vBufInsert( 	 nextPoint.x,	nextPoint.y, 				nextPoint.z, 1 	,0,0, unpackColor(color.floor.outer))
			    end
			  end
			end
			bench.pop("4")

			bench.push("4.1")
			insertTerrain(entity,{
		  	isFloor  = true,
		  	mode = "floors",
		  	id = f
		  })
			bench.pop("4.1")			

			-- ROOF 
			bench.push("5")
			startVerts()
	    if floor.roof.enabled then 
	    	for t,tri in ipairs(triangulated) do 
		     	vBufInsert(  tri[1], y-wallHeight-thicc, tri[2], 1 ,0,0, unpackColor(color.roof.outer))
		     	vBufInsert(  tri[3], y-wallHeight-thicc, tri[4], 1 ,0,0, unpackColor(color.roof.outer))
		     	vBufInsert(  tri[5], y-wallHeight-thicc, tri[6], 1 ,0,0, unpackColor(color.roof.outer))
		    end
		    if  makeThick then
		    	for t,tri in ipairs(triangulated2) do 
			     	vBufInsert(  tri[5], y-wallHeight, tri[6], 1 ,0,0, unpackColor(color.roof.inner))
			     	vBufInsert(  tri[3], y-wallHeight, tri[4], 1 ,0,0, unpackColor(color.roof.inner))
			     	vBufInsert(  tri[1], y-wallHeight, tri[2], 1 ,0,0, unpackColor(color.roof.inner))
			    end
			    for p,point in ipairs(floor.points) do 
			    	nextPoint   =  floor.points[p==#floor.points and 1 or p+1] 
			     	vBufInsert(  point.x,			point.y-wallHeight, 						point.z, 			1 ,0,0, unpackColor(color.roof.outer))
			     	vBufInsert(  nextPoint.x,	nextPoint.y-wallHeight-thicc, 	nextPoint.z, 	1 ,0,0, unpackColor(color.roof.outer))
			    	vBufInsert(  point.x,			point.y-wallHeight-thicc, 			point.z, 			1 ,0,0, unpackColor(color.roof.outer))

			     	vBufInsert(  point.x,			point.y-wallHeight, 						point.z, 			1 ,0,0, unpackColor(color.roof.outer))
			     	vBufInsert(  nextPoint.x,	nextPoint.y-wallHeight, 				nextPoint.z, 	1 ,0,0, unpackColor(color.roof.outer))
			     	vBufInsert(  nextPoint.x,	nextPoint.y-wallHeight-thicc, 	nextPoint.z, 	1 ,0,0, unpackColor(color.roof.outer))
			    end
			  end
		  end
		  bench.pop("5")

		  bench.push("5.1")
		  insertTerrain(entity,{
		  	isTerrain = true,
		  	isRoof  = true,
		  	mode = "floors",
		  	id = f
		  })
		  bench.pop("5.1")

		end

	end


	bench.pop("floors")
end









------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------







function scene.addRamps(entity)
	local cut  = 0
	local cut2 = 0
  local l1,l2, m1, m2 = {},{},{},{}
  -- if true then return end
  bench.push("ramps")
  ramps=toArray(entity.ramps, ramps)
  -- probe.insert()
  for _=1,#ramps,1 do 
    local ramp = ramps[_]
    local r = ramp.id

		local startPoint 	= ramp.points[1]
		local endPoint 		= ramp.points[#ramp.points]
    local model,insert
    for i,v in ipairs(entity.terrain.models) do 
		   if  v.id==ramp.key  then insert,model = i,v break end
     end
		if not model  
			or editor.debug.force_build
			or scene.time==0
			or (pathsPanel and pathsPanel.changed and pathsPanel.changed[1]=="ramps" and pathsPanel.changed[2]==f)  
			or (  pathsPanel and pathsPanel.changed and 
						(pathsPanel.changed[1]=="ramps" and pathsPanel.changed[2]==ramp.id) 
					or (endPoint 
						and endPoint.snapPoint 
						and entity.floors 
						and entity.floors[endPoint.snapPoint.floor] 
						and pathsPanel.changed 
						and pathsPanel.changed[1]=="floors" 
						and pathsPanel.changed[2]==endPoint.snapPoint.floor 
						and endPoint.snapPoint.id 
						and checkSnap (entity.floors[endPoint.snapPoint.floor].points, nil, endPoint ) 
						)
					or   (startPoint 
						and startPoint.snapPoint 
						and entity.floors 
						and entity.floors[startPoint.snapPoint.floor] 
						and pathsPanel.changed 
						and pathsPanel.changed[1]=="floors" 
						and pathsPanel.changed[2]==startPoint.snapPoint.floor 
						and startPoint.snapPoint.id 
						and checkSnap (entity.floors[startPoint.snapPoint.floor].points, startPoint, nil ) 
						)
					) then 

			bench.push("1")

			ramp.thick    = true 

			ramp.floor 		= ramp.floor  	or {enabled=true}					
			ramp.wall 		= ramp.wall  		or {height=0.3,enabled=false}					
			ramp.roof 		= ramp.roof  		or {height=0.3,enabled=false}					
			ramp.railing  = ramp.railing  or {count =0.3,enabled=false}		
			ramp.cornice =  {style=1, 	enabled=false} 			
			ramp.steps 		= ramp.steps  	or {count=0.3,height=1,enabled=true}	
			ramp.thick = true
			ramp.thickness = 8

			local color = defaultColors(ramp,{"floor","wall","roof"})

			local wallHeight = ramp.wall.height

			ramp.pointsL = {}
			ramp.pointsR = {}

			local rEnds  
			local lEnds  
			local firstAng = 0

			local destination
			local startShape 	
			local endShape 		

			local gradient ={}

			bench.pop("1")

			bench.push("2")
			if ramp.dest then 
				editor.addLink(endPoint,ramp.dest)
			elseif room.links[endPoint.id] then 
				room.links[endPoint.id] = nil
			end

			if ramp.source then 
				editor.addLink(startPoint,ramp.source)
			elseif room.links[startPoint.id] then 
				room.links[startPoint.id] = nil
			end

			if startPoint and startPoint.snapPoint then
				if entity.floors and entity.floors[startPoint.snapPoint.floor] then
					local floor = entity.floors[startPoint.snapPoint.floor]
					local l,p 	
          for i,v in ipairs(floor.points) do 
            if v.id==startPoint.snapPoint.id then l,p = v,i break end
          end 
					if l then 
						gradient[1] =floor.colors
						local r 	= floor.points[p+1] and floor.points[p+1] or floor.points[1]
						ramp.points[1].y = l.y
						ramp.points[1].x = (l.x+r.x)/2
						ramp.points[1].z = (l.z+r.z)/2
						startShape = {l=l,r=r}

					end
				end
			end

			if endPoint and endPoint.snapPoint then
				if entity.floors and entity.floors[endPoint.snapPoint.floor] then
					local floor = entity.floors[endPoint.snapPoint.floor]
					local l,p 	
          for i,v in ipairs(floor.points) do 
            if v.id==endPoint.snapPoint.id then l,p = v,i break end
          end 
					if l then 
						gradient[2] =floor.colors
						local r 	= floor.points[p+1] and floor.points[p+1] or floor.points[1]
						ramp.points[#ramp.points].y =l.y
						ramp.points[#ramp.points].x = (l.x+r.x)/2
						ramp.points[#ramp.points].z = (l.z+r.z)/2
						endShape = {l=l,r=r}
					end
				end
			end


			totalSteps = 0 
			currentStep = 0

			bench.pop("2")

			verts = {}

			bench.push("3")
			startVerts(ramp.thick and ramp.steps.enabled)

			for p,point in ipairs(ramp.points or {}) do 
				if p<#ramp.points or p==1 then 

					local link = (p<#ramp.points-1)

					local plane = {
						isRamp 	= 	true,
						y 		=	math.max(ramp.points[p].y,ramp.points[p+1].y),
						p			=	ramp.points[p],
						p1		=	ramp.points[p],
						p2		=	ramp.points[p+1],
						p3		=	ramp.points[p+1],
						group = #room.nextPlanes + 1
					}

					plane.length= 	math.dist  (	plane.p1.x, plane.p1.z, plane.p2.x, plane.p2.z 		)
					plane.ang 	= 	math.angle (	plane.p1.x, plane.p1.z, plane.p2.x, plane.p2.z 		)

					local ang2 		= plane.ang*1
					firstAng=ang2
					if link then 
						ang2 	= math.angle(ramp.points[p+1].x,ramp.points[p+1].z,ramp.points[p+2].x,ramp.points[p+2].z)
						cut2 	= math.abs(math.sin(math.abs(plane.ang-ang2)))*ramp.width
					else
						cut2 	= 0
					end

					plane.shape = {
						plane.p1.x + math.cos(plane.ang-pi/2)*ramp.width, plane.p1.z + math.sin(plane.ang-pi/2)*ramp.width,
						plane.p2.x + math.cos(plane.ang-pi/2)*ramp.width, plane.p2.z + math.sin(plane.ang-pi/2)*ramp.width,
						plane.p2.x + math.cos(plane.ang+pi/2)*ramp.width, plane.p2.z + math.sin(plane.ang+pi/2)*ramp.width,
						plane.p1.x + math.cos(plane.ang+pi/2)*ramp.width, plane.p1.z + math.sin(plane.ang+pi/2)*ramp.width,
					}

					local p1,p2,p3 = tmpPt1, tmpPt2, tmpPt3
					tmpPt1:set( plane.p1.x + math.cos(plane.ang)*cut, 0, plane.p1.z + math.sin(plane.ang)*cut  )
					tmpPt2:set( plane.p2.x - math.cos(plane.ang)*cut2,0, plane.p2.z - math.sin(plane.ang)*cut2 )
					tmpPt3:set( plane.p3.x + math.cos(ang2)*cut2, 	  0, plane.p3.z + math.sin(ang2)*cut2 )


					p1.y 	 = scene.evaluateRamp(plane,p1.x,p1.z)
					p2.y 	 = scene.evaluateRamp(plane,p2.x,p2.z)
					p3.y 	 = (link) and lerp(ramp.points[p+1].y,ramp.points[p+2].y,cut2/math.dist(plane.p2.x, plane.p2.z, ramp.points[p+2].x, ramp.points[p+2].z)) or p2.y

					plane.p1 = p1
					plane.p2 = p2

					plane.length 	= math.dist  (	p1.x, p1.z, p2.x, p2.z 		)
					plane.yDiff   = math.abs(p1.y-p2.y)

					plane.incline 	= (math.abs(p2.y-p1.y)/plane.length)*math.abs(p2.y-p1.y)
					
					plane.shape  	= {
						p1.x + math.cos(plane.ang-pi/2)*ramp.width, p1.z + math.sin(plane.ang-pi/2)*ramp.width,
						p2.x + math.cos(plane.ang-pi/2)*ramp.width, p2.z + math.sin(plane.ang-pi/2)*ramp.width,
						p2.x + math.cos(plane.ang+pi/2)*ramp.width, p2.z + math.sin(plane.ang+pi/2)*ramp.width,
						p1.x + math.cos(plane.ang+pi/2)*ramp.width, p1.z + math.sin(plane.ang+pi/2)*ramp.width,
					}

					if p==1 then
						if startShape then
							plane.shape[1]=startShape.l.x
							plane.shape[2]=startShape.l.z
							plane.shape[7]=startShape.r.x
							plane.shape[8]=startShape.r.z
						end
						if ramp.source then 
							plane.source 		= ramp.source
							ramp.source.line 	= {
								lerp( plane.shape[1],	plane.shape[3],	0.1 ),
								lerp( plane.shape[2],	plane.shape[4],	0.1 ),
								lerp( plane.shape[7],	plane.shape[5],	0.1 ),
								lerp( plane.shape[8],	plane.shape[6],	0.1 ),
								lerp( p1.y,				p2.y,			0.1	)
							}
						end
					end

					if p==#ramp.points-1 then
						if endShape then
							plane.shape[5]=endShape.l.x
							plane.shape[6]=endShape.l.z
							plane.shape[3]=endShape.r.x
							plane.shape[4]=endShape.r.z
						end
						if ramp.dest then 
							plane.dest 			= ramp.dest
							ramp.dest.line 		= {
								lerp( plane.shape[3],	plane.shape[1],	0.1	),
								lerp( plane.shape[4],	plane.shape[2],	0.1	),
								lerp( plane.shape[5],	plane.shape[7],	0.1	),
								lerp( plane.shape[6],	plane.shape[8],	0.1	),
								lerp( p2.y,				p1.y,			0.1	)
							}
						end
					end


					if not editingLevel  and ramp.walled~="open" then 
						plane.edges = {nocopy = true}
						insertEdge(plane.edges,plane.shape[1],plane.shape[2],plane.shape[3],plane.shape[4])
						insertEdge(plane.edges,plane.shape[1+4],plane.shape[2+4],plane.shape[3+4],plane.shape[4+4])
					end


					local steps = mu((vec3.dist(p1,p2)/100)*4) --mu((ramp.steps+0.01)*16)
					local stepHeight = math.abs(p1.y-p2.y)/steps 

					if p==1 then 
						lEnds = {{x=plane.shape[1], y=p1.y, z=plane.shape[2] ,m=stepHeight}}
						rEnds = {{x=plane.shape[7], y=p1.y, z=plane.shape[8] ,m=stepHeight}}
					end
					lEnds[2] = {x=plane.shape[3], y=p2.y, z=plane.shape[4] ,m=stepHeight}
					rEnds[2] = {x=plane.shape[5], y=p2.y, z=plane.shape[6] ,m=stepHeight}
	     
					table.insert(room.nextPlanes, plane)

					if ramp.steps.enabled then 
						vBufInsert(plane.shape[7],p1.y,plane.shape[8],1, 0,0, unpackColor(color.ramp))
						vBufInsert(plane.shape[1],p1.y,plane.shape[2],1, 0,0, unpackColor(color.ramp))
						local step
						local stepSize = 1/steps
						for i=1,steps,1 do 
							step = i*stepSize
							if not ramp.thick then 
								--gradientStep()
							end
							
							vBufInsert(lerp(plane.shape[7],plane.shape[5],step),lerp( p1.y,	p2.y,	 (i-1)*stepSize), lerp(plane.shape[8],plane.shape[6],step),1, 0,0, unpackColor(color.ramp))
							vBufInsert(lerp(plane.shape[1],plane.shape[3],step),lerp( p1.y,	p2.y,	 (i-1)*stepSize), lerp(plane.shape[2],plane.shape[4],step),1, 0,0, unpackColor(color.ramp))
							vBufInsert(lerp(plane.shape[7],plane.shape[5],step),lerp( p1.y,	p2.y,	 step), lerp(plane.shape[8],plane.shape[6],step),1, 0,0, unpackColor(color.ramp))
							vBufInsert(lerp(plane.shape[1],plane.shape[3],step),lerp( p1.y,	p2.y,	 step), lerp(plane.shape[2],plane.shape[4],step),1, 0,0, unpackColor(color.ramp))
						end
						vBufInsert(plane.shape[3],p2.y,plane.shape[4],1, 0,0, unpackColor(color.ramp))
						vBufInsert(plane.shape[5],p2.y,plane.shape[6],1, 0,0, unpackColor(color.ramp))
					else 
						vBufInsert(plane.shape[1],p1.y,plane.shape[2],1, 0,0, unpackColor(color.ramp))
						vBufInsert(plane.shape[7],p1.y,plane.shape[8],1, 0,0, unpackColor(color.ramp))
						vBufInsert(plane.shape[3],p2.y,plane.shape[4],1, 0,0, unpackColor(color.ramp))
						vBufInsert(plane.shape[5],p2.y,plane.shape[6],1, 0,0, unpackColor(color.ramp))
					end

					bench.push("corners")
					if  link  and not LOVR then 
						
						local corner= {
							edges   = {nocopy=true},
							round   =   true,
							isRamp 	= 	true,
							isLink 	= 	true,
							y 		=	math.max(scene.evaluateRamp(plane,p2.x,p2.z),scene.evaluateRamp(plane,p3.x,p3.z)),
							p1		=	p2,
							p2		=	p3,
							group 	=  	#room.nextPlanes + 1
						}

						corner.height = math.abs(corner.p2.y-corner.p1.y)

						corner.incline = 	corner.height/math.dist(corner.p1.x, corner.p1.z, corner.p2.x, corner.p2.z)

						local ang3 = (plane.ang+ang2)/2+(plane.ang-ang2>0 and pi/2 or -pi/2)

						l1 = {	plane.shape[3],plane.shape[4], p3.x + math.cos(ang2-pi/2)*ramp.width, p3.z + math.sin(ang2-pi/2)*ramp.width }
						l2 = {	p3.x + math.cos(ang2+pi/2)*ramp.width, p3.z + math.sin(ang2+pi/2)*ramp.width,plane.shape[5],plane.shape[6]  }
						m1 = { x = (l1[1]+l1[3])/2, y = (corner.p1.y+corner.p2.y)/2, z = (l1[2]+l1[4])/2 }
						m2 = { x = (l2[1]+l2[3])/2, y = (corner.p1.y+corner.p2.y)/2, z = (l2[2]+l2[4])/2 }

						corner.testShape = {l2[3],l2[4],l1[1],l1[2], l1[3],l1[4],l2[1],l2[2]}


						if corner.round then 	
								
							local adiff = math.abs(plane.ang-ang2)
							local cut3 = lume.smooth(0,cut2,(adiff>pi/2 and adiff/(pi*2.5) or adiff)/(pi/2))
							local cut4 = (l1[1]-l1[3])^2+(l1[2]-l1[4])^2>(l2[1]-l2[3])^2+(l2[2]-l2[4])^2 and cut3 or 0
							local cut5 = cut4==0 and cut3 or 0
							local len1,len2 = math.dist(l1[1],corner.p1.y, l1[3],corner.p2.y,l1[2],l1[4]), math.dist(l2[1],corner.p1.y, l2[3],corner.p2.y,l2[2],l2[4])
							
							l1 	= lume.concat( {l1[1],l1[2]} , 				{(l1[1]+l1[3])/2+math.cos(ang3)*cut4, (l1[2]+l1[4])/2+math.sin(ang3)*cut4} , {l1[3],l1[4]} )
							l1y = lume.concat( {l1[1],corner.p1.y} , 	{(l1[1]+l1[3])/2,(corner.p1.y+corner.p2.y)/2} , {l1[3],corner.p2.y} )
							l2  = lume.concat( {l2[1],l2[2]} , 				{(l2[1]+l2[3])/2+math.cos(ang3)*cut5,(l2[2]+l2[4])/2+math.sin(ang3)*cut5} , {l2[3],l2[4]} )
							l2y = lume.concat( {l2[1],corner.p2.y} , 	{(l2[1]+l2[3])/2,(corner.p1.y+corner.p2.y)/2} , {l2[3],corner.p1.y} )

							l1  = mth.newBezierCurve(l1)
							l1y = mth.newBezierCurve(l1y)
							l2  = mth.newBezierCurve(l2)
							l2y = mth.newBezierCurve(l2y)

							local xL,yL,zL 
							local xR,yR,zR 
							local detail = mu(math.max(len1,len2)/50)

							local nx,nz 
							local pL,pR 
							local dL,dR = 0,0
							for c=0, detail,1 do

								xL,zL = l1:evaluate (c/detail)
								_,yL = l1y:evaluate(c/detail)
								xR,zR = l2:evaluate ((detail-c)/detail)
								_,yR = l2y:evaluate((detail-c)/detail)

								if ramp.steps.enabled and pL and pR then 
									vBufInsert(xR,pR[2],zR,1, 0,0, unpackColor(color.ramp))
									vBufInsert(xL,pL[2],zL,1, 0,0, unpackColor(color.ramp))
								end
								vBufInsert(xR,yR,zR,1, 0,0, unpackColor(color.ramp))
								table.insert(ramp.pointsR,1,{x=xR, 	y=yR, 	z=zR , n=1, m=corner.height/detail})
								if c<detail and not editingLevel  and ramp.walled~="open" then 
									nx,nz 		= l2:evaluate ((detail-c-1)/detail)
									insertEdge(corner.edges,xR,zR,nx,nz)
								end

								vBufInsert(xL,yL,zL,1, 0,0, unpackColor(color.ramp))
									table.insert(ramp.pointsL,{x=xL, 	y=yL, 	z=zL , n=1, m=corner.height/detail})
								if c>0 then 
								end
								if c<detail and not editingLevel  and ramp.walled~="open" then 
									nx,nz 		= l1:evaluate ((c+1)/detail)
									insertEdge(corner.edges,xL,zL,nx,nz)
								end

								pL = {xL,yL,zL}
								pR = {xR,yR,zR}

							end

							l1= l1:render(2)
							l2= l2:render(2)
							corner.shape = lume.concat(l1,l2)
						else
							if not editingLevel  and ramp.walled~="open" then 
								insertEdge(corner.edges,l1[1],l1[2],l1[3],l1[4])
								insertEdge(corner.edges,l2[1],l2[2],l2[3],l2[4])
							end
							corner.shape = corner.testShape
						end
						
						table.insert(room.nextPlanes, corner)
					end 
					bench.pop("corners")

					cut = cut2
				end
			end

			bench.pop("3")


			if rEnds and #rEnds==2 then 
	   		table.insert(ramp.pointsR,	rEnds[1])
	    	table.insert(ramp.pointsR,1,rEnds[2])
	    	table.insert(ramp.pointsL,	lEnds[2])
	    	table.insert(ramp.pointsL,1,lEnds[1])
		  end

		 	bench.push("4")
			if ramp.thick and ramp.steps.enabled then 
				local y,h,h2 
				local first,last = vBufferStart+3,vBufferN
				local cutSteps = ramp.wall.enabled and  ramp.floor.enabled
				startVerts()

				if ramp.steps.height and ramp.steps.height<0.9 then 
					h2 = (ramp.steps.height+0.3)*6
				end
        local grad = (gradient[1] and gradient[2] and ramp.totalSteps and ramp.gradient) and gradientStep or nothing
        local steps = ramp.totalSteps
        if useData then 
          for i=first,last-2,2 do
            grad(steps,gradient,color) 
            y = vBuffer2[i+1] and vBuffer2[i+1].y or vBuffer2[i-4].y
            h = math.abs(vBuffer2[i].y-y) 
            y = math.max(vBuffer2[i].y,y)

            insertWallVerts(
              setValues(tempBase,
                tv1:set(vBuffer2[i-3].x, vBuffer2[i-3].z),
                tv2:set(vBuffer2[i-2].x, vBuffer2[i-2].z),
                tv3:set(vBuffer2[i-1].x, vBuffer2[i-1].z),
                tv4:set(vBuffer2[i  ].x, vBuffer2[i  ].z)
              ), 
              setValues(tempHeights,
                h2 and y-h+h2 or y,
                y-h
              ),
              color.ramp,
              setValues(tempFaceRemovals,
                cutSteps,
                cutSteps,
                cutSteps
              )
            )   
          end
        else
  				for i=first,last-2,2 do
  					if ramp.gradient then 
  						gradientStep(steps,gradient,color) 
  					end
  					y = vBuffer2[i+1] and vBuffer2[i+1][2] or vBuffer2[i-4][2]
  					h = math.abs(vBuffer2[i][2]-y) 
  					y = math.max(vBuffer2[i][2],y)

  					insertWallVerts(
  						setValues(tempBase,
  			        tv1:set(vBuffer2[i-3][1], vBuffer2[i-3][3]),
  							tv2:set(vBuffer2[i-2][1], vBuffer2[i-2][3]),
  							tv3:set(vBuffer2[i-1][1], vBuffer2[i-1][3]),
  							tv4:set(vBuffer2[i][1], 	vBuffer2[i][3])
  				    ), 
  				    setValues(tempHeights,
  				    	h2 and y-h+h2 or y,
  					    y-h
  					  ),
  				    color.ramp,
  				    setValues(tempFaceRemovals,
  				    	cutSteps,
  					    cutSteps,
  					    cutSteps
  					  )
  			  	)   
  				end
        end
			end
			bench.pop("4")

			
			
			
			ramp.totalSteps = totalSteps

			bench.push("5")
			if ramp.wall.enabled then 
				local offset,offset2
				local side 
				for i=1,2,1 do 
					side = i == 1 and ramp.pointsR or ramp.pointsL
					for i=1,#side-1,1 do 
						offset = vec2.from_cartesian(ramp.thickness, math.angle(side[i].x,side[i].z,side[i+1].x,side[i+1].z)+pi/2)
						offset2= vec2.from_cartesian(-0.1, math.angle(side[i].x,side[i].z,side[i+1].x,side[i+1].z)+pi/2)
						insertWallVerts(
							setValues(tempBase,
								tv1:set(side[i].x+offset2.x,		side[i].z+offset2.y),
								tv2:set(side[i+1].x+offset2.x,	side[i+1].z+offset2.y),
								tv3:set(side[i].x+offset.x,			side[i].z+offset.y),
								tv4:set(side[i+1].x+offset.x,		side[i+1].z+offset.y)
							),
							setValues(tempHeights2,
								side[i].y+6,
								side[i].y-wallHeight,
								side[i+1].y+6,
								side[i+1].y-wallHeight
							),
							setValues(tempColor,
							  color.wall.outer,
							  color.wall.inner
						  )
						)
					end 
				end
			end
			bench.pop("5")

			bench.push("6")
			if ramp.roof.enabled then 
				local wL, wR = ramp.pointsL , ramp.pointsR
				local j = #ramp.pointsR
				for i=1,#ramp.pointsL-1,1 do 
					
					insertWallVerts(
						setValues(tempBase,
							tv1:set(wL[i].x,			wL[i].z),
							tv2:set(wL[i+1].x,		wL[i+1].z),
							tv3:set(wR[j].x,			wR[j].z),
							tv4:set(wR[j-1].x,		wR[j-1].z)
						),
						setValues(tempHeights2,
							wL[i].y-wallHeight+6,
							wL[i].y-wallHeight-1.4,
							wL[i+1].y-wallHeight+6,
							wL[i+1].y-wallHeight-1.4
						),
						setValues(tempColor,
						  color.roof.outer,
						  color.roof.inner
					  ),
					  setValues(tempFaceRemovals,
				    	i<#wL-1,
					    i>1
					  ),
					  3
					)
					j = j-1
				end
			end
			bench.pop("6")

			insertTerrain(entity,{
				color 	= {ramp.color.r,ramp.color.g,ramp.color.b,1},
				isRamp  = true,
				id 			= r,
	     	mode 		= "ramps",
	     	smooth  = 0.4,
				transform = mat4(),
				parent 	= entity
			})
		end
	end
  -- probe.extract()
  bench.pop("ramps")
end
