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

Community Tip - Help us improve the PTC Community by taking this short Community Survey! X

how to add object(s) dynamically on press of a button in an experience?

Vatsal
12-Amethyst

how to add object(s) dynamically on press of a button in an experience?

I am working on a use case where i need to insert a 3d object into the experience dynamically on click of a button. Same 3d object needs to added in the experience when the button is pressed multiple time. Is there any way to get this done?

ACCEPTED SOLUTION

Accepted Solutions
Vatsal
12-Amethyst
(To:Vatsal)

Here is the solution i came up with. Its kind of a workaround for requirement i had.

I have done this to dynamically add upto 5 objects in the execution.

1. Add 3dmodel widget randomly in the experience, and uncheck the visibility flag. do not add any resource to the widget

2. Add desired resource(.pvz file) to the first widget (model-1).

3. Add a 2d button in the experience and call a javascript function. Below is the js function developed.

 

//get camera coordinates
tml3dRenderer.setupTrackingEventsCommand (function(target,eyepos,eyedir,eyeup) {
  // set values to a applicaiton parameter as string
  $scope.app.params['eyepos']="eyepos=("+eyepos[0].toFixed(2)+","+eyepos[1].toFixed(2)+","+eyepos[2].toFixed(2)+")";
  $scope.app.params['eyedir']="eyedir=("+eyedir[0].toFixed(2)+","+eyedir[1].toFixed(2)+","+eyedir[2].toFixed(2)+")";
  $scope.app.params['eyeup'] ="eyeup =("+ eyeup[0].toFixed(2)+","+ eyeup[1].toFixed(2)+","+ eyeup[2].toFixed(2)+")";
},undefined);

// function which is called by button 
$scope.placeNewObject=function(){
  
  //get resource value of first model
  var resourceValue = $scope.view.wdg['model-1']['src'];
 
  //this is being performed for maximum of 5 models
  var i;
  for(i=1; i<=5; i++){
    var modelName = "model-"+i;
    if( !$scope.view.wdg[modelName]['visible']){	 //check which model is visible
      $scope.view.wdg[modelName]['src'] = resourceValue;
      $scope.view.wdg[modelName]['visible'] = true;
      var pos = $scope.app.params['eyepos'];
      var dir = $scope.app.params['eyedir'];
      var posSplit = pos.slice(8,22);
      var posArray = posSplit.split(',');
      var dirSplit = dir.slice(8,22);
      var dirArray = dirSplit.split(',');
      $scope.view.wdg['3DLabel-1']['text']="modelName: "+modelName;
      //$scope.view.wdg['3DLabel-2']['text']="z: pos[3]"+posArray[2]+", dir[3]"+dirArray[2]+", p+d:"+(posArray[2]+dirArray[2]);
      //$scope.view.wdg['3DLabel-3']['text']=posArray+"::"+dirArray;
      //set the position of the widget
      $scope.setWidgetProp(modelName,  'x', ((+posArray[0])+(+dirArray[0])).toFixed(2));
      $scope.setWidgetProp(modelName,  'y', 0 );
      $scope.setWidgetProp(modelName,  'z', ( (+posArray[2])+(+dirArray[2])).toFixed(2));
      
      //break the for loop
      break;
    }
  }
};

 What does the code execute on the js function call:

1. Get the camera coordinates, in order to determine where to place the new object.

2. get the model object which is invisible (model-2).

3. get the resource of 1st model and assign to the invisible model(model-2).

4. set the model-2 visible.

5. move it to the location of the camera coordinates that we got in step 1.

 

I would appreciate if any one in the community can help me optimize or make this solution more flexible. 

 

View solution in original post

5 REPLIES 5
sdidier
17-Peridot
(To:Vatsal)

Hello Vatsal,

 

A solution can be to add all models in Uploaded folder and load them when it is needed.

In this thread, we have an example with Sequences. It should be similar with 3D Models.

https://community.ptc.com/t5/Vuforia-Studio/how-to-change-model-sequence/m-p/545186

 

A quick and small snippet example with a Select Widget to select the 3D Model to display :

 

  1. In Home View, add a Parameter named model
  2. Add a Select Widget named select-1
  3. Do a binding between Select Widget and Parameter, to populate the list
  4. Add a Model named model-1
  5. In Home.js, add this Javascript function :

 

$scope.setMdlSource = function() {
 $scope.view.wdg['model-1']['src'] = $scope.view.wdg['select-1']['value'];
}

 

     5. In Select Widget, in Event trigger Value Changed, click js button

     6. Add this javascript code :

 

setMdlSource();

 

     7. In Values property, populate the paths of 3D models, we will use a custom javascript function to add in Home.js  : 

$scope.populateModelList = function() {

  $scope.app.params.model = [
  {
    display: "Truck",
    value: "app/resources/Uploaded/Assembly.pvz"
  },
  {
    display: "F1",
    value: "app/resources/Uploaded/F1 car.pvz"
  }
  ];
}

$scope.populateModelList();

           When opening the View, populateModelList is ran.

           So, Select Widget is populated with expected values.

           In  populateModelList function, we have the value displayed in Select Widget and the value returned by the item selected.

            Here, it is the value returned is the path to a 3D model.

  

Best regards,

Samuel

Vatsal
12-Amethyst
(To:sdidier)

@sdidier ,

Thanks for your reply. The solution didnt actually fix my issue, but did give me some insights in direction i want to go.

Hello @Vatsal 

Is there, may be , the problem that the model is not inside the experience (e.g. project Upload  folder: "app/resources/Uploaded/model.pvz" ) and need to be added dynamically form anywhere outside  e.g. TWX repository or web location? Otherwise we can follow the answer from @sdidier 

@RolandRaytchev ,

thanks for your reply. In my case the cad is already defined and i need to reuse it.

Vatsal
12-Amethyst
(To:Vatsal)

Here is the solution i came up with. Its kind of a workaround for requirement i had.

I have done this to dynamically add upto 5 objects in the execution.

1. Add 3dmodel widget randomly in the experience, and uncheck the visibility flag. do not add any resource to the widget

2. Add desired resource(.pvz file) to the first widget (model-1).

3. Add a 2d button in the experience and call a javascript function. Below is the js function developed.

 

//get camera coordinates
tml3dRenderer.setupTrackingEventsCommand (function(target,eyepos,eyedir,eyeup) {
  // set values to a applicaiton parameter as string
  $scope.app.params['eyepos']="eyepos=("+eyepos[0].toFixed(2)+","+eyepos[1].toFixed(2)+","+eyepos[2].toFixed(2)+")";
  $scope.app.params['eyedir']="eyedir=("+eyedir[0].toFixed(2)+","+eyedir[1].toFixed(2)+","+eyedir[2].toFixed(2)+")";
  $scope.app.params['eyeup'] ="eyeup =("+ eyeup[0].toFixed(2)+","+ eyeup[1].toFixed(2)+","+ eyeup[2].toFixed(2)+")";
},undefined);

// function which is called by button 
$scope.placeNewObject=function(){
  
  //get resource value of first model
  var resourceValue = $scope.view.wdg['model-1']['src'];
 
  //this is being performed for maximum of 5 models
  var i;
  for(i=1; i<=5; i++){
    var modelName = "model-"+i;
    if( !$scope.view.wdg[modelName]['visible']){	 //check which model is visible
      $scope.view.wdg[modelName]['src'] = resourceValue;
      $scope.view.wdg[modelName]['visible'] = true;
      var pos = $scope.app.params['eyepos'];
      var dir = $scope.app.params['eyedir'];
      var posSplit = pos.slice(8,22);
      var posArray = posSplit.split(',');
      var dirSplit = dir.slice(8,22);
      var dirArray = dirSplit.split(',');
      $scope.view.wdg['3DLabel-1']['text']="modelName: "+modelName;
      //$scope.view.wdg['3DLabel-2']['text']="z: pos[3]"+posArray[2]+", dir[3]"+dirArray[2]+", p+d:"+(posArray[2]+dirArray[2]);
      //$scope.view.wdg['3DLabel-3']['text']=posArray+"::"+dirArray;
      //set the position of the widget
      $scope.setWidgetProp(modelName,  'x', ((+posArray[0])+(+dirArray[0])).toFixed(2));
      $scope.setWidgetProp(modelName,  'y', 0 );
      $scope.setWidgetProp(modelName,  'z', ( (+posArray[2])+(+dirArray[2])).toFixed(2));
      
      //break the for loop
      break;
    }
  }
};

 What does the code execute on the js function call:

1. Get the camera coordinates, in order to determine where to place the new object.

2. get the model object which is invisible (model-2).

3. get the resource of 1st model and assign to the invisible model(model-2).

4. set the model-2 visible.

5. move it to the location of the camera coordinates that we got in step 1.

 

I would appreciate if any one in the community can help me optimize or make this solution more flexible. 

 

Announcements

Top Tags