Xamarin NuGet Package >
AR Logo for Android
This tutorial starts from the project created following the planar marker tutorial, and teaches how to create an app that reacts to ARLogo prints.
Note: if you prefer to read existing and working code, the complete Visual Studio project can be found on Github @ https://github.com/pikkart-support/XamarinAndroid_ARLogo (remember to add you license file in the assets folder!).
ARLogo is a Pikkart proprietary technology that allows you to create multiple “versions” of the same image (marker) by adding an invisible code detectable by our SDK. This allows developers to create multiple augmented reality experiences on the same image. The ARLogo detection is on-device and thus does not need an internet connection. For more details visit the ARLogo page.
The recognition of the ARLogo code starts right after the detection of a marker, and the ARLogoFound() callback of the MainActivity is called when an ARLogo code is recognized in the image. This means that there’s a short period of time (usually less than a second) between the detection of the marker and the recognition of the ARLogo.
To give an immediate response to the user, we will show a placeholder content during this period of time.
To use the ARLogo technology on a marker created on the CMS, make sure to check the “enable ARLogo” checkbox. Then download and use the resulting .dat marker file in your app.
For this tutorial we've already created the ARLogo marker and 3 ARLogo prints, that can be found in the ARLogo sample package.
Remove all the .dat files in the Assets/markers directory of your app and copy the one in the markers folder of the sample package.
Copy all the content of the media directory in the Assets/media folder.
Modify the ARLogoFound callback to log the detected code:
public void ARLogoFound(string p0, int p1)
{
System.Diagnostics.Debug.WriteLine("ARLogo code: " + p1);
}
Run the app and point the camera to the images in the folder “ARLogo prints”, or print them.
Now we want to show a different AR content for each unique ARLogo print. In order to do this, we load four different versions of the 3D monkey object (with 4 different textures) in the ARRenderer.
Create 4 class member variables to hold the 4 meshes:
private Mesh monkeyMesh = null;
private Mesh monkeyMeshYellow = null;
private Mesh monkeyMeshBlue = null;
private Mesh monkeyMeshRed = null;
private Mesh monkeyMeshGray = null;
Create and load the meshes on the OnSurfaceCreated()
method, initialize the meshes in a separate task to quickly show the camera:
public void OnSurfaceCreated(IGL10 gl, EGLConfig config) { gl.GlClearColor(1.0f, 1.0f, 1.0f, 1.0f); //Here we create the 3D object and initialize textures, shaders, etc. monkeyMesh = new Mesh(); monkeyMeshYellow = new Mesh(); monkeyMeshBlue = new Mesh(); monkeyMeshRed = new Mesh(); monkeyMeshGray = new Mesh(); Task.Run(async() => { try { ((Activity)context).RunOnUiThread(() => { progressDialog = ProgressDialog.Show(context, "Loading textures", "The 3D template textures of this tutorial have not been loaded yet\n(this may take a while)", true); }); monkeyMesh.InitMesh(context.Assets, "media/monkey.json", "media/texture.png"); monkeyMeshYellow.InitMesh(context.Assets, "media/monkey.json", "media/texture.png"); monkeyMeshBlue.InitMesh(context.Assets, "media/monkey.json", "media/texture2.png"); monkeyMeshRed.InitMesh(context.Assets, "media/monkey.json", "media/texture3.png"); monkeyMeshGray.InitMesh(context.Assets, "media/monkey.json", "media/texturegray.png"); monkeyMesh = monkeyMeshGray; // Initially we want to display the gray monkey if (progressDialog != null) progressDialog.Dismiss(); } catch (System.OperationCanceledException ex) { Console.WriteLine("init failed: {ex.Message}"); } catch (Exception ex) { Console.WriteLine(ex.Message); } });
}
Create a public method in the ARRenderer called SelectMonkey:
public void SelectMonkey(int monkeyID)
{
switch(monkeyID) {
case 0:
monkeyMesh = monkeyMeshGray;
break;
case 1:
monkeyMesh = monkeyMeshYellow;
break;
case 2:
monkeyMesh = monkeyMeshBlue;
break;
case 3:
monkeyMesh = monkeyMeshRed;
break;
default:
monkeyMesh = monkeyMeshGray;
break;
}
}
By calling this method, we assign to the monkeyMesh reference a different (colored) mesh, that will be drawn in the onDrawFrame()
method.
In order to connect the ARLogoFound callback in the MainActivity to this method we need to add an intermediate method SelectMonkey in the ARView
class, visible from the Main Activity:
public void SelectMonkey(int monkeyID)
{
_renderer.SelectMonkey(monkeyID);
}
Now we just need to call the SelectMonkey method of the ARView in the ARLogoFound callback, selecting which color we want to assign to each ARLogo code.
To do this we need a reference to the ARView object in the ARLogoFound callback.
We create a m_arView
object as a private member of the MainActivity class and replace these two lines in the InitLayout()
method:
private void InitLayout() { SetContentView(Resource.Layout.Main); m_arView = new ARView(this); AddContentView(m_arView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MatchParent, FrameLayout.LayoutParams.MatchParent));
…
}
Now we can call the SelectMonkey()
method inside the ARLogoFound callback:
public void ARLogoFound(string p0, int p1) {
System.Diagnostics.Debug.WriteLine("ARLogo code: " + p1);
switch(p1){
case 97703:
m_arView.SelectMonkey(1);
break;
case 84895:
m_arView.SelectMonkey(2);
break;
case 65266:
m_arView.SelectMonkey(3);
break;
}
}
The last thing we need to do is set the monkey to the gray texture when we lose the tracking of a marker:
public void MarkerTrackingLost(String p0) {
m_arView.SelectMonkey(0);
Toast.MakeText(this, "PikkartAR: lost tracking of marker " + p0,
ToastLength.Short).Show();
}
Now we can run the app and see the color of the monkey change on the different ARLogo prints.
This should be the behavior of the app: