Трекинг поверхностей

Трекинг поверхностей - обнаружение горизонтальных и вертикальных поверхностей в окружающей среде, например пола или стен. Часто используется в AR приложениях для размещения на обнаруженных поверхностях виртуальных объектов. Использует камеру, сенсоры устройства, а также алгоритмы. Может не работать в плохо освещенной среде и на отражающих поверхностях.

На устройствах с iOS осуществляется с помощью технологии ARKit, на устройствах с Android - с помощью ARCore.

Код для версии Advanced, пример на нашем гитхабе:

local sys = evi.os()

local info_txt				= getReactorOrDie("info_txt")
local button				= getReactorOrDie("btn")
local ar_plane_transform	= getReactorOrDie("ar_plane_transform")
local plane_image			= getReactorOrDie("plane/image")
local plane_model			= getReactorOrDie("plane/model")

-- initial state
button:hide(0x0)			-- not visible, not clickable
ar_plane_transform:hide()	-- just hide (does not matter if clickable or not)
plane_image:show()			-- just show (does not matter if clickable or not)
plane_model:hide()

-- NOTE: trackingSystem is global (used by TrackingSystemReactor also)
local busARCore	= trackingSystem.busARCore
local busARKit	= trackingSystem.busARKit

-- Symlinks for clean code
local busAR = busARCore and busARCore or busARKit
local BusAR_Class = busARCore and evar.BusARCore or evar.BusARKit

if not busAR then
	local msg = "Cannot detect ARKit/ARcore"
	if sys == "android" then
		msg = msg .. "\nPlease install Google Play Services for AR"
	end

	logger:error(msg)
	info_txt.text.value = msg
	info_txt.text.color = osg.Vec4(1.0, 0.0, 0.0, 1.0)

	return
end


local planeFindingMode	= bit_or(BusAR_Class.PLANE_HORIZONTAL, BusAR_Class.PLANE_VERTICAL)
busAR:setPlaneFindingModeMask(planeFindingMode)
-- NOTE: Use busAR:setPlaneFindingModeMask(0) to stop finding planes (will improve performance)


local function showPlane()
	ar_plane_transform:show()
	button:show(bit_or(NodeReactor.Mask.VISIBLE, NodeReactor.Mask.CLICKABLE))
end

local function onPlaneEnter()
	logger:info("Plane entered")
	showPlane()
end

local function onPlaneMove(mat)
	local m = evar.evar2osg(mat, false)
	ar_plane_transform.node:setMatrix(m)
	if not ar_plane_transform.visible then
		showPlane()
	end
end

local function onPlaneLeave()
	logger:info("Plane leave")
	ar_plane_transform:hide(0x0)
	button:hide(0x0)
end

local classification, min_area, min_distance, max_distance = BusAR_Class.MarkerPlane.PLANE_CLASS_NONE, 1.0, 1.0, 5.0
local planeTraits		= BusAR_Class.MarkerPlane.Traits(classification, min_area, min_distance, max_distance)
local markerPlaneImpl	= BusAR_Class.MarkerPlane(planeTraits)	-- markerImpl ref. by the handler

markerImplHandler		= nil			-- handler not ref. by busARCore/busARKit, so create it global, this will be fixed in the future releases
if busARCore then
	markerImplHandler = evar.BusARCore.Marker.HandlerLua(markerPlaneImpl, onPlaneEnter, onPlaneMove, onPlaneLeave)
else
	markerImplHandler = evar.BusARKit.Marker.HandlerLua(markerPlaneImpl, trackingSystem.bus, onPlaneEnter, onPlaneMove, onPlaneLeave)
end
busAR:addListener(markerImplHandler)	-- handler not ref. by busARCore/busARKit
busAR:addMarker(markerPlaneImpl)


ar_plane_transform:subscribeEvent("onShowed", function()
	info_txt:hide()
end)
ar_plane_transform:subscribeEvent("onHidden", function()
	info_txt:show()
end)

button:subscribeEvent("onDown", function()
	if markerPlaneImpl:isTagged() then
		markerPlaneImpl:untag()
		button.text.value = "ПОМЕСТИТЬ"
		plane_image:show()
		plane_model:hide()
	else
		markerPlaneImpl:tag()
		button.text.value = "ПЕРЕМЕСТИТЬ"
		plane_image:hide()
		plane_model:show()
	end
end)