Animate the PI = 4 experiment

Page 7 of 8 Previous  1, 2, 3, 4, 5, 6, 7, 8  Next

Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Mon Dec 09, 2019 7:06 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack11
Today’s initial output view showing the completed new pi switch track. All three spheres are at their final track positions, they will be back at the start in the next frame.

All the new track ball’s spin animations are correct. The sphere pointlight and the resized table are shown.  The initial view is larger, I tried following your suggestion to make the straight track about 0.9x the view width as fas as I could without both circular loops busting the top and bottom of the frame. I’m such a wimp at times.

One minor problem, not all the pi switch track marker color animations work. It seems that changing back to black or lerping back causes a halt due to a material error when the ball crosses the three o’clock marker the second time, now past, a few frames before the image shown.
 
I’ll try saying it more clearly. The animation function contains the code for advancing each of the three spheres in alternate if branches, according to the rules for that branch corresponding to each track. Advance the sphere until the total distance allowed then go back to start. An error allows the ball in the new pi track gets past the max distance without going back to start, or I might need a larger marker set.

I’ll disconnect the pi swiches from our 8*r circular track.

I also need to come up with a convenient means to omit or include the new track in the scene as necessary. The tracks are added at the init level so a track configuration change cannot be a menu control item. Camera and table changes would be included. Plenty to do, I need a break from listing these changes. cyclops  
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Mon Dec 09, 2019 8:53 pm

I have another idea. When the balls reach a marker, they all stop moving for a few seconds, allowing the user to look at each track and see where they are.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Tue Dec 10, 2019 7:03 pm

.
Animate the PI = 4 experiment - Page 7 Reset10
Orbital viewing about the three tracks.

We have a Reset button, pressing it repositions the spheres back to their starting locations. Any change to either of the two pi switches: twopivt or twopir includes repositioning all three spheres back to start. I don’t believe a reset is necessary for changing the cycloid roll selection. The tracks always remain in synch – the three spheres arrive at their maximum distances and return back to start in the next frame. The pi switch track markers still need attention.

No joy on solving your stop at each marker for a few seconds idea yet. I believe the solution involves using a setTimeout function. I created the new function called advance(), in which the next position for each sphere is calculated. If I comment out advance, the spheres do not leave their starting spots. I’ve buried the advance() call in what I thought timeout delays such as,

Code:
setTimeout(advance(), 4*1000);

advance is clearly running but there are no delays. The continuous loops are not interrupted. I'll keep at it.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Tue Dec 10, 2019 10:24 pm

You can use setTimeout, or you could just have a wait variable that stops the motion calculations when it is above 0. If it is above 0, then it is decremented by the time since the last frame (it seems you don't have that data, look at various ThreeJS examples to see how to use a Clock object and the time values that it gives you) until it is 0 (or below and if so, set it to 0).

Notice that it should only effect the motion calculations, and not stop the rendering.

By the way, that call to setTimeout is wrong, or at least I strongly suggest that it is wrong given what you have written above. The setTimeout function takes 2 arguments: a function; and an amount of time to wait before executing that function. You are invoking the advance function, when (I believe) you should be just passing that function. The reason I say that it might be wrong is that the advance function could be returning a function which is what setTimeout will execute. But I doubt that.

It should be written like this:

Code:

setTimeout( advance, 4*1000 );

Notice that advance does not have parentheses following it, which would invoke the function and pass whatever it returns to setTimeout.

In Javascript, a function name is really a variable name and that variable just happens to point to a function. So functions can be passed around like any other variable (which is extremely useful at times). It is only by following the function name with an argument list, encapsulated by ( and ), that the function will actually be executed.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Tue Dec 10, 2019 10:31 pm

The code needs to be cleaned up a lot. The animate function basically contains everything. I think a few more functions could be used to make things a lot clearer.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Thu Dec 12, 2019 7:16 pm

.
Animate the PI = 4 experiment - Page 7 Deltav10
Showing delta values and a new pauseAtMarkers option.

You indicated it seems I didn’t have time data, you must have a nice console. Over the last two days I've looked through many clock timing examples. I believe I created a proper clock – and associated data, by adding these two lines to the start of the animate function.
Code:

     var delta = clock.getDelta();
     var time = clock.getElapsedTime() * 0.5;
I've coded PI=4 using increments, and not time. When using a time variable, it should be global, defined in the init function and updated with getDelta or getElapsedTime, once per animation. I put a console log on delta, the output should be 1/60 = 0.01666… . I included a sample of PI=4’s delta value in the image. I suspect you’ll want to ensure the most accurate time possible by updating the frame rate with the delta values(?).

I had no luck finding anything resembling a countdown timer. In addition to setTimeout I tried sleep, which froze up the rendering; and asynchronous ‘await’ – which, as far as I could tell, was a no go. I was quite desperate when I finally came up with a simple solution using setTimeout.  
Code:

    function stopAtCrossing() {
          if ( pauseMark == true ) {
               paused = true;
               var duration = pauseDuration*1000;
               setTimeout(() => {  
                    paused = false;
              }, duration );
          };
    };

Brief Joy, I hope you find it acceptable.
 
As per your direction I simplified the animation function as much as I could find breaking 6 or 7 functions out into their own functions, for a current total of 14 functions – not counting init() and animate().
.


Last edited by LongtimeAirman on Thu Dec 12, 2019 9:53 pm; edited 1 time in total (Reason for editing : P.S. corrected three typos:1. 0.0166... ; 2. added }; 3. changed 'found' to 'came up with'.)

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Thu Dec 12, 2019 11:36 pm

You don't need to find a countdown timer, you need to create one. Try to get out of the habit of finding things that others have done, and think about how you might go about it first. It is good to re-use code, even from others, but it is better to know how to do things yourself. Especially when they are trivial things. It is worth just thinking about how you might do it, before looking for what others have done. You might still go looking, because there might be other ways of doing it, but if what you come up with is simple enough, and works, then why waste the time.

All you need is a variable, and some code to make use of it. The stop-at-marker function is going to set it to some value, such as 4000(ms). The animate function is going to watch that variable and when it is above 0, then it will not execute the motion based code, and it will reduce the value by the time since the last frame (real time, not model time, hence why you need that Clock). When it is 0 or below, it will execute the motion code. That's it. The hardest part is setting up the if/else structure around the motion code, which will be a lot easier if that code was in its own function. That is why I wanted you to make some more functions. It makes the animate function a lot cleaner and you can see how to manipulate things in it. When it is 100's of lines long, you just can't see that sort of thing. It looks too hard, but it really isn't. Simplify, simplify, simplify! It really helps.

You will need to be careful of units, as the Clock uses seconds, but you really want milliseconds. You could use seconds if you wish, then the value will be set to 4, not 4000. Actually, that is probably the easier way to go. You only needed milliseconds because you were using setTimeout, but without that, you can use seconds. Play with the time too. 4 seconds seems a bit too much, but trial and error will find that out.


Get rid of the lerpHSL function. You don't need it. The THREE.Color class already does it, and it does it more efficiently than you are. Your implementation could be made more efficient, but why bother when it is already available?

There are a hell of a lot of global variables too. I would estimate about 150 to 200 of them. That needs to be fixed. I know the THREE examples do that a lot, but it is just lazy (of them, not you), and it can cause problems that are extremely difficult to find. One solution is to use a wrapper object, just like you have with the parameters object used for the DATGUI menu. There are other solutions, but they are a bit more advanced and I don't expect you to understand those ones. Don't feel bad about using global variables, we all start that way, but it is a habit best avoided rather than latched on to.

I know I'm getting picky, but it does 2 things. It educates you on better ways of going about things. It also makes the code more ready to be put into another page structure. As it is, that would be extremely difficult.


Also, I noticed that you copied the Clock code from a ThreeJS example, where it halves the time. Don't do that. You don't need to in this case, and it will effect how that 4s is treated (as it will make 4s into 8s).
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Fri Dec 13, 2019 7:06 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack12
Creating new functions actually simplifies things eh? Takes some getting used to.

Once again, thanks Nevyn for your clear and expert instructions and explanations.

As per your directions I eliminated the lerpHSL function; that made subsequent ‘simplifications’ a lot easier to see. I created and removed 14 new functions away from the animate function. The animate function is now less than a hundred lines and easier to ‘read’. I think I see at least one more pi track function to break out. The pi track marker color corrections wil follow the simplification effort.

Please let me know if I made too many new functions. I haven’t begun to think about eliminating or otherwise dealing with the global variables. After today I’m reassured, I’ll need to lookup ‘wrappers’, but I’ll point out that the new functions I created today also pass variables, suggests another way to reduce the number of global variables.

For the record, I wrote the stopAtCrossing function, I posted ‘found’ but that didn’t mean I ‘found’ the solution outside myself. I posted a correction. I was extremely frustrated from many attempts over the last two days and still not having come up with a ‘countdown timer’. I was expecting the main criticism to be directed at my use of paused and the setTimeout function. As far as that solution goes, my particular aha moment was seeing someone using time as a variable to select different branches. A few seconds later I thought to use the paused variable with the setTimeout function. Since you didn’t seem to indicate any particular problem with stopAtCrossing() I’m greatly relieved and grateful for all the rest of your most excellent criticism. Believe it or not, I think its working.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Fri Dec 13, 2019 7:57 pm

Using setTimeout was an acceptable solution, and in most other types of applications that is what you would do. However, in this app, and all 3D apps, we already have a loop that is running at all times. So it is better to take advantage of that and just create a simple count down variable. That actually runs better because JS only allows one thing to be running at a time. So to execute the setTimeout function (the one you pass to it) it has to stop the animation loop, which should be avoided if we want the 3D scene to render fluently.

In this particular case, the function you gave to setTimeout was not onerous in any way, so it would not have slowed things down in a noticeable way. However, I think it is better to remove it on principle and go with the better solution for this type of app.

Programming is about learning what sorts of things you can do, and finding ways to put them together to get some job done. Over time, as you get more experienced, you find other ways to do the same things. Eventually, you start to see when and where you should use particular solutions to specific problems.

I think the animate function can probably be reduced even more. I haven't looked at these recent changes yet, but I think that animate should be about 20 lines long, maybe even less. It should only contain the high level control structures and the code that actually does things should be in functions with clear names.

In essence, animate should look something like this:

Code:

function animate( time )
{
  requestAnimationFrame( animate );
  // do any common pre-tasks here
  if( waitAtMarker > 0 )
  {
    waitAtMarker = Math.max( 0, waitAtMarker - time.elapsedTime );
  }
  else
  {
    executeMotion( time );
  }
  // do any common post-tasks here
  renderer.render( camera, scene );
  // do any post rendering tasks here
}

Then executeMotion looks something like this:

Code:

function executeMotion( time )
{
  // do any common pre-tasks here
  executeTrackA( time );
  executeTrackB( time );
  executeTrackC( time );
  // do any common post-tasks here
  }
}

The idea is that these higher level functions read nicely. You don't have to figure out what they are doing by looking through many lines of code. The function names tell you enough to get a rough idea of what is going on. Because they are so small and simple, you can see how to manipulate things a lot easier.

Let's say you remove track C. All you have to do is comment out the call to executeTackC and it is no longer being processed. Of course, you would also have to remove the code that adds it to the scene, but we aren't looking at that at the moment (but it can also use the same treatment as we are doing here and it gains the same benefits).

Don't worry too much about it. You're doing a good job. The animation itself looks great. Cleaning up the code has the main benefit of making the transition into another page much more easy, but also it will help if you come back to this app after not looking at it for some time. Sometimes, when you go back to code you wrote a long time ago, you find that you can't understand it anymore. Right now you are in the middle of it and understand what things are doing, but you will forget a lot of that within a few months of not working on it. Comments help that too. Even if the comment seems obvious now, it may not be later. Think about how daunting it is to look at my code, and you feel a bit lost and find it difficult to understand. That can happen with your own work too. It's a bit of a surprise when it first happens, but you get used to it after a while. In fact, if you go looking through your own old code and don't feel a bit ashamed of how you do some things, then you aren't learning.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Mon Dec 16, 2019 7:02 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack13
Nevyn, you gave me three tasks:

1. Reduce the size of the animate function to a small number of high level functions and small number of code lines. Since my last post, I was able to off-load the animate function of about four more functions, bringing the number of animate code lines down to 21 – amazed me. Unfortunately, there’s nothing high level about the six var declarations, curSectionS, nexSection, … , smack in the middle of the animate function. I have not been able to move or make them into their own independent function. I hope that isn’t a problem.
 
2. Global variable cleanup. Too many global variables is the result of poor practices. True, I removed about half of the global variables. A few were moved to the init function, but many were serving no purpose except as reminders of unsuccessful efforts, and were gotten rid of. I looked up wrapper, I’ll need to look it up again.

3. Create a waitAtMarker function without using the setTimeout function. I found this task to be quite difficult. Sure I’ve messed with or modified previously existing code which used time, but I’ve never coded with time or date objects before. I had no idea the setTimeout function added an additional loop separate from the animate function. Thanks for the directions, the simplified big picture – wait or animate (as in execute the animate function’s motion or not) with code! When I came up with a working solution my mind went skipping off and hasn’t returned yet - dang, the animate function is now about 35 lines.

A couple of last effort items cleaned up but not yet Pushed, I’ll do another walk through next.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Wed Dec 18, 2019 6:58 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack14
No radical changes, the sphere and tube radii are roughly doubled. The table is opaque and reflecting the sphere pointlights making them somewhat brighter and more defined. The latest pi switch test track is at the top showing the erroneous mainstream expected experimental outcome.

The pi switch test track allows the user to violate physics in four different ways in order to compare the expected and actual (to the best of my belief) pi geometric or pi kinematic behaviors – such as cycloid or non cycloid rolling. I’m glad you came up with the idea of a third track devoted to the pi switches. Still, I’d hate to see this application misused or misrepresented and hope it’s never used for evil. I’m thinking I could remove it from the scene by placing it elsewhere in worldspace, like I did with the table, and move it to the position shown when needed. Scratch that, the track and sphere is way more complicated.
   
The pi test track markers are now working correctly, changing from blue to red, or the other starting colors change to black as the spheres pass a diameter’s length away from them.

The track time selected is now close to the time it takes to complete the track – I’ve assumed a constant fps of 60.

I’ve tried removing the animate function vaiables multiple times without success, I don’t see how to make it any shorter except for motion execution restructuring or some such r – which has no problem that I’m aware of.

I did more variable clean up, everything looks ship shape to me.

