Community Tip - New to the community? Learn how to post a question and get help from PTC and industry experts! X
Dear forum users,
I would like to implement an use case, but I am not sure if it is possible the way I imagine.
I want to set an unknown number of waypoints within the experience. In other words I want to include a 3D model, which can be multiplied within the experience by pressing a button. Every copy of the 3D model should be manipulable regarding its xyz-position.
My research has shown that 3D widgets can not be created during runtime, is that right?
It think it is a similar use case like that one: https://community.ptc.com/t5/Vuforia-Studio/how-to-add-object-s-dynamically-on-press-of-a-button-in-an/m-p/637723#M7180
but the solution is not satisfying, since creating a fixed number of models in advance is not practical for me.
I would be very happy if someone could answer me, if something like I imagine is even possible?
I am greatful for every hint!
All the best,
Katrin.
Hi Katrin,
lets break your use case down to single functionalities.
Manipulation xyz:
Using spatial tracking this is possible: Scaling, rotating around Y, moving along Z and X (on ground). To my knowledge this is only applicable on one object.
Using sliders: Scaling each axis separately or combined, rotating around every axis, moving along every axis. You can apply this on different object types (model, picture, ...) and by using an iterator in your js you can skip through objects.
Multiplying objects:
AFAIK you can't duplicate models via runtime, but you could load a fix number into your view and make them all invisible. By clicking on a next bottom, one object gets visible after another.
Other possibility is, to have 3 objects in your view, have two of them visible. The invisible one will move to the next waypoint.
If the positions must be editable and within the experience and be stored permanently, you could use thingworx or create a data bank.
I hope I understood your use case the right way. It can be a bit tricky to find out, what the final result shall be.
Cheers,
Whity
Dear Whity,
thank you very much for your detailed reply!
I managed to program the xyz-manipulation to my satisfaction. With pressing a x-, y- or z-button the 3d-models can be moved into the associated direction step by step. The incremets per button-stroke are adjustable via a slider.
And thank you for the explanation regarding the duplication of 3D-models. Apparently it just does not work during runtime. Seems like I am stuck with a fixed number of objects. But it helps to know what's possible and what not!
Again thank you.
All the best,
Katrin.
If you satisfy with solution can you please make it as accepted solution , so that it is helpfull to all users whos seeking for solution.
You can use this function from tml3dRenderer:
tml3dRenderer.addPVS: (
trackerName: string,
id: string,
src: string,
cull: unknown,
parent: unknown,
successCallback: () => void,
errorCallback: (err) => void
) => void;
An example:
tml3dRenderer.addPVS('tracker1', 'model-1', '/app/resources/Uploaded/car1.pvz', undefined, undefined, () => {
console.log(`tml3dRenderer.addPVS:: added new model`);
}, (err) => {
console.log(`tml3dRenderer.addPVS:: failed to add new model: ${JSON.stringify(err)}`);
});
Thanks Pawelek, this is great! We can also use this to dynamically create buttons. Unfortunately I cannot delete them afterwards, only hide them. Does anybody know how to achieve this?
Delete was never implemented. Best solution for now is to hide what you no longer need; next time your experience runs, simply don't create the deleted item.
Could you please show it via graphical representation? i have added this code in js but could not proceed further.
Awaiting your reply, Thanks in advance.
Hi @ppandarkar-2 ,
tested this example and it works fine / in preview and IOS where I tested it/
So following 3D view with 3 buttons, one 3d Container and one space target (but also with thingmark should work)
Then defined the following code
// in TestDyn3dModel.js
var object3DNames=[];
$scope.app.testCoffe= function() {
tml3dRenderer.addPVS('tracker1', 'model-coffe', 'app/resources/Uploaded/Coffee Maker Model_High.pvz', undefined, undefined, () => {
object3DNames.push('model-coffe')
console.log(`tml3dRenderer.addPVS:: added new model`);
}, (err) => {
console.log(`tml3dRenderer.addPVS:: failed to add new model: ${JSON.stringify(err)}`);
});
}
$scope.app.testEngine= function() {
tml3dRenderer.addPVS('tracker1', 'model-engine', 'app/resources/Uploaded/engine_test_exp-div-speed.pvz', undefined, undefined, () => {
object3DNames.push('model-engine')
console.log(`tml3dRenderer.addPVS:: added new model`);
}, (err) => {
console.log(`tml3dRenderer.addPVS:: failed to add new model: ${JSON.stringify(err)}`);
});
}
//some tests
$scope.Test3DObjects = function (){
let count =0;
if(object3DNames.length>0) {
for(var i=0; i<object3DNames.length; i++) {
if( isPreview())
{
tml3dRenderer.GetObject(object3DNames[i]).GetWidget().SetPosition(parseFloat(1.1*(i+0.2)),0.0,0.0);
tml3dRenderer.GetObject(object3DNames[i]).GetWidget().SetOrientation(0.0,parseFloat(45.0*(i+1)),0.0);
}
else {
try{ tml3dRenderer.setTranslation(object3DNames[i].trim(),1.0*(i+0.2),0.0,0.0);} catch(e){if(DEBUG)console.error(e)}
try{ tml3dRenderer.setRotation(object3DNames[i].trim(),0.0,45.0*(i+1),0.0);} catch(e){if(DEBUG)console.error(e)}
}
$scope.$applyAsync()
} } }
//====================================
//======================================
isPreview = function() {
if(window.twx.app.isPreview()) // is in Preview
return true;
return false; }
//======================================
isIOS=function() {
if(!window.twx.app.isPreview()) // is not in Preview
if(ionic.Platform.isIOS()) //and is NOT called on IOS = means Android mode detected
return true;
return false; }
//======================================
isAndroid=function() {
if(!window.twx.app.isPreview()) // is not in Preview
if(/android/i.test(navigator.userAgent || navigator.vendor || window.opera) ) // is Android
return true;
return false; }
//======================================
and tested in preview so was working fine , no problem: