заглавие | Описание | Ссылка на сайт |
---|---|---|
Приложениям дополненной реальности требуется серверная часть веб-службы. Это 90-дневное без обязательств, абсолютно бесплатное предложение использовать Windows Azure в качестве веб-службы для клиентов Windows 8. | Вы получаете: Compute / 750 небольших вычислительных часов в месяц, веб-сайты / 10 веб-сайтов, мобильные сервисы / 10 мобильных сервисов, реляционная база данных / 1 база данных SQL, отчеты SQL / 100 часов в месяц, хранилище / 35 ГБ с 50 000 000 транзакций хранения, пропускная способность / неограниченный входящий и 25 ГБ исходящий, CDN / 20 ГБ исходящий с 500 000 транзакций, кэш / 128 МБ, служебная шина / 1500 часов ретрансляции и 500 000 сообщений | http://www.microsoft.com/click/services /Redirect2.ashx?CR_CC=200114759 |
Шаг 0: Что мы будем строить. Дополненная реальность, Windows 8 и облачные вычисления — как реализовать с реальным кодом | Введение высокого уровня в наше законченное приложение. | http://blogs.msdn.com/b/brunoterkaly/archive/2012 / 11/05 / step-0-что-мы-будем-строить- дополненную реальность-windows-8-and-cloud-computing-how-how- в реализации-с реальной code.aspx # |
Шаг 1 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом | Вступление. Что такое дополненная реальность | http://blogs.msdn.com/b/brunoterkaly/archive/2012/10/29/ шаг-1-дополненная реальность-окна-8-и-облачные вычисления- как реализовать с реальным- code.aspx # |
Шаг 2 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом | Сборка первой части нашего бэкэнда Azure. | http://blogs.msdn.com/b/brunoterkaly/archive/2012/10/30/ step-2-augmented-reality-windows-8-and- cloud-computing-как реализовать с реальными code.aspx # |
Шаг 3 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом (Внедрение облачной среды) | В этом посте представлен весь исходный код и пояснения для серверной части Azure. Это серверная часть для Windows 8 Client дополненной реальности. | http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/05 / step-3-augmented-reality-windows-8-and-cloud-computing-как реализовать с реальными реализующий код из облака-обратно-end.aspx # |
Шаг 4 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом … | Этот пост содержит весь исходный код и пояснения для клиента Windows 8 (демонстрация дополненной реальности). Клиент дополненной реальности Windows 8 обращается к бэкэнду Azure, описанному в шаге 3 выше. | http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/06/ шаг-4-дополненная реальность-окна-8-и-облачные вычисления-как реализовать с реальными- код реализации Windows-8-client.aspx # |
Исходный код — серверная часть веб-службы | Это проект Windows Azure, к которому обращаются клиенты Windows 8 | http://sdrv.ms/Qoqb1J |
Исходный код — клиент Windows 8 | Это клиент дополненной реальности для Windows 8 | http://sdrv.ms/T38uBC |
Это проект Windows 8
- Он работает на ОС Windows 8 и был построен с Visual Studio 2012
- Этот пост будет строить это приложение с нуля
- Он будет связываться с облачным бэкэндом, который мы создали в последнем посте.
- Облачный бэкэнд — это облачный проект Windows Azure
- Он был развернут в центре обработки данных
Уровень клиента — Windows 8
- Этот пост основан на последнем посте, который был уровнем Front-End Web Services. Это было облачное приложение Windows Azure (с веб-ролью типа ASP.NET Web API)
- Клиент дополненной реальности Windows 8 не будет работать, если не будет облачного сервера
- Облачный сервер может работать в центре обработки данных MS
- Или он может работать как проект Visual Studio 2012 с использованием эмулятора вычислений Windows Azure
Создание приложения для Windows 8
- В Visual Studio выберите Файл / Новый проект / Приложение Магазина Windows.
- Выберите пустое приложение
Проект по умолчанию: изменение файла манифеста приложения
- Вы ищете обозреватель решений
- Он доступен из меню ВИД
- Щелкните правой кнопкой мыши Package.appmanifest и выберите VIEW DESIGNER. Это позволит нам изменить возможности. Например, мы хотим разрешить подключение к интернету.
Манифест приложения: включение возможностей
- Я выбрал варианты, которые вы видите выше.
- Интернет, микрофон, доступ к библиотеке изображений, доступ к библиотеке видео, веб-камера
- Когда вы запускаете приложение Windows 8, вам все равно необходимо подтвердить использование веб-камеры и микрофона.
Основной интерфейс: MainPage.xaml
- Вы также можете использовать EXPRESSION BLEND для редактирования вашего графического интерфейса.
- Visual Studio 2012 также имеет дизайнера, доступного в меню просмотра.
Понимание XAML
- Пользовательский интерфейс — это просто набор элементов управления XAML
- Это просто большой XML-файл, похожий на пользовательский интерфейс Android
- StackPanels и Grids составляют большую часть интерфейса
- Кнопки, текстовые блоки, изображения, прямоугольники, холсты, радиокнопки вложены в панели стека и сетки
- Существует также CapturePanel для отображения живого видео с веб-камеры.
- Этот экран показывает одну из панелей стека
- Содержит вложенные StackPanels
- Он содержит 2 кнопки и радиокнопки для симулятора GPS
- Симулятор GPS позволяет выбрать Сан-Франциско, Рено, Денвер или Долину Смерти
- Моя система не имеет встроенного симулятора
Понимание XAML
- Радиокнопки расположены в StackPanel
Понимание XAML
- Раздел дополненной реальности — это просто сетка с границами
- Сетка содержит TextBlocks, куда мы будем помещать данные, которые мы получаем от вызова нашего облачного бэкэнда Azure, облачного сервиса.
- Заполнение TextBlocks информацией о местонахождении и погоде выполняется с помощью кода (MainPage.xaml.cs)
<Page x:Class="AugmentedRealityClient.MainPage" IsTabStop="false" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AugmentedRealityClient" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" x:Name="LayoutRoot" HorizontalAlignment="Left" VerticalAlignment="Center"> <!—Two rows, One column--> <Grid.RowDefinitions> <RowDefinition Height="165"/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> </Grid.ColumnDefinitions> <Border BorderThickness="3" BorderBrush="White" Grid.Row="0"/> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="6" HorizontalAlignment="Left" VerticalAlignment="Center"> <Button x:Name="butConfigure" Content="Configure" Width="200" Height="80" FontSize="32" Margin="6" Click="ConfigureCamera_Click"/> <Button x:Name="butTurnCameraOn" Content="Take Picture" Width="218" Height="80" FontSize="32" Margin="6,6"/> <StackPanel> <TextBlock x:Name="txtGPS" FontSize="14" Canvas.Left="22" Canvas.Top="9" Margin="0,12,0,2" Foreground="Yellow" FontFamily="Segoe UI" Text="GPS Simulator" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Top" TextAlignment="Center"/> <RadioButton Name="radSF" GroupName="GPS" Content="{Binding Path=City1, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked1, Mode=TwoWay}" Checked="radSF_Checked"> </RadioButton> <RadioButton Name="radReno" GroupName="GPS" Content="{Binding Path=City2, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked2, Mode=TwoWay}" Checked="radReno_Checked"> </RadioButton> <RadioButton Name="radDenver" GroupName="GPS" Content="{Binding Path=City3, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked3, Mode=TwoWay}" Checked="radDenver_Checked"> </RadioButton> <RadioButton Name="radDeathValley" GroupName="GPS" Content="{Binding Path=City4, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked4, Mode=TwoWay}" Checked="radDeathValley_Checked"> </RadioButton> </StackPanel> </StackPanel> <StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"> <Canvas x:Name="previewCanvas1" Background="Black" Width="640" Height="600"> <CaptureElement x:Name="previewElement1" HorizontalAlignment="Left" VerticalAlignment="Top"/> <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5"> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="300"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="20"/> <RowDefinition Height="20"/> <RowDefinition Height="20"/> <RowDefinition Height="20"/> <RowDefinition Height="20"/> </Grid.RowDefinitions> <!--Row 1--> <Rectangle Grid.Column="0" Grid.Row="0" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="0" Text="Neighborhood" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="0" Stroke="white" Fill="Black" Opacity=".3"/> <TextBlock x:Name="bus_and_neighborhood" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 2--> <Rectangle Grid.Column="0" Grid.Row="1" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="1" Text="Elevation" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="1" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="elevation" Grid.Column="1" Grid.Row="1" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 3--> <Rectangle Grid.Column="0" Grid.Row="2" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="2" Text="Lat/Long" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="2" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="latlong" Grid.Column="1" Grid.Row="2" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 4--> <Rectangle Grid.Column="0" Grid.Row="3" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="3" Text="Max temp" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="3" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="max_temp" Grid.Column="1" Grid.Row="3" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 5--> <Rectangle Grid.Column="0" Grid.Row="4" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="4" Text="MinTemp" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="4" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="min_temp" Grid.Column="1" Grid.Row="4" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Image Grid.Column="2" Grid.Row="0" Grid.RowSpan="5" Source="http://www.ssec.wisc.edu/data/us_comp/image1.jpg" Opacity=".7"/> </Grid> </Canvas> </StackPanel> </Grid> </Page>
- Порядок элементов управления имеет решающее значение.
- Это позволяет нам накладывать данные поверх потока живого видео с веб-камеры.
- Если вы заметили, многие из текстовых блоков появляются ПОСЛЕ элемента управления CaptureElement.
- Это контролирует z-порядок элементов управления.
Линия | Комментарий |
---|---|
35-49 | Две кнопки. Одна кнопка предназначена для включения веб-камеры, а другая — для фотографирования. Я иллюстрировал фотографирование в предыдущем посте. Содержит ссылку на метод события (ConfigureCamera_Click) |
50-91 | Пользовательский интерфейс для симулятора GPS. Текстовый блок и куча радио кнопок. Все 4 переключателя имеют процедуру обработки события, поскольку в конечном итоге они обращаются в веб-службу Azure для получения нового местоположения GPS. |
98 | Канва для отображения живого видеопотока дополненной реальности с веб-камеры |
103-105 | Элемент управления, отображающий потоковое видео в режиме дополненной реальности |
143, 169, 196, 224, 250 | TextBlocks, которые будут отображать данные дополненной реальности, поступающие из внутреннего облачного приложения Azure. |
257 | Используется для хранения последних спутниковых изображений погоды |
MainPage.xaml.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // Some extra using statements for my code using Windows.Devices.Enumeration; using Windows.Media.Capture; using Windows.Media.MediaProperties; using System.Net.Http; using Windows.Data.Json; using System.Collections.ObjectModel; using System.ComponentModel; namespace Windows8AugmentedRealityClient { public sealed partial class MainPage : Page { private Windows.Media.Capture.MediaCapture m_mediaCaptureMgr; // Our GPS simulator GPSSimulator _gps_simulator; // This object get populated with data from calling into // our Windows Azure Web Service, which was created in the // previous blog private LocationInfo loc_info = new LocationInfo(); public MainPage() { this.InitializeComponent(); // previewElement1 is our view port to see the streaming // video content from the web cam previewElement1.Source = null; // Make sure it is visible previewCanvas1.Visibility = Windows.UI.Xaml.Visibility.Visible; // Initialize our GPS Simulator _gps_simulator = new GPSSimulator(); _gps_simulator.City1 = "San Francisco"; _gps_simulator.Gps1 = "37.788345,-122.404679"; _gps_simulator.IsChecked1 = true; _gps_simulator.City2 = "Reno"; _gps_simulator.Gps2 = "39.545353,-119.815631"; _gps_simulator.IsChecked2 = false; _gps_simulator.City3 = "Denver"; _gps_simulator.Gps3 = "39.752073,-104.979968"; _gps_simulator.IsChecked3 = false; _gps_simulator.City4 = "Death Valley"; _gps_simulator.Gps4 = "36.619937,-117.10415"; _gps_simulator.IsChecked4 = false; // Trap some change events (for debugging purposes) _gps_simulator.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(gpsChanged); // Bind our GPS Simulator to the Windows 8 form's DataContext this.DataContext = _gps_simulator; } private void gpsChanged(object sender, PropertyChangedEventArgs e) { string s = "The property:'" + e.PropertyName + "' was changed"; } // Ignored for this demo protected override void OnNavigatedTo(NavigationEventArgs e) { } // Hit when user hits the "Configure" button // This method initializes the web cam to display the live // streaming video content internal async void ConfigureCamera_Click(Object sender, Windows.UI.Xaml.RoutedEventArgs e) { // Initialize Media Capture API try { // Prepare Media Capture m_mediaCaptureMgr = new Windows.Media.Capture.MediaCapture(); var _captureSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings(); DeviceInformationCollection deviceInfos = await DeviceInformation.FindAllAsync(Windows.Devices.Enumeration.DeviceClass.VideoCapture); _captureSettings = new MediaCaptureInitializationSettings(); _captureSettings.StreamingCaptureMode = StreamingCaptureMode.Video; _captureSettings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview; if (deviceInfos.Count > 0) { _captureSettings.VideoDeviceId = deviceInfos[0].Id; } await m_mediaCaptureMgr.InitializeAsync(_captureSettings); } catch (Exception exception) { // Ignore errors for now string s = exception.Message; } // Start the Preview try { previewElement1.Source = m_mediaCaptureMgr; await m_mediaCaptureMgr.StartPreviewAsync(); } catch (Exception exception) { previewElement1.Source = null; } } // This method performs the call into our Azure Web Service // fromt the previous post. This method will pass GPS parameters // to the cloud service and receive back JSON data that will // need to be parsed. private async System.Threading.Tasks.Task CallLocationWebService(string gps) { // Call into the emulator. This assumes you are running the // cloud project from the last post in the backgruond string _location = "http://127.0.0.1:81/api/values?location={0}"; // You can use the line below once you deploy your cloud // application to the cloud (a MS data center) //string _location = "http://locationwebservice.cloudapp.net/api/values?location={0}"; // Now make the aynchronous call. We need to pass the GPS // parameters here to the _location string mentioned above. using (HttpClient clientlocation = new HttpClient()) using (var response = await clientlocation.GetAsync(string.Format(_location, gps))) { if (response.IsSuccessStatusCode) { string webresponse = await response.Content.ReadAsStringAsync(); // Parse the string into a JSONObject var parsedResults = JsonObject.Parse(webresponse); IJsonValue val; // Extract data embedded in JSONObject. // Assign to controls in user interface if (parsedResults.TryGetValue("latitude", out val)) loc_info.latitude = val.GetString(); if (parsedResults.TryGetValue("longitude", out val)) loc_info.longitude = val.GetString(); if (parsedResults.TryGetValue("bus_and_neighborhood", out val)) loc_info.bus_and_neighborhood = val.GetString(); if (parsedResults.TryGetValue("elevation", out val)) loc_info.elevation = val.GetString(); if (parsedResults.TryGetValue("bus_and_neighborhood", out val)) loc_info.bus_and_neighborhood = val.GetString(); if (parsedResults.TryGetValue("max_temp", out val)) loc_info.max_temp = val.GetString(); if (parsedResults.TryGetValue("min_temp", out val)) loc_info.min_temp = val.GetString(); this.bus_and_neighborhood.Text = loc_info.bus_and_neighborhood; this.elevation.Text = loc_info.elevation; this.latlong.Text = loc_info.latitude + "/" + loc_info.longitude; this.max_temp.Text = loc_info.max_temp; this.min_temp.Text = loc_info.min_temp; } } } // Checkbox events // Called when user clicks a radio button on the GPS Simulator private async void radSF_Checked(object sender, RoutedEventArgs e) { string s = _gps_simulator.Gps1; await CallLocationWebService(s); } private async void radReno_Checked(object sender, RoutedEventArgs e) { string s = _gps_simulator.Gps2; await CallLocationWebService(s); } private async void radDenver_Checked(object sender, RoutedEventArgs e) { string s = _gps_simulator.Gps3; await CallLocationWebService(s); } private async void radDeathValley_Checked(object sender, RoutedEventArgs e) { string s = _gps_simulator.Gps4; await CallLocationWebService(s); } // A helper method. Not currently used but was valuable during // debugging my controls. public IEnumerable<T> HelperFindMatch<T>(DependencyObject depObj) where T : DependencyObject { System.Diagnostics.Debugger.Break(); if (depObj != null) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) { DependencyObject child = VisualTreeHelper.GetChild(depObj, i); if (child != null && child is T) { yield return (T)child; } foreach (T childOfChild in HelperFindMatch<T>(child)) { yield return childOfChild; } } } } // A helper method. Not currently used but was valuable during // debugging my controls. public T HelperFindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var child = VisualTreeHelper.GetChild(parent, i); string controlName = child.GetValue(Control.NameProperty) as string; if (controlName.IndexOf("rad") != -1 && controlName != name) { return child as T; } else { T result = HelperFindVisualChildByName<T>(child, name); if (result != null) return result; } } return null; } } // This class represents the data populated by the Windows Azure // Web Service public class LocationInfo { // Data we will lookup public string latitude { get; set; } public string longitude { get; set; } public string elevation { get; set; } public string bus_and_neighborhood { get; set; } public string max_temp { get; set; } public string min_temp { get; set; } } //Implement INotifiyPropertyChanged interface to subscribe for //property change notifications public class GPSSimulator : INotifyPropertyChanged { private string _gps1; private string _city1; private bool _ischecked1; private string _gps2; private string _city2; private bool _ischecked2; private string _gps3; private string _city3; private bool _ischecked3; private string _gps4; private string _city4; private bool _ischecked4; public string Gps1 { get { return _gps1; } set { _gps1 = value; RaisePropertyChanged("Gps1"); } } public string City1 { get { return _city1; } set { _city1 = value; RaisePropertyChanged("City1"); } } public bool IsChecked1 { get { return _ischecked1; } set { _ischecked1 = value; RaisePropertyChanged("IsChecked1"); } } public string Gps2 { get { return _gps2; } set { _gps2 = value; RaisePropertyChanged("Gps2"); } } public string City2 { get { return _city2; } set { _city2 = value; RaisePropertyChanged("City2"); } } public bool IsChecked2 { get { return _ischecked2; } set { _ischecked2 = value; RaisePropertyChanged("IsChecked2"); } } public string Gps3 { get { return _gps3; } set { _gps3 = value; RaisePropertyChanged("Gps3"); } } public string City3 { get { return _city3; } set { _city3 = value; RaisePropertyChanged("City3"); } } public bool IsChecked3 { get { return _ischecked3; } set { _ischecked3 = value; RaisePropertyChanged("IsChecked3"); } } public string Gps4 { get { return _gps4; } set { _gps4 = value; RaisePropertyChanged("Gps4"); } } public string City4 { get { return _city4; } set { _city4 = value; RaisePropertyChanged("City4"); } } public bool IsChecked4 { get { return _ischecked4; } set { _ischecked4 = value; RaisePropertyChanged("IsChecked4"); } } public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } } }
Спасибо за прочтение.
Ваше задание — перейти на http://programmableweb.com и выполнить собственную дополненную реальность и сопоставления данных.
Не забудьте отправить его мне, чтобы я мог написать об этом в блоге