Community Tip - Stay updated on what is happening on the PTC Community by subscribing to PTC Community Announcements. X
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?
Solved! Go to Solution.
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.
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 :
$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
@sdidier ,
Thanks for your reply. The solution didnt actually fix my issue, but did give me some insights in direction i want to go.
thanks for your reply. In my case the cad is already defined and i need to reuse it.
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.