I have no problems with any of the functions, you indicated your dislike for the keyboard spacebar operation. Space stops the action or allows crude step motion. I see little reason to change it. I believe it involves html code, which you indicated I should avoid. Not a big deal.

Awaiting further instructions.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Wed Dec 18, 2019 9:57 pm

I don't like the table underneath everything. It washes out the colors.

You should never hide things by moving them off-screen. If they are not needed, then they should not exist. If they must be in the scene, then you can mark them as not visible. Every THREE.Object3D instance has a visible property that can be set to false. However, I would be adding something to the code to stop such entities even being created. This is complicated by the way you are processing motion. If you go back to the early posts on this thread, you will find me talking about having an array of tracks. If you follow that approach, then it is easy to remove a track without needing to remove processing code. Maybe if you read those posts now, you might understand them a bit better and see how to go about it like that.

What I don't like about the motion code is that it is specialized for each track. It should be generic and used for all tracks. The tracks define what they are and the motion code only executes the appropriate code for that particular track (actually, it would be a section of the track). So the motion code still knows how to handle a PI=4 curve, but it also knows how to handle a PI=3.14 curve, and it applies the right one for the right section of track that it is processing at the time.

I suggest you start a new HTML file and try to follow that approach. The tracks should define what they are, rather than the motion code knowing what they are. Does that make sense? It seems the current motion code determines how far along the ball is on a known type of track and performs certain motion based on that. It has to know which type of track it is. The motion code should just be a switch or if/else structure that says: if this type of section, do this, else if this type, do this, etc. It should be quite dumb as far as the track goes, but smart with respect to the types of sections that a track might have. This allows the motion code to handle any type of section, even if it never has to handle it (because you removed a certain track, for example). Basically, the motion needs to be separated from the track, and just be a structure of potential motions.

Can you see how that fixes the problem you have if you remove the PI=3.14 track? Where you currently have to remove motion code to do that, the other approach does not. The motion code can remain part of the app, but the track containing a PI=3.14 curve can be removed.

Similarly, the creation of the scene objects should be driven by the track array too. If everything works based on the track array, then you can just add and remove items from that array and everything works. This is what we call 'Data Driven' applications.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Fri Dec 20, 2019 3:31 pm

.
Thank you Sir, I think I understand, the program should be rewritten. I reviewed the thread and feel some shock and embarrassment at having diverged so far from your initial instructions. Sorry you must repeat yourself. On the positive side I can now appreciate your suggestion would lead to a better outcome and presents another excellent learning opportunity.

I wrote an extremely specialized ‘recipe’ application – akin to a painting - a curved path, a straight path, and an opposite curved path – in that order. The balls are moved around their particular paths during each frame - in that order. Alternatively, an array based structure introduces a level of abstraction and greater freedom. One might begin by just identifying the total number of items that needs to be accessed from a track array. As you indicated, each individual line from the track array could contain all information and directions necessary to create everything associated with that track as well as moving the ball along it. The track array provides a modular capability, allowing more freedom in selecting the number and types of tracks desired, easily modifiable for related applications. At best, my code might be compared to a special, one-of a kind item, where a track array based structure might be compared to an automated construction and operation set, far more efficient and versatile.  

Well then, besides going back to start, how do I proceed? The array must act primarily as an index. How is it accessed? I suppose each track array line item could be thought of like some 3D object: track1 = new THREE.TrackObject(); with all the necessary item parameters. After giving it more thought I guess I’ll try defining and building the track array first.

Pardon me for mentioning, best wishes as always, but especially over these next next few weeks. Stay safe.      
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Fri Dec 20, 2019 5:58 pm

Don't feel bad about it. I didn't stop you because I saw that you needed to focus on the specifics before you could see the larger picture. I take a lot of that for granted. I can play with ideas because I trust that I can deal with the specifics when I get there. When ever I start something that I am unsure about, I often go straight into the specifics just to see how at least some part of it looks. That gives me a feel for how other things might end up, and I can start to think about the larger picture.

Let's also remember that you did solve the problem. You did get an animation up and running that showed what you wanted it to show. Sure, you didn't go about it the way I wanted, but so what? I probably wouldn't have even mentioned it now, except you presented a problem that would have been very easily solved in my method, but difficult in what you created. I saw that as a good opportunity to demonstrate a different design decision where the focus is on the data rather than the processing. I realised early on that I was talking about higher level ideas that you weren't able to see just yet. I was trying to lead you to things that you weren't ready for, so I let you find your own way through it.

We aren't so much concerned with how the track array is going to be accessed (which will just end up being a for loop iterating over the array), but with what data it might contain. The content of the array is critical and we need to make sure that it contains everything we need to do whatever it is we want to do with it. That sounds like a difficult task, but in reality, you just take it one step at a time.

First, you think about what sort of information you need to define a track. Break it down into smaller parts. Break those parts down into smaller parts, if you need to. You can, some-what, do this in conjunction with developing the motion code. Let's give it a quick try:

Looking at the tracks you already have, we ask ourselves "What does a track have?", and the answer is "It has sections".

Code:

var tracks = [
  {
    sections: []
  }
];

Then we ask "What types of sections are there?" and we answer "There are straight sections and there are curved sections.". So we need a way to define that in our track definition.

Code:

var tracks = [
  {
    sections: [
      {
        type: 'straight'
      }
      ,{
        type: 'curve'
      }
    ]
  }
];

But wait. That doesn't really cover what we already have. We don't just have a single type of curve, we have 2 different curves. What are we going to do about that? Well, there are a few things we could do to deal with that, but the simplest would be to create another type of section.

Code:

var tracks = [
  {
    sections: [
      {
        type: 'straight'
      }
      ,{
        type: 'curve4'
      }
      ,{
        type: 'curve314'
      }
    ]
  }
];

Note that I am not creating an actual track array here, even though it looks like it (and technically, it is). What I am doing is creating a declaration of what a track array can contain and how it contains it. We wouldn't have a curve4 and curve314 in the same track. Of course we could, but in this particular application, we don't need to. But I just want to show what types of sections are possible.

What else does a track need? How about something that moves along the track? We need a ball.

Code:

var tracks = [
  {
    ball: {
    }
    ,sections: [
      {
        type: 'straight'
      }
      ,{
        type: 'curve4'
      }
      ,{
        type: 'curve314'
      }
    ]
  }
];

With this little bit of knowledge, we can now start to build the motion code a little bit. We now know what types of motion we require, and we can put that into some sort of structure.

Code:

function processMotion( time )
{
  for( var i=0; i<tracks.length; i++ )
  {
    processMotionForTrack( tracks[i], time );
  }
}

function processMotionForTrack( track, time )
{
  // TODO figure out what section the ball is in
  var section = ...;
  // process motion for section
  switch( section.type )
  {
    case 'straight':
      processStraightSection( track, section, time );
      break;
    case 'curve4':
      processCurve4Section( track, section, time );
      break;
    case 'curve314':
      processCurve314Section( track, section, time );
      break;
  }
}

See how the higher level functions are already looking like what we discussed a few days ago? Since we aren't thinking about the lower level code specific to these operations, the higher level code creates a nice, easy to read, structure. We are drilling down from the top, not piling things up from the bottom.

Also notice that we have disconnected the motion code from what tracks we need to handle. If there are no tracks defined with curve314 sections, then that particular code will not be used, but it doesn't need to be removed. The data determines what code gets executed. The data drives the code.

Basically, from here, you work the track definition and the motion code as best you can. Working one against the other. When you find that you need some sort of information in the motion code that you don't have, you go back to the track definition and see how (and if) it fits in there. First think about whether you can calculate it in some way, before adding it into the definition. We want the track definitions to be as lean as possible. You must convince yourself that what you are about to add to it absolutely must be added. Don't worry too much about that for now. I don't mind if you add more than it needs.

You will also need to do this for the 3D scene creation. Looping over the tracks to create the objects that each one needs, putting it together one section at a time. This might end up being more complicated than what you already have, but it is better in the long run.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Fri Dec 27, 2019 7:38 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack15

Holiday update. Events here have slowed my progress working on a "table array version" of the PI=4 app. I’m still in the initialization section, outputting what you see above, in festive colors. The spinning balls have yet to leave their starting lines and there are no lights. The curved and straight tubes are colored according to the direction of the surface normals, meshNormalMaterial. With global and table variable duplications and string names the table array is a 250 element monster that doesn’t seem to offer any efficiencies. I need to print it to the console so I can be sure my code is indexing the correct values. Can't wait to see how this process plays out.  
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Fri Jan 03, 2020 6:39 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack16
These are dangerous times, filled with uncertainty. All the more reason to wish everyone a Happy New Year and Decade.

As directed, I began working on the table array. Beyond that, I didn’t understand the difference between the table array structure you described and your switch case conditional method code. I recall a desperate moment stretching into days. Looking up - data driven versus object oriented coding – I found mostly discussions centered on minimizing processing time, not much help. Still, as I worked the table I did learn a few things. Starting with the fact that it is difficult to make small changes to a 250 element (give or take) array. After some effort, things began coming together, I found myself accessing the table Array’s three internal parallel data structures using two array pointers: a track starting index, and a number to add to that track starting index.

You indicated that in addition to the animation function I would also need to work on the initialization function. Over the last week I’ve just been working the table and the initialization function, but I think I’ve succeeded in reworking it as you requested. The track and all the items present are positioned by looping through the table.

I’ve begun to look at the animation function, staging the logic. The two curved track balls shown in the image above do not yet move along their curves, but instead maintain their side-by-side formation over the entire 10*r straight track length, no good reason to show a moment later. I'm happy to report I believe I understand your process logic. I couldn’t bring myself to split either the 10*r long straight or circular track into four or five sections during initialization, but I will certainly do so during the animation function processing. Data driven might be better described as an alternative methodology, approach or philosophy. It makes good sense.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Sun Jan 05, 2020 7:43 am

Airman wrote:Starting with the fact that it is difficult to make small changes to a 250 element (give or take) array.

Yes, that is difficult, and shows that the array is not structured correctly. The array should be helping you, not hindering. You need to make use of objects more. Objects allow you to create structure, with nice names for values instead of just chucking everything into some random array.

I was trying to avoid this because it would confuse things a bit more than I wanted just yet, but we are going to have to create some classes to keep things separated. Classes are awesome, but a little bit ham-handed in Javascript. When you work in a language like Java, you can't avoid classes because it is an Object-oriented language. However, Javascript is not, and is instead what is known as a prototyping language.

Before we get to that, I wanted to point out that Data-driven programming is not opposed to Object-oriented programming. We can use them both at the same time with no trouble, in fact, they can compliment each other nicely. Which is exactly what we are going to do now.

Object-oriented programming is based on the concept that everything is an object. Before that, we had Procedural programming, where everything was about the procedures (otherwise known as functions, although some languages do make a distinction between them, and to make things even more complicated, there is another paradigm called Functional programming that is different again, but forget about that). Up until now, you have been doing Procedural programming, and we are going to use a hybrid of the Procedural and Object-oriented paradigms.

Classes are the basis of Object-orientation. A Class defines what an Object is. To put it into architectural nomenclature, a Class is a blueprint, where-as an Object is the building made from it. A Class is an idea, where-as an Object is an actual thing. We can create many buildings from the same blueprint, and so it is with Classes. The Class defines what the Objects have, first by declaring their member variables, and secondly by declaring the methods that can operate on them.

In Javascript, we can just use Objects directly, without using Classes, however, a Class makes it a bit easier to keep things separated, as well as reducing potential mistakes. It does that by ensuring that all Objects created by that Class, contain the same variables in them. That may seem trivial, but it is rather important.

I'm out of time, so I'll continue on tomorrow.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Mon Jan 06, 2020 1:24 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack17
No change in the action/animation.

Message received, fine motivation. Sorry to interrupt, despite your promise of a great follow-up lesson, I felt I needed to correct - as soon as possible - some of the problems you identified by replacing all of my 'difficult' table array index numerals with nice-named variables. If you agree, whew, I’m still anxious to hear more. Maybe ‘class’ is what I think of as the tables' structure?
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Mon Jan 06, 2020 6:20 pm

In general, you should not access items in an array using literal numerical indexes. Of course you can, and sometimes you will, but an array is generally meant to be iterated over. While an array can contain any type of items in it, generally, you want the same type of items in it so that you can treat them all the same without caring about what index they are in.

Let's say that you have an array and you are referencing everything from known indexes. You have setup the array such that the first 3 items represent one thing, the next 3 items represent the next thing, and the last 3 items represent the third thing. So you could access items like this:

Code:

var array = [
  1, '#ff00ff', 10,
  3, '#f003dd', 4,
  1, '#ff0000', 230
];
var color = array[3 + 1];
// or
array[6+2] += 10;

Now, you realise that you need more information for each thing, so you add a fourth item for each of them. Every single piece of code that references that array now has to be found and changed to reflect the new size and structure of the array. That is not only a pain in the butt, but also an error prone process. So we make use of objects to fix that problem quickly and easily.

Instead of one array that contains all of the data, we create an array that contains 3 objects. Each object then contains whatever they need to, with nice variable names that are descriptive and easy to remember and use.

Code:

var array = [
  { type: 1, color: '#ff00ff', length: 10 },
  { type: 3, color: '#f003dd', length: 4 },
  { type: 1, color: '#ff0000', length: 230 }
];

Now we can use them easily:

Code:

var color = array[1].color;
array[2].length += 10;

Notice how much more descriptive that code is compared to the direct access of an array containing everything? For starters, we can see that the second statement is changing the length value. In the previous version, we didn't know that just from looking at the code itself. We had to know the structure of the array.

So far, we have only used objects, and not classes. Using objects directly is fine and often all you need for simple cases, but when things get complicated, it is best to bring in the heavy hitters, and create some classes. I tend to go directly to classes because that is what I am use to from other languages. It also means things can grow naturally without me having to change the structure of things too much.

So let's change the above example into a class based structure:

Code:

// define a class for each item in the array
function Item( type, color, length )
{
  this.type = type;
  this.color = color;
  this.length = length;
}

But Nevyn, you created a function, not a class? What gives?

Well, this is how Javascript does classes. Strictly speaking, it doesn't do classes at all, it does prototypes (although I haven't actually used a prototype in this example because it doesn't need one yet). What makes it a class is not its declaration, but how you use it. In order to create an object using that function as its class, we use the new keyword, like this:

Code:

var array = [
  new Item( 1, '#ff00ff', 10 ),
  new Item( 3, '#f003dd', 4),
  new Item( 1, '#ff0000', 230)
];

When Javascript encounters the new keyword, it expects a function to follow it. An object is created and given to the function using the variable name this. It's a bit ham-handed, but it gets the job done.

