Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X
Hi,
I would like to ask the community if there is a way to orient a 3D arrow following the direction of the camera.
I mean, I have already obtained the eyepos, eyedir & eyeup values. I know how to use eyepos, but I don't know how to use eyedir & eyeup values in order to give an arrow the right direction.
Currently, what I have built is a test project with 2 views:
1) a view used from a mobile device that every second send to Thingworx eyepos values.
2) a view used in preview mode on a laptop that gets the eyepos values from Thingworx and gives these values to a 3D moving gauge, simulating the position of the mobile device in the area.
But this 3D gauge is in billboard mode, so it's always showing his main face.
I would like to transform this billboard gauge into a rotating arrow pointing the direction of the camera.
Any ideas?
Hi @aletenti2 ,
I think this is only a problem of calculation when you have aready the position of the device and the eye vector from the tracking event.
So when you have an arrow which is directly aligned with the view then possible you do not have from this a more value , because you will see only the tail of it - so some circle on the screen. Therefore possibly it will be better to have the arrow alligned with the xz plane - so this means to rotate around the Y axis in view direction and possibly to adapt the height of the arrow part in Y direction.
My approach here is simple. I will set the position in view direction (adding the eye position to the eye direction vector with scale) and will rotate around Y something like this:
//// define camera tracking Event
tml3dRenderer.setupTrackingEventsCommand (function(target,eyepos,eyedir,eyeup) {
$scope.eye_dir[0] = eyedir[0].toFixed(2);
$scope.eye_dir[1] = eyedir[1].toFixed(2);
$scope.eye_dir[2] = eyedir[2].toFixed(2);
//model-2
var scale=$scope.app.params.distScale;
$scope.setWidgetProp('model-2', 'x', ( eyepos[0]+eyedir[0]*scale));
$scope.setWidgetProp('model-2', 'y', ( eyepos[1]+eyedir[1]*scale));
$scope.setWidgetProp('model-2', 'z', ( eyepos[2]+eyedir[2]*scale));
let vecDirXZ=[]
vecDirXZ[0]=eyedir[0]
vecDirXZ[1]=0.0
vecDirXZ[2]=eyedir[2]
vecDirXZ=$scope.vec_normilize(vecDirXZ)
vecDirZ=[0.0,0.0,-1.0]
let dotP1= $scope.dot_product(vecDirXZ,vecDirZ)
console.log("dotP1=",dotP1)
$scope.setWidgetProp('label-1', 'text',"dotP1="+String(dotP1.toFixed(3)))
let angleY=0
if ( vecDirXZ[0] < 0.0 )
angleY= 180*Math.acos(dotP1) / Math.PI;
else
angleY= 0- 180*Math.acos(dotP1) / Math.PI;
//--------------
$scope.setWidgetProp('model-2', 'ry',angleY)
$scope.$applyAsync()
})
////////////////////////////////////////////////////
where the used math function (some math basics are defined as:
////////////////////////////////////////////////////////////////////////
$scope.dot_product=function(ary1, ary2) {
if (ary1.length != ary2.length)
throw "can't find dot product: arrays have different lengths";
var dotprod = 0;
for (var i = 0; i < ary1.length; i++)
dotprod += ary1[i] * ary2[i];
return dotprod;
};
///////////////////////////////////////////////////////////////////////////////////////////////
/// the length of a vector
$scope.vec_len=function(ary1) {
var len = 0.0;
for (var i = 0; i < ary1.length; i++)
len += Math.pow(ary1[i],2);
return Math.sqrt(len);
};
///////////////////////////////////////////////////////////////////////////////////////////////
$scope.vec_normilize=function(ary1) {
ret=[];
var len=$scope.vec_len(ary1);
for (var i = 0; i < ary1.length; i++)
ret[i]=ary1[i]/len;
return ret;
};
///////////////////////////////////////////////////////////////////////////////////////////////
Then tested and have this behavior on IOS - IPad device:
Hello Roland, could you please share the whole project? I think it's a piece of code and something is missing.
Thanks!
Hi @aletenti2,
thanks for the feedback. There is no much more code - only the code what will call the definition on start event. But, yes there is not problem to share the project where I tested this . Actually I forgotten to share to the last post , because this was only a project created with the goal to test this problem. So hope that it is helpful - attached the project now.