cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X

Vuforia Studio and Chalk Tech Tips

Sort by:
Vuforia Studio The source URL of 3D Audio and 3D Video widgets can now be set dynamically Bug fixes and minor improvements Vuforia View Android Versions prior to 8.0 are no longer supported RealWear Beginning in August 2021, only RealWear 12.1 will be supported HoloLens Improvements to stability of Model Tracking Improved display of models defined at large scales Bug fixes and minor improvements Experience Service Bug fixes and security improvements
View full tip
How to define Widget at runtime time and what is possible?  For example, the following problem: required is a button e.g. 'button-1' - widget to start a sequence. Now user want to create an 3D-Label that becomes visible after click the 'button-1' and  now for each sequence and step a the 3D-Label have to be visible as long as the sequence is played. The 3d label should display an information for the specific step and also should to have specific position. Unfortunately, it is not possible (using the supported functionality) to create widget on the fly - means create a new feature on run time where the widget was not defined in the design time. Theoretical with some more intensive work – it will be possible – we simple need to check what the UI is doing when you copy and paste widget  (but it is not easy ☹-  and it is not sure if this solution will be stable(if you will be able to implement 1:1 UI) and if it will work in later version -because PTC dev team could change some functionality – but will not change your code. For the most tasks it enough to use few 3d widgets (3Dlabels) the most are invisible and then switch the visibility on runtime and move them on the desired location. According request on address of this issue  , may be it is worth here to mention following statements of the PTC dev  :   .) Question: “Vuforia Studio 8.5.3.Is it possible to create 2D and 3D widgets from Java Script? Answer: If you mean to dynamically create/instatiate a widget and set its properties at runtime, no we have no such capability today. The simplest workaround is to pre-generate the widgets and manage their visibility at runtime. 2.) Question: Is it possible to create 2D widget dynamically by Java Script? Answer: Its fairly easy to have a couple of hidden widgets that are displayed and moved with a tap event. It might be possible to create some 2d widgets on the fly, but 3d widgets would be a bit harder as more of the unsupported api under the hood would be needed.   According to the statement of the PTC development team  - here the we will consider the possible workaround :. The following requirement: When the sequence 1 is played the labels 1, 2 and 3 have to be visible. When the sequence 2 is played the labels 4, 5 and 6 have to be visible. In all of these labels are only one word in it, so not a step description or something like this. Here is a sample table with coordinates for a better overview:   There is no a real reason to have 4,5,6 here. In this case we can use 1,2,3 again - also for step 2 but we could here change the position and will change the text content. In this case we need to have to define number of 3DLabel widgets which is equal to the maximum of used notes per step - and display and update only the necessary number of widget in particular step.   To demonstrate the workaround the following example was created and tested. This   example should show the suggestion above. It is not perfect but should demonstrate the general approach to achieve similar goal. The table with values is a json file- in the attached example is the file steps.json in the Project upload folder. Here example of values: {"1":{"3DLabel-1":{"visible":true,"text":"text Label1 Step 1", "x":0.0,"y":0.1,"z":0.0,"rx":0.0,"ry":0.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel1"}, "3DLabel-2":{"visible":true,"text":"text Label2 Step 1", "x":0.0,"y":0.2,"z":0.0,"rx":0.0,"ry":0.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel2"}, "3DLabel-3":{"visible":true,"text":"text Label3 Step 1", "x":0.0,"y":0.3,"z":0.0,"rx":0.0,"ry":0.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel3"}}, "2":{"3DLabel-1":{"visible":true,"text":"text Label1 Step 2", "x":0.0,"y":0.1,"z":0.1,"rx":0.0,"ry":10.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel2"}, "3DLabel-2":{"visible":false,"text":"text Label2 Step 2", "x":0.0,"y":0.2,"z":0.0,"rx":0.0,"ry":10.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel2"}, "3DLabel-3":{"visible":true,"text":"text Label3 Step 2", "x":0.0,"y":0.3,"z":0.1,"rx":0.0,"ry":10.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel2"}}, "3":{"3DLabel-1":{"visible":true,"text":"text Label1 Step 3", "x":0.0,"y":0.1,"z":0.0,"rx":0.0,"ry":20.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel3"}, .... "8":{"3DLabel-1":{"visible":true,"text":"text Label1 Step 8", "x":0.0,"y":0.1,"z":0.0,"rx":0.0,"ry":0.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel1"}, "3DLabel-2":{"visible":true,"text":"text Label2 Step 8", "x":0.0,"y":0.2,"z":0.0,"rx":0.0,"ry":0.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel2"}, "3DLabel-3":{"visible":true,"text":"text Label3 Step 8", "x":0.0,"y":0.3,"z":0.0,"rx":0.0,"ry":0.0,"rz":0.0,"scale":1.0,"class":"ptc-3DLabel3"}}}      The table contains the most possible values to set for 3DLabels. We can add other or omit values in the list. In generally we need only the values which should be changed but such list template which contains all values is better for editing. It should still work so far, the json syntax is correct First point is to load the list to a global variable from the project upload folder. Here a sample code:   $scope.jsonData_steps={}; //global $scope variable //================================== readSteps=function (jsonFile){ console.warn("**=>readSteps :: "+jsonFile); fetch(jsonFile) .then(response=>response.text()) .then(data=>{$scope.jsonData_steps=JSON.parse(data); console.warn( JSON.stringify($scope.jsonData_steps))}) .catch((wrong) => {console.log("problem in fetch: "); console.warn(wrong)}) } //================================== $scope.Init=function() { $timeout(readSteps('app/resources/Uploaded/'+stepsjson),200); } //================================================================================================= // $ionicView.afterEnter -> this event fires when 2d view was entered //================================================================================================= $scope.$on('$ionicView.afterEnter',function(){ console.log("$ionicView.afterEnter was called"); $scope.Init();}) //event: when 2d View loaded //=================================================================================================     further in the "stepstarted" event the code will set the values of the widget properties which are contained by the json object  with the same number as the started step number:     //================================================================================================= $scope.$on('stepstarted', function(evt, arg1, arg2, arg3) { var parsedArg3 = JSON.parse(arg3); console.log("stepstarted stepNumber="+parsedArg3.stepNumber + " nextStep="+parsedArg3.nextStep); $timeout(()=>{ $scope.setMutipleProps($scope.jsonData_steps[parsedArg3.stepNumber.toString()])},10) $scope.setWidgetProp('label-1', 'text',"STEP: "+ parsedArg3.stepNumber) $scope.$applyAsync(); }); //================================================================================================= //this function set multiply properties from a list //================================================================================================= $scope.setMutipleProps = function(obj){ Object.keys(obj).forEach(function (item) { for(var prop in obj[item]) { $scope.view.wdg[item][prop]=obj[item][prop]; //print the setting for debugging console.log("==>$scope.view.wdg["+item+"]["+prop+"]="+obj[item][prop] ) } }) $scope.$applyAsync(); }; ///=================================================================================================     Finally,  the project was  tested  and  it was working as expected:     The demo project is attached to this article.
View full tip
How to associate my image texture UV on my 3D Model Here the suggested   workflow is the following: 1.) we will create the CAD data in any CAD tools /   Creo Parametric or any AutoDesk , Catia, Solidwors and etc. / In generally when we prepare the model for the AR usage and there /in the CAD tool/ we will also assigned the texture to a model, component or particular surfaces. So means  the native CAD data will contain already the texture/'s before we will try to use it in Vuforia Studio 2.) So to use the data in Vuforia Studio we need to import it. The import tool is a part of studio and will convert the geometry . Internal Studio used the optimizer tool (here want to refer to the post: "Optimize PVZ before") So means that the native cad data is converted always to PTC light ware format pvz. According to rcp. setting it will  import also the textures or will not import them. So this is the most used way to use textures in Vuforia Studio.  Also UV setting are something what should be set in the CAD tool - e.g. in Creo Parametric:      3.) In case that we have a texture file  and want to assigned it to a model or modelItem  using some U V parameters in Vuforia Studio  this will make it more difficult. It is possible but you need to define an GLSL shader in the tmlText widget and assigned to the shader property. The glsl shader will used also the file refer in the texture property and could display it projected on the UV model geometry:     e.g. in Javascript;   $scope.app.shaderString="texture_test;scale f 2;moveX f 0;moveY f 0"; $rootScope.$on('modelLoaded', function() { $scope.view.wdg['modelItem-1']['texture'] = "app/resources/Uploaded/cvc.jpg?name=Texture0&edge=repeat"; $scope.setWidgetProp('modelItem-1', 'shader', $scope.app.shaderString); $scope.view.wdg['3DImage-1']['src'] = "app/resources/Uploaded/pinger_half.png?name=Texture0&edge=mirror"; $scope.setWidgetProp('3DImage-1', 'shader',$scope.app.shaderString); })     Here the pictures are created in project wher I used the following tmlText defintion. Please, pay attention that it is not a solution , but more only an example which display the general usage. If you need more to optimize the display you need to do some improvements - ,please, refer to some addtional links: https://wiki.delphigl.com/index.php/Tutorial_glsl2 https://viscircle.de/einsteigerguide-einfuehrung-in-glsl/ https://stackoverflow.com/questions/27646383/glsl-shader-for-texture-smoke-effect or lot of other links / key words glsl  fragmet vertex shader defintion, web.gl javascipt/   So in this example I used the following test shader code:     <script name="texture_test" type="x-shader/x-fragment"> precision mediump float; uniform sampler2D Texture0; uniform float scale; uniform float moveX; uniform float moveY; // determine varying parameters varying vec3 N; varying vec4 vertexCoord; // determine shader input parameters uniform vec4 surfaceColor; const vec3 lightPos = vec3(1.0, 2.2, 0.5); const vec4 ambientColor = vec4(0.3, 0.3, 0.3, 1.0); void main() { // calc the dot product and clamp based on light position // 0 -> 1 rather than -1 -> 1 // ensure everything is normalized vec3 lightDir = -(normalize(lightPos)); vec3 NN = normalize(N); // calculate the dot product of the light to the vertex normal float dProd = max(0.0, dot(NN, -lightDir)); { // calculate the color based on light-source and shadows on model vec2 TexCoord = vec2( vertexCoord )*scale; TexCoord.x=TexCoord.x+moveX; TexCoord.y=TexCoord.y+moveY; vec4 color = texture2D(Texture0, TexCoord) ; gl_FragColor = (ambientColor + vec4(dProd)) *color ;// surfaceColor; } } </script> <script name="texture_test" type="x-shader/x-vertex"> attribute vec3 vertexPosition; attribute vec3 vertexNormal; varying vec3 N; varying vec4 vertexCoord; uniform mat4 modelMatrix; uniform mat4 modelViewProjectionMatrix; void main() { vec4 vp = vec4(vertexPosition, 1.0); gl_Position = modelViewProjectionMatrix * vp; vertexCoord = modelMatrix*vp; // the surface normal vector N = vec3(normalize(modelMatrix* vec4(vertexNormal,0.0))); } </script>   The GLSL code should be added in the text area of the tmlText widget:     At the end I want to provide to this post  a sample project which demonstrate how to use the textures with shaders in Studio. Please, pay attention this is only an example which demonstrate the general principle. So far I now this way , works only on mobile devices. I did not get it work with the shader on the HoloLens. I tested the project in preview on Android and on IOS. On Android and in preview mode it work fine. On IOS it works fine for the ModelItem but not for the 3dImage- but I think there we need to downscale the value of the light intensity:   gl_FragColor = (ambientColor*lightscale + vec4(dProd)) *color ;// s project was attached : testShaderProperties-EXAMPLE.zip
View full tip
Experience Service Added Entra ID Configuration Examples An Entra ID SSO configuration example was added to the Help Center. For more information, see Microsoft Entra ID Configuration Example in the Experience Service and Admin Help Center. Added Okta SSO Configuration Example An Okta SSO configuration example was added to the Help Center. For more information, see Okta Configuration Example in the Experience Service and Admin Help Center. Bug Fixes See Bug Fixes for additional information on bugs resolved in this release
View full tip
Vuforia Studio ThingWorx 9.5 Support ThingWorx 9.5 is now supported in Vuforia Studio. New Observation for Stationary Objects Preset A new Observation for Stationary Objects preset is available for Advanced Views for objects that can be recognized from any angle when standing around the object, but not from below it. For more information, see Observation for Stationary Objects in the Vuforia Developer Library. Note: This new guide view replaces the 360 Dome guide view that was previously available. macOS Sonoma Support macOS Sonoma is now supported. Vuforia View RealWear HMT-1 Devices No Longer Supported Vuforia View is no longer supported on RealWear HMT-1 devices, as RealWear has announced that the HMT-1 devices are at end-of-life and will no longer receive firmware or security updates beyond v12.6. We encourage you to upgrade to RealWear’s Navigator series for continued device support from PTC. For more information, see RealWear’s RealWear HMT-1 and HMT-1Z1 End of Security Update support notice and Firmware Update and Support Policy. Bug Fixes See Bug Fixes for additional information on bugs resolved in this release
View full tip
Currently, we do not recommend using Vuforia Studio with Chrome 106.0.5249.91 or later and Microsoft Edge 106.0.1370.37 due to a major issue with Chromium; Google has been made aware of the issue. Until it is resolved, we recommend using older versions of Chrome or Microsoft Edge.   Vuforia Studio The Wayfinder widget is now out of beta and full access is available. Improvements to the Wayfinder widget include: A pop-up with information about the Wayfinder widget appears when the widget is added to an experience A new Looping property is available that returns a user to the first Waypoint in the array once the last Waypoint is reached Improved ribbon density Improved property names Default gaze vector is now 90 degrees from the surface that the Waypoint is mated to Improved text label design Vuforia View Target acquisition effect is available on all mobile platforms NOTE: The model recognition for Advanced Model Targets will be visualized by a snapping effect in the experience.  HoloLens 2: Wayfinder and Waypoints are now available for 3D eyewear experiences Experience Service There are no new features or updates for the 9.7.1 version of the Experience Service
View full tip
This post should provide more detailed steps additionally  to the posts ("How to extract the components with properties from a pvz file"[1.] and "How to use ThingView Widget from Navigate to display CAD Model/Viewables in custom mashup- Concept"[2])  This post should consider more detailed the steps for the extracting of viewables and also how to extract the sequence steps information from a .pvz / Creo Illustrate model for further usage in a Thingworx service. Following steps: 1.) Extracting the data from the Creo View Model ( Created from Creo Illustrate via publish to pvz functionality) As described in [1.] we required for the extraction of information a Creo View Toolkit.  A good choice will be the usage the Creo View  WebGL toolkit module.   A web toolkit program is called inside a html document ,where the javaScript Creo View WebGl Api is embedded. So, the most important logic could be called on the windows load function. The code below will initialize  the thingview library and  will open the pvz model file (value of variable CUR_MODELPATH in the code below  is set the complete model path):   ... window.onload = function() { ThingView.init("js/ptc/thingview", function() { // ThingView should only be initialised once per frame //---------------------------------- //send the modelname to server var xhr = new XMLHttpRequest(); xhr.open("POST", "RAY_LOG_FILE:", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { var json = JSON.parse(xhr.responseText); } }; //set the json modelname object var JSON_BOM_MODEL_OBJ = new Object; MODELNAME = CUR_MODELPATH.substring(CUR_MODELPATH.lastIndexOf("/") + 1) JSON_BOM_MODEL_OBJ.name = "BOMMODELNAME"; JSON_BOM_MODEL_OBJ.value = MODELNAME; xhr.send(JSON.stringify(JSON_BOM_MODEL_OBJ)) console.warn("sent BOMMODELNAME=" + MODELNAME) //finish the sending of the model_name //---------------------------------- console.log("Creo View WebGL Viewer is now initialised"); session = ThingView.CreateSession("CreoViewWebGLDiv"); //refers to the CreoViewWebGLDiv -> a div area in the html fileSource // which contains the code var xhttp = new XMLHttpRequest(); MODELNAME = CUR_MODELPATH.substring(CUR_MODELPATH.lastIndexOf("/") + 1) xhttp.open("POST", "RAY_JSON_VIEWABLE:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var js_obj = new Object; js_obj.name = "VIEWABLE"; js_obj.value = MODELNAME; var data = JSON.stringify(js_obj); xhttp.send(data); model = session.MakeModel(); ////==================LoadFromURL Callback model.LoadFromURLWithCallback(CUR_MODELPATH, true, true, false, function(success, isStructure, errorStack) { var illustrations = model.GetIllustrations(); for (var i = 0; i < illustrations.size(); i++) { console.log("Illistration name: " + illustrations.get(i).name); // seems illustrations.get(i).name == pviFile model.LoadIllustrationWithCallback(illustrations.get(i).name, function(success, pviFile, stepInfoVec) { if (success === true) { var hasAnimation = model.HasAnimation() var hasSequence = model.HasSequence() xhttp.open("POST", "RAY_JSON_VIEWABLE:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var js_obj = new Object; js_obj.name = pviFile; js_obj.value = pviFile; js_obj.type = "viewable"; js_obj.hasSequence = hasSequence; js_obj.hasAnimation = hasAnimation; var data = JSON.stringify(js_obj); xhttp.send(data); for (var ii = 0; ii < stepInfoVec.size(); ++ii) { xhttp.open("POST", "RAY_JSON_VIEWABLE_STEP:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var step_obj = new Object; console.log("step nr=" + ii); step_obj.viewablename = pviFile; step_obj.nr = ii; step_obj.name = stepInfoVec.get(ii).name; step_obj.description = stepInfoVec.get(ii).description; var data = JSON.stringify(step_obj); xhttp.send(data); //============================================= } } }) } ////============= setTimeout(function() { { xhttp.open("POST", "RAY_JSON_VIEWABLE:", true); xhttp.setRequestHeader("Content-Type", "application/json"); xhttp.onreadystatechange = function() { if (xhttp.readyState === 4 && xhttp.status === 200) { var json = JSON.parse(xhttp.responseText); } }; var js_obj = new Object; js_obj.name = "FINISHVIEWABLES"; var data = JSON.stringify(js_obj); xhttp.send(data); } }, 10000); }); ///model load from URL funciton ///////////// }); // ThingView.init( ) }; //window onload function   The program will generate 2 different json files and will send them to the http server. When the Creo View WegGl program is started (load  the html file from the http server)  - on the server side - in the node.js console  we can see the printing of the received data - example on the picture below:     The Creo View WebGl program will create on the server side  2 json files (this requires also handling of the received  data on the server side as allready mention in the post [1.]  ) For the data extraction I used in this example the PTC demo file (provided with the installation of Creo View Toolkit) : worldcar-brake-multi-figure.pvz,  worldcar-brake-multi-figure.pvz-viewableSteplist.json   [{"viewablename":"Sequence","nr":0,"name":"Sequence","description":""}, {"viewablename":"Sequence","nr":1,"name":"Step 1","description":"Remove spring clips"}, {"viewablename":"Sequence","nr":2,"name":"Step 2","description":"Release 4 bolts"}, {"viewablename":"Sequence","nr":3,"name":"Step 3","description":"Pull apart the calipers"}] worldcar-brake-multi-figure.pvz-viewablelist.json [{"name":"Figure 1","value":"Figure 1","type":"viewable","hasSequence":false,"hasAnimation":false}, {"name":"Sequence","value":"Sequence","type":"viewable","hasSequence":true,"hasAnimation":false}, {"name":"Parts List","value":"Parts List","type":"viewable","hasSequence":false,"hasAnimation":false}, {"name":"Sectioning","value":"Sectioning","type":"viewable","hasSequence":false,"hasAnimation":false}, {"name":"Translation","value":"Translation","type":"viewable","hasSequence":false,"hasAnimation":false}, {"name":"Animation","value":"Animation","type":"viewable","hasSequence":false,"hasAnimation":true}]   2.) Definition of a service in Thingworx for the returning of the Sequence Step List (see also "Service for creating of Bom - and Viewable Lists from json files"  [3]  )    Here the first Step is to define a general service which will will convert the JSON file from a file repository to an InfoTable using particular dataShape.  The json file will be taken from a  repository:   var params = { path: the_json_path /* STRING */ }; var Content = Things[the_Repository_Name].LoadJSON(params); var params1 = { infoTableName: undefined /* STRING */, dataShapeName: the_dataShape_name /* DATASHAPENAME */ }; // result: INFOTABLE var jsonTable = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params1); var result = DataShapes.ThingviewBomData.CreateValues(); for(i in Content.array){ jsonTable.AddRow(Content.array[i]); } result = jsonTable; //returns the InfoTable     The service has 3 Input parameters : the_json_path, the_dataShape_name and the_Repository_Name (all are String type)       This service could be called for any filerepository, containing any json files(it is not file specific) . Via the dataShape name we will specify the filed definitions.  We need to do this  for each specific json file. In this case we have to  create first manually a DataShape which is compatible to the Json Object.  For example when we start the service RayJsonToInfoTable:     And the dataShape what we need to define for  this particular example:       For the achieving  of the final goal -> the creation of the  Sequence Step List. We need to create a  another service where we can specify the arguments for DataShape and  repository name. Example:     So the input argumets are:  I.) the path to the json file and II.) the name of the sequence for which we want to see the steps.     I am not sure if we can omit the step , where we create a  dataShape for specific json - so some kind of  dynamic dataShape generation - because in such case  we need only to specify the json file without manual editing opreration.      
View full tip
Vuforia Studio New Page Size property for the 3D Document widget allows you to select automatic sizing based on common paper sizes Improvements to tooltips throughout the user interface to provide more details information Bug fixes Issues with occurrence path definitions have been resolved Model training processing issues for Advanced Model training have been resolved Sequence hiding issues in Preview mode have been resolved; the model is now properly hidden when configured correctly Issues with property values not being loaded to Vuforia Studio when the Experience Service is run as HTTP have been resolved Vuforia View Vuforia View is no longer supported on HoloLens (1st gen) devices. Support for HoloLens 2 devices will continue uninterrupted Bug Fixes HoloLens 2 Auto-focus issue resolved Issues with Creo Illustrate animations have been resolved Navigation issues and possible process problems when switching views have been resolved Guide views now appear correctly in new experiences that contain Area Targets Windows Auto-focus issue resolved Issue with app freezing when opening certain Gallery experiences has been resolved iOS Auto-focus issue resolved QR Code recognition issue that prevented users from opening experiences with long names has been resolved RealWear Auto-focus issue resolved Issue with Up and Down commands being unresponsive on Library page has been resolved Experience Service Studio Client ID is now configurable when installing an Experience Service with SSO authentication Ability to configure one instance of ThingWorx with multiple Experience Services Bug Fixes Experience Services configured to use SSO can now be validated in Vuforia Studio
View full tip
Vuforia Studio Ability to set the distance of the 3D Audio and 3D Video widgets that have the Tagalong property enabled New ways to move around the space in your Area Target on the 3D canvas using your keyboard Support for Windows 11 Bug fixes and minor improvements Vuforia View Support for Windows 11 Bug fixes and minor improvements Experience Service Bug fixes and minor improvements
View full tip
In this particular cases we have some sensors/devices which could be accessed via WLAN/ Web  and also  we need to scan /request the values of these sensors via rest API calls. For example from javascript code for simple REST API request the code   should looks like (used a test web page which provides demo response) :   //this code will work fetch('https://jsonplaceholder.typicode.com/todos/6') .then(response => response.json()) .then(json => {console.log(json); }) .catch(error =>{ console.error(error);}) };   ... but the same code will not work for http url   fetch('http://ip.jsontest.com/') .then(response => response.json()) .then(json => {console.log(json); }) .catch(error =>{ console.error(error);}) };   When I tested it - my observation was that https and http requests will work in Studio in preview mode.  But only the https request will work on both Android and IOS devices. The http fetch request will not work ...   This means trying to design a solution which will call javaScript on the Vuforia view where we will try to read data will not work / or at least  will not work  stable. Therefore,  a better  way  is  /also it is the supported way /- to get (to bind)  the sensors data via the External DATA panel:     To achieve this goal , we need: we need first to create a Thing with properties which could be displayed in the experience project. The next step is to read the sensors and update the properties. In case that we can see the sensors URLs from the thingworks instance / in this case we can use a thingworks service called by  a timer. The time  will call the service  in  particular interval  , so that the  service will  read then the  data from the sensors.     In the picuture above we need to define a service which will call a rest API to read the sensors. Here in the example to simulate the call we will read a timestamp from a postman-echo service. As the name say's it will return exact the same values what  was  send to it (but with different format - as JSON object) . So for example when we call in a web browser the following link:   http://postman-echo.com/time/object?timestamp=2018-6-9:8:8:4   this will return the following json object:   {"years":2018,"months":5,"date":1,"hours":9,"minutes":8,"seconds":8,"milliseconds":4}   In this  example we will create a service "testGetValue() which will call the echo service and will return the json respose as an InfoTable as output )   //URL_STRING="http://postman-echo.com/time/object?timestamp=2018-6-9:8:8:4" var year= 2010 +Math.floor((Math.random() * 10) + 1);//2011...2020 var month= Math.floor((Math.random() * 8) + 1);//1-9 var day= Math.floor((Math.random() * 18) + 10);//10-28 var hour= Math.floor((Math.random() * 24) );//1-24 var minute= Math.floor((Math.random() * 60) );//0-59 var second= Math.floor((Math.random() * 60) );//0-59 var msecond= Math.floor((Math.random() * 1000) );//0-999 //these values are only here specific to the web side not to have an error //calling the rest API var URL_STRING="http://postman-echo.com/time/object?timestamp="+year+"-0"+ month+"-"+day+":"+hour+":"+minute+":"+second+":"+msecond; var params = { proxyScheme: undefined /* STRING */, headers: undefined /* JSON */, ignoreSSLErrors: undefined /* BOOLEAN */, useNTLM: undefined /* BOOLEAN */, workstation: undefined /* STRING */, useProxy: undefined /* BOOLEAN */, withCookies: undefined /* BOOLEAN */, proxyHost: undefined /* STRING */, url: undefined /* STRING */, timeout: undefined /* NUMBER */, proxyPort: undefined /* INTEGER */, password: undefined /* STRING */, domain: "postman-echo.com" /* STRING */, username: undefined /* STRING */ }; params.url=URL_STRING; // result: JSON var json = Resources["ContentLoaderFunctions"].GetJSON(params); //var json_string= JSON.stringify(json); //var new_json = JSON.parse(json_string); var params1 = { infoTableName: "InfoTable", dataShapeName : "InoTableDataShape_Time1" }; var infotabletest = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params1); infotabletest.AddRow({years:json.years, months:json.months, date:json.date, hours:json.hours, minutes:json.minutes, seconds:json.seconds, milliseconds:json.milliseconds}); var result = infotabletest; //set now the value to the properties me.years=parseInt((infotabletest).getFirstRow().getValue('years')).toString(); me.months=parseInt((infotabletest).getFirstRow().getValue('months')).toString(); me.date=parseInt((infotabletest).getFirstRow().getValue('date')).toString(); me.hours=parseInt((infotabletest).getFirstRow().getValue('hours')).toString(); me.minutes=parseInt((infotabletest).getFirstRow().getValue('minutes')).toString(); me.seconds=parseInt((infotabletest).getFirstRow().getValue('seconds')).toString(); me.milliseconds=parseInt((infotabletest).getFirstRow().getValue('milliseconds')).toString(); //=================================================================   To be able to convert the json object to an infotable we need to define a datashape with the same fields -> corresponding to the json elements (here e.g  InoTableDataShape_Time1):         So every time when we call this service it will call the postman-echo web.side with some random data and will set the values of properties based on the received data  from the request. In this case the request returns the sent data (makes no really sense) but here is only important to demonstrate the principle how to call it. This should demonstrate how to request values from some edge devices (measurments) via REST API calls - supposing that the edge device supports  REST API call. (For example we can setup some Arduinos, Raspberry ,  ESP8266, etc...  as Web Service supporting REST API calls for reading of measurment values) Now we need to create a timer object  which will call call the service  for  an particular interval (here 1 sec /1000msec)  -> the used  service is here testGetValues() according the definition above.     this will update the values of the property and we can see the updated property  in Vuforia Studio.       But often the sensors URLs are not visible for the thingworx instance. In this case we can try to read the values of the sensors in the local network (some kind of intermediate service)  and then send the values to the thing properties using one of the methods described in the PTC guide “Choose a Connectivity Method ->Guidelines for selecting the optimal method for connecting to ThingWorx.” https://developer.thingworx.com/en/resources/guides/choosing-connectivity-method An  example for one alternative way you can fine in "Node.js Rest API example  how to display data from the local network in Vuforia Studio project?"  
View full tip
ThingWorx properties can be updated from a Vuforia Studio experience.    Below is a simple example: Create a test Thing and a test property for the Thing in ThingWorx :   Create a service for the Thing with text input parameter(Test) and add the below code to update the TestProperty value:   Click Done and Save the Thing In Vuforia Studio, Add a Text Input widget and a Button widget in 2D canvas Add the service of the Thing in the External data Panel Now, bind the Text property of the ‘Text Input’ widget to the Test Parameter of the service as shown below:   Bind the Click event of the Button widget to the Service to update the value of Thing property in ThingWorx   Test the experience by clicking Preview. Enter text in the Text Input widget and click the button. The Thing property should then be updated.      If you are creating a public experience, ensure that run time permissions for the es-public-access user have been assigned to the properties, events and services of the entity.  From ThingWorx composer, open the entity whose data must be accessed by a public experience Click the Permissions icon in the last column of the row containing the entity Click Run Time under Permissions Under All Properties, Events, Services, use the search box to find and add the es-public-access user Click green dot under the appropriate permissions columns   Click Save See the Vuforia Studio Help Center for more information on granting user permissions in ThingWorx for Vuforia Studio.  
View full tip
PDFs can be linked to experiences using a few methods. Below is an example of using the toggle widget or a toggle button to open and close a PDF within your experience.          Example of JavaScript code to add to Home.js file: $scope.toggleButton = function() { //if the toggle is pressed if ( $scope.view.wdg['toggleButton-1']['pressed']==true) { window.location='app/resources/Uploaded/%5BBD-Logbuch%5D20190208-20190310.pdf' console.log($scope.view.wdg['file-1']['url']) } //unpress the toggle button after 1,5 sec $timeout(function () { $scope.view.wdg['toggleButton-1']['pressed']=false;}, 1500); }      
View full tip
This is the third JavaScript quark in the series: it can be used to change a widget color by cycling through a given array of colors. You can find the second quark here.   Here's the code to copy & paste to your Home.js:   $scope.cycleColors = function(widget, colors, time, interval) {   let w = (widget.color !== undefined ? widget : $scope.view.wdg[widget]);   if (!w || w.color === undefined) { throw "Cannot color-cycle this widget"; }   let originalColor = w.color;   w.color = colors[0];   w.visible = true;   w.opacity = 1;    let nSteps = Math.ceil(Math.floor(time/interval) / colors.length) * colors.length;   return $interval(iterationCount => w.color = iterationCount === nSteps ? originalColor : colors[iterationCount % colors.length], interval, nSteps); } This JavaScript quark will make the widget color cycle through the colors provided in the colors array. The effect will last time milliseconds, and each color change will happen every interval milliseconds.   Invoke the function like this:   cycleColors(widget, colors, time, interval);   where widget is either the id of the widget (e.g. modelItem-1) or the widget itself (e.g. $scope.view.wdg['modelItem-1']), colors represents an array of colors (e.g. ["rgba(200,0,0,1)", "rgba(0,0,200,1)"]), time represents the total time in milliseconds it takes to execute this effect, and interval represents the amount of time in milliseconds between each color change.   Here's an example:   cycleColors("modelItem-1", ["rgba(200,0,0,1)", "rgba(0,200,0,1)", "rgba(0,0,200,1)"], 2000, 50); This example cycles the model item color through red, green and blue; the effect will last for 2 seconds with a color change every 50 ms.   Comments and suggestions are welcome.   -Alessio  
View full tip
Hi,   we can do many tricks with Javascript in Studio and most of the times it's just a matter of copying & pasting the right code.   I'd like all Studio users, not just coders, to benefit from this, and thought I could drop here a snippet to blink a widget.    I call this a quark - from the particle physics standard model - and not atom, because it's really a smaller building block than an atom    Blinking a widget can be useful, for example, if you are not using Creo Illustrate to create a sequence but still want to draw the user attention to some item in the scene.     Here's the Javascript code to copy & paste to your Home.js:  (to Javascript coders: I'm using modern Javascript syntax, don't be frightened by that )   $scope.blink = function(widget, times, interval) { let w = (widget.visible !== undefined ? widget : $scope.view.wdg[widget]); if (!w || w.visible === undefined) { throw "Cannot blink this widget"; } $interval(() => w.visible = !w.visible, interval, times); }    Invoke the function like this:   blink(widget, times, delay); where widget is either the id of the widget (e.g. modelItem-1) or the widget itself (e.g. $scope.view.wdg['modelItem-1']). The other two numbers are the number of times that you want visibility to change, and the amount of milliseconds between each visibility change.     Here follow some examples.   You want to blink the widget 4 times with a 300 ms interval (and leave the widget visible at the end): blink('modelItem-1', 2*4, 300);   You want to blink the widget 4 times with a 300 ms interval (and leave the widget not visible at the end): blink('modelItem-1', 2*4+1, 300);   You can comment and suggest additional quarks if you want.   Alessio  
View full tip
With release 1.9.1, pilot and free trial participants can auto-configure Vuforia Studio to make it easier to get up and running quickly.  The auto-configure process does the following:​ Configures the sample projects included with your Vuforia Studio installation so that when you publish those projects they are published to your experience service and can be viewed in Vuforia View using one of your ThingMarks Retrieves the Experience Service (ES) URL - can find at Project -> Configuration -> Info section. We are no longer sending the ES url through welcome email. Downloads your ThingMarks and makes them available on the My ThingMarks page inside Vuforia Studio so that you can view your ThingMarks and print them out In order to complete the auto-configuration process, users are first required to authenticate using their PTC Account credentials.  For participants in the Vuforia Studio Free Trial, this does not introduce any confusion since they use their PTC Account credentials for everything: accessing the Studio Portal, publishing experiences from Vuforia Studio, downloading experiences to Vuforia View and working in ThingWorx Composer.   However, for participants in the Vuforia Studio Pilot Program, this may introduce some confusion.  Unlike free trial participants, pilot participants have two sets of credentials: PTC Account credentials used to access the Studio Portal and Auto-Configure Vuforia Studio Experience Service credentials provided in their Pilot Program Welcome Email that are used to publish experiences from Vuforia Studio, view experiences in Vuforia View and access ThingWorx Composer The auto-configuration process requires users to authenticate using their PTC Account credentials.  Since the auto-configuration process occurs inside Vuforia Studio and pilot participants do not normally use their PTC Account credentials inside Vuforia Studio, this may cause some confusion.   Note   The users that received access to an experience service instance before February 17, 2017 is a participant in the pilot program Any user that received access to an experience service on or after February 17, 2017 is a participant in the free trial.  
View full tip
Vuforia Studio See Bug Fixes Vuforia View HoloLens: Vuforia View for HoloLens now users Vuforia Engine 10.8 Bug fixes and minor improvements Experience Service There are no new features or updates for the 9.6.0 version of the Experience Service
View full tip
With various Augmented Reality applications in PTC's product portfolio the technical aspects and use cases could leave you with some questions. Did you know that we do not only have a full blown Augmented Reality SDK but offer also the possibility for a easy to use integration with live sensor data coming in via ThingWorx?   This blog post hopefully clarifies some of the questions around what can be done with Vuforia SDK and Vuforia Studio.   Welcome to the real world   In the real world, or the "real reality" (sounds weird, but it's basically what you can see with your own eyes - no augmentation involved) there are various objects. These might look the same - or not. Just take the following example... that's what we perceive when looking at things around us:     These objects are recognized​ via shapes, contrasts (black & white) and whatever defines the actual form. ​Vuforia SDK ​is able to recognize those objects via it's built-in object recognition capabilities. However, there might be limits - depending on the use cases...   While buildings could be distinguished by their form, playing cards could be distinguished via their suits and nominations. The machines however, they all look the same, they probably all ​are​ the same.   Combining the real world with a virtual world   "Augmented Reality" will allow to enhance this physical object with virtual properties, e.g. overlay its CAD-Model or overlay some animations for a better gaming experience. Check out this video for the Genesis Augmented Reality Trading Card Game example.   Object Recognition allows to put actual names to what the (digital) eye can see:     Once the object is recognized and identified all kinds of virtual attributes can be added. Vuforia SDK allows to do this with e.g. Unity.   As all of the machines are basically the same... they look the same, come from the same manufacturer and behave the same, ​identification​ can only be done via a manual effort, e.g. selecting the actual machine manually within an app (via a menu etc.). This manual selection process will then map a generic form and shape of the machine to the actual physical machine you can see and touch just in front of you.   In an app this might be necessary if you can recognize the generic form of a playing card but forgot to implement the suit and nominations. In that case, either extend the recognition part, or choose a drop-down list when the card is identified to choose the actual​ card in front of you.   How do ThingMarks fit in?   Using the functionality of Vuforia SDK, Vuforia Studio combines the power of Vuforia (AR) with the power of ThingWorx (live sensor data / object information). In an industry environment I could select the correct machine I'm looking at. However, what's the identifier? It is probably written somewhere on the back of the machine with lots of other information, so I don't really know what to look for. Therefore I could be looking at any machine, but without the identifier I can not retrieve information for ​my​ machine.   Vuforia Studio uses ThingMarks​. They work similar to a QR-Code and allow for direct identification of individual machines. So instead of choosing manually in the app, the ThingMark automatically chooses the correct object and relates that ID to a Thing Entity in ThingWorx.     In above image, the ThingMark allows to a) identify we're looking at a machine and b) are looking at the specific machine A03 It's basic point and shoot. Scan the ThingMark with your mobile device and you're directly taken to this particular experience for this particular machine.   In this case, it's not the machine that defines our object's properties and shapes and contrasts and sizes etc. In this case, it's the ThingMark that's the object being recognized. That's quite a difference.   So now, in an additional step, we're using the power of Vuforia to identify individual machines by a ThingMark. Recognition is driven by the ThingMark's shape which includes an encoded object ID (the QR-code looking pattern).   How does ThingWorx fit in?   After recognizing the machine, ThingWorx studio provides the link between this specific object (or its instance) and the ThingWorx Thing Entity we've defined in Vuforia Studio.   This allows to retrieve individual properties, services, events, alerts etc. directly via ThingWorx. Those values are unique per object, not per shape!   So this allows to directly look at temperature, level and failure-indicator for the actual machine in front of us:     Bridging the gap   Vuforia Studio​ is used to bridge the gap between ​Vuforia ​and its Augmented Reality capabilites as well as ThingWorx ​and its Internet of Things (IoT) capabilities. Vuforia Studio uses parts of both applications, adds own functionality and defines its own product category: Connected Augmented Reality​     There are quite some components involved in this:     This can be split into two processes: developing and experiencing   Development   Create a new experience in VuforiaStudio, map the experience to the ThingMark ID, map the experience to a Thing Entity in ThingWorx. Publish the experience to the Experience Server. Done.   Experience   Scan the ThingMark with the Vuforia View app. Vuforia View will utilize Vuforia to recognize the ThingMark Vuforia View will load the data and the model(s) for this ThingMark from the Experience Server Vuforia View will automatically receive and update the experience you're viewing with live data from the ThingWorx platform Enjoy.   Resources   There are quite some videos, tutorial, best practices etc. available on how to develop and experience the world of Vuforia Studio. Check out ThingWorx Studio Resources: Getting Started Guides, Tutorials, Troubleshooting for the Article Hub and quite a lot of good stuff!   More information   To get more information visit the product pages at https://www.vuforia.com https://trial.studio.vuforia.com/   If you're looking for help, these might be of interest:   https://developer.vuforia.com/support for Vuforia SDK https://community.ptc.com/t5/Studio/bd-p/studio for Vuforia Studio https://community.ptc.com/t5/ThingWorx-Developers/bd-p/twxdevs for ThingWorx https://support.ptc.com/    What's next?   Get involved, create your own experience. It's fun, it's quite easy and well... it looks good, too!  
View full tip
If the experience project exists in Vuforia Studio Unpublish the project by hovering over the project and clicking the unpublish project Experiences icon . This action removes Experiences from the Experience Service. If the experience project does not exist in Vuforia Studio Using CURL Command Curl -u <username>:<password> -H "Content-Type: Application/JSON" -X "DELETE" https://<your-domain-name>/ExperienceService/content/projects/<projectname> username: Experience Service username password: Experience Service password your-domain-name: Experience Service domain projectname: Experience project name to be deleted Using REST call from Postman Select query method as 'DELETE' Enter the URL as https://​<your-domain-name>/ExperienceService/content/projects/<project-name> your-domain-name: Experience Service domain projectname: Experience project name to be deleted In Authorization menu Choose Authorization type as 'Basic Auth'. Add the user credentials and update request.  
View full tip
To reference a function on a voice command or gesture use  viewCtrl.myFunction() where "myFunction" is the name of your function.     Check out the Vuforia Studio Help Center for detailed instructions on creating a HoloLens experience using gestures.  
View full tip
Vuforia Studio Enhancements to userpick Event (iOS and Android only) The userpick event now contains geometric information that can be used to localize augmentations based on user interactions. For more information, see Geometric Information Mapping with the userpick Event. The response payload of the user pick event is added to the result “eventData” of the event listener $scope.$on(‘userpick’, function(event, targetName, targetType, eventData). Tracking Status API Now Available (iOS and Android only) Tracking status is now exposed via the Tracking API allowing you to build your own business logic linked to tracking status or tracking status changes. For more information, see Tracking Status API. Note: Tracking status is not available in preview. Multibyte Characters Now Fully Supported Multibyte characters are now supported in all of the following places: Display URLs Folder names Exported ZIP files The following enhancements were also made as part of this update: Experiences with only whitespace characters in the name will be renamed to untitled+<timestamp>. Whitespace characters at the very beginning or end of a project name will be removed. Project names must contain no more than 255 characters. Note: A known issue exists where renaming a project that has more than 255 characters results in a non-localized system message. Improvements to Model Rendering and Lighting Improvements were made to the rendering and lighting environment for 3D models in Vuforia Studio to be consistent with other PTC products such as Creo Parametric and Creo Illustrate. Modernized Architecture to Resolve AngularJS Vulnerabilities Modernized the architecture of the Vuforia Studio web editor to address and resolve AngularJS–related vulnerabilities. Note: Improvements to the runtime components for this issue remain in progress. ThingWorx 9.6 Now Supported ThingWorx 9.6 is now supported. Vuforia View Support for iOS/iPadOS 18.0 iOS/iPadOS 18.0 is now supported. Support for Android 15 Android 15 is now supported. Bug Fixes See Bug Fixes for additional information on bugs resolved in this release    
View full tip
Vuforia Studio A beta version of the new Wayfinder widget is now available! The Wayfinder widget allows you to place Waypoints that help lead users towards a specific part of a model or place in their environment. Before you can start trying out the Wayfinder widget, you'll need to enable the widget so that it is displayed in your Widget panel. The following Creo Illustrate sequence properties are now exposed in Vuforia View for HoloLens 2 devices when stepStarted and stepCompleted events are triggered: stepDescription and duration. Vuforia View Windows: Update Vuforia View to the latest version to resolve an issue with the app crashing when gallery experiences are opened. Experience Service There are no new features or updates for the 9.5.0 version of the Experience Service.
View full tip
Announcements