Even though we are now using a class to create the array items, the code that accesses it remains the same:

Code:

var color = array[1].color;
array[2].length += 10;

You may point out that I am still using literal numerical indexes to access this array, and that is totally correct. This is a trivial example, so I have not gone to any trouble to create something that is iterable. However, for this app, where we are going to create a class for each Track, it will be.

To be continued...
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Wed Jan 08, 2020 1:33 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack18

Status update. As always, thanks for your patient guidance.

Arrays are collections of elements, only the length of the array needs to be defined in some way. The array elements may be objects, numbers, boolean, other arrays or left undefined. Using Arrays allows many associated methods. For example, the trackArrayData.indexOf(‘type’) method makes finding the specific numerical index of the S track data with respect to appropriate ‘string’ element a breeze. These string elements also serve to explain the table data, making the code much easier to understand. In summary, we want a well organized table with appropriate string elements.

Code:

     'type', 'curve4',
     'c0', 'strSect', posC.x, posC.y, posC.z,  
     'c1', 'c4Sect', posC.x  + 2*tracks.r, posC.y, posC.z,
     'c2', 'c4Sect', posC.x  + 3*tracks.r, posC.y, posC.z - tracks.r,
     'c3', 'c4Sect', posC.x  + 2*tracks.r, posC.y, posC.z - 2*tracks.r,
     'c4', 'c4Sect', posC.x  + tracks.r, posC.y, posC.z-r,
     'c5', 'c4Sect', posC.x + 2*tracks.r + tracks.r * Math.cos(tracks.piRotG), posC.y, posC.z - tracks.r - tracks.r * Math.sin(tracks.piRotG),
     'c6', 'c4Sect', posC.x + 2*tracks.r, posC.y, posC.z,

I believe that part is done. Here’s the top curved track portion of the array table, elements from index 30 (‘type’) to index 90, posC.z - the curved track endpoint’s z coordinate. The data portions for the other two tracks are organized in the same way. The three data sections contain all the positional information necessary for the proper execution of the animation function.

I'm enjoying the array lesson. There's plenty more to the subject. I haven't been able to access one data section of the table array, a second colored array comprised of the title 'colorArray2' followed by nine color objects, { magenta: new THREE.Color("hsl(300,100%,50%)") } is the first. I need to learn more about accessing and or processing data, which must come through practice.

Reading your message however, I’m missing something. Why would we need a class (function) to create those track values? I suppose it would make mass producing tracks easier.  
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Nevyn on Wed Jan 08, 2020 8:44 pm

You can create functions, or just take advantage of the available methods on an array, to find parts of it and then work relative to that. However, classes (or even just objects without classes) provide a nice, clean way of defining everything related to a specific thing in one place. It keeps all of the relevant code for that thing together and easy to find and easy to manipulate. It also makes that code much easier to understand when you haven't looked at it for a while. Right now, you are comfortable with the structure that you have created with an array, but in a years time, when you haven't looked at this in months, it won't be, and you won't remember that the third element from the index of 'type' is a color, or a length, or some other piece of data.

I haven't gotten to this part about classes yet, but you can declare methods on a class (a method is just a function of a class), and those methods perform operations on an object of that class. Your example using the indexOf method of the Array class is a classic case. This allows the class to hide its internal structure (if you want to), and creates a nice interface for using an object of that class. This is also where prototypes come into it, but we'll get to that shortly.

For example, an array in Javascript is not really like arrays in other languages. It is, in fact, an object, and not an array. There is an Array class (defined by Javascript itself) and any array you actually create, is really an object of the class Array. This allows you to skip indexes in an array. So you could create an array and only add items to indexes 3, 50, and 3124565334234. In nearly all other languages, that would require an array that contains 3124565334234 items. But in Javascript, because it is an object, it only actually has 3 items in that array. Those items use the keys '3', '50' and '3124565334234', respectively. Yes, the numerical indexes you use are actually converted into strings internally. The Array.indexOf method knows this, and takes advantage of it, so a search for the value stored at index 3124565334234 performs very quickly, only really looking at the 3 items.

I know that classes require a bit of a conceptual leap. They require new syntax, and it is easy to get confused. After a while, all of that syntax becomes superfluous. You just see it at a glance, know that it means you have a class, and move on to the important things about that class. You do have to slog through it for a while, though, so I understand any reticence that you may feel. It is worth it, though. I remember learning about classes when I was starting, and it took a few months before I saw the real benefit of them. I initially just saw them as a collection of variables. Sure, they had nice names, and were easy to use, but it wasn't until I really understood how to use methods that I found classes to be a great thing. We may get to that in this app, and the classes I am trying to create for the next post are already hinting at it, so you may see it soon enough. Unfortunately, to see the greatest benefit from them, it requires use of an advanced concept of classes: Inheritance. Which we will get to shortly.
Nevyn
Nevyn
Admin

Posts : 1781
Join date : 2014-09-11
Location : Australia

