local mapped, xavg, yavg,wobbledView

function newViewCanvas(view)
	gfx.setDefaultFilter("nearest")

	if view.canvas and not view.preview then 
		-- view.canvas:release()
		view.canvas = newCanvas(view.bounds.w,view.bounds.h,view.flags)
	else 
		view.canvas = view.canvas 
			or (view.bounds and newCanvas(view.bounds.w,view.bounds.h,view.flags) or newCanvas(screenWidth,screenHeight,view.flags))
	end

	if LOVE then 

		if isLit(view.room) then 
			view.gbuffer = view.gbuffer or {}
			view.gbuffer.diffuse  = newCanvas(view.bounds.w,view.bounds.h,{format="normal"})
			view.gbuffer.position = newCanvas(view.bounds.w,view.bounds.h,{format="rgba16f"})
			view.gbuffer.normal   = newCanvas(view.bounds.w,view.bounds.h,{format="rgba16f"})--rgb565
			view.gbuffer.light    = newCanvas(view.bounds.w,view.bounds.h,{format="normal"})
			view.gbuffer.depth    = newCanvas(view.bounds.w,view.bounds.h,{format="depth24",readable=true})
		else 
			releaseGbuffer(view)
		end
	else
		-- if isLit(view.room) then 
		-- 	view.gbuffer = view.gbuffer or {}
		-- 	view.gbuffer.diffuse  = gfx.newTexture(view.bounds.w,view.bounds.h,1,{mipmaps=false,format="rgba"})
		-- 	view.gbuffer.position = gfx.newTexture(view.bounds.w,view.bounds.h,1,{mipmaps=false,format="rgba16f"})
		-- 	view.gbuffer.normal   = gfx.newTexture(view.bounds.w,view.bounds.h,1,{mipmaps=false,format="rgba"})
		-- 	view.gbuffer.depth    = gfx.newTexture(view.bounds.w,view.bounds.h,1,{mipmaps=false,format="d16"})
		-- 	view.gbuffer.light    = gfx.newTexture(view.bounds.w,view.bounds.h,1,{mipmaps=false,format="rgba"})
		-- 	view.gcanvas = gfx.newCanvas({
		-- 		view.gbuffer.diffuse,  
		-- 		view.gbuffer.position, 
		-- 		view.gbuffer.normal,     
		-- 	},{depth="d16"})
		-- else 
			releaseGbuffer(view)
		-- end
	end
end

function setViewCanvas(view)
	if not view.canvas or (view.gbuffer and not isLit(view.room)) or (not view.gbuffer and isLit(view.room)) then 
		newViewCanvas(view)
	end
	if view.gbuffer then 
		trace("Render: Deferred")
		if LOVE then 
			gfx.setCanvas(view.gbuffer.position)
			gfx.clear(0,0,0,0)
			gfx.setCanvas(view.gbuffer.normal)
			gfx.clear(0,0,0,0)
			return gfx.setCanvas({
				view.gbuffer.diffuse,
				view.gbuffer.normal,
				view.gbuffer.position,
				-- depth=true,
				depthstencil=view.gbuffer.depth
			})
		else 
			return gfx.setCanvas(view.gcanvas)
		end
	else 
		trace("Render: Forward")
		if LOVE then  
			return gfx.setCanvas{view.canvas,depth=true}
		else
			-- trace("resizingWindow",resizingWindow==true)
			if level.isAnim and animationPanel.antiAlias and resizingWindow then 
				gfx.setCanvas()
				_flipView = true
			else
				_flipView = false
				gfx.setCanvas(view.canvas)
				-- print(view.canvas:getMSAA())
			end
			gfx.clear(1,0,1,1,1,1)
		end
	end
end

function updateViewport(view,viewzoom)
	if not view.viewport then return end
	bench.push("viewport")
	view.viewPolys 			= {}
	local newCenter  		= {x=0,y=0}
	local wob 				= editingLevel and {0,0} or {view.viewport.wobble.speed,view.viewport.wobble.dist}
	view.viewport.center  	= view.viewport.center or {}
	view.viewport.center.x = view.viewport.center.x or 0
	view.viewport.center.y = view.viewport.center.y or 0
	view.viewport.centerContained = false

	currentRoom.viewport.size = currentRoom.viewport.size or 1
	currentRoom.viewport.zoom = viewzoom

	view.flags = view.flags or {}
	view.flags.msaa = (level.isAnim and animationPanel.antiAlias and animationPanel.antiAliasing) or ((hiSpec and editor.debug.anti_alias) and 8 or 0 )

	local filter = animationPanel.antiAlias and "linear" or "nearest"
	
	if level.isAnim then 
		animationPanel.viewport = view 
	end
	
	if view.bounds and view.bounds.w 
			and animationPanel.antiAliasing~=animationPanel.pantiAliasing 
			or animationPanel.antiAlias~=animationPanel.pantiAlias 
			or editor.debug.anti_alias~=editor.debug.panti_alias 
			or room.lighting.dynamic.enabled~=room.lighting.dynamic.penabled then 
		 newViewCanvas(view)
	end

	animationPanel.pantiAliasing = animationPanel.antiAliasing
	animationPanel.pantiAlias    = animationPanel.antiAlias
	editor.debug.panti_alias		 = editor.debug.anti_alias
	room.lighting.dynamic.penabled=room.lighting.dynamic.enabled

	for i,poly in ipairs(view.viewport.polys) do 
		bench.push("map")
		mapped, xavg, yavg = mapViewPoly(poly,currentRoom.viewport)

		if view.viewport.center and point_in_poly(mapped, {x=view.viewport.center.x*renderWidth,y=view.viewport.center.y*renderHeight}) then 
			view.viewport.centerContained 	= true
		end
		bench.pop("map")

		if not lmouse.getRelativeMode() and not view.viewport.scissor and roomZoom>0.9 and editingLevel and (altDown or stageHovered) and point_in_poly(mapped,mouse,true) then
			roomHovered = view
			lastroomHovered = view
			print(view.room.name)
			if  (mouse.click() or mouse.clickR() or not mouse.down.L) and not animationPanel.open and #contextMenu.items==0 then 
				lastRoom = view
				nextRoom = roomHovered
			end
		end

		newCenter.x = newCenter.x + xavg
		newCenter.y = newCenter.y + yavg

		if not view.viewport.scissor then 
			bench.push("wobble")
			wobbledView = effects.wobble( mapped ,view.viewport.wobble.speed,view.viewport.wobble.dist)
				-- ((editingLevel and wobbleRoom~=view.key and currentRoom~=view) or animationPanel.open) and mapped  or effects.wobble( mapped ,view.viewport.wobble.speed,view.viewport.wobble.dist)
			view.viewpoly =  wobbledView

			view.viewVerts = view.viewVerts or {}
			view.prevpoly = view.prevpoly or {}
			view.changed = false

			if #view.prevpoly ~= #view.viewpoly then 
				lume.clear(view.viewVerts)
				view.viewVerts.nocopy=true
			end

			bench.pop("wobble")

			for i=1,#view.viewpoly,1 do 
				if view.prevpoly[i] ~= view.viewpoly[i] then 
					view.changed = true 
				end
				view.prevpoly[i] = view.viewpoly[i]
			end

			view.bounds = view.bounds or {}
			view.bounds.l,view.bounds.r,view.bounds.t,view.bounds.b = 99999,-99999,99999,-99999
			
			for i=2,#mapped,2 do
				view.bounds.l = math.min(view.bounds.l, mapped[i-1])
				view.bounds.r = math.max(view.bounds.r, mapped[i-1])
				view.bounds.t = math.min(view.bounds.t, mapped[i])
				view.bounds.b = math.max(view.bounds.b, mapped[i])
			end

			if currentRoom==view then 
				view.bounds.l  = math.max(view.bounds.l, 0)
				view.bounds.r  = math.min(view.bounds.r, renderWidth)
				view.bounds.t  = math.max(view.bounds.t, 0)
				view.bounds.b  = math.min(view.bounds.b, renderHeight)
			end

			view.bounds.x = view.bounds.l
			view.bounds.y = view.bounds.t
			view.bounds.changed = (view.bounds.w ~= (view.bounds.r-view.bounds.l) or view.bounds.h ~= (view.bounds.b-view.bounds.t) )
			view.bounds.w = (view.bounds.r-view.bounds.l)
			view.bounds.h = (view.bounds.b-view.bounds.t)

			bench.push("canvas")
			if not view.canvas then 
				if roomZoom<0.5 then 
					view.bounds.w = view.bounds.w/4
					view.bounds.h = view.bounds.h/4
					newViewCanvas(view)
					view.bounds.w = view.bounds.w/4
					view.bounds.h = view.bounds.h/4
				end
			elseif not resizingWindow then
				local newed =false 
				if (currentRoom==view and roomZoom==0) 
					or (view.bounds.l == 0 and view.bounds.t == 0 and view.bounds.w == renderWidth and view.bounds.h == renderHeight)   then
					if math.abs(view.canvas:getWidth()-renderWidth)>4 and not animationPanel.exporting then 
						newViewCanvas(view)
						newed = true
					end
				end
				if not newed and roomZoom==1  and   view.bounds.w == renderWidth and not animationPanel.exporting then 
					newViewCanvas(view)
				end
			end
			bench.pop("canvas")

			if view.changed then 
				bench.push("triangulate")
				local success,tris = pcall(mth.triangulate,view.viewpoly)
				if not success then 
					tris = mth.triangulate({
						0,0,
						100,0,
						100,100,
						0,100,
					})
				end

				local v = 1
				for t,tri in ipairs(tris) do
					view.viewVerts[v] = {tri[1], tri[2], 0, 1, (tri[1]-view.bounds.l)/view.bounds.w, (tri[2]-view.bounds.t)/view.bounds.h, 1,1,1,1 }	
					v=v+1
					view.viewVerts[v] = {tri[3], tri[4], 0, 1, (tri[3]-view.bounds.l)/view.bounds.w, (tri[4]-view.bounds.t)/view.bounds.h, 1,1,1,1 }	
					v=v+1
					view.viewVerts[v] = {tri[5], tri[6], 0, 1, (tri[5]-view.bounds.l)/view.bounds.w, (tri[6]-view.bounds.t)/view.bounds.h, 1,1,1,1 }	
					v=v+1
				end
			
				bench.pop("triangulate")


				bench.push("mesh")
				if #view.viewVerts>0 and view.canvas then
					if view.viewMesh and #view.viewVerts == view.numVerts then
						bench.push("mesh1")
						trace("view.viewVerts",#view.viewVerts)
						view.viewMesh:setVertices(view.viewVerts,1)
						gfx.setTexture(view.viewMesh,view.canvas)
						bench.pop("mesh1")
					else 
						bench.push("mesh2")
						view.viewMesh = gfx.newMesh(zformat,view.viewVerts,"triangles","stream",true)
						gfx.setTexture(view.viewMesh,view.canvas)
						view.numVerts = #view.viewVerts
						bench.pop("mesh2")
					end
				end
				bench.pop("mesh")
			end
		else
			trace("preview",newCenter.x,newCenter.y)
		end
		bench.pop("viewport")
	end

	view.aspectRatio = view.bounds.w/view.bounds.h
	view.bounds.c = view.bounds.c or vec2()
	view.bounds.c.x = view.bounds.x+view.bounds.w/2
	view.bounds.c.y = view.bounds.y+view.bounds.h/2 

	view.viewport.center.x 			= effects.wobble(newCenter.x/#view.viewport.polys,wob[1]*0.2,wob[2]*0.005)
	view.viewport.center.y 			= effects.wobble(newCenter.y/#view.viewport.polys,wob[1]*0.2,wob[2]*0.005)
	
	if pcam then
		--view.cam = pcam
	else
		view.camera.center = {x=lerp((renderWidth)/2,view.viewport.center.x*(renderWidth),currentRoom==view and roomZoom or 1) , y=lerp((renderHeight)/2,view.viewport.center.y*(renderHeight),currentRoom==view and roomZoom or 1)  }
	end
	
	-- gfx.push()
	-- if roomZoom>0 then 
	-- 	gfx.translate(
	-- 		-view.bounds.l+view.viewport.wobble.dist,
	-- 		-view.bounds.t+view.viewport.wobble.dist
	-- 	)
	-- end

	editor.linkHovered 		= false

	return view
end

function drawSetBackground()
	if animationPanel and (not animationPanel.open or animationPanel.active) then
		gfx.setShader()
		if LOVR then 
			gfx.setCanvas(canvasMain)
			gfx.clear(currentSet.sky.color.r,currentSet.sky.color.g,currentSet.sky.color.b,1,1,1)
		else
			gfx.setCanvas({canvasMain,depth=true})
			gfx.clear(currentSet.sky.color.r,currentSet.sky.color.g,currentSet.sky.color.b,1,true,true)
		end
	end
end

local rpoly ={}
local xtotal= 0
local ytotal= 0
local bbox  ={}

function mapViewPoly(poly,viewport)
	lume.clear(rpoly)
	xtotal = 0
	ytotal = 0
	bbox[1],bbox[2],bbox[3],bbox[4]   = poly[1],poly[2],poly[1],poly[2]

	for i,p in ipairs(poly) do
		table.insert(rpoly, ((i+1)%2==0) 	and (p)
											or  (p))
		xtotal = ((i+1)%2==0) and xtotal+p or xtotal
		ytotal = ((i+1)%2==0) and ytotal or ytotal+p

	    if i%2==0 then 
	        bbox[2] = (poly[i]<bbox[2]) and poly[i] or bbox[2]
	        bbox[4] = (poly[i]>bbox[4]) and poly[i] or bbox[4]
	    else 
	        bbox[1] = (poly[i]<bbox[1]) and poly[i] or bbox[1]
	        bbox[3] = (poly[i]>bbox[3]) and poly[i] or bbox[3]
	    end
	end

	if currentRoom==room then 
		viewport.size = 1+1-((bbox[4]-bbox[2])*(bbox[3]-bbox[1]))*2
	end

	local xavg,yavg=xtotal/(#poly/2), ytotal/(#poly/2)
	local toZoom = viewport.zoom and 1 or roomZoom

	for i,p in ipairs(rpoly) do
		rpoly[i] = ((i+1)%2==0) and lerp( (p-viewport.center.x)*viewport.size*16+0.5 , p , toZoom) *renderWidth
								or  lerp( (p-viewport.center.y)*viewport.size*16+0.5 , p , toZoom) *renderHeight
	end

	return rpoly, xavg,yavg
end

function roomBack(room)
	if not (animationPanel.open and drawingPanel.backing) then
	end
end

function prepareView(view,light,cache)
	bench.push("prepareView")

	if not view.bounds then 
		view.bounds = {l=0,t=0,l=view.w,r=view.h,w=view.w,h=view.h}
	end

	gfx.push("all")
	setViewCanvas(view)
	gfx.setDepthMode("lequal", true)
	
	camera.adjust 	(view.camera,view)
	gfx.setCamera ( view.camera )
  gfx.clear     (level.isAnim and {1,1,1,1} or {0,0,0,0})

	gfx.setColor 		(1,1,1,1)
	gfx.setShader(shaders.forwardRender)

	drawShadowed = not editor.debug.no_lights and not editor.debug.wireframe
	shaders.forwardRender:send("drawShadowed",drawShadowed)

	bench.pop("prepareView")
end

function unprepareView(view)
	bench.push("unprepareView")
	gfx.pop()
	gfx.setShader()
	shaders.forwardRender:send("drawShadowed",false)
	-- gfx.setColor(1,1,1,lmouse.getRelativeMode() and 1 or 0)
	-- gfx.circle("line",renderWidth/2-16,renderHeight/2-16,1,16)
	gfx.setWireframe( false )  
	bench.pop("unprepareView")
end

function drawView(view)
	bench.push("drawView")

	local update 
	if hiSpec then 
	 	update = true
 	else
 		update = not editingLevel or  (view == currentRoom) or (roomZoom<1) or mf((time*60)%((view.room.id==currentRoom.id) and (transform and 1 or 4) or 60))==0 
 	end

	local changed = (roomZoom>0) and lastRoom~=currentRoom


	if not editor.slowDraw and update then 
		drawRoom  				(view)
	end

	gfx.reset()
	gfx.setCanvas(canvasMain)

	if  editingLevel and (stageHovered or altDown) and wobbleRoom~=view.key and not animationPanel.open and roomZoom ==1 and currentRoom==view then gfx.setScissor()
		gfx.setColor((currentSet.sky.color.r+view.room.sky.color.r)/2,(currentSet.sky.color.g+view.room.sky.color.g)/2,(currentSet.sky.color.b+view.room.sky.color.b)/2,0.8)
		if  not view.viewport.shapes then 
			view.viewport.shapes = {}
			editor.parseShapes(view.viewport.polys,view.viewport.shapes)	
		end
		editor.shapeEditor(view.viewport,1,{x=0,y=0,w=screenWidth,h=screenHeight, dotSize=10,out=true,skipOutline=true,res=game.resolution})
	end

	gfx.setColor(1,1,1,1)

	if view.viewMesh  and roomZoom>0 then 
		gfx.setDepthMode	() 
		gfx.setShader()
		
	  gfx.draw(view.viewMesh)

	  gfx.setWireframe(false)
	  trace("draw viewmesh")
	  
		if altDown then 
			gfx.push("all")
			gfx.setColor(1,1,1,0.2)
			gfx.print(lume.find(currentRooms,view),view.bounds.x+view.bounds.w/2,view.bounds.y+view.bounds.h/2)
			gfx.setColor(0,0,0,0.2)
			gfx.print(lume.find(currentRooms,view),view.bounds.x+view.bounds.w/2+2,view.bounds.y+view.bounds.h/2+2)
			gfx.pop()
		end
	elseif view.canvas then
		gfx.push()
			if LOVR then 
				rl.rlLoadIdentity() 
			end
			local panel = animationPanel 
			if _flipView then 
			else 
				if panel.exporting then 
					local scale = math.min(view.bounds.w/panel.stageWidth,1)
					gfx.scale (scale,scale)
					gfx.translate((renderWidth-scale*panel.stageWidth)*0.5,(renderHeight-scale*panel.stageHeight)*0.5)
				end
				-- gfx.clear(1,1,1,1)
				gfx.draw 		(view.canvas)
			end
			-- editor.testCanvas = view.canvas
		gfx.pop()
	else
		trace("cant draw view")
	end
	
	bench.pop("drawView")
end


function drawRoom(view)
	bench.push("drawRoom")
	gfx.push("all")
	
	updateLights 		(view)
	
	if not _pathTraceOnly then 
		prepareView 	 	(view)
			editor.drawGrid ()
			scene.drawPaths (view)
		  drawTests  			(view)
			drawLinks 			(view)
			drawRoomStuff 	(view)
			drawRayMesh     ()
		unprepareView 	(view)

		renderLights    (view)
		releaseView     (view)
	end
	
	-- trace("_pathTraceOnly",_pathTraceOnly)
	gfx.pop()
	bench.pop("drawRoom")
	return view
end

function releaseView(view)
	if not view.release then return end
	releaseGbuffer(view)
end

function releaseGbuffer(view)
	if not view.gbuffer then return end
	if type(view.gbuffer.diffuse)=="userdata" then 
		view.gbuffer.diffuse  :release() view.gbuffer.diffuse  =nil
		view.gbuffer.position :release() view.gbuffer.position =nil
		view.gbuffer.normal   :release() view.gbuffer.normal   =nil
		view.gbuffer.light    :release() view.gbuffer.light    =nil
	-- view.gbuffer.depth    :release()
	end
	requireSources(true)
	view.gbuffer = nil 
end

function drawRayMesh()
	if editor.rayMesh then 
		-- trace("ray")
		gfx.push("all")
		gfx.setColor(1,1,1,1)
		gfx.setWireframe(true)
		--gfx.setShader(forwardRender)
		shaders.forwardRender:send("modelMatrix", mat4())
		 shaders.forwardRender:send("MVP",zcam.vp)
		gfx.draw(editor.rayMesh)
		gfx.pop()
	end
end


function drawRoomStuff(view)
	bench.push("drawRoomStuff")
	local room = view.room
	prepModels(view)
	sortModels(room.models)
	sortModels(room.delayed,true)
	bench.push("drawModels")
	
	shaders.forwardRender:send("MVP","column",gfx.camera.vp)
	
	for m,model in ipairs(room.models) do
		drawModel(model)
	end

	if not scene.drawingShadow  then
		shaders.forwardRender:send("overlay",1) 
		for d,delayed in ipairs(room.delayed) do
			delayed.draw()
		end
		shaders.forwardRender:send("overlay",0)
		lume.clear(room.delayed)
	end
 
	stageBorder(true)

	bench.pop("drawModels")
	lume.clear(room.models)
	room.models.nocopy=true
	bench.pop("drawRoomStuff")
end

local function setValues(t,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10)
	t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10]=
	v1,v2,v3,v4,v5,v6,v7,v8,v9,v10
	return t
end

function stageBorder(over)
	if level.isAnim and animationPanel.stageWidth then 

		if not animationPanel.showPasteboard then 

			shaders.forwardRender:send("alpha",1)

			if over then 
				shaders.forwardRender:send("layer",-999)
				shaders.forwardRender:send("MVP","column",gfx.camera.vp)
				gfx.setColor(0,0,0,1)
				-- gfx.rectangle("fill",0,0,10,10)
				-- if not animationPanel.stageBorder then 
					local out = 99999
					local x1,y1 = -animationPanel.stageWidth/2,-animationPanel.stageHeight/2
					local x2,y2 = -x1,-y1
					local x3,y3,x4,y4 = x1-out,y1-out,x2+out,y2+out
					local verts = {{x1,y1}, {x3,y3}, {x2,y1}, {x4,y3}, {x2,y2}, {x4,y4}, {x1,y2}, {x3,y4}, {x1,y1}, {x3,y3}, {x2,y1} }
					for v=1,#verts,1 do 
						setValues(verts[v],verts[v][1],verts[v][2],0,1, 0,0, 0,0,0,1)
					end
					animationPanel.stageBorder = gfx.newMesh(zformat,verts,"strip")
				-- end
				gfx.setMeshCullMode("none")
				gfx.draw(animationPanel.stageBorder)
				gfx.setMeshCullMode("back")
			end
		else
			gfx.setColor(0,0,0,1)
			gfx.setLineWidth(1)
			shaders.forwardRender:send("alpha",0.3)
			shaders.forwardRender:send("layer",100)
			gfx.rectangle("line",-1*animationPanel.stageWidth/2,-1*animationPanel.stageHeight/2,1*animationPanel.stageWidth,1*animationPanel.stageHeight)
			shaders.forwardRender:send("alpha",1)
			shaders.forwardRender:send("layer",0)
		end
	end
end

function prepModels(view)

	bench.push("prepModels")
	view.room.models = view.room.models or {nocopy=true}
	bench.push("ents")

	stageBorder()

	for e,entity in ipairs(view.room.entities) do

		if (entity.light.isLight)  then 
			-- drawSimple(entity,true)
		elseif not entity.visible then 

		elseif entity.simple   then 
			if entity.visible and not entity.ikbone then 
				drawSimple(entity)
			end
		elseif not entity.img  then 
			drawSimple(entity,true)
		else
			for m,model in ipairs(entity.models) do
				table.insert(view.room.models,model)
			end
			if view == currentRoom then 
				if entity.visible then testCursorModel(entity) end
				
				local unp = camera.project(entity,{0,0,renderWidth,renderHeight})
				entity.render = entity.render or {}
				entity.render.x,	entity.render.y		=	mf(unp.x),mf(unp.y)
				-- local dist = vec2.dist(view.bounds.c,entity.render)
				-- entity.render.alpha = 1-(dist*(3/view.bounds.w))*(vec3.dist(entity,zcam.pos)/500)
				
				if editingLevel and not animationPanel.open then 
					drawEntityReloader(entity)
					if not entity.selected and not editor.debug.no_icons then 
						drawEntityVisible(entity,view)
						drawEntityScripts(entity,view)
					end
				end
			end
		end
	end

	bench.pop("ents")

	bench.push("frm")
	if animationPanel then 
		editor.drawFrameMesh(animationPanel)
	end

	bench.pop("frm")

	if not scene.drawingShadow  then 
		if view == currentRoom then
			bench.push("toools")
			for t,tool in ipairs(editor.toolModels) do 
				drawModel(tool)
			end
			lume.clear(editor.toolModels)
			bench.pop("toools")

			bench.push("int")
			if not animationPanel.open and editor.intersect and editor.intersectNormal then 
				local size = 5
				drawModel({
					wireframe=true,
					mesh = gfx.newMesh(zformat,{
						{-editor.intersect.x,-editor.intersect.y,-editor.intersect.z,1,0,0,1,1,1,1},
						{-editor.intersect.x+editor.intersectNormal.x*size,-editor.intersect.y+editor.intersectNormal.y*size,-editor.intersect.z+editor.intersectNormal.z*size,1,0,0,1,1,1,1},
						{-editor.intersect.x,-editor.intersect.y,-editor.intersect.z,1,0,0,1,1,1,1}},"triangles")
				})

			end
			if animationPanel.open and animationPanel.l.remodel and animationPanel.selectMode[3] and editor.entityHovered==animationPanel.instance and editor.intersectTri and editor.intersectMat then 
				local tri = editor.intersectTri
				drawModel({
					wireframe=true,
					layer=1,
					transform = editor.intersectMat,
					mesh = gfx.newMesh(zformat,{
						{tri[1].x,tri[1].y,tri[1].z,1,0,0,1,1,1,1},
						{tri[2].x,tri[2].y,tri[2].z,1,0,0,1,1,1,1},
						{tri[3].x,tri[3].y,tri[3].z,1,0,0,1,1,1,1}},
						"triangles"
					)
				})
			end
			bench.pop("int")
		end
	end
	bench.pop("prepModels")
end

function pushView(view)
	table.insert(scene.views,view)
end

local tempMat,tempMat2,tempMat3,tempMat4 = mat4(),mat4(),mat4(),mat4()
local tempVec = vec3(0,0,0)
local zeroVec = {0,0,0,0}

function sortModels(models,deferred)
	if not(models and #models>0) then return end
	bench.push("sortModels")
	bench.push("dist")
	for m,model in ipairs(models) do
		if model.transform then 
			getModelToCamDist(model)
			--trace("model.camDist",model.camDist)
		end
		-- else 
		-- 	model.camDist = vec3.dist2(zcam.pos, model.x and model or vec3(0))
		-- 	--applyTransform(model)
		-- 	--model.matrix = scene.getMatrix(model)
		-- end
	end
	bench.pop("dist")
	bench.push("sort")
	table.sort 		(models,
		function(a, b) 
			if deferred then 
				return (a.camDist and b.camDist) and a.camDist>b.camDist or false
			else
				return (a.camDist and b.camDist) and a.camDist<b.camDist or false
			end
		end
	)
	bench.pop("sort")
	bench.pop("sortModels")
end

function getModelToCamDist(model)
	model.camDist = vec3.dist(-zcam.pos, getTransform(model)*tempVec)
end
