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

Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X

Water flow visible after a time

DenGrz
8-Gravel

Water flow visible after a time

Hello,

 

The following js-code shows a water flow. It was also made with the HTML function.

 

$timeout(function() {
//$scope.setShader();
}, 1500);


$scope.setShader = function() {

$scope.view.wdg['3DImage-2']['shader'] = "textMove; time f 0.3";
$scope.view.wdg['3DImage-2']['src'] = "app/resources/Uploaded/Kalt_Pfeil.png?edge=repeat";

 

 

$scope.val=0;
$rootScope.$on('modelLoaded', function() {

$scope.setShader();
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.view.wdg['3DImage-2']['shader'] = "textMove; time f " +$scope.val/-50 + ";"
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250)

 

 

 And this code to visible the flow by click on a button:

 

$scope.buttonClick12 = function()
{
if ($scope.view.wdg['3DImage-2']['visible'] == true)
$scope.view.wdg['3DImage-2']['visible'] = false;
else
$scope.view.wdg['3DImage-2']['visible'] = true;

 

 

Now i want to do this like i click on the button the flow is visible first after for example 5 sec.

Then the flow is for example 3 sec visible and then automatically unvisible.

 

 

Is there any way to do this so?

Your help will be highly appreciated.

Thanks in advance.

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @DenGrz ,

I tested it now more detailed. There are some mistakes in my code , sorry. now it is working in the following code:

 

 

$rootScope.$on('modelLoaded',function(){
  $scope.setWidgetProp('3DImage-1','src',  "app/resources/Uploaded/cvc.jpg?edge=repeat");
  $scope.setWidgetProp('3DImage-1','shader',  "textMove; time f " +$scope.val);
  $scope.$applyAsync()
})
////////////
$scope.app.setShader= function(widgetName,delay,duration)
{
var calldelay =3000; //3 seconds
var  callduration=10000;//10secs
var jumpInterval=10;
  
 if(delay !=undefined)    calldelay    = delay;
 if(duration !=undefined) callduration = duration;
  
$timeout( () => {
  
  $interval(function() { 
    if($scope.val >50) $scope.val =0
    else $scope.val +=1
    $scope.setWidgetProp(widgetName,'shader',  "textMove; time f " +$scope.val/100);
    console.info( "textMove; time f " +$scope.val/100 + ";")
    //this console print is a bad idea to have it on run time - only for testing
  
  }, jumpInterval, callduration/jumpInterval)},calldelay);

$timeout( () => {$scope.setWidgetProp(widgetName,'shader',"Default")},calldelay+callduration);
};

 

 

Following points:

- the shader float parameter time is actually  a moving in x direction ! for better reading of the code we have to pay attention when we use the name- but of course for the functionality is not so relevant.  If you require a parameter based on time you can use the tick parameter which is passed to the shader. You need to use the uniform float definition in the frame shader.

-of course, such shader to work depends on the picture size / uv texture coordinates. Therefore the function setShader should be updated according the used picture after some tests.

 

 

I attached a demo project where I used an other similar shader mention in the post :How to associate my image texture UV on my 3D Model

The project contains only one button for testing:

2020-05-08_12-10-27.gif

View solution in original post

4 REPLIES 4

I think the mention shader is simple moving a  picture (showing water) in particular direction and has not really  a water flow shader / only  apparitional a picture which has a water texture and it will be moved form A to B with specific speed  - parameter f= 0.3

I think with an appropriate water picture we can the shader mention in the article:

https://community.ptc.com/t5/Vuforia-Studio-and-Chalk-Tech/How-to-associate-my-image-texture-UV-on-my-3D-Model/ta-p/659754

For a real water flow you can check this one:

https://threejs.org/examples/webgl_shaders_ocean.html

OK , to be able to  understand what you shader is doing I need the definition of the tmlText widget. But… so far, I see the description it is not your question…. The shader seems to work and you want to call it on click for button

So for this simple define a function :

 

 

$scope.app.myButtonFunction= function()
{
//here you code 
};

 

 

 

And then in the click event of the button write the JavaScript  app.myButtonFunction();

To the question how to start it with 3 seconds delay , then playing for 10 seconds and stopping it . Your need the following function definition:

 

 

 

$scope.app.myButtonFunction= function()
{
var calldelay =3000; //3 seconds
var  callduration=10000;//5secs
$timeout( () => {
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.setWidgetProp('3DImage-2','shader', = "textMove; time f " +$scope.val/-50);
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250, callduration/250)},calldelay);
// reset the shader after 10 secs
$timeout( () => {$scope.setWidgetProp('3DImage-2','shader',"")},callduration);

};

 

I did not tested the code above but if it does not work then, please,  let me know .

 

 

Hi @RolandRaytchev ,

 

i tested it but unfortunately it not working.

The defenition of the tmlText widget i use is:

 

 

 

<script name="textMove" type="x-shader/x-vertex">
attribute vec4 vertexPosition;
attribute vec2 vertexTexCoord;

varying vec2 texcoord;

uniform mat4 modelViewProjectionMatrix;
void main() {
gl_Position=vec4(modelViewProjectionMatrix * vertexPosition);
texcoord = vertexTexCoord ;
}
</script>

<script name="textMove" type="x-shader/x-fragment">
precision mediump float;
const float PI=3.1415926;
varying vec2 texcoord;

// user-provided parameters ---------------------------------
// usage : you can specify shader=image-pinger and it will use the defaults of rings=1,direction=1,rgb=0,1,0,rate=1 (green pulse running outwards)
// you can also specify specific parameters e.g. shader=image-pinger;rate f 10;r f 1;direction f -1 (=red rings, running inwards)

uniform float time;

// system provided values ------------------------------------
uniform sampler2D texSampler2D;
uniform vec4 surfaceColor;

void main() {

// generate a rolling sin wave - velocity (speed, direction) are specified by user

gl_FragColor = texture2D(texSampler2D,vec2(texcoord.x-time ,texcoord.y));
}
</script>

 

 

 

The Js-Code looks like so now:

 

 

 

$scope.app.myButtonFunction = function()
{

$timeout(function() {
//$scope.setShader();
}, 1500);


$scope.setShader = function() {

$scope.view.wdg['3DImage-1']['shader'] = "textMove; time f 0.3";
$scope.view.wdg['3DImage-1']['src'] = "app/resources/Uploaded/Kalt_Pfeil.png?edge=repeat";
}


$scope.val=0;
$rootScope.$on('modelLoaded', function() {

$scope.setShader();
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.view.wdg['3DImage-1']['shader'] = "textMove; time f " +$scope.val/-50 + ";"
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250)
})

$scope.buttonClick1 = function()
{
if ($scope.view.wdg['3DImage-1']['visible'] == true)
$scope.view.wdg['3DImage-1']['visible'] = false;
else
$scope.view.wdg['3DImage-1']['visible'] = true;

}

};


$scope.app.myButtonFunction = function()
{
var calldelay =3000; //3 seconds
var callduration=10000;//5secs
$timeout( () => {
$interval(function() {
if($scope.val >50) $scope.val =0
else $scope.val +=1
$scope.setWidgetProp['3DImage-1']['shader'] = "textMove; time f 0,3" +$scope.val/-50;
console.info( "textMove; time f " +$scope.val/100 + ";")
}, 250, callduration/250)},calldelay);
// reset the shader after 10 secs
$timeout( () => {$scope.setWidgetProp('3DImage-1','shader',"")},callduration);

};

 

Where can my mistake be?

Thanks in advance.

Hi @DenGrz ,

I tested it now more detailed. There are some mistakes in my code , sorry. now it is working in the following code:

 

 

$rootScope.$on('modelLoaded',function(){
  $scope.setWidgetProp('3DImage-1','src',  "app/resources/Uploaded/cvc.jpg?edge=repeat");
  $scope.setWidgetProp('3DImage-1','shader',  "textMove; time f " +$scope.val);
  $scope.$applyAsync()
})
////////////
$scope.app.setShader= function(widgetName,delay,duration)
{
var calldelay =3000; //3 seconds
var  callduration=10000;//10secs
var jumpInterval=10;
  
 if(delay !=undefined)    calldelay    = delay;
 if(duration !=undefined) callduration = duration;
  
$timeout( () => {
  
  $interval(function() { 
    if($scope.val >50) $scope.val =0
    else $scope.val +=1
    $scope.setWidgetProp(widgetName,'shader',  "textMove; time f " +$scope.val/100);
    console.info( "textMove; time f " +$scope.val/100 + ";")
    //this console print is a bad idea to have it on run time - only for testing
  
  }, jumpInterval, callduration/jumpInterval)},calldelay);

$timeout( () => {$scope.setWidgetProp(widgetName,'shader',"Default")},calldelay+callduration);
};

 

 

Following points:

- the shader float parameter time is actually  a moving in x direction ! for better reading of the code we have to pay attention when we use the name- but of course for the functionality is not so relevant.  If you require a parameter based on time you can use the tick parameter which is passed to the shader. You need to use the uniform float definition in the frame shader.

-of course, such shader to work depends on the picture size / uv texture coordinates. Therefore the function setShader should be updated according the used picture after some tests.

 

 

I attached a demo project where I used an other similar shader mention in the post :How to associate my image texture UV on my 3D Model

The project contains only one button for testing:

2020-05-08_12-10-27.gif

Hi @RolandRaytchev ,

 

yes i tested it and it works perfectly.

Tanks a lot.

Top Tags