http://www.nevyns-lab.com

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Fri Jan 10, 2020 6:15 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack19
You mentioned trying to create new classes for your next post. Rather than wait for an ‘inheritance’ I’m doing my best at trying to keep up. I purchased a reference book, JavaScript, The Definitive Guide, sixth Edition, by David Flanagan. Close to the beginning - on page 8 of the 1080 page tome, I found some simple class code for 2D point objects that gave me something to play with. I’ve left the original comments but added the straight track marker locations.  
Code:

// Define a constructor function to initialize a new Point object
function Point(x,y,z) {    
     this.x = x;            
     this.y = y;            
     this.z = z;
}

// Use a constructor function with the keyword "new" to create instances
var s0 = new Point( -2*r, 0, 0 );  
var s1 = new Point( 0, 0, 0 );
var s2 = new Point( 2*r, 0, 0 );
var s3 = new Point( 4*r, 0, 0 );
var s4 = new Point( 6*r, 0, 0 );
var s5 = new Point( 2*Math.PI*r, 0, 0 );
var s6 = new Point( 8*r, 0, 0 );

// Define methods for Point objects by assigning them to the prototype
// object associated with the constructor function.
Point.prototype.dist = function() {
     return Math.sqrt(     // Returns the distance to the origin
          this.x * this.x +  
          this.y * this.y +  
          this.z * this.z
     );
};
// Now the Point object (and all future Point objects) inherits the method dist().

I’m currently trying to come up with a generic Point function to determine the angular difference between two points on the unit circle. I’ll need to translate points, while distinguishing between both of the c4 and c314 type track locations, etc. I’m sure I would need to expand Points with additional properties. Doing a web search I see there’s also at least one so-called Point.js on github, where someone made their own Point class and functions available for use, review and development by others. https://github.com/moagrius/Point/blob/master/Point.js

There might even be an existing standard Point class that I’ve mistaken for the new ‘prototype’ above.  cyclops  
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Wed Jan 15, 2020 6:55 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack20
Update. I’ve delayed posting till I could include some ‘significant’ progress.

Version 2 of the PI=4 Experiment now includes proper ball animations: staying on track, cycloid rolling, and the single rotation the circular track balls make in rotating about their circular track centers. All three balls are hitting their markers ‘simultaneously’. That’s most of the animation function.

In doing so, I believe I've conformed to your top/down idea; at least I used the process motion animation function structure you identified – that is after converting the switch case to if statements. I should mention, other than dT*velocity, I haven’t used any explicit time variable yet. Another difference, instead of passing a variable identifying the current section, I pass the ball's next possible position.

I believe version two’s code has been simplified, but to be perfectly honest I have no idea if it’s improved or not. There’s no denying the able array is a fine addition – it simplifies writing and understanding code. Many thanks for bringing to my attention the simple object type, also known as property:value. That awareness will make a big difference. I've certainly done a lot of reading on these subjects and am almost overwhelmed by amount of things I don't know.

I seem to have lost all my objectivity.

And then I've been thwarted – yet again - in writing a dat.gui with pull-down choices, such as would allow easy selection of piG track motion violations which I’ve previously implemented using checkboxes. You may note the newby test gui, it controls the track time in seconds and a couple of dummy variables. I tried to control the ball materials with a pull-down - no joy. Only the pull-downs don’t work. A good faith, albeit unsuccessful, effort, after three strikes on my part you might consider giving it a look. I’ll clean it up before too long.

Next comes the color change animation, the marker makes just after the ball rolls through. That would change the marker colors in the above image to: the three final track markers would be red, all the rest would be black.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Chromium6 on Thu Jan 16, 2020 12:12 am

Nice work!

Chromium6

Posts : 30
Join date : 2019-11-29

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by LongtimeAirman on Sun Jan 19, 2020 8:57 pm

.
Animate the PI = 4 experiment - Page 7 Gtrack21
Rolling along, the track marker color animations are now working properly.

Progress report. Thanks Cr6. Javascript is – beyond a doubt - a great thing to know; but if you’re like me, it requires a great deal of time and effort to get any good at it. I hope my frustrations aren’t too obvious. Of course it’s worth the effort.

Actually most of the color changes are now opacity animations, maximum or minimum transparency. Nevyn mentioned that alternative with respect to my tying to hide a table below the tracks. Only the circular track blue/red start/stop changes are “color” animations. I know I’m learning.

For some unknown reason, orange is always white.

Still making changes to the color portions of the table array - by incorporating more objects.

I suppose I’ll try looking for a better spacebar pause control next.
.

LongtimeAirman
Admin

Posts : 1449
Join date : 2014-08-10

Back to top Go down

Animate the PI = 4 experiment - Page 7 Empty Re: Animate the PI = 4 experiment

Post by Sponsored content


Sponsored content


Back to top Go down

Page 7 of 8 Previous  1, 2, 3, 4, 5, 6, 7, 8  Next

Back to top


 
Permissions in this forum:
You cannot reply to topics in this forum