simple Vuforia to HoloLens - c#

I am trying to get a simple Vuforia image from HoloLens to a function that converts QRCodes to text (via ZXing). I have imported the ZXing library and upon reading over similar implementations have found that the below implementation is in it's simplest form.
It is actually quite simple, the steps are
start by setting up the barcode object
initialize the camera
send the QRcode's text value to console
using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using Vuforia;
using ZXing;
public class HelloWorldV2 : MonoBehaviour
{
private bool cameraInitialized;
private BarcodeReader barReader;
void Start()
{
GameObject sometext = GameObject.Find("Text");
Text txt = sometext.GetComponent<Text>();
txt.text = "Right before BarReader";
barReader = new BarcodeReader();
txt.text = "Right after BarReader"; //NEVER GETS HERE!
StartCoroutine(InitializeCamera());
}
private IEnumerator InitializeCamera()
{
// Waiting a little seem to avoid the Vuforia's crashes.
yield return new WaitForSeconds(1.25f);
var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Vuforia.Image.PIXEL_FORMAT.RGB888, true);
Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
// Force autofocus.
var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
if (!isAutoFocus)
{
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
cameraInitialized = true;
}
private void Update()
{
if (cameraInitialized)
{
try
{
var cameraFeed = CameraDevice.Instance.GetCameraImage(Vuforia.Image.PIXEL_FORMAT.RGB888);
if (cameraFeed == null)
{
return;
}
var data = barReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
if (data != null)
{
// QRCode detected.
Debug.Log(data.Text);
}
else
{
Debug.Log("No QR code detected !");
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
So the issue occurs simply on the constructor call to BarcodeReader(). Which I'm not sure how this would be happening. Why would a simple constructor call fail?
The only other hint I'm getting from a debug session is the following:
FileLoadException: Could not load file or assembly 'System.Core,
Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of
its dependencies. The located assembly's manifest definition does not match
the assembly reference. (Exception from HRESULT: 0x80131040)
at ZXing.BarcodeReader..ctor()
at HelloWorldV2.Start()
Can someone replicate the issue through VisualStudio's Emulator? (Note, this works in Unity when replacing the FrameFormats to grayscale.

I was able to build a working solution for scanning QR codes with ZXing on HoloLens based on this blog post:
https://mtaulty.com/2016/12/28/windows-10-uwp-qr-code-scanning-with-zxing-and-hololens/

That's because you used the wrong dll file (which is not supported on hololens). Try the winmd file in ZXing.net

Related

Unity WebGL Simple JSON

I am trying to import text in my Unity script with WebGL but it seems like in WebGL, it is not able to find the JSON file itself. I have saved the file in StreamingAssets. How do I fix this?
using System.Collections;
using System.Collections.Generic;
using System.IO;
using SimpleJSON;
using UnityEngine;
using UnityEngine.UI;
public class ReadScene : MonoBehaviour {
public string jsonFile;
JSONNode itemsData;
string path;
public Text sceneText;
// Start is called before the first frame update
void Start () {
path = Path.Combine (Application.streamingAssetsPath, "Settings.json");
if (File.Exists (path)) {
jsonFile = File.ReadAllText (path);
DeserializePages ();
} else {
sceneText.gameObject.SetActive(false);
}
}
public void DeserializePages () {
itemsData = JSON.Parse (jsonFile);
var parseJSON = JSON.Parse (jsonFile);
sceneText.text = parseJSON["Scene01"].Value;
}
}
Also I have tried to change the folder location to "Resources" and still facing the same issue.
From Application.streamingAssetsPath
It is not possible to access the StreamingAssets folder on WebGL and Android platforms. No file access is available on WebGL. Android uses a compressed .apk file. These platforms return a URL. Use the UnityWebRequest class to access the Assets.
tbh I don't even know right now whether this No file access is available on WebGL is just misleading or indeed means there is no way to access StreamingAssets. I will assume it is just formulated badly and just means you can not access any file/directory directly but you can still go through UnityWebRequest.Get like
IEnumerator Start ()
{
sceneText.gameObject.SetActive(false);
path = Path.Combine(Application.streamingAssetsPath, "Settings.json");
using(var request = UnityWebRequest.Get(path))
{
yield return request.SendWebRequest();
if(!request.result == UnityWebRequest.Result.Success)
{
Debug.LogError("Error: " + result.error);
yield break;
}
jsonFile = webRequest.downloadHandler.text;
DeserializePages();
}
}
private void DeserializePages()
{
itemsData = JSON.Parse (jsonFile);
sceneText.text = itemsData["Scene01"].Value;
sceneText.gameObject.SetActive(true);
}

I am getting a break in my android emulator: failed to load libc++_shared exception dalvik.system.PathClassLoader[DexPathList[[zip file \"/system/…"

I am trying to implement a routine to cast a video stream using LibVLCSharp but when it gets to where I invoke the core.initialise command, it triggers the above error.
Here's the code in question:
private void BroadcastStream() //string[] args)
{
var serverIpAddress = "192.168.1.101";
var streamUrl = $"rtsp://{serverIpAddress}:554/stream.sdp";
try
{
LibVLCSharp.Shared.Core.Initialize();
var libVlc = new LibVLC();
var media = new Media(libVlc, "fe48f269-4f89-4c58-afd4-04c2e2e3f10f.MP4");
media.AddOption(
$":sout=#transcode{{vcodec=h264,vb=0,scale=0,acodec=mp4a,ab=128,channels=2,samplerate=44100}}:rtp{{mux=ts,sdp={streamUrl}}}");
media.AddOption(":sout-keep");
var player = new MediaPlayer(media);
player.Play();
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
I am using using "LibVLCSharp.Shared;" in the code file and as per instructions I invoked "LibVLCSharpFormsRenderer.Init();" inside "protected override void OnCreate(Bundle savedInstanceState)" in the Android project's MainActivity.cs file.
So, how do I get around this issue?
I loaded the default LibVLSharp.forms library from Nuget for all the projects (iOS, Android & UWP) and that's what caused the issue. I uninstalled the library for iOS and Android and installed their own specific LibVLSharp libraries and it appears to be ok now (at least it no more breaks at core.initialise).

COM+ exception "Class Not Registered" after Microsoft update in February 2020 [duplicate]

This question already exists:
COM+ component - Class not registered error [closed]
Closed 2 years ago.
I have an application which is in Delphi and interacts with other .NET application through old COM+ component. The component is invoked from Delphi code and there was no issue until Microsoft introduced some security patches on Feb 11, 2020 (this year).
The issue it throws now is "Class not registered" After searching a lot on Google, I have tried the following things :
As this COM+ component is written in .NET (ComVisible attribute, had an assumption that it needs to be registered again. So tried to register it usign RegAsm using :
Regasm
But it didn't work though
Confirmed if assembly is in GAC. it is placed there indeed.
List item
Deleting registration of the DLL and then registering using regasm /u but that also provided no luck.
Some blogs over google suggested about COM+ security. Tried playing with that to.
Disabled the COM+ component to test whether COM+ component has any impact and yes indeed it turned to different error. Something like COmponent doesn't exist.
Someone suggested to run DCOMCNFG and traverse into DCOM config tree and press "Yes" if there are warnings to record the anomalies in registry. Still no luck.
Opened up Registry using RegEdit and tried to permit full control on relevant registries including Microsoft Ole. Still didn't work
Also, there were some thoughts around COM security, it was also checked and was permitted well.
The caveat is if we revert the microsoft patches, it works well again. I matched all the security settings before and after the patches which seems same.
PLEASE suggest if someone has sound knowledge about it.
Adding more details:
COM+ Component
COM component properties
Here is the .NET COM component code:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.EnterpriseServices;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Text;
using System.Threading;
using System.Xml.XPath;
using Acclipse.Config;
using Acclipse.FileSystem.Shared;
using Aspose.Words;
[assembly: ApplicationActivation(ActivationOption.Library)]
[assembly: ApplicationAccessControl(false)]
[assembly: ApplicationName("Acclipse FileSystem Client")]
[assembly: Description("Client to communicate with the Acclipse FileSystem server.")]
namespace Acclipse.FileSystem
{
class Singleton
{
private static Singleton m_Instance = new Singleton();
private Singleton()
{
Trace.WriteLine("Singleton.Create");
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
private IRemotedFS m_IRemotedFS;
public static Singleton Instance
{
get
{
return m_Instance;
}
}
internal static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Trace.WriteLine("CurrentDomain_AssemblyResolve", "Acclipse.FileSystem");
try
{
string[] parts = args.Name.Split(',');
string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), string.Format("{0}.dll", parts[0]));
//Trace.WriteLine(string.Format("Loading resolved assembly at {0}", path), "Acclipse.Licencing");
Assembly a = Assembly.LoadFile(path);
Trace.WriteLine(string.Format("Assembly is {0}, looking for {1}", a.FullName, args.Name), "Acclipse.FileSystem");
if (a.FullName != args.Name)
{
throw new ApplicationException("Unable to load correct assembly");
}
return a;
}
catch (Exception ex)
{
Trace.WriteLine(string.Format("Failed to resolve with error {0}", ex.Message), "Acclipse.FileSystem");
}
return Assembly.GetExecutingAssembly();
}
public IRemotedFS FS
{
get
{
Trace.WriteLine("Get IRemotedFS", "Acclipse.FileSystem");
if (m_IRemotedFS == null)
{
try
{
Trace.WriteLine("Creating IRemotedFS", "Acclipse.FileSystem");
Trace.WriteLine("Configfile at " + Path.GetFullPath("Config.file"), "Acclipse.FileSystem");
ConfigFile config = ConfigFile.FromFile("Config.file");
Trace.WriteLine("Loading url", "Acclipse.FileSystem");
string url = config["FileStore.Url"];
if (string.IsNullOrEmpty(url))
{
throw new ApplicationException("Url of server is not configured in Config.file");
}
Trace.WriteLine(string.Format("Url is {0}", url));
TcpClientChannel chan = new TcpClientChannel();
ChannelServices.RegisterChannel(chan, false);
m_IRemotedFS = Activator.GetObject(typeof(IRemotedFS), url) as IRemotedFS;
if (m_IRemotedFS == null)
{
Trace.WriteLine("Oops, RemoteFS is null!!");
}
}
catch (Exception e)
{
Trace.WriteLine(string.Format("Error in getting FS *** {0} - {1}", e.Message, e.StackTrace));
throw;
}
}
Trace.WriteLine("..Done");
return m_IRemotedFS;
}
internal set
{
m_IRemotedFS = value;
}
}
}
[ComVisible(true)]
[ProgId("Acclipse.FileSystem.SqlZipClient.SqlZipFileSystemRemote")]
[Guid("5A940543-24EF-4f31-B45B-6832C8211986")]
[ClassInterface(ClassInterfaceType.None)]
[JustInTimeActivation(true)]
public class SqlZipFileSystemRemote : ServicedComponent, IFileSystem
{
private IConfigFile m_Config;
public SqlZipFileSystemRemote()
{
Trace.WriteLine("SqlZipFileSystemRemote Created", "Acclipse.FileSystem");
m_Config = DefaultConfigFile.FromFile("Config.file");
}
static SqlZipFileSystemRemote()
{
Trace.WriteLine("Set Aspose.Words license info", "Acclipse.FileSystem");
try
{
new License().SetLicense("Acclipse.FileSystem.SqlZipClient.Aspose.Words.lic");
}
catch (Exception ex)
{
Trace.WriteLine(string.Format("Exception encountered setting license details: {0}", ex.StackTrace), "Acclipse.FileSystem");
throw;
}
Trace.WriteLine("Done", "Acclipse.FileSystem");
}
internal void AttachConfigFile(IConfigFile config)
{
this.m_Config = config;
}
}
}

Dynamically Load and Activate a dataset (vuforia and unity)

I want to make a system that I can use to download various targets dynamically from my website without using "Cloud" system.
I also want to save the dataset to .xml and .dat formats which I want to activate from my saving device.
There are a lot of methods and pages to doing that with vuforia and unity, but unfortunately when I test it I receive an error for all of them.
It seems that i have made a mistake in my code or a vuforia class was changed.
For instance please look this link:
https://developer.vuforia.com/library/articles/Solution/Unity-Load-DataSet-from-SD-Card
I got Error: Using Vuforia;
I placed the .xml and .dat files in "Application.persistentDataPath + "/" + "Building1.xml"
i used this Script "DataSetLoadBehavior" that attached "AR Camera and placed my code in it. I got an Error:
NullReferenceException: Object reference not set to an instance of an
object DataSetLoadBehaviour.OnInitialized () (at Assets/Qualcomm
Augmented Reality/Scripts/DataSetLoadBehaviour.cs:49)
DataSetLoadBehaviour.Start () (at Assets/Qualcomm Augmented
Reality/Scripts/DataSetLoadBehaviour.cs:80)
My code is this:
unity 4.2 pro and vuforia 2.8.9 or 3.0.9
/*==============================================================================
Copyright (c) 2010-2014 Qualcomm Connected Experiences, Inc.
All Rights Reserved.
Confidential and Proprietary - Qualcomm Connected Experiences, Inc.
==============================================================================*/
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// This behaviour allows to automatically load and activate one or more DataSet on startup
/// </summary>
public class DataSetLoadBehaviour : DataSetLoadAbstractBehaviour
{
[HideInInspector, SerializeField]
public List<string> mDataSetsToActivate2 = new List<string>();
[SerializeField, HideInInspector]
public List<string> mDataSetsToLoad2 = new List<string>();
protected DataSetLoadBehaviour()
{
}
private void OnDestroy()
{
QCARAbstractBehaviour behaviour = (QCARAbstractBehaviour) UnityEngine.Object.FindObjectOfType(typeof(QCARAbstractBehaviour));
if (behaviour != null)
{
}
}
public void OnInitialized()
{
if (QCARRuntimeUtilities.IsQCAREnabled())
{
foreach (string str in this.mDataSetsToLoad2)
{
if (!DataSet.Exists(str, QCARUnity.StorageType.STORAGE_ABSOLUTE))
{
Debug.LogError("Data set " + str + " does not exist.");
}
else
{
ImageTracker tracker = TrackerManager.Instance.GetTracker<ImageTracker>();
DataSet dataSet = tracker.CreateDataSet();
if (!dataSet.Load(str))
{
Debug.LogError("Failed to load data set " + str + ".");
}
else if (this.mDataSetsToActivate2.Contains(str))
{
tracker.ActivateDataSet(dataSet);
}
}
}
}
}
public void OnTrackablesUpdated()
{
}
private void Start()
{
QCARAbstractBehaviour behaviour = (QCARAbstractBehaviour) UnityEngine.Object.FindObjectOfType(typeof(QCARAbstractBehaviour));
if (behaviour != null)
{
mDataSetsToLoad2.Add(Application.persistentDataPath + "/" + "Building1.xml");
OnInitialized();
}
}
public override void AddOSSpecificExternalDatasetSearchDirs()
{
#if UNITY_ANDROID
if (Application.platform == RuntimePlatform.Android)
{
// Get the external storage directory
AndroidJavaClass jclassEnvironment = new AndroidJavaClass("android.os.Environment");
AndroidJavaObject jobjFile = jclassEnvironment.CallStatic<AndroidJavaObject>("getExternalStorageDirectory");
string externalStorageDirectory = jobjFile.Call<string>("getAbsolutePath");
// Get the package name
AndroidJavaObject jobjActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
string packageName = jobjActivity.Call<string>("getPackageName");
// Add some best practice search directories
//
// Assumes just Vufroria datasets extracted to the files directory
AddExternalDatasetSearchDir(externalStorageDirectory + "/Android/data/" + packageName + "/files/");
// Assume entire StreamingAssets dir is extracted here and our datasets are in the "QCAR" directory
AddExternalDatasetSearchDir(externalStorageDirectory + "/Android/data/" + packageName + "/files/QCAR/");
}
#endif //UNITY_ANDROID
}
void Update()
{
}
}
Yeah, Vuforia has has changed a lot.
You will now have to include Vuforia as a header in order for it to work
using Vuforia;
Hope this works.
If it says Vuforia hasn't been found it's probably because you haven't imported the Unitypackage for Vuforia. You can follow these instructions.
Also, I believe you haven't followed the steps to Migrating your Unity Project. The new Vuforia doesn't support ImageTracker anymore, hence you will have to change all instances of ImageTracker to ObjectTracker

compiling/merging dll into standalone exe with wpf

Background : Merging dlls into a single .exe with wpf
How shall i merge a .dll reference into the .exe file, i read the above post, got principle behind it, but i am not able to figure out how to do it?( i am newbie, sorry)
The reference file is HtmlagilityPack.dll
Currently my App.xaml.cs contains :
public partial class App : Application
{
public App(){
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
// proceed starting app...
}
static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
{
//We dont' care about System Assembies and so on...
if (!args.Name.ToLower().StartsWith("Html")) return null;
Assembly thisAssembly = Assembly.GetExecutingAssembly();
//Get the Name of the AssemblyFile
var name = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";
//Load form Embedded Resources - This Function is not called if the Assembly is in the Application Folder
var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(name));
if (resources.Count() > 0)
{
var resourceName = resources.First();
using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
{
if (stream == null) return null;
var block = new byte[stream.Length];
stream.Read(block, 0, block.Length);
return Assembly.Load(block);
}
}
return null;
}
}
Where else am i supposed to make changes?, i have being trying past an hour with an example of http://blog.mahop.net/post/Merge-WPF-Assemblies.aspx But not able to figure out how to do it with HtmlAgilityPack.
Okay, finally had to use the SmartAssembly program.
But still looking for a solution to do it by code.
Your code looks slightly off, it should look more like this:
public class App : Application
{
[STAThreadAttribute()]
public static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly);
// etc...
}
// etc...
You then also need to change the "Startup object" setting in the properties page of your project to use the App class (i.e. the above code) - you should then see the Main method of this class being the first code executed when you start debugging.

Categories