Animate the PI = 4 experiment
+2
Vexman
Cr6
6 posters
Page 2 of 8
Page 2 of 8 • 1, 2, 3, 4, 5, 6, 7, 8
Re: Animate the PI = 4 experiment
.
My ulterior motive has always been to get Nevyn to post the final PI=4 experiment at his site *. Obviously he can do the job perfectly well on his own. As a civil engineer I’ve worked on many base level projects, large or small, as lead or member. I’ll point out that a final product created through a team approach to review and development can greatly improve the product’s quality. I present myself as a hard ass editor or semi-skilled enthusiastic free labor Nevyn may direct as he chooses.
Nevyn, in addition to the tubular track changes, I created the last animation of the curved ball’s z-axis rotation and so the animation has reached its initial/final draft. Sorry, that last animation doesn’t look right and will require your attention. I also added an orbital camera which causes errors if I move my mouse wheel **. I’ll put my animate function on the shelf for the time being and begin following your 24 Sep directions by creating an alternative animateDynamic function that can replace it.
* https://www.nevyns-lab.com/
** OrbitControls.js:765 [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
.
Airman. Thanks Vexman, I agree, a simulation of the PI=4 Experiment would be an a priori necessary accessory in trying to understand curved motion. With regard to my effort, you’re being kind. I’m still a relative beginner. My code is poxied with beginner’s mistakes and lack any sophistication whatsoever. I have no means of making the code more accessible than by posting my updates as I have already done. I’m not anywhere near experienced enough to create a cloud GIT (software development) PI=4 Experiment software repository that people could download or build upon.This really looks impressive, Airman.
Will you consider making such animation accessible at some website, open for general public? It would make an excellent accessory when discussing Pi(k) with people having different opinion about what's going on inside the curve when motion is involved.
My ulterior motive has always been to get Nevyn to post the final PI=4 experiment at his site *. Obviously he can do the job perfectly well on his own. As a civil engineer I’ve worked on many base level projects, large or small, as lead or member. I’ll point out that a final product created through a team approach to review and development can greatly improve the product’s quality. I present myself as a hard ass editor or semi-skilled enthusiastic free labor Nevyn may direct as he chooses.
Nevyn, in addition to the tubular track changes, I created the last animation of the curved ball’s z-axis rotation and so the animation has reached its initial/final draft. Sorry, that last animation doesn’t look right and will require your attention. I also added an orbital camera which causes errors if I move my mouse wheel **. I’ll put my animate function on the shelf for the time being and begin following your 24 Sep directions by creating an alternative animateDynamic function that can replace it.
* https://www.nevyns-lab.com/
** OrbitControls.js:765 [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
I can't tell what version of ThreeJS you are using, and I suspect that you need a newer version, along with its version of OrbitControls.js, to fix this bug. I also can't execute the code without knowing the ThreeJS version.
Re: Animate the PI = 4 experiment
.
The code began as one of the examples included in the three.js r87 download.
\threejs\three.js-r87\examples\webgl - geometry - cube
I used the orbital camera source from that same group of js source files.
.
The code began as one of the examples included in the three.js r87 download.
\threejs\three.js-r87\examples\webgl - geometry - cube
I used the orbital camera source from that same group of js source files.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
That's a really old version, and browsers have moved on. The latest I used, which was a few months ago now, was r104. There are probably a few more versions out now, I haven't looked recently. I saw a comment in the wild a week ago that there is a WebGL 2.0 coming out, or is out, or is being tested, not sure. That will mean a lot of changes in ThreeJS coming up.
Re: Animate the PI = 4 experiment
.
I downloaded the latest three.js. version 109 as a zip file. I then moved the zip file to my threejs folder and extracted it. No joy, I cannot run any of the new three.js files, I'm receiving the following console errors.
Any clues as to how I might correct this? Am I lacking the proper permissions?
.
I downloaded the latest three.js. version 109 as a zip file. I then moved the zip file to my threejs folder and extracted it. No joy, I cannot run any of the new three.js files, I'm receiving the following console errors.
webgl_geometry_cube.html:1 Access to script at 'file:///C:/Users/Robert/Downloads/three.js-master/build/three.module.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
three.module.js:1 Failed to load resource: net::ERR_FAILED
Any clues as to how I might correct this? Am I lacking the proper permissions?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
You're using a full file path. Make it relative to the location of the HTML file and it will work.
Re: Animate the PI = 4 experiment
.
Sorry, I am not understanding. How am I using the whole path? I extracted the files, and go to the examples folder using windows explorer. I usually launch a three.js file by right finger clicking, then ‘use/chrome’, or I might select Run/Launch while coding in notepad++. The URLs are what appear in chrome’s file line. Are you saying I can change that? The examples are all installed relative to the build, I just don’t see where I can change the source relative to the example. Unless I selected a poor location to store the three.js-master?
Here’s the latest html header for v109. The import line is something new.
Sorry, I am not understanding. How am I using the whole path? I extracted the files, and go to the examples folder using windows explorer. I usually launch a three.js file by right finger clicking, then ‘use/chrome’, or I might select Run/Launch while coding in notepad++. The URLs are what appear in chrome’s file line. Are you saying I can change that? The examples are all installed relative to the build, I just don’t see where I can change the source relative to the example. Unless I selected a poor location to store the three.js-master?
Here’s the latest html header for v109. The import line is something new.
- Code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - geometry - cube</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="module">
import * as THREE from '../build/three.module.js';
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
Don't use the import method, it has limitations including not being supported by some browsers. Use a script tag instead. In that script tag, use a relative URL rather than an absolute one.
So your above import should be changed to and move it to the section. That already uses a relative URL, too.
So your above import should be changed to
Re: Animate the PI = 4 experiment
.
If I understand correctly, I may use the existing files if I replace the import method with the previous standard script source.
I attempted to do so by saving wedgl_geometry_cube as wedgl_geometry_pi4, then made several changes, replacing import with:
Resulting in - ReferenceError. THREE is not defined.
There must be an easier way. I did a search and found a question that may help.
Three.js : Very first setup…?
https://stackoverflow.com/questions/43617077/three-js-very-first-setup
The question was been answered 2yrs 5 months ago and doesn’t seem very clear. Would you agree that answer- instructions for installing three.js is correct? If so I’ll try to follow them next.
.
If I understand correctly, I may use the existing files if I replace the import method with the previous standard script source.
I attempted to do so by saving wedgl_geometry_cube as wedgl_geometry_pi4, then made several changes, replacing import with:
- Code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - geometry - pi4</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script type="text/javascript" src="../build/three.js" style="margin: 0px; padding: 0px;">
</head>
<body>
<script src="../build/three.js"></script>
<script>
var camera, scene, renderer;
Resulting in - ReferenceError. THREE is not defined.
There must be an easier way. I did a search and found a question that may help.
Three.js : Very first setup…?
https://stackoverflow.com/questions/43617077/three-js-very-first-setup
The question was been answered 2yrs 5 months ago and doesn’t seem very clear. Would you agree that answer- instructions for installing three.js is correct? If so I’ll try to follow them next.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
My guess is that your problem is with src="../build/three.js". That may not be the path to the file. I recommend following some of those instructions, but not all because you have already gotten passed most of it.
The part I was going to recommend yesterday, but didn't want to confuse things too much, was to copy the three.js file (and any other required JS files from ThreeJS, such as orbit-controls.js) into your project directory (in a sub-directory called js, and use any sub-directories inside of that that you want).
So your project file system should look something like this:
project.html
js/three.js
js/controls/orbit-controls.js
Then you replace src="../build/three.js" with src="js/three.js".
The best thing about doing it this way is that it keeps the project self-contained. You recently downloaded a new version of ThreeJS and put it into the same place as the previous one. This means that all other projects that refer to it just got upgraded but their source code has not been changed to reflect that. So they may not work anymore.
The part I was going to recommend yesterday, but didn't want to confuse things too much, was to copy the three.js file (and any other required JS files from ThreeJS, such as orbit-controls.js) into your project directory (in a sub-directory called js, and use any sub-directories inside of that that you want).
So your project file system should look something like this:
project.html
js/three.js
js/controls/orbit-controls.js
Then you replace src="../build/three.js" with src="js/three.js".
The best thing about doing it this way is that it keeps the project self-contained. You recently downloaded a new version of ThreeJS and put it into the same place as the previous one. This means that all other projects that refer to it just got upgraded but their source code has not been changed to reflect that. So they may not work anymore.
Re: Animate the PI = 4 experiment
.
Thanks Nevyn, I've read up about minified installs that doesn't seem to help. src="../build/three.js" seems relative and correct to me. I'll continue with your latest directions.
.
Thanks Nevyn, I've read up about minified installs that doesn't seem to help. src="../build/three.js" seems relative and correct to me. I'll continue with your latest directions.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
The version you are using has not been minified. There is another file called three-min.js that is the minified version of three.js. Programmatically, they are the same, but the contents are actually different. A minified version just takes out all of the stuff that isn't needed to execute the file. So any comments are removed, extraneous whitespace, variables are renamed to shorter names, etc. The idea is to create a version that works exactly the same, but is the smallest it can be.
Try this: after the three script tag, add the ending tag.
It shouldn't need the style attribute either. I don't see what that would do because the script tag is not visible.
Try this: after the three script tag, add the ending tag.
- Code:
<script type="text/javascript" src="../build/three.js" style="margin: 0px; padding: 0px;"></script>
It shouldn't need the style attribute either. I don't see what that would do because the script tag is not visible.
Re: Animate the PI = 4 experiment
.
We have Joy, PI=4 is working under v109 in its own project folder.
Project files.
PI=4.
The cube kept giving me grief with the same - blocked by CORS policy; turns out the cube code requests a crate gif (not in the source list) from the v109 textures folder. Rather than bring the texture in I tried PI=4 and it worked, well almost, the only thing not yet working is the orbital camera. Lines 62 and 63 are commented out since they are causing errors:
62 // controls = new THREE.OrbitControls( camera ); // comes with errors
63 // controls.damping = 0.2;
1. controls is not defined.and
2. TypeError: THREE.OrbitControls is not a constructor
By the way, that stye error was something strange. I routinely copy/paste forum comments into a word document as a back-up historical file. Often I read the word document instead of the forum post itself. In your quote
Nevyn So your above import should be changed to script type …
Airman. Your instructions just after that quote - before you changed it - your text between the script signs converted the into a block of styling information which seemed like a complicated instruction. When I quoted you after the ... it turned back into simple text.
I need to catch up with your last set of directions.
.
We have Joy, PI=4 is working under v109 in its own project folder.
Project files.
PI=4.
The cube kept giving me grief with the same - blocked by CORS policy; turns out the cube code requests a crate gif (not in the source list) from the v109 textures folder. Rather than bring the texture in I tried PI=4 and it worked, well almost, the only thing not yet working is the orbital camera. Lines 62 and 63 are commented out since they are causing errors:
62 // controls = new THREE.OrbitControls( camera ); // comes with errors
63 // controls.damping = 0.2;
1. controls is not defined.and
2. TypeError: THREE.OrbitControls is not a constructor
By the way, that stye error was something strange. I routinely copy/paste forum comments into a word document as a back-up historical file. Often I read the word document instead of the forum post itself. In your quote
Nevyn So your above import should be changed to script type …
Airman. Your instructions just after that quote - before you changed it - your text between the script signs converted the into a block of styling information which seemed like a complicated instruction. When I quoted you after the ... it turned back into simple text.
I need to catch up with your last set of directions.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
You need a 2nd script tag to import the OrbitControls.js file. Put it after the three.js import (because it needs three itself). Then the controls will work.
Re: Animate the PI = 4 experiment
.
Which way is up?
Plenty to do, thank you very much. Little things that will delay any dynamic animation function work for the moment.
Catching up with your instructions: I’ve replaced three.js with three.min.js. And, the Orbit controls tag is below the three.min.js tag:
Zooming the mouse wheel works on the screen, although it causes the following console error; the number at the left - 80 in this case, increases as with mouse wheel changes.
But first, I thought I’d like to try changing the perspective type camera for the orthographic. I’m in the middle of that. I’d like to make it perfectly clear that the two tubular tracks lie side by side on a flat plane, thus accounting for the rolling action. The orbit control allows me to really confuse myself, clearly the height and width don’t agree.
When I change the vector
//var cTrackCenter = new THREE.Vector3( 3*r, -r, 5*r );
from ( 0, 0, 0 ) to ( 3*r, -r, 5*r ), the objects comprising the two tracks aren’t all located at their proper locations. The track objects' positions need to be made relative to the c track as well as radius r.
Pardon me while I putz around a bit.
.
Which way is up?
Plenty to do, thank you very much. Little things that will delay any dynamic animation function work for the moment.
Catching up with your instructions: I’ve replaced three.js with three.min.js. And, the Orbit controls tag is below the three.min.js tag:
- Code:
<script src="js/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
Zooming the mouse wheel works on the screen, although it causes the following console error; the number at the left - 80 in this case, increases as with mouse wheel changes.
I’m trying to find out why – I have two intertoob orbit control documents open in separate tabs.80[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See
But first, I thought I’d like to try changing the perspective type camera for the orthographic. I’m in the middle of that. I’d like to make it perfectly clear that the two tubular tracks lie side by side on a flat plane, thus accounting for the rolling action. The orbit control allows me to really confuse myself, clearly the height and width don’t agree.
When I change the vector
//var cTrackCenter = new THREE.Vector3( 3*r, -r, 5*r );
from ( 0, 0, 0 ) to ( 3*r, -r, 5*r ), the objects comprising the two tracks aren’t all located at their proper locations. The track objects' positions need to be made relative to the c track as well as radius r.
Pardon me while I putz around a bit.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
The current view of the PI=4 Experiment is again orthographic. I like it better than the perspective view.
All the new lines are ‘intended to make development easier’ and indeed they (perspective too) do. They make it clearer how the js camera operates. I went and included the new source in two new folders in the project files.
The white line begins at (0,0,0) and goes upward in a positive Z direction. The orbit controls in the current image also ‘rotates’ about that same up/down axis. The two tracks lie side by side on the plane marked by the red x.
I completed adding var cTrackCenter to all objects. Using it one may move the PI=4 Experiment anywhere in world space without effecting the animation. Above, cTrackCenter was used to move the tracks slightly away from (0,0,0) in order to more center the image's range of motion within the camera scene.
I had to go through my if statements again, made another == correction.
Not sure what’s next. I suppose I should go through all the coordinate point indices(?) to allow switching over to them instead of all the line segments that are currently used in the init function. There's also the zooming error and the height/width still don’t agree.
Feel free to add.
.
The current view of the PI=4 Experiment is again orthographic. I like it better than the perspective view.
All the new lines are ‘intended to make development easier’ and indeed they (perspective too) do. They make it clearer how the js camera operates. I went and included the new source in two new folders in the project files.
- Code:
<script src="js/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="src/helpers/CameraHelper.js"></script>
The white line begins at (0,0,0) and goes upward in a positive Z direction. The orbit controls in the current image also ‘rotates’ about that same up/down axis. The two tracks lie side by side on the plane marked by the red x.
I completed adding var cTrackCenter to all objects. Using it one may move the PI=4 Experiment anywhere in world space without effecting the animation. Above, cTrackCenter was used to move the tracks slightly away from (0,0,0) in order to more center the image's range of motion within the camera scene.
I had to go through my if statements again, made another == correction.
Not sure what’s next. I suppose I should go through all the coordinate point indices(?) to allow switching over to them instead of all the line segments that are currently used in the init function. There's also the zooming error and the height/width still don’t agree.
Feel free to add.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
Airman wrote:I completed adding var cTrackCenter to all objects. Using it one may move the PI=4 Experiment anywhere in world space without effecting the animation.
That doesn't sound right. I'm sure it works, but what I mean is, it shouldn't be the way chosen to make it work. You're not using the scene hierarchy to your advantage. You should have all track parts in a group, then you just move the group where you want it. The current method is like moving a house brick by brick instead of as a house.
This happens when you do too much during initialization. It is easy to do that in this type of application (and many others), a lot of the ThreeJS examples do this, but it creates fragile code. You don't notice until you want some new feature and soon realise that you have to change lots of little bits instead of just one, or a few. You may also notice it when you try to copy code from one project to another to re-use it and you start to see how different the apps are.
Re: Animate the PI = 4 experiment
.
Airman wrote:I completed adding var cTrackCenter to all objects. Using it one may move the PI=4 Experiment anywhere in world space without effecting the animation.
Nevyn wrote. That doesn't sound right. I'm sure it works, but what I mean is, it shouldn't be the way chosen to make it work. You're not using the scene hierarchy to your advantage. You should have all track parts in a group, then you just move the group where you want it. The current method is like moving a house brick by brick instead of as a house.
Airman. I thought cTrackCenter was a good addition, oh well, thanks for explaining why not, a lot of bricks. I couldn’t possibly enjoy starting my weekend without correcting it as soon as possible. I completely removed var cTrackCenter from the code. Instead, as you suggested, I added a new var grp = new THREE.Group(). All track objects are added to grp. If I wish to move the PI=4 Experiment elsewhere in world space, I can re-position grp before it is added to the scene.
Tested good.
.
Airman wrote:I completed adding var cTrackCenter to all objects. Using it one may move the PI=4 Experiment anywhere in world space without effecting the animation.
Nevyn wrote. That doesn't sound right. I'm sure it works, but what I mean is, it shouldn't be the way chosen to make it work. You're not using the scene hierarchy to your advantage. You should have all track parts in a group, then you just move the group where you want it. The current method is like moving a house brick by brick instead of as a house.
Airman. I thought cTrackCenter was a good addition, oh well, thanks for explaining why not, a lot of bricks. I couldn’t possibly enjoy starting my weekend without correcting it as soon as possible. I completely removed var cTrackCenter from the code. Instead, as you suggested, I added a new var grp = new THREE.Group(). All track objects are added to grp. If I wish to move the PI=4 Experiment elsewhere in world space, I can re-position grp before it is added to the scene.
Tested good.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Back in perspective view. The curved and straight track spheres have almost reached their starting points.
Beau coup changes. Imho, the passive animation has reached a fine draft final.
I couldn’t figure out how to get the whole table to rotate easily about the +z vertical axis. So I went and switched all the coordinates’ y and z values (including negating z). I changed the balls’ paths accordingly. Lo and behold, I see good rotations for the balls in either track. Do you agree?
The camera helper isn't included in the 'neat' version - my working file is a mess with comments mistakes etc.
I edited the code comments to better agree with the code, I always include errors somewhere, so added a nearby image.
After I get through smiling I’ll be ready to begin the dynamic animation.
.
Back in perspective view. The curved and straight track spheres have almost reached their starting points.
Beau coup changes. Imho, the passive animation has reached a fine draft final.
I couldn’t figure out how to get the whole table to rotate easily about the +z vertical axis. So I went and switched all the coordinates’ y and z values (including negating z). I changed the balls’ paths accordingly. Lo and behold, I see good rotations for the balls in either track. Do you agree?
- Code:
<script>
var camera, scene, renderer;
var mesh, sphereC, sphereS;
var r = 1; // Track radius
var widt = window.innerWidth;
var heit = window.innerHeight;
var aspectRatio = widt/heit;
var viewSize = 8*r;
var q = r; // track separation
var tRadius = 0.25*r;
var tubeTot = 200;
var tubeInc = 10*r/tubeTot;
var w = tRadius; // r; // 0.75 * r; // track width
var iRadius = r - w/2;
var oRadius = r + w/2; // r + w/2;
// Inverse velocity. The greater the number of increments the slower the ball's velocity along the track.
var increments = 1000; // 5000; // Just over two minutes to complete the courses.
var pathInc = 150;
var forInc = 8/increments;
var angInc = 2*Math.PI*r/increments;
var kMult = 4/Math.PI;
var bRadius = tRadius;
var bCircum = 2 * Math.PI * bRadius;
var ang2rot = 10*r/bCircum; // 8*r*kMult/bCircum; //the number of rolling rotations for the total
var ang2Inc = 4 * ang2rot * kMult/ increments; // the straight ball is rolling
var curTrackAngle = 0;
var curBallAngle = 0;
var inLoop = false;
var overShot, fRatio;
var cClicks = 0;
var sClicks = 0;
init();
animatePassive();
function init() {
var grp = new THREE.Group();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, aspectRatio, 0.1*r, 100*r );
//camera = new THREE.OrthographicCamera( -aspectRatio*viewSize/2, aspectRatio*viewSize/2, viewSize/2, -viewSize/2);
camera.position.set( 0, 0, 4*r );
camera.lookAt(0, 0, -5*r);
controls = new THREE.OrbitControls( camera, renderer ); // comes with errors
controls.target.set( 0, 0, -5*r );
camera.updateProjectionMatrix();
//scene.background = new THREE.Color('FFFFFF'); // #009900 pool table green // #0000FF nice high contrast blue //
var sphereMat = new THREE.MeshBasicMaterial( { wireframe: true, color: 'yellow' } ); // yellow
var material = new THREE.LineBasicMaterial( { color: 'red', linewidth: 0.5*r } ); // markers
var material2 = new THREE.LineBasicMaterial( { color: 'grey' } ); // Increment markers
var MAT_LINE_CP = new THREE.LineBasicMaterial( { color: 0x00cc00, linewidth: 0.5 } ); // distances
//cTrackCenter -4 curved paths
for(th=1;th<=360;th+=1) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 1);
if (th === 359) { radians2 = (Math.PI/180) }
for ( i = -1; i < 2; i=i+2 ) {
configRadius = r + i*w;
var XYPlaneLine = new THREE.Geometry();
XYPlaneLine.vertices.push(
new THREE.Vector3( configRadius * Math.cos(radians1), 0, -configRadius*Math.sin(radians1) ),
new THREE.Vector3( configRadius * Math.cos(radians2), 0, -configRadius*Math.sin(radians2) ) );
var XYLine = new THREE.Line( XYPlaneLine, MAT_LINE_CP);
grp.add(XYLine);
configRadius = r + i*w;
var XYPlaneLine = new THREE.Geometry();
XYPlaneLine.vertices.push(
new THREE.Vector3( r * Math.cos(radians1), i*tRadius, -r*Math.sin(radians1) ),
new THREE.Vector3( r * Math.cos(radians2), i*tRadius, -r*Math.sin(radians2) ));
var XYLine = new THREE.Line( XYPlaneLine, MAT_LINE_CP);
grp.add(XYLine);
};
};
// S track markers
for ( j = 0; j < 6; j++ ) {
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*j, 0, -(-r-q-2*w) ) );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*j, 0, -(-r-q ) ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*j, -tRadius, -(-r-q-w ) ) );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*j, tRadius, -(-r-q-w ) ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
};
// PI marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( 2*r*Math.PI, 0, -(-r-q-2*w ) ) );
geometry.vertices.push(new THREE.Vector3( 2*r*Math.PI, 0, -(-r-q )) );
var line = new THREE.Line( geometry, material );
grp.add( line );
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( 2*r*Math.PI, -tRadius, -(-r-q-w ) ) );
geometry.vertices.push(new THREE.Vector3( 2*r*Math.PI, tRadius, -(-r-q-w ) ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
// C track straight section markers
for ( m = 0; m < 2; m++ ) {
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*m, 0, -(-r+w ) ) );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*m, 0, -(-r-w ) ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*m, -tRadius, r ) );
geometry.vertices.push(new THREE.Vector3( -2*r+2*r*m, tRadius, r ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
};
// parallel circles curved path's initial straight section
for( ber=0; ber<tubeTot/5+1; ber++ ) {
for(th=1;th<=360;th+=12) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 12);
if (th === 348) { radians2 = (Math.PI/180) }
var yZPlaneCircle = new THREE.Geometry();
yZPlaneCircle.vertices.push( //viewing x and y.
new THREE.Vector3( 0, tRadius*Math.sin(radians1), -tRadius * Math.cos(radians1) ),
new THREE.Vector3( 0, tRadius*Math.sin(radians2), -tRadius * Math.cos(radians2) ) );
var tCircle = new THREE.Line( yZPlaneCircle, material2);
tCircle.position.set( -2*r+ber*tubeInc, 0, r );
grp.add(tCircle);
};
};
// parallel circles straight path
for( num=0; num<tubeTot+1; num++ ) {
for(th=1;th<=360;th+=18) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 18);
if (th === 342) { radians2 = (Math.PI/180) }
var yZPlaneCircle = new THREE.Geometry();
yZPlaneCircle.vertices.push( //viewing x and y.
new THREE.Vector3( 0, tRadius*Math.sin(radians1), -tRadius * Math.cos(radians1) ),
new THREE.Vector3( 0, tRadius*Math.sin(radians2), -tRadius * Math.cos(radians2) ) );
var tCircle = new THREE.Line( yZPlaneCircle, material2);
tCircle.position.set( -2*r+num*tubeInc, 0, -(-r-q-w) );
grp.add(tCircle);
};
};
// parallel circles circular path
var curAngl;
var curAnglInc = 2*Math.PI*r/tubeTot;
var yZPlaneCircle = new THREE.Geometry();
for(th=1;th<=360;th+=18) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 18);
if (th === 342) { radians2 = (Math.PI/180) }
yZPlaneCircle.vertices.push(
new THREE.Vector3( 0, tRadius*Math.sin(radians1), -tRadius * Math.cos(radians1) ),
new THREE.Vector3( 0, tRadius*Math.sin(radians2), -tRadius * Math.cos(radians2) ) );
};
for( ber=0; ber < tubeTot; ber++ ) {
var tCircle = new THREE.Line( yZPlaneCircle, material2);
curAngl = ber*curAnglInc;
tCircle.rotation.y = curAngl + Math.PI/2;
tCircle.position.set( r * Math.cos(curAngl), 0, -r * Math.sin(curAngl) );
grp.add(tCircle);
};
for ( k = -1; k < 2; k=k+2 ) {
// S track lengths: +/-z edges
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r, 0, -(-r-w-q+k*w ) ) );
geometry.vertices.push(new THREE.Vector3( 8*r, 0, -(-r-w-q+k*w ) ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
// S track lengths: +/-z edges
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r, k*tRadius, -(-r-w-q ) ) );
geometry.vertices.push(new THREE.Vector3( 8*r, k*tRadius, -(-r-w-q ) ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
// C track lengths: +/-z edges
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r, 0, -(-r+k*w ) ) );
geometry.vertices.push(new THREE.Vector3( 0, 0, -(-r+k*w ) ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
// C track lengths: +/-y edges
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -2*r, k*tRadius, r ) );
geometry.vertices.push(new THREE.Vector3( 0, k*tRadius, r ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
}
// C track markers
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( r-w, 0, 0 ) );
geometry.vertices.push(new THREE.Vector3( r+w, 0, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track One Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( r, -tRadius, 0 ) );
geometry.vertices.push(new THREE.Vector3( r, tRadius, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track One Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( 0, 0, -r-w ) );
geometry.vertices.push(new THREE.Vector3( 0, 0, -r+w ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Two Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( 0, -tRadius, -r ) );
geometry.vertices.push(new THREE.Vector3( 0, tRadius, -r ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Two Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -r-w, 0, 0 ) );
geometry.vertices.push(new THREE.Vector3( -r+w, 0, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Three Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -r, -tRadius, 0 ) );
geometry.vertices.push(new THREE.Vector3( -r, tRadius, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Three Marker
// Balls
var sphereGeom = new THREE.SphereGeometry( bRadius, 16, 16 );
sphereC = new THREE.Mesh( sphereGeom, sphereMat );
sphereC.position.set( -2*r, 0, r );
sphereS = new THREE.Mesh( sphereGeom, sphereMat );
sphereS.position.set( -2*r, 0, -(-r-q-w ) );
var ballOne = new THREE.Object3D();
ballOne.add(sphereC);
var ballTwo = new THREE.Object3D();
ballTwo.add(sphereS);
grp.add( ballOne, ballTwo );
grp.position.set( -2.5*r, 0, -6*r ); //repositions the world rotation point
scene.add(grp);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, true );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
};
function animatePassive() {
requestAnimationFrame( animatePassive );
cClicks += 1;
sClicks += 1;
if (( sphereC.position.x + forInc >= 0 ) && ( sphereC.position.z == r ) && ( inLoop == false )) {
overShot = sphereC.position.x + forInc - 0;
fRatio = overShot/forInc;
curTrackAngle = -angInc + fRatio*angInc;
};
sphereC.rotation.z -= ang2Inc;
sphereC.position.x += forInc;
if ((sphereC.position.x >= 0) && ( sphereC.position.z == r )){
inLoop = true;
};
if ( inLoop ) {
curTrackAngle += angInc;
sphereC.rotation.y = curTrackAngle;
sphereC.position.set( r*Math.sin(curTrackAngle), 0, r*Math.cos(curTrackAngle) )
};
if ( (sphereC.position.x >= 0) && ( cClicks > increments*1.25 )) {
sphereC.position.set( -2*r, 0, r );
curTrackAngle = 0;
inLoop = false ;
cClicks = 0 ;
};
sphereS.rotation.z -= ang2Inc;
sphereS.position.x += forInc;
if (( sphereS.position.x >= 8*r ) && ( sClicks > increments*1.25 )){
sphereS.position.set( -2*r, 0, -(-r-q-w) );
curBallAngle = 0;
sClicks = 0;
};
renderer.render( scene, camera );
};
</script>
The camera helper isn't included in the 'neat' version - my working file is a mess with comments mistakes etc.
I edited the code comments to better agree with the code, I always include errors somewhere, so added a nearby image.
After I get through smiling I’ll be ready to begin the dynamic animation.
.
Last edited by LongtimeAirman on Sun Oct 06, 2019 5:23 pm; edited 2 times in total (Reason for editing : Corrected code comment errors and added a second)
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Progress, I believe, but the product is far from complete - the process continues, as evidenced below. Some code changes I’ve made since last time.
1. var tubeTot. Corrected. You can change the total number of circles or hoops in both tracks by changing the tube total, tubeTot. Say you’d like 10 divisions for each track section, then the initial section plus sections 1 through 4 make 5 times 10, so let tubeTot =50. Note, an additional circle will be added to the end of the straight track – if the value of tubeTot selected is divisible by 5.
Line 156 is included as a reference. From
4. Updated the coordinate points list - something I'll try incorporating next - made necessary after having switched y and z and negating z.
5. Centerline x value coordinate arrays. Adding lines 55-57; straight and curved track centerline x value arrays just before the init function call. Slight simplification, i.e. it eliminated the need for a separate - now gone - straight track PI marker code section. The thought is that, given r, w, q and these two arrays, the two tracks can be generated a lot simpler than I have thus far. Maybe expand to an indexed coordinate array. In any case, these two track arrays are the basis for both the Passive and the Dynamic animate functions.
Hope all is well.
.
Progress, I believe, but the product is far from complete - the process continues, as evidenced below. Some code changes I’ve made since last time.
1. var tubeTot. Corrected. You can change the total number of circles or hoops in both tracks by changing the tube total, tubeTot. Say you’d like 10 divisions for each track section, then the initial section plus sections 1 through 4 make 5 times 10, so let tubeTot =50. Note, an additional circle will be added to the end of the straight track – if the value of tubeTot selected is divisible by 5.
Line 156 is included as a reference. From
- Code:
156 // parallel circles straight path
157 for( num=0; num<tubeTot+1; num++ ) {
- Code:
157 for( num=0; num<tubeTot; num++ ) {
- Code:
172 var curAnglInc = 2*Math.PI*r/tubeTot;
- Code:
172 var curAnglInc = 2*Math.PI*r/(4*tubeTot/5);
- Code:
39 var pathInc = 75;
4. Updated the coordinate points list - something I'll try incorporating next - made necessary after having switched y and z and negating z.
5. Centerline x value coordinate arrays. Adding lines 55-57; straight and curved track centerline x value arrays just before the init function call. Slight simplification, i.e. it eliminated the need for a separate - now gone - straight track PI marker code section. The thought is that, given r, w, q and these two arrays, the two tracks can be generated a lot simpler than I have thus far. Maybe expand to an indexed coordinate array. In any case, these two track arrays are the basis for both the Passive and the Dynamic animate functions.
- Code:
55 // Centerpath x coordinates.
56 var sTrack = [ -2*r, 0, 2*r, 4*r, 6*r, 8*r, 2*Math.PI*r ];
57 var cTrack = [ -2*r, 0, r, 0, -r, 0 ];
58
59 init();
Hope all is well.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Progress, I believe, but the product is far from complete - the process continues, as evidenced below. Some code changes I’ve made since last time.
1. var tubeTot. Corrected. You can change the total number of circles or hoops in both tracks by changing the tube total, tubeTot. Say you’d like 10 divisions for each track section, then the initial section plus sections 1 through 4 make 5 times 10, so let tubeTot =50. Note, an additional circle will be added to the end of the straight track – if the value of tubeTot selected is divisible by 5.
Line 156 is included as a reference. From
4. Updated the coordinate points list - something I'll try incorporating next - made necessary after having switched y and z and negating z.
5. Centerline x value coordinate arrays. Adding lines 55-57; straight and curved track centerline x value arrays just before the init function call. Slight simplification, i.e. it eliminated the need for a separate - now gone - straight track PI marker code section. The thought is that, given r, w, q and these two arrays, the two tracks can be generated a lot simpler than I have thus far. Maybe expand to an indexed coordinate array. In any case, these two track arrays are the basis for both the Passive and the Dynamic animate functions.
Hope all is well.
.
Progress, I believe, but the product is far from complete - the process continues, as evidenced below. Some code changes I’ve made since last time.
1. var tubeTot. Corrected. You can change the total number of circles or hoops in both tracks by changing the tube total, tubeTot. Say you’d like 10 divisions for each track section, then the initial section plus sections 1 through 4 make 5 times 10, so let tubeTot =50. Note, an additional circle will be added to the end of the straight track – if the value of tubeTot selected is divisible by 5.
Line 156 is included as a reference. From
- Code:
156 // parallel circles straight path
157 for( num=0; num<tubeTot+1; num++ ) {
- Code:
156 // parallel circles straight path
157 for( num=0; num<tubeTot; num++ ) {
- Code:
172 var curAnglInc = 2*Math.PI*r/tubeTot;
- Code:
172 var curAnglInc = 2*Math.PI*r/(4*tubeTot/5);
- Code:
39 var pathInc = 75;
4. Updated the coordinate points list - something I'll try incorporating next - made necessary after having switched y and z and negating z.
5. Centerline x value coordinate arrays. Adding lines 55-57; straight and curved track centerline x value arrays just before the init function call. Slight simplification, i.e. it eliminated the need for a separate - now gone - straight track PI marker code section. The thought is that, given r, w, q and these two arrays, the two tracks can be generated a lot simpler than I have thus far. Maybe expand to an indexed coordinate array. In any case, these two track arrays are the basis for both the Passive and the Dynamic animate functions.
- Code:
55 // Centerpath x coordinates.
56 var sTrack = [ -2*r, 0, 2*r, 4*r, 6*r, 8*r, 2*Math.PI*r ];
57 var cTrack = [ -2*r, 0, r, 0, -r, 0 ];
58
59 init();
Hope all is well.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
How dynamic is dynamic? For one thing, spin seems arbitrary. Unlike the two tabletop tracks which must impart rolling spins on the two spheres, I imagine that the dynamic, non-rolling sphere can move linearly through the straight track, beginning to end, with no spin or change in orientation. As such, this simulation might resemble action in a vacuum. I imagine a non spinning sphere moving through a circular path must execute a single rotation. Or do we want a table surface in the dynamic model as well? Still thinking.
The control panel is present but not operational.
I keep procrastinating the dynamic animation, I’m trying to be productive here. How about controls? We’ll need them sooner or latter. We used them in the CPIM project. I looked at CPIM and dat.gui.
Simple instructions eh? The first of three,
Here's the very rudimentary control panel at the end of the init() function - so far. Like I said, everything else is still running, no controls yet. I have no idea what's next, I'll keep trying to follow directions.
How dynamic is dynamic? For one thing, spin seems arbitrary. Unlike the two tabletop tracks which must impart rolling spins on the two spheres, I imagine that the dynamic, non-rolling sphere can move linearly through the straight track, beginning to end, with no spin or change in orientation. As such, this simulation might resemble action in a vacuum. I imagine a non spinning sphere moving through a circular path must execute a single rotation. Or do we want a table surface in the dynamic model as well? Still thinking.
The control panel is present but not operational.
I keep procrastinating the dynamic animation, I’m trying to be productive here. How about controls? We’ll need them sooner or latter. We used them in the CPIM project. I looked at CPIM and dat.gui.
- Code:
<script src="js/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
Simple instructions eh? The first of three,
Trying to follow those instructions, many changes later, everything is still working - thank goodness. I created a new function; daControlValues (). All the variables defined within daControlValues are identified with the (this.) identifier. All the var values created in the init function now use this.values. For example, the radius will be identified as this.r instead of r. I placed daControlValues (); before init();.The property must be public, i.e. defined by this.prop = value.
- Code:
var mesh, sphereC, sphereS;
var daControlValues = function() {
// Some of these will hopefully be control panel variables
this.r = 1; // Track radius
this.q = this.r; // track separation
this.bRadius = 0.25*this.r;
this.tRadius = this.bRadius;
this.tubeTot = 120; // = 120;
this.w = this.tRadius; // r; // 0.75 * r; // track width
// Inverse velocity. The greater the number of increments the slower the ball's velocity along the track.
this.increments = 500; // 5000; // Just over two minutes to complete the courses.
this.widt = window.innerWidth;
this.heit = window.innerHeight;
this.aspectRatio = this.widt/this.heit;
this.viewSize = 8*this.r;
this.tubeInc = 10*this.r/tubeTot;
this.forInc = 8/increments;
this.angInc = 2*Math.PI*this.r/increments;
this.kMult = 4/Math.PI;
this.bRadius = this.tRadius;
this.bCircum = 2 * Math.PI * this.bRadius;
this.ang2rot = 10*this.r/this.bCircum; // 8*this.r*this.kMult/bCircum; //the number of rolling rotations for the total
this.ang2Inc = 4 * this.ang2rot * this.kMult/ this.increments;
this.curTrackAngle = 0;
this.curBallAngle = 0;
this.inLoop = false;
this.overShot;
this.fRatio;
this.cClicks = 0;
this.sClicks = 0;
// Centerpath coordinate arrays.
this.tracSep = this.r+this.q+this.w;
this.sTrackX = [ -2*this.r, 0, 2*this.r, 4*this.r, 6*this.r, 8*this.r, 2*Math.PI*this.r ];
this.cTrackX = [ -2*this.r, 0, this.r, 0, -this.r, 0 ];
};
daControlValues();
init();
animatePassive();
Here's the very rudimentary control panel at the end of the init() function - so far. Like I said, everything else is still running, no controls yet. I have no idea what's next, I'll keep trying to follow directions.
- Code:
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//$('body').append(renderer.domElement); // ?????
// call the render function
// var step = 0;
var controls = new function () {
this.r = 1;
this.increments = 100;
this.tubeTot = 15;
};
var gui = new dat.GUI();
gui.add(controls, 'r',0.1,10);
gui.add(controls, 'increments', 50, 500);
gui.add(controls, 'tubeTot',0 ,200 );
// render();
window.addEventListener( 'resize', onWindowResize, true );
};
Last edited by LongtimeAirman on Wed Oct 09, 2019 6:53 pm; edited 1 time in total (Reason for editing : Included script source change)
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
I wouldn't worry about the spin of the ball. You can keep that preset. It is possible to work out how far the ball has traveled since the last frame and calculate the required rotation, but maybe try that once you have the main motions working correctly.
Re: Animate the PI = 4 experiment
.
function animateDynamic() {}
Pardon my thinking. We wish to simulate the comparative equal velocities/ distances traveled by two spheres along two different paths through space: linear and curved. The two particles do not interact in any way (i.e no collisions). As shown by the PI=4 Experiment – the two paths provide equal distances when the straight track is 4 times the length of the curved track’s diameter. * PI(kinematic)=4.
I’d say this is a simple two case particle kinematic problem.
As a reference, allow me to suggest –not for the first time – Euclidean Space. Copyright (c) 1998-2017 Martin John Baker
https://www.euclideanspace.com/
http://www.euclideanspace.com/physics/kinematics/index.htm
Martin John Baker's site is quite extensive and comprehensive. I'm happy with it, but as is quickly clear, it's getting a bit old. Many links no longer work. If you have another source, please consider sharing it.
Below, summarizing and outlining the relevant material from the Kinematics page as I believe it pertains to the current PI=4 ‘Simulation’.
Summarizing, we would expect to have to work with position, velocity and acceleration vectors, generally along the lines of.
• v = v0 + a*t
• p = p0 + v0 t + ½ a t2
• v2 = v02 + 2 * a * p
Orientation and position mean six degrees of freedom. Little more than standard high school physics. Except where it isn’t. Miles has identified the correct orbital acceleration equation, changing a = v2/r to a = v2/2r. I believe it’s necessary to include it, although I’m not sure how, i.e to explain why the sphere exiting the circular path would be leaving at a reduced 'velocity'.
Moving to Euclidean Space’s next page,
Point being, that until such time as mass is necessary, we can stick to the Kinematics page.
* Remember, linear ‘lengths’ are ok, but until everyone understands the new kinematic PI=4, lengths calculated along curves using PI(geometric) are wrong. We can generally translate length (L), to distance (D) around a circular path by, D=L*4/PI(G).
.
function animateDynamic() {}
Pardon my thinking. We wish to simulate the comparative equal velocities/ distances traveled by two spheres along two different paths through space: linear and curved. The two particles do not interact in any way (i.e no collisions). As shown by the PI=4 Experiment – the two paths provide equal distances when the straight track is 4 times the length of the curved track’s diameter. * PI(kinematic)=4.
I’d say this is a simple two case particle kinematic problem.
As a reference, allow me to suggest –not for the first time – Euclidean Space. Copyright (c) 1998-2017 Martin John Baker
https://www.euclideanspace.com/
http://www.euclideanspace.com/physics/kinematics/index.htm
Martin John Baker's site is quite extensive and comprehensive. I'm happy with it, but as is quickly clear, it's getting a bit old. Many links no longer work. If you have another source, please consider sharing it.
Below, summarizing and outlining the relevant material from the Kinematics page as I believe it pertains to the current PI=4 ‘Simulation’.
Physics – Kinematics.
…Kinematics can be studied without regard to mass or physical quantities that depend on mass.
Movement in one dimension
If an object is moving in a straight line, and if we measure its position along that line, then its position, velocity and acceleration can all be represented by scalar quantities. This makes the analysis much easier, so lets start there.
Summarizing, we would expect to have to work with position, velocity and acceleration vectors, generally along the lines of.
• v = v0 + a*t
• p = p0 + v0 t + ½ a t2
• v2 = v02 + 2 * a * p
Orientation and position mean six degrees of freedom. Little more than standard high school physics. Except where it isn’t. Miles has identified the correct orbital acceleration equation, changing a = v2/r to a = v2/2r. I believe it’s necessary to include it, although I’m not sure how, i.e to explain why the sphere exiting the circular path would be leaving at a reduced 'velocity'.
Moving to Euclidean Space’s next page,
Physics - Dynamics
In the previous kinematics page the mathematics of moving objects was discussed. If the objects are representing physical objects, with properties like mass and inertia, then we probably want to calculate the kinematics from the dynamics
Point being, that until such time as mass is necessary, we can stick to the Kinematics page.
* Remember, linear ‘lengths’ are ok, but until everyone understands the new kinematic PI=4, lengths calculated along curves using PI(geometric) are wrong. We can generally translate length (L), to distance (D) around a circular path by, D=L*4/PI(G).
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
You shouldn't need anything more than v=d/t for the straight section. We don't have any accelerations as used in those equations. The curves will be more tricky. You need to calculate the next position that the ball will end up at after this frame. I'm not sure if this will use PI=4 or PI=3.14, but calculate the angle using the balls velocity by assuming it will travel that distance on the curves circumference.
C = circumference = 2*PI*r
d = vt
So we want to know how much of C is d:
P = d/C
= vt/C
= vt/(2PI*r)
Since C represents the complete circle, we now have a percentage (actually, it is %/100 as it's just the ratio) of that, so we can convert it into an angle like this:
A = P * 2PI
We can put all that together like this:
A = 2PI*v*t/(2*PI*r)
A = vt/r
However, we must be sure that those to PI's are actually the same value before we can reduce it like that. My guess is that they are actually different versions of PI, so we can't reduce it. You will need to implement this to test which PI is the right one. The PI used to calculate the angle would be 3.14, but my guess is that the PI used for the circumference should be 4, but I'm not sure of that (fairly confident that it is, though).
I suggest you implement it using the full A = 2PI*v*t/(2*PI*r) equation, but have 2 variables for the PI values (piK and piG, for example) so it would become:
A = 2PIg*v*t/(2*PIk*r)
= PIg*v*t/(PIk*r)
Then you can adjust the values of PIg and PIk to determine which one looks right when viewing the motion.
Something to be aware of is that applying the angle, as a rotation, will actually spin the ball a bit, which will conflict with the rolling rotation of the ball. You may need to subtract the motion angle from the rolling angle to get it to look right.
It might be better to not use a rotation, but just calculate the point that it would rotate to (apply the rotation to the current position of the ball, as a vector). Then move the ball to that location and apply the normal rolling rotation.
Remember that the rotation must be applied with respect to the center of the circle.
I have just realised that the equation I just derived is almost the same equation I derived in my Spin Velocity paper. The only difference is that I used Miles angular velocity equation in the paper which is replaced by v here.
Once you have this up and running, we might try using that full equation and see how it goes. If we find that we need it, then that is good confirmation of Miles angular velocity equation.
C = circumference = 2*PI*r
d = vt
So we want to know how much of C is d:
P = d/C
= vt/C
= vt/(2PI*r)
Since C represents the complete circle, we now have a percentage (actually, it is %/100 as it's just the ratio) of that, so we can convert it into an angle like this:
A = P * 2PI
We can put all that together like this:
A = 2PI*v*t/(2*PI*r)
A = vt/r
However, we must be sure that those to PI's are actually the same value before we can reduce it like that. My guess is that they are actually different versions of PI, so we can't reduce it. You will need to implement this to test which PI is the right one. The PI used to calculate the angle would be 3.14, but my guess is that the PI used for the circumference should be 4, but I'm not sure of that (fairly confident that it is, though).
I suggest you implement it using the full A = 2PI*v*t/(2*PI*r) equation, but have 2 variables for the PI values (piK and piG, for example) so it would become:
A = 2PIg*v*t/(2*PIk*r)
= PIg*v*t/(PIk*r)
Then you can adjust the values of PIg and PIk to determine which one looks right when viewing the motion.
Something to be aware of is that applying the angle, as a rotation, will actually spin the ball a bit, which will conflict with the rolling rotation of the ball. You may need to subtract the motion angle from the rolling angle to get it to look right.
It might be better to not use a rotation, but just calculate the point that it would rotate to (apply the rotation to the current position of the ball, as a vector). Then move the ball to that location and apply the normal rolling rotation.
Remember that the rotation must be applied with respect to the center of the circle.
I have just realised that the equation I just derived is almost the same equation I derived in my Spin Velocity paper. The only difference is that I used Miles angular velocity equation in the paper which is replaced by v here.
Once you have this up and running, we might try using that full equation and see how it goes. If we find that we need it, then that is good confirmation of Miles angular velocity equation.
Re: Animate the PI = 4 experiment
.
Quick update.
// this.trackCircumP = 2*Math.PI*this.r;
// this.trackCircumK = 8*this.r;
Everything looks good? More later.
.
Quick update.
Airman. Agreed. Here’s how the straight path in both the animatePassive and the animateDynamic functions compare.Nevyn wrote. You shouldn't need anything more than v=d/t for the straight section. We don't have any accelerations as used in those equations.
- Code:
// sphereS.position.x += this.forInc; // animatePassive
sphereS.position.x += dT*vel; // animateDynamic
Airman. Correct. I'm converting from one angle function to another so it's an easy task. The circumferences are calculated in daControlValues.Nevyn wrote. The curves will be more tricky…
// this.trackCircumP = 2*Math.PI*this.r;
// this.trackCircumK = 8*this.r;
- Code:
var dT = 0.024; // ???? This is a strange number? It seems to be a constant of some kind.
var T = this.increments*1.25*dT; // total time
var omegaG = 2*Math.PI; // Circumference G or K
var omegaK = 2 * 4 ;
var vel = 10 * this.r / T;
var angleC = vel*dT/this.trackCircumP;
// A = 2PI*v*t/(2*PI*r) angle a function of the circumference traveled.
var angleC = vel*dT/this.trackCircumP;
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
Everything looks good? More later.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
- Code:
var dT = 0.024; // ???? This is a strange number? It seems to be a constant of some kind.
This is the time for this frame, in seconds. Which makes it about 40 frames per second. Strange choice. It doesn't really matter too much and can be used to control the speed of the animation. I would replace it with a fraction like 1/60 or 1/30.
- Code:
var T = this.increments*1.25*dT; // total time
Why is this line needed? You shouldn't need the total time in a dynamic calculation since it should only be thinking about the transition from the current position to the next. i.e. 1 frame.
What does the 1.25 stand for? I guess you are using it as the speed control since it is effectively changing the value of dT.
- Code:
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
This will always rotate from a set position, it will not add to the current position. So if the ball is 1/4 way around the circle, adding another angle will not move it from that position, but will move if from 0 (which is usually the X dimension in a cartesion graph).
Think about creating a Quaternion from the angle. Apply the quaternion to the position vector of the ball.
Re: Animate the PI = 4 experiment
.
Hey Nevyn, I just saw your latest post, so I have yet to make any of your suggested changes.
One thing though, Explaining why everything looked good yesterday was that after copying and changing the title to animateDynamic, I hadn't changed the next line requesting an animation frame from animatePassive. Dumb.
So now I see that the two tracks do operate independently. And I'm where you asked me to be.
Ortho view, both spheres are almost at the finish lines – with the same rolls.
Airman. I converted the animatePassive into animateDynamic by finding the three variables: incremental time dT, total time T and straight velocity vel. Everything is running well. The image above shows the two spheres end the track with synchronized rolls.
I include the animateDynamic function below, but I’d like to focus on this inLoop section, the code that advances the sphere abound the circular path.
if ( this.inLoop ) {
this.curTrackAngle += this.angInc;
sphereC.rotation.y = this.curTrackAngle;
this.inLoopCounter += 1 ;
// var angleC = omegaG * vel*dT*this.inLoopCounter/this.trackCircumP; // maybe 5/4 too fast
// var angleC = omegaK * vel*dT*this.inLoopCounter/this.trackCircumP; // faster 4/3 too fast
var angleC = vel*5*dT*this.inLoopCounter/this.trackCircumP; // I found a perfect(?) 5 by trial and effort
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
};
I tried to follow your directions explicitly. I found that neither an omegaG nor omegaK multiplier allowed the two spheres to end simultaneously (by my eyeballs). I quickly found the multiplier 5 worked perfectly. I don’t understand it.
I noticed you noticed, but here I go on a bit about dT = 0.024.
// this.increments = 4167; // A counter, not a clock. Here are the experimental track times.
// Select T, the desired time to travel d. 4167 = roughly 100 secs. 500 about 12 sec, 2500 = 1 min
// 5000, just a second or two over two minutes to complete the courses.
// dT = T/this.increments = 120/5000 = 0.024 sec, 90/3750 = 0.024. Why is dT fixed?
I’m using a counter, not a clock. I suppose I tapped into the CPU rate?
.
Hey Nevyn, I just saw your latest post, so I have yet to make any of your suggested changes.
One thing though, Explaining why everything looked good yesterday was that after copying and changing the title to animateDynamic, I hadn't changed the next line requesting an animation frame from animatePassive. Dumb.
So now I see that the two tracks do operate independently. And I'm where you asked me to be.
Ortho view, both spheres are almost at the finish lines – with the same rolls.
Nevyn wrote. I suggest you implement it using the full A = 2PI*v*t/(2*PI*r) equation.
A = 2PIg*v*t/(2*PIk*r)
= PIg*v*t/(PIk*r)
Airman. I converted the animatePassive into animateDynamic by finding the three variables: incremental time dT, total time T and straight velocity vel. Everything is running well. The image above shows the two spheres end the track with synchronized rolls.
I include the animateDynamic function below, but I’d like to focus on this inLoop section, the code that advances the sphere abound the circular path.
if ( this.inLoop ) {
this.curTrackAngle += this.angInc;
sphereC.rotation.y = this.curTrackAngle;
this.inLoopCounter += 1 ;
// var angleC = omegaG * vel*dT*this.inLoopCounter/this.trackCircumP; // maybe 5/4 too fast
// var angleC = omegaK * vel*dT*this.inLoopCounter/this.trackCircumP; // faster 4/3 too fast
var angleC = vel*5*dT*this.inLoopCounter/this.trackCircumP; // I found a perfect(?) 5 by trial and effort
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
};
I tried to follow your directions explicitly. I found that neither an omegaG nor omegaK multiplier allowed the two spheres to end simultaneously (by my eyeballs). I quickly found the multiplier 5 worked perfectly. I don’t understand it.
- Code:
function animateDynamic() {
requestAnimationFrame( animateDynamic );
var omegaG = 2 * Math.PI;
var omegaK = 2 * 4 ;
var dT = 0.024;
var T = this.increments*1.25*dT;
var vel = 10 * this.r / T;
this.cClicks += 1;
this.sClicks += 1;
// Next if is NOT USED YET Check to see whether the start/finish line occurs within the next dT*vel.
// If so, this section will determine determine exactly where the boundary occurs.
// if (( sphereC.position.x + dT*vel >= 0 ) && ( sphereC.position.z == this.r ) && ( this.inLoop == false )) {
// this.overShot = sphereC.position.x + dT*vel - 0;
// this.fRatio = this.overShot/dT*vel;
// this.curTrackAngle = -this.angInc + this.fRatio*this.angInc;
// };
sphereC.rotation.z -= this.ang2Inc;
sphereC.position.x += dT*vel;
if ((sphereC.position.x >= 0) && ( sphereC.position.z == this.r )){
this.inLoop = true;
};
if ( this.inLoop ) {
this.curTrackAngle += this.angInc;
sphereC.rotation.y = this.curTrackAngle;
this.inLoopCounter += 1 ;
// var angleC = omegaG * vel*dT*this.inLoopCounter/this.trackCircumP; // maybe 5/4 too fast
// var angleC = omegaK * vel*dT*this.inLoopCounter/this.trackCircumP; // faster 4/3 too fast
var angleC = vel*5*dT*this.inLoopCounter/this.trackCircumP; // I found a perfect(?) 5 by trial and effort
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
};
if ( (sphereC.position.x >= 0) && ( this.cClicks > this.increments*1.25 )) {
sphereC.position.set( -2*this.r, 0, this.r );
this.curTrackAngle = 0;
this.inLoop = false ;
this.inLoopCounter = 0;
this.cClicks = 0 ;
};
sphereS.rotation.z -= this.ang2Inc;
sphereS.position.x += dT*vel;
if (( sphereS.position.x >= 8*this.r ) && ( this.sClicks > this.increments*1.25 )){
sphereS.position.set( -2*this.r, 0, this.tracSep ); // this.sTrackZ[j] );
this.curBallAngle = 0;
this.sClicks = 0;
};
renderer.render( scene, camera );
};
I noticed you noticed, but here I go on a bit about dT = 0.024.
// this.increments = 4167; // A counter, not a clock. Here are the experimental track times.
// Select T, the desired time to travel d. 4167 = roughly 100 secs. 500 about 12 sec, 2500 = 1 min
// 5000, just a second or two over two minutes to complete the courses.
// dT = T/this.increments = 120/5000 = 0.024 sec, 90/3750 = 0.024. Why is dT fixed?
I’m using a counter, not a clock. I suppose I tapped into the CPU rate?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Did you notice - that last image I posted - that if you cross your eyes you can see a third, middle, three dimensional sphere? Stereopsis - try this one.
var T = this.increments*1.25*dT; // total time
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
Nevyn wote. This will always rotate from a set position, it will not add …
Think about creating a Quaternion from the angle. Apply the quaternion to the position vector of the ball.
Airman. I posted in some alarm because I saw I wasn't controlling the sphere in the circular track . Correcting requestAnimationFrame( animateDynamic ); and using the this.inLoopCounter properly positions the sphere on the circular track. I believe that solution is adequate but will change it to a quaternion if you like – are you sure?
var angleC = vel*5*dT*this.inLoopCounter/this.trackCircumP;
I still need to figure out why 5 worked in angleC. I expected omegaK to work. What next? Do you have any idea?
.
Did you notice - that last image I posted - that if you cross your eyes you can see a third, middle, three dimensional sphere? Stereopsis - try this one.
var T = this.increments*1.25*dT; // total time
Airman. I’m just using the total time T, incremental time dT, and the total distance d = 10*r and velocity vel. I suppose I can stick to just the next dT*vel. I'm not sure what you mean by dynamic.Nevyn wote. Why is this line needed? You shouldn't need the total time in a dynamic calculation since it should only be thinking about the transition from the current position to the next. i.e. 1 frame.
Airman. Increments is used as the Time control. The number of increments applies to the circular track or the 8*r straight track. The number of increments for the entire track, including the initial 2*r section becomes 1.25 times this.increments.Nevyn wote. What does the 1.25 stand for? I guess you are using it as the speed control since it is effectively changing the value of dT.
sphereC.position.set( this.r*Math.sin( angleC ), 0, this.r*Math.cos( angleC ));
Nevyn wote. This will always rotate from a set position, it will not add …
Think about creating a Quaternion from the angle. Apply the quaternion to the position vector of the ball.
Airman. I posted in some alarm because I saw I wasn't controlling the sphere in the circular track . Correcting requestAnimationFrame( animateDynamic ); and using the this.inLoopCounter properly positions the sphere on the circular track. I believe that solution is adequate but will change it to a quaternion if you like – are you sure?
var angleC = vel*5*dT*this.inLoopCounter/this.trackCircumP;
I still need to figure out why 5 worked in angleC. I expected omegaK to work. What next? Do you have any idea?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
I know the attraction of it, but trying to change the existing function will be error prone. It really is a different way of seeing the problem, so it is better to start afresh. Look over my previous outline here: https://milesmathis.forumotion.com/t554p25-animate-the-pi-4-experiment#5635.
Setup an array of track sections where each section knows its start and end distance. Note that it is not a 3D point. It is the distance along the track, regardless of curvature. The ball will also need to know the distance along the track that it has traveled (which will be updated every frame). They will be compared in order to find the current track section(s) to use.
Everything is with respect to the current frame. At the start of the function, we are at the current point along the tracks. By the end of the function, we are at the next point along the tracks. You just need to fill in the gap with the rules of the system. The only tricky part is when you are on a straight track and a curved track section during the same frame, but even that isn't hard to deal with, it just requires a little bit of thought.
What do I mean by dynamic? That it reacts to its current situation. The code shows no signs of knowing before or after. It isn't predicted, and then made to go through the motions. Think of things from the balls perspective. That is what everything happens to in this system. That is how the code should be structured. The ball only has a few simple questions:
Where am I?
What can I do?
The track represents the limitations of the ball. It is what guides it. So the ball is going to think of things in respect to that.
Where am I on this track?
What type of section am I in?
What can I do on this type of section?
How much time do I have to do it?
Setup an array of track sections where each section knows its start and end distance. Note that it is not a 3D point. It is the distance along the track, regardless of curvature. The ball will also need to know the distance along the track that it has traveled (which will be updated every frame). They will be compared in order to find the current track section(s) to use.
Everything is with respect to the current frame. At the start of the function, we are at the current point along the tracks. By the end of the function, we are at the next point along the tracks. You just need to fill in the gap with the rules of the system. The only tricky part is when you are on a straight track and a curved track section during the same frame, but even that isn't hard to deal with, it just requires a little bit of thought.
What do I mean by dynamic? That it reacts to its current situation. The code shows no signs of knowing before or after. It isn't predicted, and then made to go through the motions. Think of things from the balls perspective. That is what everything happens to in this system. That is how the code should be structured. The ball only has a few simple questions:
Where am I?
What can I do?
The track represents the limitations of the ball. It is what guides it. So the ball is going to think of things in respect to that.
Where am I on this track?
What type of section am I in?
What can I do on this type of section?
How much time do I have to do it?
Re: Animate the PI = 4 experiment
.
Evidence of effort.
I'm working on the section/boundary frame-end/re-positioning, expecting to see a single to(the)boundary value less than Td*vel - NOT many values. Something gets hung up at the first and second 2*this.r boundary. Routine stuff. The code is too ugly to share at present, I think I need another day or two to get this to where I can share.
.
Evidence of effort.
I'm working on the section/boundary frame-end/re-positioning, expecting to see a single to(the)boundary value less than Td*vel - NOT many values. Something gets hung up at the first and second 2*this.r boundary. Routine stuff. The code is too ugly to share at present, I think I need another day or two to get this to where I can share.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
No rush. Just work through it. Think about it. Make sure you understand why the code is the way it is, at least mathematically.
Re: Animate the PI = 4 experiment
.
Status. Almost there.
I believe I’ve made progress but it’s hard to tell. In order to keep track of both sphereC and sphereS I created a heap of new variables and so keep the two spheres separate. All that’s left is for me to make the angle as a function of a point on the circumference. I’ve done it once already but you suggested I use quaternions instead. I tried and feel particularly frustrated in not having done so. I recall you using that solution - How exactly did you do that?
I was curious about whether I understood your last comment about frames, and ended up on this three.js Cookbook free chapter. Determining The Frame Rate For Your Scene.
https://subscription.packtpub.com/book/web_development/9781783981182/1/ch01lvl1sec15/determining-the-frame-rate-for-your-scene
For once, the instructions were so simple I didn’t need to read them, the code 'pictures' were enough. Everything from including the new source
New function createStats() {}; right after function onWindowResize() { }
Created a new var stats. And included a stats.update(); at the end of the animateDynamic function.
The FPS thingee appeared as if by majic.
.
Status. Almost there.
I believe I’ve made progress but it’s hard to tell. In order to keep track of both sphereC and sphereS I created a heap of new variables and so keep the two spheres separate. All that’s left is for me to make the angle as a function of a point on the circumference. I’ve done it once already but you suggested I use quaternions instead. I tried and feel particularly frustrated in not having done so. I recall you using that solution - How exactly did you do that?
I was curious about whether I understood your last comment about frames, and ended up on this three.js Cookbook free chapter. Determining The Frame Rate For Your Scene.
https://subscription.packtpub.com/book/web_development/9781783981182/1/ch01lvl1sec15/determining-the-frame-rate-for-your-scene
For once, the instructions were so simple I didn’t need to read them, the code 'pictures' were enough. Everything from including the new source
- Code:
<script src="js/libs/stats.min.js"></script>
New function createStats() {}; right after function onWindowResize() { }
Created a new var stats. And included a stats.update(); at the end of the animateDynamic function.
The FPS thingee appeared as if by majic.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Everything appears to be working properly, including rolling spins, under the new animate Dynamic function.
I used parametric rotations and not quaternions to position and rotate the sphere on the curved track.
Here’s the animateDynamic function
I believe I followed the intent if not the letter of the algorithm you identified on 24 September. https://milesmathis.forumotion.com/t554p25-animate-the-pi-4-experiment#5635 , let me know if you see otherwise or want anything else changed.
I'll be cleaning up then resuming the next challenge, the controls.
.
Everything appears to be working properly, including rolling spins, under the new animate Dynamic function.
I used parametric rotations and not quaternions to position and rotate the sphere on the curved track.
- Code:
var trackAngle = 2*Math.PI*(this.distNextC - cTracSectK)/this.trackCircumK;
sphereC.position.set( this.r*Math.sin( trackAngle ), 0, this.r*Math.cos( trackAngle ));
Here’s the animateDynamic function
- Code:
function animateDynamic() {
requestAnimationFrame( animateDynamic );
var dT = 0.006;
this.T = this.increments * dT; // this.increments = 1000. T = 1000*0.024 = 24 sec
var vel = 10 * this.r / T;
// from daControlValues ///////////
// this.distTraveledS = 0;
// this.distTraveledC = 0;
// this.T;
// this.trackCircumP = 2*Math.PI*this.r;
// this.trackCircumK = 8*this.r;
///////////////////////////////////////
var cTrackLengthP = 2*this.r + 2*Math.PI*this.r;
var cTrackLengthK = 2*this.r + 8*this.r;
var cTracSectP = cTrackLengthP/5;
var cTracSectK = cTrackLengthK/5;
var sTrackLength = 10*this.r;
var sTrackSect = 10*this.r/5;
var quaternion = new THREE.Quaternion;
sphereS.rotation.z -= this.ang2Inc;
sphereC.rotation.z -= this.ang2Inc;
this.distNextS = this.distTraveledS + dT*vel;
this.distNextC = this.distTraveledC + dT*vel;
this.curSectionS = Math.floor( this.distTraveledS / sTrackSect );
this.curSectionC = Math.floor( this.distTraveledC / cTracSectK );
this.nexSectionS = Math.floor( this.distNextS / sTrackSect );
this.nexSectionC = Math.floor( this.distNextC / cTracSectK );
if ( this.nexSectionS == this.curSectionS + 1 ){ // sphereS has passed a section boundary.
var pastBoundary = this.distNextS - this.nexSectionS * 2 * this.r;
//this.distNextS = this.distTraveledS + dT*vel - pastBoundary; // sphereS is now on the section boundary.
//console.log( 'nexSectionS = ' + this.nexSectionS + ', curSectionS = ' + this.curSectionS + ', pastBoundary = ' + pastBoundary );
//console.log( 'distTraveledS = ' + this.distTraveledS + ', distNextS = ' + this.distNextS );
this.curSectionS = this.curSectionS + 1;
};
if ( this.nexSectionC == this.curSectionC + 1 ){ // sphereC has passed a section boundary.
var pastBoundary = this.distNextC - this.nexSectionC * 2 *this.r;
//this.distNextC = this.distTraveledS + dT*vel - pastBoundary; // sphereC is now on the section boundary.
//console.log( 'nexSectionC = ' + this.nexSectionC + ', curSectionC = ' + this.curSectionC + ', pastBoundary = ' + pastBoundary );
//console.log( 'distTraveledC = ' + this.distTraveledC + ', distNextC = ' + this.distNextC );
//this.curSectionC = this.curSectionC + 1;
this.curSectionC = this.nexSectionC;
};
if ( this.distNextC < cTracSectK ) { // cTrackLengthP // the sphere stops at the pi(g) mark.
sphereC.position.set( -2*this.r+ this.distNextC, 0, this.r ); // ( -2*this.r+ this.distNextS, 0, this.r ); // sTrackLength
this.distTraveledC = this.distNextC;
this.curSectionC = this.nexSectionC;
}
else if (( this.distNextC >= cTracSectK ) && ( this.distNextC < cTrackLengthK )) { // In the loop
var trackAngle = 2*Math.PI*(this.distNextC - cTracSectK)/this.trackCircumK;
sphereC.position.set( this.r*Math.sin( trackAngle ), 0, this.r*Math.cos( trackAngle ));
sphereC.rotation.y = trackAngle;
this.distTraveledC = this.distNextC;
this.curSectionC = this.nexSectionC;
}
else if ( this.distNextC >= cTrackLengthK ) {
sphereC.position.set( -2*this.r, 0, this.r );
this.distTraveledC = 0;
this.curSectionC = 0;
};
if ( this.distNextS < sTrackLength ) {
sphereS.position.set( -2*this.r+ this.distNextS, 0, this.tracSep );
this.distTraveledS = this.distNextS;
this.curSectionS = this.nexSectionS;
}
else if ( this.distNextS >= sTrackLength ) {
sphereS.position.set( -2*this.r, 0, this.tracSep );
this.distTraveledS = 0;
this.curSectionS = 0;
};
renderer.render( scene, camera );
stats.update();
};
I believe I followed the intent if not the letter of the algorithm you identified on 24 September. https://milesmathis.forumotion.com/t554p25-animate-the-pi-4-experiment#5635 , let me know if you see otherwise or want anything else changed.
I'll be cleaning up then resuming the next challenge, the controls.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Sorry Charge Field Fans, it's been difficult slogging. Mostly frustration in not getting a working dat GUI installed.
For those interested in the programming, here's a reference, Introduction to THREE.js - 4 – Creating and Controlling an Animation with the DAT.GUI Interface
In trying to follow the directions I first came to realize my code is probably too complicated. Here it is, stripped of all the variables and functions.
But, surprise, surprise; I’ve also come to realize that both those sources identify the animation function by the same name - the function render, preceded by the function call render().
It's too soon to say, at least I've got something to work on.
.
Sorry Charge Field Fans, it's been difficult slogging. Mostly frustration in not getting a working dat GUI installed.
For those interested in the programming, here's a reference, Introduction to THREE.js - 4 – Creating and Controlling an Animation with the DAT.GUI Interface
In trying to follow the directions I first came to realize my code is probably too complicated. Here it is, stripped of all the variables and functions.
- Code:
init();
animateDynamic();
- Code:
]);
- Code:
// function init() {
var grp = new THREE.Group();
scene = new THREE.Scene();
this.r = 1; // Track radius
this.w = 0.25// track width
this.q = 0.5; // track separation
…
stats = createStats();
document.body.appendChild( stats.domElement );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, true );
renderer.render( scene, camera );
stats.update();
//};
But, surprise, surprise; I’ve also come to realize that both those sources identify the animation function by the same name - the function render, preceded by the function call render().
- Code:
render();
function render() {
... // some action
requestAnimationFrame(render);
renderer.render(scene, camera);
}
It's too soon to say, at least I've got something to work on.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
The heart of a ThreeJS application is the render function. It does not need to be called render. It can be any name you want. It is the way you define and use it that matters.
The most important, even critical, part is that call to requestAnimationFrame, which is given the function to use for rendering. i.e. this function which happens to be called render.
You have to call the render function your self on the first time, but it will repeatedly call itself (although not recursively) through the requestAnimationFrame function. This is the way browsers have defined an animating application. If you were working in a more traditional language, with no browser, then you would need to create a loop that does this sort of thing. It is called a render loop. Since ThreeJS is in a browser, some of that is handled by the browser, so you don't see a normal loop, but it should be thought of as one.
Commenting out the init function declaration, but leaving the guts of it still executing, will cause those statements to be executed where ever they are specified in the code. That may not be the best, or even a good, place for it to be executed. Also, you have references to this in that function, but there is no this, so I am not sure where those values end up (probably on the window object supplied by the browser).
You don't need an init function, but you do need initialization code. Most of the ThreeJS examples just write that init code where they want it (with respect to the rest of the code so that it is executed when it should). However, I prefer an explicit function because it is more flexible to change when it is executed and it is easier to copy it to another project. It also allows you to use intermediate variables within that function. If you do that without a function, then those variables exist for the life time of the application. They also cause clutter in the window object and can cause problems by overwriting other variables with the same name.
For example, I had problems in Atomic Viewer because I had a variable called performance. I didn't know that the browser already has a variable with that name that was used for fast time calculations, such as those required by ThreeJS. It took some time to find that problem and fix it.
I'm not sure what your problems are with DATGUI, but something to be aware of is that it uses an object that it references properties in. That probably sounds confusing so I will try to explain it.
Let's say you want 2 menu items, one called One and one called Two. The easiest way to provide that is to create an object with properties using those names, like this:
Now, you just tell DATGUI that you want to create a menu item for each of them.
See how DATGUI is actually given the parent object, menuData, and not the values for One and Two? It will retrieve those values when it wants them and it will update them when the user changes its value in the menu. You can also update them yourself, but you then need to tell DATGUI to update the menu or the user won't see those changes.
The most important, even critical, part is that call to requestAnimationFrame, which is given the function to use for rendering. i.e. this function which happens to be called render.
You have to call the render function your self on the first time, but it will repeatedly call itself (although not recursively) through the requestAnimationFrame function. This is the way browsers have defined an animating application. If you were working in a more traditional language, with no browser, then you would need to create a loop that does this sort of thing. It is called a render loop. Since ThreeJS is in a browser, some of that is handled by the browser, so you don't see a normal loop, but it should be thought of as one.
Commenting out the init function declaration, but leaving the guts of it still executing, will cause those statements to be executed where ever they are specified in the code. That may not be the best, or even a good, place for it to be executed. Also, you have references to this in that function, but there is no this, so I am not sure where those values end up (probably on the window object supplied by the browser).
You don't need an init function, but you do need initialization code. Most of the ThreeJS examples just write that init code where they want it (with respect to the rest of the code so that it is executed when it should). However, I prefer an explicit function because it is more flexible to change when it is executed and it is easier to copy it to another project. It also allows you to use intermediate variables within that function. If you do that without a function, then those variables exist for the life time of the application. They also cause clutter in the window object and can cause problems by overwriting other variables with the same name.
For example, I had problems in Atomic Viewer because I had a variable called performance. I didn't know that the browser already has a variable with that name that was used for fast time calculations, such as those required by ThreeJS. It took some time to find that problem and fix it.
I'm not sure what your problems are with DATGUI, but something to be aware of is that it uses an object that it references properties in. That probably sounds confusing so I will try to explain it.
Let's say you want 2 menu items, one called One and one called Two. The easiest way to provide that is to create an object with properties using those names, like this:
- Code:
var menuData = {
One: 1,
Two: 2
};
Now, you just tell DATGUI that you want to create a menu item for each of them.
- Code:
var gui = ...
gui.add( menuData, 'One' );
gui.add( menuData, 'Two' );
See how DATGUI is actually given the parent object, menuData, and not the values for One and Two? It will retrieve those values when it wants them and it will update them when the user changes its value in the menu. You can also update them yourself, but you then need to tell DATGUI to update the menu or the user won't see those changes.
Re: Animate the PI = 4 experiment
.
We can control spherical hues.
Thanks Nevyn, I must say, you bring out the best in me. I'm very grateful. OK, lots of changes. init() remains intact. I renamed animateDynamic() to render() – and would have killed a chicken too if I had one. render() is called from close to the end of the init function. I removed any remains – lingering vars - of previous animations.
I eliminated all instances of, ”this.”. Now global variables are declared in the main, before init() is called. Shown here.
Only increments and Color works “properly”, mostly ad hoc, color was added as an afterthought, and I didn't expect keeping it.
Changing w and q will knock at least one ball off off its track. This may require more thought than I’d expected.
I’ll continue cleaning up before posting any additional code changes.
Thanks again.
.
We can control spherical hues.
Thanks Nevyn, I must say, you bring out the best in me. I'm very grateful. OK, lots of changes. init() remains intact. I renamed animateDynamic() to render() – and would have killed a chicken too if I had one. render() is called from close to the end of the init function. I removed any remains – lingering vars - of previous animations.
I eliminated all instances of, ”this.”. Now global variables are declared in the main, before init() is called. Shown here.
- Code:
var mesh;
var camera, scene, renderer;
var stats;
var sphereMat;
var r = 1;
var w = 0.25// track width
var q = 0.5; // track separation
var bRadius = 0.25; // *r;
var distTraveledS = 0;
var distTraveledC = 0;
var increments = 100;
init();
function init() {
Only increments and Color works “properly”, mostly ad hoc, color was added as an afterthought, and I didn't expect keeping it.
Changing w and q will knock at least one ball off off its track. This may require more thought than I’d expected.
I’ll continue cleaning up before posting any additional code changes.
Thanks again.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
Showing a problem, the two spheres are off their identified tracks, and close to their finishing ‘locations’.
I’m still learning about the control panel. I need to include the ball radius parameter.
I moved all functions out of the init function. That appeared to improve the fps from about 32 to 38.
There’s a problem when changing the track parameters. Above you can see that r, the circular track radius has been increased from 1 to 1.4. The balls are in their ‘correct’ locations in space, but the tracks need to be reinitialized when changes are made to r, w, or q.
Since this program is in a constant loop, I may need a re-initialize button. And then I’d like to include a checkbox in order to stop the continuous loop, and another button to launch a single runs.
Anyway, Here’s the entire body (minus the html head), problems and all. I'll keep working to improve it.
Showing a problem, the two spheres are off their identified tracks, and close to their finishing ‘locations’.
I’m still learning about the control panel. I need to include the ball radius parameter.
I moved all functions out of the init function. That appeared to improve the fps from about 32 to 38.
There’s a problem when changing the track parameters. Above you can see that r, the circular track radius has been increased from 1 to 1.4. The balls are in their ‘correct’ locations in space, but the tracks need to be reinitialized when changes are made to r, w, or q.
Since this program is in a constant loop, I may need a re-initialize button. And then I’d like to include a checkbox in order to stop the continuous loop, and another button to launch a single runs.
Anyway, Here’s the entire body (minus the html head), problems and all. I'll keep working to improve it.
- Code:
<body>
<script src="js/three.min.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
var camera, scene, renderer;
var stats;
var gui;
var sphereMat;
var r = 1;
var w = 0.25; // track width
var q = 0.5; // track separation
var bRadius = 0.25; // *r;
var distTraveledS = 0;
var distTraveledC = 0;
var TracTSecs = 25; // seconds
init();
function init() {
var grp = new THREE.Group();
scene = new THREE.Scene();
var viewSize = 8*r;
var widt = window.innerWidth;
var heit = window.innerHeight;
var aspectRatio = widt/heit;
var tubeTot = 60; // 5, 120
var tRadius = bRadius; // r; // 0.75 * r;
var tubeInc = 10*r/tubeTot;
// Centerpath coordinate arrays.
var tracSep = r+q+w;
var sTrackX = [ -2*r, 0, 2*r, 4*r, 6*r, 8*r, 2*Math.PI*r ];
var cTrackX = [ -2*r, 0, r, 0, -r, 0 ];
//camera = new THREE.PerspectiveCamera( 70, aspectRatio, 0.1*r, 100*r );
camera = new THREE.OrthographicCamera( -aspectRatio*viewSize/2, aspectRatio*viewSize/2, viewSize/2, -viewSize/2);
camera.position.set( 0, 0, 4*r );
camera.lookAt(0, 0, -5*r);
controls = new THREE.OrbitControls( camera, renderer ); // comes with errors
controls.target.set( 0, 0, -5*r );
camera.updateProjectionMatrix();
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//scene.background = new THREE.Color('FFFFFF'); // #009900 pool table green // #0000FF nice high contrast blue //
sphereMat = new THREE.MeshBasicMaterial( { wireframe: true, color: 'yellow' } ); // yellow
var material = new THREE.LineBasicMaterial( { color: 'red', linewidth: 0.5*r } ); // markers
var material2 = new THREE.LineBasicMaterial( { color: 'grey' } ); // Increment markers
var MAT_LINE_CP = new THREE.LineBasicMaterial( { color: 0x00cc00, linewidth: 0.5 } ); // distances
//cTrackCenter -4 curved paths
for(th=1;th<=360;th+=1) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 1);
if (th === 359) { radians2 = (Math.PI/180) }
for ( i = -1; i < 2; i=i+2 ) {
var configRadius = r + i*w;
var XYPlaneLine = new THREE.Geometry();
XYPlaneLine.vertices.push(
new THREE.Vector3( configRadius * Math.cos(radians1), 0, -configRadius*Math.sin(radians1) ),
new THREE.Vector3( configRadius * Math.cos(radians2), 0, -configRadius*Math.sin(radians2) ) );
var XYLine = new THREE.Line( XYPlaneLine, MAT_LINE_CP);
grp.add(XYLine);
configRadius = r + i*w;
var XYPlaneLine = new THREE.Geometry();
XYPlaneLine.vertices.push(
new THREE.Vector3( r * Math.cos(radians1), i*tRadius, -r*Math.sin(radians1) ),
new THREE.Vector3( r * Math.cos(radians2), i*tRadius, -r*Math.sin(radians2) ));
var XYLine = new THREE.Line( XYPlaneLine, MAT_LINE_CP);
grp.add(XYLine);
};
};
// S track markers
for ( j = 0; j < 7; j++ ) {
var sHML = new THREE.Geometry( 1, 1, 1 );
sHML.vertices.push(new THREE.Vector3( sTrackX[j], 0, r+q+2*w ) );
sHML.vertices.push(new THREE.Vector3( sTrackX[j], 0, r+q ) );
var sHMLine = new THREE.Line( sHML, material );
grp.add( sHMLine ); // horizontal
var sVML = new THREE.Geometry( 1, 1, 1 );
sVML.vertices.push(new THREE.Vector3( sTrackX[j], w, tracSep ) ); // sTrackZ[j]
sVML.vertices.push(new THREE.Vector3( sTrackX[j], -w, tracSep ) );
var sVMLine = new THREE.Line( sVML, material );
grp.add( sVMLine ); // vertical
};
// C track straight section markers
for ( m = 0; m < 2; m++ ) {
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( cTrackX[m], 0, r-w ) );
geometry.vertices.push(new THREE.Vector3( cTrackX[m], 0, r+w ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( cTrackX[m], -tRadius, r ) );
geometry.vertices.push(new THREE.Vector3( cTrackX[m], tRadius, r ) );
var line = new THREE.Line( geometry, material );
grp.add( line );
};
// parallel circles curved path's initial straight section
for( ber=0; ber<tubeTot/5+1; ber++ ) { ///////////changed
for(th=1;th<=360;th+=12) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 12);
if (th === 348) { radians2 = (Math.PI/180) }
var yZPlaneCircle = new THREE.Geometry();
yZPlaneCircle.vertices.push( //viewing x and y.
new THREE.Vector3( 0, tRadius*Math.sin(radians1), -tRadius * Math.cos(radians1) ),
new THREE.Vector3( 0, tRadius*Math.sin(radians2), -tRadius * Math.cos(radians2) ) );
var tCircle = new THREE.Line( yZPlaneCircle, material2);
tCircle.position.set( -2*r+ber*tubeInc, 0, r );
grp.add(tCircle);
};
};
// parallel circles straight path
for( num=0; num<=tubeTot; num++ ) {
for(th=1;th<=360;th+=18) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 18);
if (th === 342) { radians2 = (Math.PI/180) }
var yZPlaneCircle = new THREE.Geometry();
yZPlaneCircle.vertices.push( //viewing x and y.
new THREE.Vector3( 0, tRadius*Math.sin(radians1), -tRadius * Math.cos(radians1) ),
new THREE.Vector3( 0, tRadius*Math.sin(radians2), -tRadius * Math.cos(radians2) ) );
var tCircle = new THREE.Line( yZPlaneCircle, material2);
tCircle.position.set( -2*r+num*tubeInc, 0, tracSep );
grp.add(tCircle);
};
};
// parallel circles circular path
var curAngl;
var curAnglInc = 2*Math.PI*r/(4*tubeTot/5);
var yZPlaneCircle = new THREE.Geometry();
for(th=1;th<=360;th+=18) {
var radians1 = (Math.PI/180) * th;
var radians2 = (Math.PI/180) * (th + 18);
if (th === 342) { radians2 = (Math.PI/180) }
yZPlaneCircle.vertices.push(
new THREE.Vector3( 0, tRadius*Math.sin(radians1), -tRadius * Math.cos(radians1) ),
new THREE.Vector3( 0, tRadius*Math.sin(radians2), -tRadius * Math.cos(radians2) ) );
};
for( ber=0; ber < tubeTot; ber++ ) {
var tCircle = new THREE.Line( yZPlaneCircle, material2);
curAngl = ber*curAnglInc;
tCircle.rotation.y = curAngl + Math.PI/2;
tCircle.position.set( r * Math.cos(curAngl), 0, -r * Math.sin(curAngl) );
grp.add(tCircle);
};
// S track lengths
for ( k = -1; k < 2; k=k+2 ) {
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( sTrackX[0], 0, r+w+q+k*w ) );
geometry.vertices.push(new THREE.Vector3( sTrackX[5], 0, r+w+q+k*w ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
// S track lengths:
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( sTrackX[0], k*tRadius, r+w+q ) );
geometry.vertices.push(new THREE.Vector3( sTrackX[5], k*tRadius, r+w+q ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
// C track lengths: +/-z edges
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( cTrackX[0], 0, r-k*w ) );
geometry.vertices.push(new THREE.Vector3( cTrackX[1], 0, r-k*w ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
// C track lengths:
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( cTrackX[0], k*tRadius, r ) );
geometry.vertices.push(new THREE.Vector3( cTrackX[1], k*tRadius, r ) );
var line = new THREE.Line( geometry, MAT_LINE_CP );
grp.add( line );
}
// C track markers
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( r-w, 0, 0 ) );
geometry.vertices.push(new THREE.Vector3( r+w, 0, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track One Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( r, -tRadius, 0 ) );
geometry.vertices.push(new THREE.Vector3( r, tRadius, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track One Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( 0, 0, -r-w ) );
geometry.vertices.push(new THREE.Vector3( 0, 0, -r+w ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Two Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( 0, -tRadius, -r ) );
geometry.vertices.push(new THREE.Vector3( 0, tRadius, -r ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Two Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -r-w, 0, 0 ) );
geometry.vertices.push(new THREE.Vector3( -r+w, 0, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Three Marker
var geometry = new THREE.Geometry( 1, 1, 1 );
geometry.vertices.push(new THREE.Vector3( -r, -tRadius, 0 ) );
geometry.vertices.push(new THREE.Vector3( -r, tRadius, 0 ) );
var line = new THREE.Line( geometry, material );
grp.add( line ); // C track Three Marker
// Balls
var sphereGeom = new THREE.SphereGeometry( bRadius, 16, 16 );
sphereC = new THREE.Mesh( sphereGeom, sphereMat );
sphereC.position.set( -2*r, 0, r );
sphereS = new THREE.Mesh( sphereGeom, sphereMat );
sphereS.position.set( -2*r, 0, tracSep );
ballOne = new THREE.Object3D();
ballOne.add(sphereC);
var ballTwo = new THREE.Object3D();
ballTwo.add(sphereS);
grp.add( ballOne, ballTwo );
grp.position.set( -2.5*r, 0, -6*r ); //repositions the world rotation point
scene.add(grp);
stats = createStats();
document.body.appendChild( stats.domElement );
window.addEventListener( 'resize', onWindowResize, true );
render();
displaygui();
};
function displaygui(){
gui = new dat.GUI();
parameters =
{
r: 1,
w: 0.25,
q: 0.125,
TracTSecs: 25,
color: "#ffff00",
};
var folder1 = gui.addFolder('Tracks');
var rTrack = folder1.add( parameters, 'r' ).min(1).max(10).step(0.1).listen();
var wTrack = folder1.add( parameters, 'w' ).min(0.01).max(0.5).step(.01).listen();
var qTrack = folder1.add( parameters, 'q' ).min(0).max(1).step(0.01).listen();
//folder1.open();
rTrack.onChange(function(value)
{ r = value; });
wTrack.onChange(function(value)
{ w = value; });
qTrack.onChange(function(value)
{ q = value; });
var TracTInSecs = gui.add( parameters,'TracTSecs').min(3).max(200).step(1).listen();
TracTInSecs.onChange(function(value)
{ TracTSecs = value; });
var ballColor = gui.addColor( parameters, 'color' ).name('Color').listen();
ballColor.onChange(function(value) // onFinishChange
{ sphereMat.color.setHex( value.replace("#", "0x") ); });
function updateStuff() {
r = parameters.r;
w = parameters.w;
q = parameters.q;
TracTSecs = parameters.TracTSecs;
sphereMat.color.setHex( parameters.color.replace("#", "0x") );
};
};
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
};
function createStats() {
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0';
stats.domElement.style.top = '0';
return stats;
};
function render() {
var T = TracTSecs;
var vel = 10 * r / T;
var increments = T*30; // roughly the fps
var dT = T/increments;
var tracSep = r+q+w; // duplicated in init. ////////////
var trackCircumP = 2*Math.PI*r;
var trackCircumK = 8*r;
var cTrackLengthP = 2*r + 2*Math.PI*r;
var cTrackLengthK = 2*r + 8*r;
var cTracSectP = cTrackLengthP/5;
var cTracSectK = cTrackLengthK/5;
var sTrackLength = 10*r;
var sTrackSect = 10*r/5;
var quaternion = new THREE.Quaternion;
var bCircum = 2 * Math.PI * bRadius;
var ang2rot = 10*r/bCircum;
var kMult = 4/Math.PI;
var ang2Inc = 4 * ang2rot * kMult/ increments;
var distNextS = distTraveledS + dT*vel;
var distNextC = distTraveledC + dT*vel;
var curSectionS = Math.floor( distTraveledS / sTrackSect );
var curSectionC = Math.floor( distTraveledC / cTracSectK );
var nexSectionS = Math.floor( distNextS / sTrackSect );
var nexSectionC = Math.floor( distNextC / cTracSectK );
sphereS.rotation.z -= ang2Inc;
sphereC.rotation.z -= ang2Inc;
if ( nexSectionS == curSectionS + 1 ){
var pastBoundary = distNextS - nexSectionS * 2 * r;
curSectionS = curSectionS + 1;
};
if ( nexSectionC == curSectionC + 1 ){
var pastBoundary = distNextC - nexSectionC * cTracSectK ; // 2 *r; //
curSectionC = nexSectionC;
};
if ( distNextC < cTracSectK ) {
sphereC.position.set( -2*r+ distNextC, 0, r );
distTraveledC = distNextC;
curSectionC = nexSectionC;
}
else if (( distNextC >= cTracSectK ) && ( distNextC < cTrackLengthK )) { // In the loop
var trackAngle = 2*Math.PI*(distNextC - cTracSectK)/trackCircumK;
sphereC.position.set( r*Math.sin( trackAngle ), 0, r*Math.cos( trackAngle ));
sphereC.rotation.y = trackAngle;
distTraveledC = distNextC;
curSectionC = nexSectionC;
}
else if ( distNextC >= cTrackLengthK ) {
sphereC.position.set( -2*r, 0, r );
distTraveledC = 0;
curSectionC = 0;
};
if ( distNextS < sTrackLength ) {
sphereS.position.set( -2*r+ distNextS, 0, tracSep );
distTraveledS = distNextS;
curSectionS = nexSectionS;
}
else if ( distNextS >= sTrackLength ) {
sphereS.position.set( -2*r, 0, tracSep );
distTraveledS = 0;
curSectionS = 0;
};
renderer.render( scene, camera );
requestAnimationFrame( render );
stats.update();
};
</script>
</body>
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
Why does the user need to change these things? I can't see a reason to change the track width (or ball). The only control I think you absolutely need is a speed control. Maybe some start, stop, reset controls, and a step control to move it frame by frame if you feel up to it.
Re: Animate the PI = 4 experiment
.
Ortho view, near the finish lines.
We have a speed control, var trTimeInSecs. The user can dial up the number of seconds it takes for the balls to complete the tracks. Increment is now a function of trTimeInSecs, var increment = trTimeInSecs *35. Alternatively, trTimeInSecs can be converted into a velocity by dividing by 10*r.
Color kind of grows on you, I’ll get rid of it if you like.
Track changes. I thought we might give the user the option two or three options: 1) Scale the PI Equal 4 Experiment to match the values used by StevenO – where the ball radius is less than a tenth of the curved track radius and the tracks are completed in about a second. Or 2) Scale the ball radii to about a quarter of the track radius to allow close examination of the rolling action, which is what is shown by most of the recent PI Equal 4 images. Let the the user access to swap out the cycloid, pi(k) and expected rolling actions pi(g) to see the difference. Or 3) Scale the balls a magnitude smaller than that.
Camera choice. Let’s give the user the choice between an orthogonal versus perspective cameras –both cameras have their advantages and disadvantages as the prior images have shown. Might something like this work to switch cameras? Or might a reset capability simplify things?
Yes indeedy. I’m sure you could tell I needed a break; I’m fully recovered now. That dat gui had been a huge bugaboo for me for a couple of years now. Good to get past that mental barrier.
I’m not at all certain the curved track sphere is rolling correctly, and would very much hope that anyone may examine the rolling as well. I believe start, stop, (back and forth) reset and step controls would allow that.
Feel free to correct my thinking.
.
Ortho view, near the finish lines.
We have a speed control, var trTimeInSecs. The user can dial up the number of seconds it takes for the balls to complete the tracks. Increment is now a function of trTimeInSecs, var increment = trTimeInSecs *35. Alternatively, trTimeInSecs can be converted into a velocity by dividing by 10*r.
Color kind of grows on you, I’ll get rid of it if you like.
Track changes. I thought we might give the user the option two or three options: 1) Scale the PI Equal 4 Experiment to match the values used by StevenO – where the ball radius is less than a tenth of the curved track radius and the tracks are completed in about a second. Or 2) Scale the ball radii to about a quarter of the track radius to allow close examination of the rolling action, which is what is shown by most of the recent PI Equal 4 images. Let the the user access to swap out the cycloid, pi(k) and expected rolling actions pi(g) to see the difference. Or 3) Scale the balls a magnitude smaller than that.
Camera choice. Let’s give the user the choice between an orthogonal versus perspective cameras –both cameras have their advantages and disadvantages as the prior images have shown. Might something like this work to switch cameras? Or might a reset capability simplify things?
- Code:
if (this._cameraState.type == CameraMode.Perspective) {
this._mainCamera = this._perspectiveCamera;
this._mainCamera.position.copy(this._orthographicCamera.position);
this._mainCamera.rotation.copy(this._orthographicCamera.rotation);
} else if (this._cameraState.type == CameraMode.Orthographic) {
this._mainCamera = this._orthographicCamera;
this._mainCamera.position.copy(this._perspectiveCamera.position);
this._mainCamera.rotation.copy(this._perspectiveCamera.rotation);
}
this._control.object = this._mainCamera;
Maybe some start, stop, reset controls, and a step control to move it frame by frame if you feel up to it.
Yes indeedy. I’m sure you could tell I needed a break; I’m fully recovered now. That dat gui had been a huge bugaboo for me for a couple of years now. Good to get past that mental barrier.
I’m not at all certain the curved track sphere is rolling correctly, and would very much hope that anyone may examine the rolling as well. I believe start, stop, (back and forth) reset and step controls would allow that.
Feel free to correct my thinking.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
The cycloidRoll checkbox is added.
It works. I believe the cycloidRoll option is necessary, and confusing. The default is true, but when cycloidRoll is unchecked as above, extending the seconds to 200 and getting very close to the track, above or toward the side; the balls in either track seem to glide forward above the surface without contact. When cycloidRoll is true, the balls are clearly rolling. The action needs some study.
I’ve had no luck with changing cameras.
One out of two new controls ain't bad. I’ll try finding a way to start/stop and step next.
.
The cycloidRoll checkbox is added.
It works. I believe the cycloidRoll option is necessary, and confusing. The default is true, but when cycloidRoll is unchecked as above, extending the seconds to 200 and getting very close to the track, above or toward the side; the balls in either track seem to glide forward above the surface without contact. When cycloidRoll is true, the balls are clearly rolling. The action needs some study.
- Code:
var ang2Inc;
var bCircum = 2 * Math.PI * bRadius;
var ang2rot = 10*r/bCircum;
var kMult = 4/Math.PI;
if ( kPiOrNot )
ang2Inc = 4 * ang2rot * kMult/ increments;
else
ang2Inc = Math.PI * ang2rot / increments;
I’ve had no luck with changing cameras.
- Code:
// var value = parameters.cameraView
// if ( value )
// camera = cameraO;
// else
// camera = cameraP;
One out of two new controls ain't bad. I’ll try finding a way to start/stop and step next.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
Creating a drop-down menu in DATGUI requires either an array of items to choose from, or an object. The difference is that the array will contain the items themselves, but the object allows you to use a name for each item that is shown to the user, but the actual value selected is something else.
The first one uses an array. When the user selects 'chrome', say, then the text.message value will be set to 'chrome'.
The second one uses an object, so selecting 'Slow' would set text.speed to 0.1.
Note that the array or object is only providing values to select. It is not used to set/retrieve the current value to/from. That still works like all other menu items and comes from the text object, in this example, and the property name specified (message or speed).
- Code:
// Choose from accepted values
gui.add(text, 'message', [ 'pizza', 'chrome', 'hooray' ] );
// Choose from named values
gui.add(text, 'speed', { Stopped: 0, Slow: 0.1, Fast: 5 } );
The first one uses an array. When the user selects 'chrome', say, then the text.message value will be set to 'chrome'.
The second one uses an object, so selecting 'Slow' would set text.speed to 0.1.
Note that the array or object is only providing values to select. It is not used to set/retrieve the current value to/from. That still works like all other menu items and comes from the text object, in this example, and the property name specified (message or speed).
Re: Animate the PI = 4 experiment
.
MaterialOne and MaterialTwo appear to be proper pull down boxes, but they cannot be changed.
Attempting to click on the apparent pull down arrows for MaterialOne or MaterialTwo are futile. No alternatives are displayed and nothing changes. The other three parameters – Seconds, CycloidRoll, and Color all behave properly.
The fact that the spheres’ color can be changed makes it seem likely that I should also be able to change the spheres’ appearance from mesh into a solid or normal color. I can certainly initialize them as mesh basic or normal. Please ignore the Lambert or Phong as they appear as a mat black even though I added a point light to the scene, I’m just interested in getting a pull down. These two functions are from the Stemkowski source I’d cited recently.
Since you offered help, I went over ‘everything’ again. Several changes with little or no progress to show for it.
Here are the displaygui and update sphere functions.
By the way I had also tried implementing the http://workshop.chromeexperiments.com/examples/gui/#2--Constraining-Input example with [ 'pizza', 'chrome', 'hooray' ] that you described in your last post. I’m not delirious, I’m clearly doing something wrong. So I took the opportunity to review arrays and objects
A BRIEF JavaScript TUTORIAL: PART 1
https://discoverthreejs.com/book/introduction/javascript-tutorial-1/
It seems that javaScript has progressed since I learned it. Did you notice that the ‘var’ designators have been replaced with ‘let’ in the two functions above? I replaced all the ‘var’, variable identifiers with ‘const’ (for constants) and ‘let’ the newer variable designator. I learned several details I hadn’t come across before. Here's a great link to Mozilla’s Array page. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
After beating myself silly here I think I found my first clear evidence that I may be able to Pause.
https://discoverthreejs.com/book/first-steps/resize/
Promising?
.
MaterialOne and MaterialTwo appear to be proper pull down boxes, but they cannot be changed.
Attempting to click on the apparent pull down arrows for MaterialOne or MaterialTwo are futile. No alternatives are displayed and nothing changes. The other three parameters – Seconds, CycloidRoll, and Color all behave properly.
The fact that the spheres’ color can be changed makes it seem likely that I should also be able to change the spheres’ appearance from mesh into a solid or normal color. I can certainly initialize them as mesh basic or normal. Please ignore the Lambert or Phong as they appear as a mat black even though I added a point light to the scene, I’m just interested in getting a pull down. These two functions are from the Stemkowski source I’d cited recently.
Since you offered help, I went over ‘everything’ again. Several changes with little or no progress to show for it.
Here are the displaygui and update sphere functions.
- Code:
function displaygui(){
gui = new dat.GUI();
parameters =
{
MaterialOne: "Wireframe",
MaterialTwo: "Wireframe",
timeInSecs: 25,
CycloidRoll: true,
color: "#ffff00"
};
let sphereMaterialOne = gui.add( parameters, 'MaterialOne', [ "Basic", "Lambert", "Phong", "Wireframe" ] ).listen();
sphereMaterialOne.onChange(function(value)
{ updateSphere(); });
let sphereMaterialTwo = gui.add( parameters, 'MaterialTwo', { a:"Basic", b:"Lambert", c:"Phong", d:"Wireframe" } ).listen();
sphereMaterialTwo.onChange(function(value)
{ updateSphere(); });
let sphereColor = gui.addColor( parameters, 'color' ).name('Color').listen();
sphereColor.onChange(function(value) // onFinishChange
{ updateSphere(); });
let TracTInSecs = gui.add( parameters,'timeInSecs').min(1).max(200).step(1).name('Seconds').listen();
TracTInSecs.onChange(function(value)
{ trTimeInSecs = value; });
let rollingPi = gui.add( parameters, 'CycloidRoll').listen();
rollingPi.onChange(function(value)
{ kPiOrNot = value; });
// gui.close();
};
function updateSphere() {
let value = parameters.materialOne;
let newMaterial;
if (value == "Basic")
newMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
else if (value == "Lambert")
newMaterial = new THREE.MeshLambertMaterial( { color: 0x000000 } );
else if (value == "Phong")
newMaterial = new THREE.MeshPhongMaterial( { color: 0x000000 } );
else // (value == "Wireframe") // only wireframe is left
newMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
sphereMat.material = newMaterial;
value = parameters.materialTwo;
if (value == "a")
newMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
else if (value == "b")
newMaterial = new THREE.MeshLambertMaterial( { color: 0x000000 } );
else if (value == "c")
newMaterial = new THREE.MeshPhongMaterial( { color: 0x000000 } );
else if (value == "d")
newMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
sphereMat.material = newMaterial;
sphereMat.color.setHex( parameters.color.replace("#", "0x") );
};
By the way I had also tried implementing the http://workshop.chromeexperiments.com/examples/gui/#2--Constraining-Input example with [ 'pizza', 'chrome', 'hooray' ] that you described in your last post. I’m not delirious, I’m clearly doing something wrong. So I took the opportunity to review arrays and objects
A BRIEF JavaScript TUTORIAL: PART 1
https://discoverthreejs.com/book/introduction/javascript-tutorial-1/
It seems that javaScript has progressed since I learned it. Did you notice that the ‘var’ designators have been replaced with ‘let’ in the two functions above? I replaced all the ‘var’, variable identifiers with ‘const’ (for constants) and ‘let’ the newer variable designator. I learned several details I hadn’t come across before. Here's a great link to Mozilla’s Array page. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
After beating myself silly here I think I found my first clear evidence that I may be able to Pause.
https://discoverthreejs.com/book/first-steps/resize/
Using setAnimationLoop()
Switching to the setAnimationLoop method allows us to abstract away requestAnimationFrame() completely. Delete your current animate() function and replace with the setAnimationLoop code.
Promising?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
You don't want to stop the rendering loop in order to pause the animation. That stops all rendering, so the user can't move the camera around while paused. You have to add it into your rendering function. Something like this:
Notice that the scene is always rendered, however, the processing code is only run when not paused.
- Code:
function render()
{
setAnimationFrame( render );
if( !paused )
{
// TODO normal processing
}
renderer.render( scene, camera );
}
Notice that the scene is always rendered, however, the processing code is only run when not paused.
Re: Animate the PI = 4 experiment
I don't think you want to use the listen function on the gui. That causes DAT to check the values and update the menu items if they change. This can be expensive, although it shouldn't be a problem in this case. Basically, only use listen if you are going to change the values yourself, in code, or some other way other than DATGUI.
Other than that, the onChange function should be called when the menu item is changed. Can you confirm that it is being executed by adding a console.log to it?
I assume the parameters variable is being initialized outside of the code that you posted. Can you confirm that? There should be a line like this in the global scope (i.e. at the same level as the render function).
You probably should initialize it there, rather than in the displaygui function, although it doesn't matter too much.
Other than that, the onChange function should be called when the menu item is changed. Can you confirm that it is being executed by adding a console.log to it?
I assume the parameters variable is being initialized outside of the code that you posted. Can you confirm that? There should be a line like this in the global scope (i.e. at the same level as the render function).
- Code:
var parameters;
You probably should initialize it there, rather than in the displaygui function, although it doesn't matter too much.
Re: Animate the PI = 4 experiment
.
Here’s the console output showing my gui changes to Color, Seconds, CycloidRoll and Paused. Note, the red errors are caused whenever the orbital camera zooms (or dollys).
dynamic animate(). Is the render function you used a new render function? I placed this 'similar code' to the end of the animate() function at the end of the piEqFour script.
I'm not all that bothered by the lack of a non-working pull-down parameter, for the time being anyway.
.
Amn. Thank you Sir, good to know. I removed ‘.listen’ from all the gui parameter items.I don't think you want to use the listen function on the gui. …. Basically, only use listen if you are going to change the values yourself, in code, or some other way other than DATGUI.
Amn. updateSphere can only be called by the onChange function. I moved the control changes to CycloidRoll and trTimeInSecs to the updateSphere function to keep all the parameters together. Here’s the current updateSphere function including the console log.Other than that, the onChange function should be called when the menu item is changed. Can you confirm that it is being executed by adding a console.log to it?
- Code:
function updateSphere() {
console.log( 'materialOne = '+ parameters.materialOne +', materialTwo = '+ parameters.materialTwo
+', color = '+ parameters.color +', Seconds = '+ parameters.timeInSecs + ', kPiOrNot = '+ parameters.CycloidRoll );
let value = parameters.materialOne;
let newMaterial;
if (value == "Basic")
newMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
else if (value == "Lambert")
newMaterial = new THREE.MeshLambertMaterial( { color: 0x000000 } );
else if (value == "Phong")
newMaterial = new THREE.MeshPhongMaterial( { color: 0x000000 } );
else // (value == "Wireframe") // only wireframe is left
newMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
sphereMat.material = newMaterial;
value = parameters.materialTwo;
if (value == "a")
newMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
else if (value == "b")
newMaterial = new THREE.MeshLambertMaterial( { color: 0x000000 } );
else if (value == "c")
newMaterial = new THREE.MeshPhongMaterial( { color: 0x000000 } );
else if (value == "d")
newMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
sphereMat.material = newMaterial;
sphereMat.color.setHex( parameters.color.replace("#", "0x") );
value = parameters.timeInSecs;
trTimeInSecs = value;
value = parameters.CycloidRoll;
kPiOrNot = value;
value = parameters.Pause;
paused = value;
};
Here’s the console output showing my gui changes to Color, Seconds, CycloidRoll and Paused. Note, the red errors are caused whenever the orbital camera zooms (or dollys).
Amn. Affirmative. Here’s the current main variable list - left messy to show prior thinking/efforts; it includes ‘let parameters;’.I assume the parameters variable is being initialized outside of the code that you posted. Can you confirm that? There should be a line like this in the global scope (i.e. at the same level as the render function). You probably should initialize it there … .
- Code:
<script>
let camera, cameraO, cameraP;
let scene, renderer;
let stats, gui;
const r = 1;
const w = 0.25; // track width
const q = 0.5; // track separation
const bRadius = 0.25; // *r;
let kPiOrNot = true;
let orthoView = true;
let orthoCamera = true;
let paused = false;
let parameters;
//let pchArray = ['pizza', 'chrome', 'hooray'];
let sphereMat;
let sphereGeom;
let sphereC, sphereS;
let distTraveledS = 0;
let distTraveledC = 0;
let trTimeInSecs = 25; // seconds
//const rollingPi = 4; // Math.PI;
const trackCircumK = 8*r;
//velocity = 10*r/trTimeInSecs;
//let speed = { Stopped: 0, Slow: 0.5, Fast: 1 };
//let whichPI = 'kinematic'; // 'geometric'
//let e = ['Apple', 'Banana'];
//let materialOne = [ "Basic", "Lambert", "Phong", "Wireframe" ];
//let materialTwo = { a:"Basic", b:"Lambert", c:"Phong", d:"Wireframe" };
//const materialOne = [ "Basic", "Lambert", "Phong", "Wireframe" ];
//const materialTwo = { a:"Basic", b:"Lambert", c:"Phong", d:"Wireframe" };
init();
function init() {
You don't want to stop the rendering loop in order to pause the animation. That stops all rendering, so the user can't move the camera around while paused. You have to add it into your rendering function. Something like this:
- Code:
function render()
{
setAnimationFrame( render );
if( !paused )
{
// TODO normal processing
}
renderer.render( scene, camera );
}
Amn. I never expected it could be that easy. Maybe that’s part of the reason ‘some people’ regard the requestAnimationFrame as the best function ever. Confusing things, I’d changed the name of the function render() back to
Notice that the scene is always rendered, however, the processing code is only run when not paused.
- Code:
requestAnimationFrame( animate );
if ( !paused ) {
renderer.render( scene, camera );
};
stats.update();
};
</script>
I'm not all that bothered by the lack of a non-working pull-down parameter, for the time being anyway.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
Don't use let, use var. There are differences between them and they can cause problems if you use let in the wrong place. It could be causing the problem with parameters.
The pausing code has nothing to do with requestAnimationFrame. The problem is you put the renderer.render( scene, camera ); part inside the pause block. Look at my example again and see that it is outside of it. That is why the orbit control isn't working.
My example render function is not a new function, you are supposed to change the existing one to reflect that, but add the processing code to the pause block. I suggest you put that processing code into its own function (which you may have already) and just call it from inside the !paused block.
With respect to event handlers, you should have a unique function for each (unless they can be shared, but they can't in this case). You can put them all together in one function, but then you are updating everything when only one thing has actually changed. Note that event handlers are often inline functions, declared where they are used rather than a full function definition.
Full function example:
Inline function definition:
The pausing code has nothing to do with requestAnimationFrame. The problem is you put the renderer.render( scene, camera ); part inside the pause block. Look at my example again and see that it is outside of it. That is why the orbit control isn't working.
My example render function is not a new function, you are supposed to change the existing one to reflect that, but add the processing code to the pause block. I suggest you put that processing code into its own function (which you may have already) and just call it from inside the !paused block.
With respect to event handlers, you should have a unique function for each (unless they can be shared, but they can't in this case). You can put them all together in one function, but then you are updating everything when only one thing has actually changed. Note that event handlers are often inline functions, declared where they are used rather than a full function definition.
Full function example:
- Code:
function render()
{
}
Inline function definition:
- Code:
gui.onChange( function( value )
{
}
);
Re: Animate the PI = 4 experiment
.
The pause checkbox is now working correctly, with orbital camera and action resuming from where it was stopped. You can see the fps is at 60 while I found a good starting line image.
Whether it's correct or not, here’s the animate function with the internal if ( !paused ) loop beginning just after the variable declarations, and requestAnimationFrame( animate ) command.
Thanks. I can now well appreciate the in-line versus the full named function descriptions, with the onChange as well as the parameters functions. I changed the displaygui function to let the onChange functions update their respective variables and eliminated the function updateSphere. I didn’t get much further today, busier than usual, and the paperwork comes first.
Now I can think of steps.
.
Amn. Copy that, all const and let designators have been changed back to var. I believe I’d mentioned my problem with the pull-down parameters before changing them to let and const, no problem switching them back. I also ‘fully typed’ two new draw down parameters, bodyMat array and object types. I say fully typed, someone showed me a Turkish question mark used as a semicolon planted in code to prevent copy/paste actions from working correctly. May be an urban code legend. Anyway, still no active pull-down parameters.Don't use let, use var. There are differences between them and they can cause problems if you use let in the wrong place. It could be causing the problem with parameters.
Amn. Even with clear instructions, I must make at least one or two mistakes before I do anything right. May as well get my mistakes out of the way as soon as possible. I was overwhelmed seeing the simple !pause loop working; stopped in amazement and went ahead and posted for the day, fully expecting a proper pause including orbital controls today.The pausing code has nothing to do with requestAnimationFrame. The problem is you put the renderer.render( scene, camera ); part inside the pause block. Look at my example again and see that it is outside of it. That is why the orbit control isn't working.
The pause checkbox is now working correctly, with orbital camera and action resuming from where it was stopped. You can see the fps is at 60 while I found a good starting line image.
Whether it's correct or not, here’s the animate function with the internal if ( !paused ) loop beginning just after the variable declarations, and requestAnimationFrame( animate ) command.
- Code:
function animate() {
var T = trTimeInSecs;
var velocity = 10*r/trTimeInSecs;
//var vel = 10 * r / T;
var increments = T*35; // roughly the fps
var dT = T/increments;
var tracSep = r+q+w; // duplicated in init.
var cTrackLengthP = 2*r + 2*Math.PI*r;
var cTrackLengthK = 2*r + 8*r;
var cTracSectP = cTrackLengthP/5;
var cTracSectK = cTrackLengthK/5;
var sTrackLength = 10*r;
var sTrackSect = 10*r/5;
var quaternion = new THREE.Quaternion;
var ang2Inc;
var bCircum = 2 * Math.PI * bRadius;
var ang2rot = 10*r/bCircum;
var kMult = 4/Math.PI;
if ( kPiOrNot )
ang2Inc = 4 * ang2rot * kMult/ increments;
else
ang2Inc = Math.PI * ang2rot / increments;
var distNextS = distTraveledS + dT*velocity;
var distNextC = distTraveledC + dT*velocity;
var curSectionS = Math.floor( distTraveledS / sTrackSect );
var curSectionC = Math.floor( distTraveledC / cTracSectK );
var nexSectionS = Math.floor( distNextS / sTrackSect );
var nexSectionC = Math.floor( distNextC / cTracSectK );
requestAnimationFrame( animate );
if ( !paused ) { // TODO normal processing
sphereS.rotation.z -= ang2Inc;
sphereC.rotation.z -= ang2Inc;
if ( nexSectionS == curSectionS + 1 ){
var pastBoundary = distNextS - nexSectionS * 2 * r;
curSectionS = curSectionS + 1;
};
if ( nexSectionC == curSectionC + 1 ){
pastBoundary = distNextC - nexSectionC * cTracSectK ; // 2 *r; //
curSectionC = nexSectionC;
};
if ( distNextC < cTracSectK ) {
sphereC.position.set( -2*r+ distNextC, 0, r );
distTraveledC = distNextC;
curSectionC = nexSectionC;
}
else if (( distNextC >= cTracSectK ) && ( distNextC < cTrackLengthK )) { // In the loop
var trackAngle = 2*Math.PI*(distNextC - cTracSectK)/trackCircumK;
sphereC.position.set( r*Math.sin( trackAngle ), 0, r*Math.cos( trackAngle ));
sphereC.rotation.y = trackAngle;
distTraveledC = distNextC;
curSectionC = nexSectionC;
}
else if ( distNextC >= cTrackLengthK ) {
sphereC.position.set( -2*r, 0, r );
distTraveledC = 0;
curSectionC = 0;
};
if ( distNextS < sTrackLength ) {
sphereS.position.set( -2*r+ distNextS, 0, tracSep );
distTraveledS = distNextS;
curSectionS = nexSectionS;
}
else if ( distNextS >= sTrackLength ) {
sphereS.position.set( -2*r, 0, tracSep );
distTraveledS = 0;
curSectionS = 0;
};
};
renderer.render( scene, camera );
stats.update();
};
</script>
Thanks. I can now well appreciate the in-line versus the full named function descriptions, with the onChange as well as the parameters functions. I changed the displaygui function to let the onChange functions update their respective variables and eliminated the function updateSphere. I didn’t get much further today, busier than usual, and the paperwork comes first.
Now I can think of steps.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
.
The latest: a stepAhead (frame) checkbox, and new PI type folder.
Here's how the step ahead works, in the animate function, the !pause loop start is changed to:
if pause is checked true, one can step through each subsequent animation frame rendering by clicking on stepAhead two times. The first to uncheck the box, and the second to execute the next single frame step. Rudimentary right? but adequate. The color shown is white, which can make rolling studies easier. For example, by creating masks. I screen copy the paused animation, then paste (in transparent mode) the white lined spheres onto the color of my choice – and so convert all the isolated pixels of the white lined image to any color. Also in paint, I change the black background from black to white. One can then take a series of images, changing the color slightly each time (or not) in order to build a multiple image of the rolling contact point on the track. There are probably easier ways, and paint is going away, but first, there’s something more important.
Nevyn, as you can see, I haven’t forgotten. We’d like to confirm Miles angular velocity equation, note the new PI folder with pi choices. Forgive me for taking so long to get here. My latest delay is my attention to paperwork and less than complete understanding of your 10 October posting. https://milesmathis.forumotion.com/t554p50-animate-the-pi-4-experiment#5692
Old and new gui parameter additions including folder.
Some existing and two new animate function variables.
Finally, the existing animate function’s circular track section code.
I still need to figure out the necessary changes to that last section. There seems like more than enough to work with, organizing it like this certainly helped. Feel free to comment or correct.
.
The latest: a stepAhead (frame) checkbox, and new PI type folder.
Here's how the step ahead works, in the animate function, the !pause loop start is changed to:
- Code:
if (( !paused ) || ( ( paused ) && ( stepA ) )) {
stepA = false;
if pause is checked true, one can step through each subsequent animation frame rendering by clicking on stepAhead two times. The first to uncheck the box, and the second to execute the next single frame step. Rudimentary right? but adequate. The color shown is white, which can make rolling studies easier. For example, by creating masks. I screen copy the paused animation, then paste (in transparent mode) the white lined spheres onto the color of my choice – and so convert all the isolated pixels of the white lined image to any color. Also in paint, I change the black background from black to white. One can then take a series of images, changing the color slightly each time (or not) in order to build a multiple image of the rolling contact point on the track. There are probably easier ways, and paint is going away, but first, there’s something more important.
Nevyn, as you can see, I haven’t forgotten. We’d like to confirm Miles angular velocity equation, note the new PI folder with pi choices. Forgive me for taking so long to get here. My latest delay is my attention to paperwork and less than complete understanding of your 10 October posting. https://milesmathis.forumotion.com/t554p50-animate-the-pi-4-experiment#5692
OK, I’ve made ready. Here's how. Two new and existing main variables.I suggest you implement it using the full A = 2PI*v*t/(2*PI*r) equation, but have 2 variables for the PI values (piK and piG, for example) so it would become:
A = 2PIg*v*t/(2*PIk*r)
= PIg*v*t/(PIk*r)
Then you can adjust the values of PIg and PIk to determine which one looks right when viewing the motion.
- Code:
var piG = Math.PI;
var piK = 4;
var piTopKOrNot = true;
var piBottomKOrNot = true;
var kPiOrNot = true; // CycloidRoll
Old and new gui parameter additions including folder.
- Code:
CycloidRoll: true,
twopivt: true,
twopir: true,
var whichPI = gui.addFolder('PI type. Check/true for K, leave blank for G');
var rollingPi = whichPI.add( parameters, 'CycloidRoll');
rollingPi.onChange(function(value)
{ kPiOrNot = value; });
var numeratorPi = whichPI.add( parameters, 'twopivt');
numeratorPi.onChange(function(value)
{ piTopKOrNot = value; }); // A = 2PI*v*t/(2*PI*r). piTopKOrNot is used for 2PI*v*t
var denominatorPi = whichPI.add( parameters, 'twopir');
denominatorPi.onChange(function(value)
{ piBottomKOrNot = value; }); // A = 2PI*v*t/(2*PI*r). piBottomKOrNot is used for (2*PI*r)
whichPI.open();
Some existing and two new animate function variables.
- Code:
var cTrackLengthP = 2*r + 2*Math.PI*r;
var cTrackLengthK = 2*r + 8*r;
var cTracSectP = cTrackLengthP/5;
var cTracSectK = cTrackLengthK/5;
var distNextC = distTraveledC + dT*velocity;
// A = 2PI*v*t/(2*PI*r) = numerator/denominator.
var numerator;
var denominator;
Finally, the existing animate function’s circular track section code.
- Code:
else if (( distNextC >= cTracSectK ) && ( distNextC < cTrackLengthK )) { // In the loop
var trackAngle = 2*Math.PI*(distNextC - cTracSectK)/trackCircumK;
sphereC.position.set( r*Math.sin( trackAngle ), 0, r*Math.cos( trackAngle ));
sphereC.rotation.y = trackAngle;
distTraveledC = distNextC;
curSectionC = nexSectionC;
};
I still need to figure out the necessary changes to that last section. There seems like more than enough to work with, organizing it like this certainly helped. Feel free to comment or correct.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Animate the PI = 4 experiment
- Code:
if (( !paused ) || ( ( paused ) && ( stepA ) ))
Is the same as
- Code:
if( !paused || stepA )
However, you can implement stepping slightly differently and it will be a bit more clear.
Stepping is just selective pausing. Essentially, when the user says they want to step a single frame, they are saying 'I want to unpause this, run a single frame, and then re-pause it'. So we can do exactly that.
- Code:
if( !paused )
{
// normal processing code
...
if( stepping )
{
paused = true;
}
}
This puts a bit more of the effort into the event handlers, but not much.
Using a check-box to control pausing is bad. You need a button, and DAT allows you to use them. You can use a checkbox for the stepping, but I would tend to use a button for that too. I would also bind them to key events so the user can press the space bar, or something like that. See if you can figure out how to use buttons.
Here are the event handlers:
Pause handler:
- Code:
function( event ) {
// toggle the current state
paused = !paused;
}
Step handler:
- Code:
function( event ) {
stepping = true;
paused = false;
}
They are written as inline function (also called anonymous functions), so you should be able to drop them into the button creation code for DAT.
Page 2 of 8 • 1, 2, 3, 4, 5, 6, 7, 8
Similar topics
» PI NINE - Pi experiment with two edge track
» How about an Experiment to Simulate Attraction?
» The Event Horizon Telescope experiment
» Photonics experiment resolves quantum paradox
» Revisiting the Pound-Rebka experiment in light of Miles' new Gravity Paper and the Charge Field
» How about an Experiment to Simulate Attraction?
» The Event Horizon Telescope experiment
» Photonics experiment resolves quantum paradox
» Revisiting the Pound-Rebka experiment in light of Miles' new Gravity Paper and the Charge Field
Page 2 of 8
Permissions in this forum:
You cannot reply to topics in this forum