Virtual Scattering Application
4 posters
Page 3 of 4
Page 3 of 4 • 1, 2, 3, 4
Re: Virtual Scattering Application
I've only had a quick look so far, but this might be one of the problems:
line 1270, 1271:
The model.parts.turning value is actually a THREE.Group. You probably shouldn't be putting new properties onto it (although it is totally possible to do so). Either make model.parts.turning into an object (model.parts.turning = {}) or remove the turning part so it looks like this:
Depending on what you want. My guess is that you didn't really want the turning part on the parts reference.
line 1270, 1271:
- Code:
model.parts.turning[ keyS ] = new THREE.Group();
model.parts.turning[ keyS ].add( mesh );
The model.parts.turning value is actually a THREE.Group. You probably shouldn't be putting new properties onto it (although it is totally possible to do so). Either make model.parts.turning into an object (model.parts.turning = {}) or remove the turning part so it looks like this:
- Code:
model.parts[ keyS ] = new THREE.Group();
model.parts[ keyS ].add( mesh );
Depending on what you want. My guess is that you didn't really want the turning part on the parts reference.
Re: Virtual Scattering Application
.
Ring gun now has spinning “RedHotSteel” spirals.
Thanks Nevyn. As soon as you answered my request for your help inside the loop – which you did, thank you very much,
was created before the loop and certainly didn’t need to be created for each object inside the loop - I knew where to look. My new rotatator -
Spinning (ellispes) ellipses look much the same as my last image, one needs to monitor the phase angle. To make up for my error and in a positive spirit I decided to glom spinning “RedHotSteel” spirals. I invoke it like this-
https://api.nevyns-lab.com/g3d/1.0.0/docs/module-G3DGeometry.html
One question. Line 1272. I was unable to indirectly address the textures in the texture Def function.
.
Ring gun now has spinning “RedHotSteel” spirals.
Thanks Nevyn. As soon as you answered my request for your help inside the loop – which you did, thank you very much,
- Code:
model.parts.turning = new THREE.Group();
was created before the loop and certainly didn’t need to be created for each object inside the loop - I knew where to look. My new rotatator -
- Code:
var rotatorS = new G3DAnim.RotateAnimator( keyS, G3D.NEGATIVE_Y_AXIS, Math.PI, 2 );
Spinning (
- Code:
this.geometry.spiralX = G3DGeometry.createSpiralGeometry( this, 0.5 );
https://api.nevyns-lab.com/g3d/1.0.0/docs/module-G3DGeometry.html
One question. Line 1272. I was unable to indirectly address the textures in the texture Def function.
- Code:
if ( m == 0 ){ // how can I indirectly address the spiral colors? This doesn't seem to work. Nor does this.material.keyColor
var mesh = new THREE.Mesh( this.geometry.centerRingE, this.material.centerRingE );// RedHotSteel
}
else if ( m == 1 ){
...
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
I don't know what is wrong with that code at line 1272, other than the fact that you aren't doing anything with the mesh. The code immediately after that section is creating a new mesh and saving it to the same variable, there-by overwriting it. It maybe just needs to be added to the group.
The G3DGeometry.createSpiralGeometry function can have up to 2 arguments. The first, if supplied, is an object containing the properties used to generate the spiral(s). The second argument, if supplied, is the number of spirals to create and they are arranged around a circle, so they inter-weave with each other. Giving it a count of 0.5 would be the same as giving it 1. Note that the count can actually be inside the object specified as the first argument. You are passing in this, which might be a bit dangerous, since it will have more properties than the createSpiralGeometry function wants, although it will just ignore them. The problem is if this contains a property not meant for the spirals, but will be used as such. It is better to create a new object like this:
OR
You could also create that object in the constructor and then just use it like this:
in constructor:
in createModel:
That allows the user of this class to control the spirals while still keeping the spiral information separate from all other properties on this.
With respect to using rotators, try to minimize them. You should be able to create the rotator outside of the loop and just give it an array containing the names of the targets to rotate. Even better than that, if they are all rotating the same way (frequency, etc) then put them all into 1 THREE.Group and just rotate that group.
The G3DGeometry.createSpiralGeometry function can have up to 2 arguments. The first, if supplied, is an object containing the properties used to generate the spiral(s). The second argument, if supplied, is the number of spirals to create and they are arranged around a circle, so they inter-weave with each other. Giving it a count of 0.5 would be the same as giving it 1. Note that the count can actually be inside the object specified as the first argument. You are passing in this, which might be a bit dangerous, since it will have more properties than the createSpiralGeometry function wants, although it will just ignore them. The problem is if this contains a property not meant for the spirals, but will be used as such. It is better to create a new object like this:
- Code:
this.geometry.spiralX = G3DGeometry.createSpiralGeometry( {
radius: this.spiralRadius,
tubeRadius: this.spiralTubeRadius,
...
}, 1 );
OR
You could also create that object in the constructor and then just use it like this:
in constructor:
- Code:
...
this.spiralInfo = {
radius: 4,
tubeRadius: 1,
tubeSegments: 25,
...
};
...
in createModel:
- Code:
this.geometry.spiralX = G3DGeometry.createSpiralGeometry( this.spiralInfo, 1 );
That allows the user of this class to control the spirals while still keeping the spiral information separate from all other properties on this.
With respect to using rotators, try to minimize them. You should be able to create the rotator outside of the loop and just give it an array containing the names of the targets to rotate. Even better than that, if they are all rotating the same way (frequency, etc) then put them all into 1 THREE.Group and just rotate that group.
Re: Virtual Scattering Application
.
I'd be careful with rotator use - I assume the're computationally expensive, etc.
Actually, I want each spiral to rotate about it's own spiral central axis. Like a Gatling gun. Alternatively, I'd also like a circular cross section to better fit within the rings.
How does one ‘close’ or cap the spiral cylinders’ ends? I tried true and false without result.
Why do the spirals have ‘straight’ ends? I couldn’t see how to get rid of them.
What is an object? Is it the same as a 3D object?
.
I'd be careful with rotator use - I assume the're computationally expensive, etc.
Actually, I want each spiral to rotate about it's own spiral central axis. Like a Gatling gun. Alternatively, I'd also like a circular cross section to better fit within the rings.
How does one ‘close’ or cap the spiral cylinders’ ends? I tried true and false without result.
Why do the spirals have ‘straight’ ends? I couldn’t see how to get rid of them.
What is an object? Is it the same as a 3D object?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
The animators aren't exactly expensive, but they can soon add up to be. They are executed every frame (although that can be configured), so we just need to be a little bit vigilant about their usage.
If each spiral is spinning about its own central axis, and they are all arranged about that same central axis, then rotating them all as a group will be the same. I can't imagine a way for them to rotate individually and not move through one another. But I don't know what you are thinking, so just get it working how you want and we can optimize later.
I am going to have to apologize about those end caps on the spirals. I initially had them without the caps, but they didn't join the other mesh I had them up against very well. So I found a way to specify straight sections. All of that is well and good, but what I didn't do is to make it so that you can use either method, or even a way to tell it how long the straight sections should be (which is possible in the actual generation code of the spiral). I will have to make some changes to get that working for you.
An object is basically a collection of properties. It is a way to keep related variables together and transport them around. In Javascript, everything is an object. Even things that you wouldn't think are, such as functions and even arrays. Most other languages, at least the strongly typed ones, have a distinction between an object and a primitive. A primitive is something very low level, such as a number or character. A primitive can only store that one type of data. If it is an int, then only integer numbers can be stored in it. An object, on the other hand, can have many different fields, some may be primitives and some may be other objects. Sometimes, an object may even store another object of the same type as itself.
Let's say we wanted to represent the version number of an application. The version has 3 parts: major, minor and build number. Each part is an integer number.
With primitives, we would do this:
That is fine for some purposes. However, let's assume that we actually need to pass this version around while still being able to access each part individually. To do that with primitives, we have to add 3 parameters to any function that wants them.
Even that might be ok for some purposes, but we run into problems if a function needs to change the numbers in the version. At first, you might think that this should work:
and it will, within that function, but any code outside of it will not see that change.
So we introduce an object structure to store the version numbers like this:
Now we can easily pass around the whole version number with only a single parameter:
And any changes to the numbers on the object will be seen by outside code because we are not assigning a new value to the parameter like with the primitive (which is actually a copy of the primitive).
However, we can still assign a new value to the parameter, even with an object:
After executing that function, the outside version will have minor=1 and build=10. Basically, when inside of a function, you have a reference to the object. It is the same object as outside of the function, but the reference is not.
Think of it like an address to your house. The address is a reference which can be used to find the real house. Once you find the house, you can access the people and things in it. However, if mother nature decides to destroy your neighborhood, and it is rebuilt in a different configuration, then your address may actually point to a different house than before, even a different physical location.
Dealing with references, also called pointers, can be a bit frustrating at first, but you soon learn the greatness of it. Most modern languages hide them from you, but they are still there if you know what to look for.
So, is an object the same as a 3D object? By 3D object, I assume you mean THREE.Object3D.
Yes, and no.
THREE.Object3D is a class, and a class is used to create objects. So in this way, yes, Object3D is an object, or what you have in your code is an object. A class is the idea of an object. It is the definition of it. When you have some code like this:
then node is an object of the class THREE.Group. THREE.Group extends from the class THREE.Object3D. So node is an object that is an instance of Group and is also an instance of Object3D. Now we are getting into class hierarchies.
In the beginning (actually, quite a while after that), we only had classes, sometimes called structs or records, and they could only contain variables, probably even just primitives. At some stage, we realised that it would be great if an object could store another object and give it depth. Then, because we are never happy with what we have, we decided that we wanted to be able to extend a class.
What the hell does that mean?
Only an example will help here, I think.
Suppose we have 2 classes: A and B.
Now we realise that we really want B to have a name too. We could just add that to the B class like this:
However, that is inefficient for the developer as it is usually a lot more than just a single value that we want.
So we make B extend A like this:
Now, B is calling A from within its constructor so that any object created from B will have both name and title values.
This is the Javascript way of doing it, and I am leaving out some parts for clarity. The above method works when it is only values that we want to inherit. If there are also functions, now called methods because they are on a class, then we have to do more and deal with prototypes, but that gets confusing.
When I say to 'just create an object', I usually mean create one on-the-spot. You dynamically create an object like this:
The 1 and N are just there to show that many properties can be used, not that their names must increment or have numbers or anything else.
That is probably more than you wanted to know.
If each spiral is spinning about its own central axis, and they are all arranged about that same central axis, then rotating them all as a group will be the same. I can't imagine a way for them to rotate individually and not move through one another. But I don't know what you are thinking, so just get it working how you want and we can optimize later.
I am going to have to apologize about those end caps on the spirals. I initially had them without the caps, but they didn't join the other mesh I had them up against very well. So I found a way to specify straight sections. All of that is well and good, but what I didn't do is to make it so that you can use either method, or even a way to tell it how long the straight sections should be (which is possible in the actual generation code of the spiral). I will have to make some changes to get that working for you.
An object is basically a collection of properties. It is a way to keep related variables together and transport them around. In Javascript, everything is an object. Even things that you wouldn't think are, such as functions and even arrays. Most other languages, at least the strongly typed ones, have a distinction between an object and a primitive. A primitive is something very low level, such as a number or character. A primitive can only store that one type of data. If it is an int, then only integer numbers can be stored in it. An object, on the other hand, can have many different fields, some may be primitives and some may be other objects. Sometimes, an object may even store another object of the same type as itself.
Let's say we wanted to represent the version number of an application. The version has 3 parts: major, minor and build number. Each part is an integer number.
With primitives, we would do this:
- Code:
// version: 1.0.10
var major = 1;
var minor = 0;
var build = 10;
That is fine for some purposes. However, let's assume that we actually need to pass this version around while still being able to access each part individually. To do that with primitives, we have to add 3 parameters to any function that wants them.
- Code:
var myFunction = function( major, minor, build )
{
...
};
Even that might be ok for some purposes, but we run into problems if a function needs to change the numbers in the version. At first, you might think that this should work:
- Code:
var myFunction = function( major, minor, build )
{
minor = 1;
};
and it will, within that function, but any code outside of it will not see that change.
So we introduce an object structure to store the version numbers like this:
- Code:
var version = {
major: 1,
minor: 0,
build: 10
};
Now we can easily pass around the whole version number with only a single parameter:
- Code:
var myFunction = function( version )
{
version.minor = 1;
};
And any changes to the numbers on the object will be seen by outside code because we are not assigning a new value to the parameter like with the primitive (which is actually a copy of the primitive).
However, we can still assign a new value to the parameter, even with an object:
- Code:
var myFunction = function( version )
{
version.minor = 1;
version = { major: 1, minor: 2, build: 20 };
};
After executing that function, the outside version will have minor=1 and build=10. Basically, when inside of a function, you have a reference to the object. It is the same object as outside of the function, but the reference is not.
Think of it like an address to your house. The address is a reference which can be used to find the real house. Once you find the house, you can access the people and things in it. However, if mother nature decides to destroy your neighborhood, and it is rebuilt in a different configuration, then your address may actually point to a different house than before, even a different physical location.
Dealing with references, also called pointers, can be a bit frustrating at first, but you soon learn the greatness of it. Most modern languages hide them from you, but they are still there if you know what to look for.
So, is an object the same as a 3D object? By 3D object, I assume you mean THREE.Object3D.
Yes, and no.
THREE.Object3D is a class, and a class is used to create objects. So in this way, yes, Object3D is an object, or what you have in your code is an object. A class is the idea of an object. It is the definition of it. When you have some code like this:
- Code:
var node = new THREE.Group();
then node is an object of the class THREE.Group. THREE.Group extends from the class THREE.Object3D. So node is an object that is an instance of Group and is also an instance of Object3D. Now we are getting into class hierarchies.
In the beginning (actually, quite a while after that), we only had classes, sometimes called structs or records, and they could only contain variables, probably even just primitives. At some stage, we realised that it would be great if an object could store another object and give it depth. Then, because we are never happy with what we have, we decided that we wanted to be able to extend a class.
What the hell does that mean?
Only an example will help here, I think.
Suppose we have 2 classes: A and B.
- Code:
var A = function()
{
this.name = 'My name';
};
var B = function()
{
this.title = 'My title';
};
Now we realise that we really want B to have a name too. We could just add that to the B class like this:
- Code:
var A = function()
{
this.name = 'My name';
};
var B = function()
{
this.title = 'My title';
this.name = 'My name';
};
However, that is inefficient for the developer as it is usually a lot more than just a single value that we want.
So we make B extend A like this:
- Code:
var A = function()
{
this.name = 'My name';
};
var B = function()
{
A.call( this );
this.title = 'My title';
};
Now, B is calling A from within its constructor so that any object created from B will have both name and title values.
This is the Javascript way of doing it, and I am leaving out some parts for clarity. The above method works when it is only values that we want to inherit. If there are also functions, now called methods because they are on a class, then we have to do more and deal with prototypes, but that gets confusing.
When I say to 'just create an object', I usually mean create one on-the-spot. You dynamically create an object like this:
- Code:
var myObject = {
property1: value1,
...
propertyN: valueN
};
The 1 and N are just there to show that many properties can be used, not that their names must increment or have numbers or anything else.
That is probably more than you wanted to know.
Re: Virtual Scattering Application
I fixed up the caps on the spirals. You have to call G3DGeometry.createCappedSpiralGeometry if you want them back, and you can now specify the start and end points of the straight sections. The documentation has been updates so read that and see if it helps. I think you will find that you want a little bit of straight section because the ends of the spirals are on angles. They line up with the axis of the tube creating the spiral.
The start and end points are specified as a value between 0 and 1, inclusive. So if you say you want the spiral to start at 0.2 and end at 0.8, then you will get straight sections on the start and end that are 20% of the length of the complete tube. That is the absolute height, not the curved length of the tube. So you might give them really small values so that the very ends of the spirals are flat. Try 0.01, maybe even 0.001.
The start and end points are specified as a value between 0 and 1, inclusive. So if you say you want the spiral to start at 0.2 and end at 0.8, then you will get straight sections on the start and end that are 20% of the length of the complete tube. That is the absolute height, not the curved length of the tube. So you might give them really small values so that the very ends of the spirals are flat. Try 0.01, maybe even 0.001.
Re: Virtual Scattering Application
.
Current image of createCappedSpiralGeometry.
I reviewed the G3D documentation changes. After all that work, I'm sorry to say I don't believe you've fully implemented the change yet. True, the uncapped Ring gun spirals are spirals throughout their length, the ‘cap’ or straight end sections aren’t present. I've got the app up and running in side-by-side browser screens, alternating the // line comment. Using my repo copy of course, - not Pushed.
line 1287
That's including the additional variables in Ring gun's this.list - Line 1030
Comment. CappedSpiralCurve and SpiralCurve. A curve is a two dimensional line. The spiral, capped or uncapped - defines a type of cylinder. Recommend changing SpiralCurve to SpiralCylinder, and CappedSpiralCurve to CappedSpiralCylinder. Please consider another alternative form of cap - the same way one caps a cylinder, the surface formed by rotating the radius orthogonal to the tube's forward direction.
Another possible ending cap is formed by cutting the tube on the surface formed by rotating a radius about the center of the tube’s rotation. That would have the additional benefit of a ninety degree flush cut which you might prefer.
How can I use the last number to make the circular array referred to in the documentation?
Thanks for the Object treatise. I'll can mostly follow. I'll no doubt refer to it in the future. Is 'my solution' involving - model.parts.turning = new THREE.Group(); // 'correct'? I didn't come up with it without your help.
.
Current image of createCappedSpiralGeometry.
I reviewed the G3D documentation changes. After all that work, I'm sorry to say I don't believe you've fully implemented the change yet. True, the uncapped Ring gun spirals are spirals throughout their length, the ‘cap’ or straight end sections aren’t present. I've got the app up and running in side-by-side browser screens, alternating the // line comment. Using my repo copy of course, - not Pushed.
line 1287
- Code:
//this.geometry.spiral = G3DGeometry.createSpiralGeometry( this, 1 );
this.geometry.spiral = G3DGeometry.createCappedSpiralGeometry( this, 1 );
That's including the additional variables in Ring gun's this.list - Line 1030
- Code:
this.phase = 0;
// These next two are new to the list.
this.start = 0.5; // var start = typeof options.start === 'number' ? options.start : 0.1;
this.end = 0.6; // var end = typeof options.end === 'number' ? options.end : 0.9;
Comment. CappedSpiralCurve and SpiralCurve. A curve is a two dimensional line. The spiral, capped or uncapped - defines a type of cylinder. Recommend changing SpiralCurve to SpiralCylinder, and CappedSpiralCurve to CappedSpiralCylinder. Please consider another alternative form of cap - the same way one caps a cylinder, the surface formed by rotating the radius orthogonal to the tube's forward direction.
Another possible ending cap is formed by cutting the tube on the surface formed by rotating a radius about the center of the tube’s rotation. That would have the additional benefit of a ninety degree flush cut which you might prefer.
How can I use the last number to make the circular array referred to in the documentation?
Thanks for the Object treatise. I'll can mostly follow. I'll no doubt refer to it in the future. Is 'my solution' involving - model.parts.turning = new THREE.Group(); // 'correct'? I didn't come up with it without your help.
.
Last edited by LongtimeAirman on Wed Jun 26, 2019 2:50 pm; edited 1 time in total (Reason for editing : Added Another possible ending)
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
The Actual view of createCappedSpiralGeometry with this.start = 0.5, and this.end = 0.6.
As you've probably noticed, my biggest problems usually involve the little typos I constantly produce or details I really shouldn't be missing. Coding is an excellent way to recognize such problems. Now as far as corrections go ... .
Oh well, my other comments/requests still apply.
.
The Actual view of createCappedSpiralGeometry with this.start = 0.5, and this.end = 0.6.
- Code:
this.geometry.spiralX = G3DGeometry.createCappedSpiralGeometry( this, 1 );
As you've probably noticed, my biggest problems usually involve the little typos I constantly produce or details I really shouldn't be missing. Coding is an excellent way to recognize such problems. Now as far as corrections go ... .
Oh well, my other comments/requests still apply.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Glad you found the mistake. I was a bit confused because I tested it with the SpiralGunGenerator and it was still working as expected with the straight sections.
The SpiralCurve and CappedSpiralCurve classes are correctly named. They do generate line segments, not tubes. They extend from THREE.Curve. The THREE.BufferTubeGeometry class uses the line to create a tube. That is why everything is specified as values between 0 and 1. The Curve class is given values between 0 and 1 and it returns a point for that value. So if you wanted a tube that is 2 units high, then when the Curve is given a value of 0, it returns 0. When it is given 1, it returns 2. When it is given 0.2, it returns 0.4. Well, it is really returning THREE.Vector3 objects, so they are 3D points, but that should paint the picture well enough.
The create*SpiralGeometry methods could be renamed, but I think it is good enough until we actually want to create a spiral line, and then it will get confusing enough to change it.
The G3DGeometry.create*SpiralGeometry functions can be used to create multiple spirals that are arrayed around a circle, at the radius specified in the options argument, or 1 by default. So if you call it like this:
Then g will be an array of THREE.BufferTubeGeometry objects with 2 items in it. The spirals will be on opposite sides of a circle at their start and end locations.
If you use this:
Then you will get back a THREE.Group containing THREE.Mesh instances for both geometries. If you want to treat them all as 1 object (generic use of object), then this is the way to do it. You can use as many Materials as you need. It will apply them to each spiral in the order they are defined in the array. If there are not enough materials, then it will cycle through them.
You can omit the number of spirals and it will use the length of the materials array to decide how many to generate, if the number of materials matches the number of spirals you want.
Little typos are the bane of every programmers life. Even seasoned pro's do it and we struggle to find them because we skim over our code, not really reading it closely. It often takes a fresh set of eyes to look over it and find some small mistake. When you aren't familiar with the code, you read it much more closely and find such problems. If you've been reading my documentation then you've probably found a few typos in there. I fixed a couple yesterday on the createSpiralGeometry functions.
The fix for model.parts.turning looks fine.
The SpiralCurve and CappedSpiralCurve classes are correctly named. They do generate line segments, not tubes. They extend from THREE.Curve. The THREE.BufferTubeGeometry class uses the line to create a tube. That is why everything is specified as values between 0 and 1. The Curve class is given values between 0 and 1 and it returns a point for that value. So if you wanted a tube that is 2 units high, then when the Curve is given a value of 0, it returns 0. When it is given 1, it returns 2. When it is given 0.2, it returns 0.4. Well, it is really returning THREE.Vector3 objects, so they are 3D points, but that should paint the picture well enough.
The create*SpiralGeometry methods could be renamed, but I think it is good enough until we actually want to create a spiral line, and then it will get confusing enough to change it.
The G3DGeometry.create*SpiralGeometry functions can be used to create multiple spirals that are arrayed around a circle, at the radius specified in the options argument, or 1 by default. So if you call it like this:
- Code:
var options = { radius: 2, ... };
var g = G3DGeometry.createSpiralGeometry( options, 2 );
Then g will be an array of THREE.BufferTubeGeometry objects with 2 items in it. The spirals will be on opposite sides of a circle at their start and end locations.
If you use this:
- Code:
var materials = [ new THREE.MeshBasicMaterial() ];
var options = { radius: 2, ... };
var mesh = G3DGeometry.createSpiralMesh( materials, options, 2 );
Then you will get back a THREE.Group containing THREE.Mesh instances for both geometries. If you want to treat them all as 1 object (generic use of object), then this is the way to do it. You can use as many Materials as you need. It will apply them to each spiral in the order they are defined in the array. If there are not enough materials, then it will cycle through them.
You can omit the number of spirals and it will use the length of the materials array to decide how many to generate, if the number of materials matches the number of spirals you want.
Little typos are the bane of every programmers life. Even seasoned pro's do it and we struggle to find them because we skim over our code, not really reading it closely. It often takes a fresh set of eyes to look over it and find some small mistake. When you aren't familiar with the code, you read it much more closely and find such problems. If you've been reading my documentation then you've probably found a few typos in there. I fixed a couple yesterday on the createSpiralGeometry functions.
The fix for model.parts.turning looks fine.
Re: Virtual Scattering Application
.
I haven’t gotten the createSpiralGeometry function to make a circular array yet.
Var options caused a reference error.
That didn’t prevent me from playing with the rotator animation
The “y axis” is with respect to the center of each gun’s position to the center of the target zone. The guns fire particles along those same target lines. A group of nine spirals is rotating about each of the configuration’s 14 gun/target axes. Overall, the constant swinging is enough to cause motion sickness. Please forgive me for posting this Macaroni and cheese nightmare.
There's been a misunderstanding - surprise! When I said cap, I imagined the circular end of the spiral cylinder, the round part of the can you cut off to get to the tuna inside. When you say cap, you seem to mean a straight end section, as is present in Spiral gun. I know that by using very small increments of this.start and this.end one can trim the end of the spiral curve nicely, so that it may fit better with an adjacent object. Nevertheless, using this.start and this.endm both ends of the cylinder are always open – holes in the texture. I was suggesting closing those holes with small circles or ellipses.
.
I haven’t gotten the createSpiralGeometry function to make a circular array yet.
Var options caused a reference error.
- Code:
//var materials = [ new THREE.MeshBasicMaterial() ];
//var options = { radius: 2, ... }; // uncommenting causes reference error, GunModels is not defined.
//var mesh = G3DGeometry.createSpiralMesh( materials, options, 2 );// options is not defined.
That didn’t prevent me from playing with the rotator animation
The “y axis” is with respect to the center of each gun’s position to the center of the target zone. The guns fire particles along those same target lines. A group of nine spirals is rotating about each of the configuration’s 14 gun/target axes. Overall, the constant swinging is enough to cause motion sickness. Please forgive me for posting this Macaroni and cheese nightmare.
There's been a misunderstanding - surprise! When I said cap, I imagined the circular end of the spiral cylinder, the round part of the can you cut off to get to the tuna inside. When you say cap, you seem to mean a straight end section, as is present in Spiral gun. I know that by using very small increments of this.start and this.end one can trim the end of the spiral curve nicely, so that it may fit better with an adjacent object. Nevertheless, using this.start and this.endm both ends of the cylinder are always open – holes in the texture. I was suggesting closing those holes with small circles or ellipses.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Oh, ok. I didn't think about that because I had them flush against another mesh, covering those areas. That is a more appropriate use of the term 'cap'. I didn't have any better names when I was creating that.
Turns out that THREE.TubeBufferGeometry supports that. I have added it to the code so that you can now add another property to the options called 'closed' and it can be true or false. It is false by default.
I'll update G3D later today with those changes.
Actually, I just updated the site with those changes, but can't minify the code. So I have changed the way scattering.html imports those files to use the raw version. You should have those changes once you pull them from GIT.
That code section above that you commented out needs to be changed for it to work. The '...' is invalid and I just wrote it like that to imply that more can be added as required. I often forget that obvious things to me are not so obvious to others, and they may be taken literally. Especially in programming where we can be fiddling with things we don't fully understand (even pro's). See the documentation for what properties are allowed in the options argument.
Turns out that THREE.TubeBufferGeometry supports that. I have added it to the code so that you can now add another property to the options called 'closed' and it can be true or false. It is false by default.
I'll update G3D later today with those changes.
Actually, I just updated the site with those changes, but can't minify the code. So I have changed the way scattering.html imports those files to use the raw version. You should have those changes once you pull them from GIT.
That code section above that you commented out needs to be changed for it to work. The '...' is invalid and I just wrote it like that to imply that more can be added as required. I often forget that obvious things to me are not so obvious to others, and they may be taken literally. Especially in programming where we can be fiddling with things we don't fully understand (even pro's). See the documentation for what properties are allowed in the options argument.
Re: Virtual Scattering Application
I should add that I have not tested that change. I don't expect any problems, but just call out if there are.
Re: Virtual Scattering Application
.
this.closed = false. I had to follow that last 'error' image with a closely related but much more respectable Ring and Spiral combination.
I've practiced using the createSpiral function. In the above image, the function is called from within loops, passing the loop variables to the option list, resulting in different sets of spiral parameters. Its still rough - by eye, not properly math functioned. I especially like seeing different - non-interfering - wavelengths and wave angles.
Spiral Function phase error - me or the function; of all the variables on the spiral's option list, I could not get the phase variable to do anything.
Spiral Function options. As I understand it, one lets the function know to use the options list by selecting a final 2 (two spirals will be produced) in the function call; can one use an option list without specifying '2'?
I'll try to give it some more thought, unfortunately, I'm a bit dizzy - spirally saturated - at the moment. If it's Ok with you(?), I'll think I'll duplicate and clean up Ring gun, then work on 'finalizing' this configuration as it's own separate gunModel(?).
.
this.closed = false. I had to follow that last 'error' image with a closely related but much more respectable Ring and Spiral combination.
I've practiced using the createSpiral function. In the above image, the function is called from within loops, passing the loop variables to the option list, resulting in different sets of spiral parameters. Its still rough - by eye, not properly math functioned. I especially like seeing different - non-interfering - wavelengths and wave angles.
Spiral Function phase error - me or the function; of all the variables on the spiral's option list, I could not get the phase variable to do anything.
Spiral Function options. As I understand it, one lets the function know to use the options list by selecting a final 2 (two spirals will be produced) in the function call; can one use an option list without specifying '2'?
I'll try to give it some more thought, unfortunately, I'm a bit dizzy - spirally saturated - at the moment. If it's Ok with you(?), I'll think I'll duplicate and clean up Ring gun, then work on 'finalizing' this configuration as it's own separate gunModel(?).
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
The phase is definitely working, as it is used to arrange multiple spirals around a circle. Maybe you are expecting it to work differently than it will. The phase option sets the starting value of the spiral itself. Let's say we are generating a single spiral and by default it will start at the 12:00 position of a circle (we are behind the spiral and looking along the axis that it rotates around and can see the full face of that circle). If we set the phase to Math.PI, then it will start at the 6:00 position of the circle. So we have taken a spiral that started at the top of the circle, and turned it into one that starts at the bottom. It does not move it along its rotational axis, which you may have expected. In a way it does do that, but not from a positional perspective, only from a rotational perspective.
While the create*SpiralGeometry functions allow you to specify the count as a parameter, you do not have to and can instead include it in the options parameter. So these are equivalent:
If you don't specify a count at all then it will default to 1. So these 3 are all equivalent:
Sure, do with it as you please. Cleaning things up is always a good idea once you have things where you like them.
While the create*SpiralGeometry functions allow you to specify the count as a parameter, you do not have to and can instead include it in the options parameter. So these are equivalent:
- Code:
var options = {
radius: 5
};
var g = G3DGeometry.createSpiralGeometry( options, 3 );
- Code:
var options = {
radius: 5,
count: 3
};
var g = G3DGeometry.createSpiralGeometry( options );
If you don't specify a count at all then it will default to 1. So these 3 are all equivalent:
- Code:
var options = {
radius: 5
};
var g = G3DGeometry.createSpiralGeometry( options, 1 );
- Code:
var options = {
radius: 5,
count: 1
};
var g = G3DGeometry.createSpiralGeometry( options );
- Code:
var options = {
radius: 5
};
var g = G3DGeometry.createSpiralGeometry( options );
Sure, do with it as you please. Cleaning things up is always a good idea once you have things where you like them.
Re: Virtual Scattering Application
.
In progress. Spiral Ring gun with 5 spirals each.
Thanks again for all the information Nevyn. I found a computer science guy who’s been involved in lots of frontier three.js work - Ian Webster – you might be interested in. Check out his work at, http://www.ianww.com/
This time I tried working from the clean Ring gun code. I broke the previous orange color into the entire texture Def function to make the spirals easier to distinguish - as in the above image. While I made good progress - the code is much cleaner. There are always problem, now there are two.
1. For the time being, a 2 spiral array does not work. Of course the error is mine.
2. I seem to have lost the rotation animation - again. What goes around comes around.
That’s all for now.
.
In progress. Spiral Ring gun with 5 spirals each.
Thanks again for all the information Nevyn. I found a computer science guy who’s been involved in lots of frontier three.js work - Ian Webster – you might be interested in. Check out his work at, http://www.ianww.com/
This time I tried working from the clean Ring gun code. I broke the previous orange color into the entire texture Def function to make the spirals easier to distinguish - as in the above image. While I made good progress - the code is much cleaner. There are always problem, now there are two.
1. For the time being, a 2 spiral array does not work. Of course the error is mine.
- Code:
var keySY = 'spiralY' + (i+1);
this.geometry[keySY] = G3DGeometry.createSpiralGeometry( options, 1 ); // Ok
// this.geometry[keySY] = G3DGeometry.createSpiralGeometry( options, 2 ); // 2 does not work .
2. I seem to have lost the rotation animation - again. What goes around comes around.
That’s all for now.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
1. If you ask for more than 1 spiral geometry, it has to return an array of them. You probably want to use the G3DGeometry.createSpiralMesh function, which will put them into a Mesh for you and return either a THREE.Mesh, a THREE.Group containing all of the meshes, or null if no geometry was created.
Of course, that won't work very well in the init function, only the createModel function, since we can't share meshes. So either change init to work with an array of geometries being returned from G3DGeometry.createSpiralGeometry (which will get a bit complicated, I think) or do it in createModel. It is less efficient to do it in createModel, since it will happen for every model created. It might just be easier to create 1 spiral geometry at a time. There is no advantage to creating multiple at once, only convenience. They are still individual Geometry objects.
2. Here is the current code:
It is defining the key, called keyPos, but only uses it twice when it should be using it 4 times. But that is not the problem, just a way to make it better and cleaner and less likely to cause errors.
So in the first instance, we will change that to this:
Now that it is a little bit cleaner, it is easier to see that you are creating a THREE.Group, but not adding anything to it.
I don't know what it is you should be adding to that group, but something needs to go in there.
Of course, that won't work very well in the init function, only the createModel function, since we can't share meshes. So either change init to work with an array of geometries being returned from G3DGeometry.createSpiralGeometry (which will get a bit complicated, I think) or do it in createModel. It is less efficient to do it in createModel, since it will happen for every model created. It might just be easier to create 1 spiral geometry at a time. There is no advantage to creating multiple at once, only convenience. They are still individual Geometry objects.
2. Here is the current code:
- Code:
var keyPos = 'rotator'+(i+1)+'Pos';
var rotator = new G3DAnim.RotateAnimator( keyPos, G3D.NEGATIVE_Y_AXIS, Math.PI, 4-i );
model.addAnimator( keyPos, rotator );
model.parts['rotator' + (i+1) + 'Pos' ] = new THREE.Group();
model.parts.body.add( model.parts['rotator' + (i+1) + 'Pos' ]);
It is defining the key, called keyPos, but only uses it twice when it should be using it 4 times. But that is not the problem, just a way to make it better and cleaner and less likely to cause errors.
So in the first instance, we will change that to this:
- Code:
var keyPos = 'rotator'+(i+1)+'Pos';
var rotator = new G3DAnim.RotateAnimator( keyPos, G3D.NEGATIVE_Y_AXIS, Math.PI, 4-i );
model.addAnimator( keyPos, rotator );
model.parts[keyPos] = new THREE.Group();
model.parts.body.add( model.parts[keyPos]);
Now that it is a little bit cleaner, it is easier to see that you are creating a THREE.Group, but not adding anything to it.
- Code:
var keyPos = 'rotator'+(i+1)+'Pos';
var rotator = new G3DAnim.RotateAnimator( keyPos, G3D.NEGATIVE_Y_AXIS, Math.PI, 4-i );
model.addAnimator( keyPos, rotator );
model.parts[keyPos] = new THREE.Group();
// TODO add mesh(es) to the model.parts[keyPos] group
model.parts.body.add( model.parts[keyPos] );
I don't know what it is you should be adding to that group, but something needs to go in there.
Re: Virtual Scattering Application
.
Current Spiral ring gun. The version with different colored spirals is a bit confusing, I like this version better. I’m tempted to call them Yellowjackets – like the wasps. There are 4 pairs of interpenetrating positive/negative spirals. Randomness has been added to each of the pair’s wavelength and phase angle. The list of spiral options is called twice, once each for positive and negative spirals, as is also done for each set of positive and negative rings. Here the center ring is removed in order to see the spirals better.
Nevyn coded and wrote.
.
Current Spiral ring gun. The version with different colored spirals is a bit confusing, I like this version better. I’m tempted to call them Yellowjackets – like the wasps. There are 4 pairs of interpenetrating positive/negative spirals. Randomness has been added to each of the pair’s wavelength and phase angle. The list of spiral options is called twice, once each for positive and negative spirals, as is also done for each set of positive and negative rings. Here the center ring is removed in order to see the spirals better.
Nevyn coded and wrote.
Your suggestion worked perfectly. I added-I don't know what it is you should be adding to that group, but something needs to go in there.
- Code:
// TODO add mesh(es) to the model.parts[keyPos] group
- Code:
model.parts[ keyPos ].add( mesh );
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
That's why we call it a scene graph. It is a hierarchy of nodes. A tree, if you like. They can get very wide and deep, and confusing. Try to focus on a small part of it that you are working on at any given time. Know which nodes (any Object3D is a node) are at the top, for your current problem, and try to keep an eye on the structure that you are creating. Write it out or draw a picture if you have to. You will start to see where you can fit in new things that you want to add. How to make better use of the groups that you already have. Even how you might restructure it to work better for you. It's all a learning experience and we get better at it the more we work with it. You're doing fine.
Re: Virtual Scattering Application
.
Simple gun is now available in a seven pack.
I’ll submit this as a possible extra pointer attempting to illustrate a hierarchical change in Simple gun’s scene graph. Is that correct? All I know is the code makes such changes a simple matter. Six more iterations of the same sphere mesh (in +/-X, +/-Y, +/-Z positions) and another (rotate orthogonal to Y) band mesh copy results in a worthy new gun model, Simple array gun.
.
Simple gun is now available in a seven pack.
I’ll submit this as a possible extra pointer attempting to illustrate a hierarchical change in Simple gun’s scene graph. Is that correct? All I know is the code makes such changes a simple matter. Six more iterations of the same sphere mesh (in +/-X, +/-Y, +/-Z positions) and another (rotate orthogonal to Y) band mesh copy results in a worthy new gun model, Simple array gun.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Are you sure it isn't supposed to be a 6-pack?
Here's an idea. Use the honeycomb body from SimpleGunGenerator, but line them up in a circle around some other central body, maybe just a tube like the hot metal tube I have at the center of SpiralGunGenerator. Then the honeycomb parts rotate around that central tube. Like a 6-shooter. You could even make each honeycomb part rotate so that it looks like they are rolling along that central tube, like ball-bearings. Add an outer case over the honeycomb parts and it will look, and act, just like a chamber in a 6-shooter. Eventually, we might even be able to match the rotation frequency of that chamber to the firing rate of the gun. That will take a bit of work though.
Here's an idea. Use the honeycomb body from SimpleGunGenerator, but line them up in a circle around some other central body, maybe just a tube like the hot metal tube I have at the center of SpiralGunGenerator. Then the honeycomb parts rotate around that central tube. Like a 6-shooter. You could even make each honeycomb part rotate so that it looks like they are rolling along that central tube, like ball-bearings. Add an outer case over the honeycomb parts and it will look, and act, just like a chamber in a 6-shooter. Eventually, we might even be able to match the rotation frequency of that chamber to the firing rate of the gun. That will take a bit of work though.
Re: Virtual Scattering Application
.
From SpiralGunGenerator. The top and bottom plates are removed to view the 'centerTube'.
Your wish - or was that beer talking(?) - is my command. Some sort of Simple gun revolving mechanism. Each of the Simple guns are in a circular array like bullets in a revolver. You’d like to cycle each Simple gun through or around some stationary, central tube, or barrel. If so, so be it.
I’ve copied SimpleGunGenerator to a new RevolvingGunGenerator.
Given the preliminary discussion, please note that the so-called centerTube from SpiralGunGenerator is not a tube – it’s a ‘solid’ cylinder. Just like the barrel in SimpleGunGenerator. In SpiralGunGenerator, one is able to position the viewpoint inside the RedHotSteel centerTube where one cannot see its outer surface and so it disappears from view, from the outside it appears to be a solid rod.
I know I can build a nice tube from a circular array of rods, but how would you make a tube with inside and outside radii? Is that why this.centerTubeRadius appears twice in the cylinder geometry call? Might the Virtual Scattering Application allow us to subtract one cylinder from another? G3DGeometry doesn’t appear to include any hollow cylinder or tube geometry. Three.js TubeBufferGeometry * allows a 3D curved path – it's complicated, maybe we can simplify it. Is that what G3D is for? To pipeline geometric functions by eliminating unnecessary complex details?
Speak now lest you regret it later. It would be correct to view anything I post tomorrow with some suspicion. July 4th must be our biggest beer drinking day of the year.
*url=https://threejs.org/docs/index.html#api/en/geometries/TubeBufferGeometry]https://threejs.org/docs/index.html#api/en/geometries/TubeBufferGeometry[/url]
.
From SpiralGunGenerator. The top and bottom plates are removed to view the 'centerTube'.
- Code:
this.geometry.centerTube = new THREE.CylinderGeometry( this.centerTubeRadius, this.centerTubeRadius, this.length, 32 );
Your wish - or was that beer talking(?) - is my command. Some sort of Simple gun revolving mechanism. Each of the Simple guns are in a circular array like bullets in a revolver. You’d like to cycle each Simple gun through or around some stationary, central tube, or barrel. If so, so be it.
I’ve copied SimpleGunGenerator to a new RevolvingGunGenerator.
Given the preliminary discussion, please note that the so-called centerTube from SpiralGunGenerator is not a tube – it’s a ‘solid’ cylinder. Just like the barrel in SimpleGunGenerator. In SpiralGunGenerator, one is able to position the viewpoint inside the RedHotSteel centerTube where one cannot see its outer surface and so it disappears from view, from the outside it appears to be a solid rod.
I know I can build a nice tube from a circular array of rods, but how would you make a tube with inside and outside radii? Is that why this.centerTubeRadius appears twice in the cylinder geometry call? Might the Virtual Scattering Application allow us to subtract one cylinder from another? G3DGeometry doesn’t appear to include any hollow cylinder or tube geometry. Three.js TubeBufferGeometry * allows a 3D curved path – it's complicated, maybe we can simplify it. Is that what G3D is for? To pipeline geometric functions by eliminating unnecessary complex details?
Speak now lest you regret it later. It would be correct to view anything I post tomorrow with some suspicion. July 4th must be our biggest beer drinking day of the year.
*url=https://threejs.org/docs/index.html#api/en/geometries/TubeBufferGeometry]https://threejs.org/docs/index.html#api/en/geometries/TubeBufferGeometry[/url]
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
There doesn't seem to be any Geometry class in THREE that can create a pipe with a specified wall thickness. I will create one in G3DGeometry.
You could cheat and just use a solid cylinder, but the honeycomb parts stick out from it. Then the cylinder will fill in the gaps between them. Not sure if that will look good or not. Probably not unless the honeycomb sections were turned into cylinders themselves, which may cause problems where the 2 geometries meet. May be worth trying anyway.
The G3DGeometry.create*SpiralGeometry methods can accept 2 radii. The first, called radius, specifies the spiral radius. The center of the spiral itself will always be at that radius. The second radius, called tubeRadius, is the radius of the tube that makes the spiral. So if they were equal values, then the spiral would rotate around the center line and you would not be able to see the gap along that line. There would be no gap. It would look like the tube was twisted around its own center line (if it wasn't twisted).
The main point of G3DGeometry is just to contain Geometry related code. Yes, it may be for simplification, it may be complex geometry creation, or it may be anything else. It just has to be about geometry.
You could cheat and just use a solid cylinder, but the honeycomb parts stick out from it. Then the cylinder will fill in the gaps between them. Not sure if that will look good or not. Probably not unless the honeycomb sections were turned into cylinders themselves, which may cause problems where the 2 geometries meet. May be worth trying anyway.
The G3DGeometry.create*SpiralGeometry methods can accept 2 radii. The first, called radius, specifies the spiral radius. The center of the spiral itself will always be at that radius. The second radius, called tubeRadius, is the radius of the tube that makes the spiral. So if they were equal values, then the spiral would rotate around the center line and you would not be able to see the gap along that line. There would be no gap. It would look like the tube was twisted around its own center line (if it wasn't twisted).
The main point of G3DGeometry is just to contain Geometry related code. Yes, it may be for simplification, it may be complex geometry creation, or it may be anything else. It just has to be about geometry.
Re: Virtual Scattering Application
.
Six simple guns in a alternate-rotating circular array. Six large rods between the spheres on the periphery, and six smaller pins are between the spheres on the inside. I admit I look forward to tubular cylinders. The vague mechanism I have in mind is removing two adjacent internal pins, say by rotating openings tangentially to the center y-axis. Or a rotating open spiral, ... .
I believe the Helix’s rectangular cross-section probably makes it a better fit in this mechanical device. Say two contra rotating 5/6 helices, cycling the Simple spheres through the center.
Most of my time up to now. has been assembling way more than I can use. I think I have copies of Helix gun’s ribbons geometry and material initialized and ready. I just need to add the ribbon meshes to the create model function - ha ha ha – knock wood.
No drinking beer or lighting fireworks till dark.
.
Six simple guns in a alternate-rotating circular array. Six large rods between the spheres on the periphery, and six smaller pins are between the spheres on the inside. I admit I look forward to tubular cylinders. The vague mechanism I have in mind is removing two adjacent internal pins, say by rotating openings tangentially to the center y-axis. Or a rotating open spiral, ... .
I believe the Helix’s rectangular cross-section probably makes it a better fit in this mechanical device. Say two contra rotating 5/6 helices, cycling the Simple spheres through the center.
Most of my time up to now. has been assembling way more than I can use. I think I have copies of Helix gun’s ribbons geometry and material initialized and ready. I just need to add the ribbon meshes to the create model function - ha ha ha – knock wood.
No drinking beer or lighting fireworks till dark.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
I survived another fourth of July.
Helices are added to the list of Revolving gun parts.
If G3D is all things geometrical, shouldn’t we add a helix maker to G3D? Note that the helix appears inside out – you can only see the inside surfaces. The same problem no doubt exists in the Helix ring gun, but I didn’t notice it till now. I'll play with the variables to see if I can correct that from this.list.
I’ve tried adding Spirals too, this.spiral.geometry and this.spiral.material are available in the init function, but I haven’t gotten any spiral meshes to work in the create model function yet.
I changed the color animation to cycle through strong primary colors but was unable to change the color animation phase of the individual gun spheres such that they would all appear with different colors.
Still wondering about a suitable mechanism. I suppose I'll try making a design for your coordination/approval.
.
I survived another fourth of July.
Helices are added to the list of Revolving gun parts.
If G3D is all things geometrical, shouldn’t we add a helix maker to G3D? Note that the helix appears inside out – you can only see the inside surfaces. The same problem no doubt exists in the Helix ring gun, but I didn’t notice it till now. I'll play with the variables to see if I can correct that from this.list.
I’ve tried adding Spirals too, this.spiral.geometry and this.spiral.material are available in the init function, but I haven’t gotten any spiral meshes to work in the create model function yet.
I changed the color animation to cycle through strong primary colors but was unable to change the color animation phase of the individual gun spheres such that they would all appear with different colors.
Still wondering about a suitable mechanism. I suppose I'll try making a design for your coordination/approval.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Strictly speaking, the create*Spiral* functions should actually be create*Helix* functions. I just checked the definitions to determine the difference and a spiral should have an increasing or decreasing radius, but a helix has a constant radius. So we really have helices already.
Maybe I should create a new set of create*Helix functions, which will just be the current implementations, and then fix the create*Spiral functions to actually create a spiral. I will probably rename radius to be startRadius and add an endRadius property to control the changes.
The inside-out object is caused, I think, by mis-using the THREE.BoxGeometry class. It isn't meant to create curved shapes. I think the way you are manipulating the vertices of that geometry is causing the inside-out-ness. You are using a cosine function which will return negative numbers for some input values. I think that is causing the geometries vertices to be re-arranged.
There are a number of ways to turn a geometry inside-out. Firstly, you can specify which face to render in the Material. You can render only the Front Face, the Back Face, or you can render both faces. But that is not your problem.
Secondly, you can set the normals in the geometry to point in a certain direction, and that direction will be determined to be the Front Face. But that is not your problem.
Thirdly, in lieu of specified normals, it will try to guess the normal. It does that by assuming that the vertices are specified in anti-clockwise order (sometimes it is clockwise, but I think THREE uses anti-clockwise). All polygon geometry is broken down into triangles in order to be rendered. The order of the 3 vertices that make each triangle can be used to determine the face direction, or normal. I think this is your problem.
Because you are manipulating those vertices, I think it is changing the apparent order of them. You might have started with a triangle with vertices at (0,0) - (1,1) - (0,1). We'll use 2D for simplicity. Now if we inverted the Y values, we would have (0,0) - (1,-1) - (0,-1), which are now in clockwise order instead of anti-clockwise. That will flip the face normal over and it will render from the opposite direction.
You should be able to use the create*Spiral functions to do what you are. Reduce the tubeSegments and/or radialSegments until you get the effect you want. The tubes can be square.
I also fixed another problem that you didn't mention. There was an invisible spiral going through the center of the arrangement. It was using the wrong kind of Material so it didn't render.
Maybe I should create a new set of create*Helix functions, which will just be the current implementations, and then fix the create*Spiral functions to actually create a spiral. I will probably rename radius to be startRadius and add an endRadius property to control the changes.
The inside-out object is caused, I think, by mis-using the THREE.BoxGeometry class. It isn't meant to create curved shapes. I think the way you are manipulating the vertices of that geometry is causing the inside-out-ness. You are using a cosine function which will return negative numbers for some input values. I think that is causing the geometries vertices to be re-arranged.
There are a number of ways to turn a geometry inside-out. Firstly, you can specify which face to render in the Material. You can render only the Front Face, the Back Face, or you can render both faces. But that is not your problem.
Secondly, you can set the normals in the geometry to point in a certain direction, and that direction will be determined to be the Front Face. But that is not your problem.
Thirdly, in lieu of specified normals, it will try to guess the normal. It does that by assuming that the vertices are specified in anti-clockwise order (sometimes it is clockwise, but I think THREE uses anti-clockwise). All polygon geometry is broken down into triangles in order to be rendered. The order of the 3 vertices that make each triangle can be used to determine the face direction, or normal. I think this is your problem.
Because you are manipulating those vertices, I think it is changing the apparent order of them. You might have started with a triangle with vertices at (0,0) - (1,1) - (0,1). We'll use 2D for simplicity. Now if we inverted the Y values, we would have (0,0) - (1,-1) - (0,-1), which are now in clockwise order instead of anti-clockwise. That will flip the face normal over and it will render from the opposite direction.
You should be able to use the create*Spiral functions to do what you are. Reduce the tubeSegments and/or radialSegments until you get the effect you want. The tubes can be square.
I also fixed another problem that you didn't mention. There was an invisible spiral going through the center of the arrangement. It was using the wrong kind of Material so it didn't render.
Re: Virtual Scattering Application
.
Here a rudimentary concept design for rotating each of the six spheres into the central - perhaps elevated - 'Burner' position. The central position and switchout mechanisms can be as imaginative as you like. I may slow things down a bit. Alternative 2 might be where the six spheres would be rotated through a burner which is fixed at 3, or 12 o’clock.
After an hour or two of effort I was sure to mention being unable to get a working mesh for 'spiralHelix' to work. I'm glad you found it. I tried to put it to good use in the image above.
Great read on boxHelix’s inverted surfaces. I went directly to the Ribbon function – and observed that a negative sign added to either v.x or v.z corrected the helix’s surface appearance. I went to the source and was grateful to notice that I had not inadvertently dropped the negative sign and created the inverted appearance myself.
I also tried commenting out v.y. This had the result of making the box Helix into a well defined circular ring with very nice ends! I believe BoxHelix can be used to make the tubes or pipes I was hoping for. The image included shows a 300 degree boxHelix around the outside perimeter of spheres. I imagine a rotating central inner wall with a 60 degree opening that would allow only one sphere access to the central location.
I tried reducing spiralHelix’s tube segments to four, thereby creating a spiraling square cross section. That doesn’t compare well with boxHelix’s definite specifiable rectangular cross section. The four sided - square tube - is most visible on the start and end sections. Please let’s keep both the Box and Spiral Helix functions - the two are very different.
.
Here a rudimentary concept design for rotating each of the six spheres into the central - perhaps elevated - 'Burner' position. The central position and switchout mechanisms can be as imaginative as you like. I may slow things down a bit. Alternative 2 might be where the six spheres would be rotated through a burner which is fixed at 3, or 12 o’clock.
After an hour or two of effort I was sure to mention being unable to get a working mesh for 'spiralHelix' to work. I'm glad you found it. I tried to put it to good use in the image above.
Great read on boxHelix’s inverted surfaces. I went directly to the Ribbon function – and observed that a negative sign added to either v.x or v.z corrected the helix’s surface appearance. I went to the source and was grateful to notice that I had not inadvertently dropped the negative sign and created the inverted appearance myself.
- Code:
(function( generator ) {
ribbonAFct = function( v ) {
let angle = -v.x;
let radius = Math.sin(this.angleR)* ringConfigRadius * mult2 - v.z;
let shift = (v.x / (Math.PI * 2)) * generator.rbnStepLength + v.y;
// a neg sign is required either v.z or v.x to view the outside surfaces correctly.
v.x = Math.cos(angle) * radius; // v.x = -1*Math.cos(angle) * radius;
// v.y = shift; // lets y remain constant
v.z = -Math.sin(angle) * radius;
}
}( this ));
I also tried commenting out v.y. This had the result of making the box Helix into a well defined circular ring with very nice ends! I believe BoxHelix can be used to make the tubes or pipes I was hoping for. The image included shows a 300 degree boxHelix around the outside perimeter of spheres. I imagine a rotating central inner wall with a 60 degree opening that would allow only one sphere access to the central location.
I tried reducing spiralHelix’s tube segments to four, thereby creating a spiraling square cross section. That doesn’t compare well with boxHelix’s definite specifiable rectangular cross section. The four sided - square tube - is most visible on the start and end sections. Please let’s keep both the Box and Spiral Helix functions - the two are very different.
.
Last edited by LongtimeAirman on Sat Jul 06, 2019 10:34 pm; edited 1 time in total (Reason for editing : Corrected the http: code typo)
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
Another alternative 1 possibility.
All the guns shown are animated in two ways, with color changes, and a 180deg alternate rotation. I'm playing with the available parts - treating it as a construction set, trying to come up with something appealing. The image included shows a better example of a ‘cycling through the center burner position’ mechanism.
The central spiralHelix (and supporting structures such as barrel – etc - remains oriented toward the target. The boxHelix rings must rotate as necessary to place any of the six spheres into the forward firing position.
Or how about a Jitterbug structure. A shape that would open as it were spun, but which closes when the spin stops. That may be a bit difficult. Forgive me if I'm over-complicating a simple exercise in applying animations.
.
Another alternative 1 possibility.
All the guns shown are animated in two ways, with color changes, and a 180deg alternate rotation. I'm playing with the available parts - treating it as a construction set, trying to come up with something appealing. The image included shows a better example of a ‘cycling through the center burner position’ mechanism.
The central spiralHelix (and supporting structures such as barrel – etc - remains oriented toward the target. The boxHelix rings must rotate as necessary to place any of the six spheres into the forward firing position.
Or how about a Jitterbug structure. A shape that would open as it were spun, but which closes when the spin stops. That may be a bit difficult. Forgive me if I'm over-complicating a simple exercise in applying animations.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
How about this? An r=1.5 sphere in the center is connected by springs (or rods or some mechanism) to six r=1 spheres in the Cardinal positions (+/-X, +/-Y, +/-Z). There is a framework of three orthogonal raceways which rotate or bump and roll all 4 of the 6 outside spheres 90 degrees on the inside of one of the three orthogonal racetracks at a given time. For example, the center sphere retracts the spring connections from the 4 (+/-X, +/-Z) outside spheres. Next, the +/-Y axis rotates the +/- Y race track + or – 90 degrees about the Y-axis like a carousal. For any given position and allowing a single +/- 90 degree rotation, there are 6 possible rotations.
Once again, there’s an existing alternating rotation animation that rotates all the Revolver gun components 180deg back and forth about the target/gun y-axis. I’d like to add 6 new 90 degree rotations plus some mechanism action. All the curent components will rotate 90 degrees about the gun’s X, Y, or Z axis. I'd like to be able to cycle all the r=1 spheres through the forward emission position.
Side note. The field distortion is surprising, it forces me to re-verify all the component sizes and positions.
Feel free to suggest changes, there are plenty of meshes in the code to play with. Your coordination, input, and approval are respectfully requested.
.
How about this? An r=1.5 sphere in the center is connected by springs (or rods or some mechanism) to six r=1 spheres in the Cardinal positions (+/-X, +/-Y, +/-Z). There is a framework of three orthogonal raceways which rotate or bump and roll all 4 of the 6 outside spheres 90 degrees on the inside of one of the three orthogonal racetracks at a given time. For example, the center sphere retracts the spring connections from the 4 (+/-X, +/-Z) outside spheres. Next, the +/-Y axis rotates the +/- Y race track + or – 90 degrees about the Y-axis like a carousal. For any given position and allowing a single +/- 90 degree rotation, there are 6 possible rotations.
Once again, there’s an existing alternating rotation animation that rotates all the Revolver gun components 180deg back and forth about the target/gun y-axis. I’d like to add 6 new 90 degree rotations plus some mechanism action. All the curent components will rotate 90 degrees about the gun’s X, Y, or Z axis. I'd like to be able to cycle all the r=1 spheres through the forward emission position.
Side note. The field distortion is surprising, it forces me to re-verify all the component sizes and positions.
Feel free to suggest changes, there are plenty of meshes in the code to play with. Your coordination, input, and approval are respectfully requested.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
I like the springs. They could use a little bit more resolution though. They look fine in the images above, but when I loaded it up they looked a bit flat. Increase the tubeSegments or radialSegments value. I think it is the latter. They could also use a smaller radius as they are getting covered a bit too much in the current incarnation. Maybe give them more compression too, as in the spring in compressed. More spiral angle per length.
Maybe try some other textures rather than the honeycomb. I do like that honeycomb, but there may be some others that work just as well.
I think the field distortion is caused by the camera settings.
Maybe try some other textures rather than the honeycomb. I do like that honeycomb, but there may be some others that work just as well.
I think the field distortion is caused by the camera settings.
Re: Virtual Scattering Application
.
This image is taken from a position very close to the previous in order to be able to closely compare the two and see that the recommended changes were made. The springs are definitely nicer. I verified and corrected a couple of framework spacing errors which are too difficult to see here. The spheres shown are ‘rock’ textured. The only place that honeycomb appears is at https://img.nevyns-lab.com/textures/ and thats where I found the rock.
.
This image is taken from a position very close to the previous in order to be able to closely compare the two and see that the recommended changes were made. The springs are definitely nicer. I verified and corrected a couple of framework spacing errors which are too difficult to see here. The spheres shown are ‘rock’ textured. The only place that honeycomb appears is at https://img.nevyns-lab.com/textures/ and thats where I found the rock.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
I’m thinking I could use arcs to simplify the Revolving gun framework and as a possible rotation mechanism. Neither the spiral nor bow Helices can produce a ninety degree arc. Is it too late to beg for Torus Buffer geometry? Other than that I’m satisfied with the present configuration of the Revolving gun. The rock spheres still pulse with a color animation and I also like the concrete color for the framework and center sphere 'structure'. The springs are still under some consideration – I made a random color generator but that varies too much; in the image above, the springs are MeshLambertMaterial({color:'orange'}). The springs make a nice measuring device, showing the camera field distorts all objects equally.
Revolving gun still has the alternating-rotation animation, turning 180 degrees in the Y-positive direction followed by a 180 degree turn toward the Y-negative direction. Sorry, I imagine you’re bored to tears with my progress, animations are still beyond my grasp. I went back and reviewed your explanations and directions. I also did a search on “javascript animations” and came up with a few hits I need to review. Simplifying my immediate plans I’d like to make two other alternating-rotations - about the X and Z axii. We know there can only be one alternating-rotation animation operating at a time, so the three animations would need to be alternated somehow. I don’t know if that’s a delegate function or not.
.
I’m thinking I could use arcs to simplify the Revolving gun framework and as a possible rotation mechanism. Neither the spiral nor bow Helices can produce a ninety degree arc. Is it too late to beg for Torus Buffer geometry? Other than that I’m satisfied with the present configuration of the Revolving gun. The rock spheres still pulse with a color animation and I also like the concrete color for the framework and center sphere 'structure'. The springs are still under some consideration – I made a random color generator but that varies too much; in the image above, the springs are MeshLambertMaterial({color:'orange'}). The springs make a nice measuring device, showing the camera field distorts all objects equally.
Revolving gun still has the alternating-rotation animation, turning 180 degrees in the Y-positive direction followed by a 180 degree turn toward the Y-negative direction. Sorry, I imagine you’re bored to tears with my progress, animations are still beyond my grasp. I went back and reviewed your explanations and directions. I also did a search on “javascript animations” and came up with a few hits I need to review. Simplifying my immediate plans I’d like to make two other alternating-rotations - about the X and Z axii. We know there can only be one alternating-rotation animation operating at a time, so the three animations would need to be alternated somehow. I don’t know if that’s a delegate function or not.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
It looks great. I really like the rings around the center sphere. They mesh together nicely. The roll-cage looks good too.
Maybe try using a MeshPhongMaterial on the springs. It is more expensive but looks a lot nicer. If it doesn't look a lot better, then go back to Lambert.
Find some nice colors that work well together. Simple can sometimes be better here. Fading from black or white into another color can work really well. Same for a natural color (for whatever texture is being used) into a bright or dull color can look good. It really depends on what you want out of it.
What sort of geometry do you need? We previously discussed a pipe with an inner and outer wall of different radii. Are you thinking of something different now? Looking at your images above I could see some geometry that spans the parallel bars in the roll-cage. You would specify the inner and outer radius, and the width of the ring.
I did make some progress on that pipe geometry, but haven't worked on it recently. I haven't done any programming recently, but haven't forgotten about it.
Not quite correct. In the case of the alternating rotations, which use the WaveAnimator class, we can have as many delegates as we want, and each delegate will rotate a different part. They could rotate the same parts, but that would be better handled by a single rotation which is a combination of the two, but sometimes it just works better to have two separate rotations for other reasons.
The WaveAnimator class should be thought of as the timing mechanism. It is the clock. The delegates are the actions that occur based on the current value of the wave. If we have 3 rotations that we want to apply, and they are all based on the same timing, then we can use a single WaveAnimator for all of them. However, if 1 of them needs to be based on a different timing scheme, then it will need its own WaveAnimator that has different settings than the other.
Any WaveAnimator can have as many delegates as you want to add to it. It is preferable to have more delegates than WaveAnimators, but not necessary, and only when it makes sense to do so.
Here's how I would go about such things. When I add new functionality to a section of existing code, I create it without regard to the rest of the code (except for how it fits into it). What I mean is, I would create a new WaveAnimator object for the new section and not re-use an existing one. Once I have it working the way I want it to, then I go and look for other WaveAnimator objects that might be able to do the same job, and use it if I find one. This allows total freedom to change that WaveAnimator (or whatever it is) without effecting other code while I work on it.
Basically, don't worry about efficiency, just get it working the way you want it to and we can find alternative ways later.
Maybe try using a MeshPhongMaterial on the springs. It is more expensive but looks a lot nicer. If it doesn't look a lot better, then go back to Lambert.
Find some nice colors that work well together. Simple can sometimes be better here. Fading from black or white into another color can work really well. Same for a natural color (for whatever texture is being used) into a bright or dull color can look good. It really depends on what you want out of it.
What sort of geometry do you need? We previously discussed a pipe with an inner and outer wall of different radii. Are you thinking of something different now? Looking at your images above I could see some geometry that spans the parallel bars in the roll-cage. You would specify the inner and outer radius, and the width of the ring.
I did make some progress on that pipe geometry, but haven't worked on it recently. I haven't done any programming recently, but haven't forgotten about it.
Airman wrote:We know there can only be one alternating-rotation animation operating at a time, so the three animations would need to be alternated somehow. I don’t know if that’s a delegate function or not.
Not quite correct. In the case of the alternating rotations, which use the WaveAnimator class, we can have as many delegates as we want, and each delegate will rotate a different part. They could rotate the same parts, but that would be better handled by a single rotation which is a combination of the two, but sometimes it just works better to have two separate rotations for other reasons.
The WaveAnimator class should be thought of as the timing mechanism. It is the clock. The delegates are the actions that occur based on the current value of the wave. If we have 3 rotations that we want to apply, and they are all based on the same timing, then we can use a single WaveAnimator for all of them. However, if 1 of them needs to be based on a different timing scheme, then it will need its own WaveAnimator that has different settings than the other.
Any WaveAnimator can have as many delegates as you want to add to it. It is preferable to have more delegates than WaveAnimators, but not necessary, and only when it makes sense to do so.
Here's how I would go about such things. When I add new functionality to a section of existing code, I create it without regard to the rest of the code (except for how it fits into it). What I mean is, I would create a new WaveAnimator object for the new section and not re-use an existing one. Once I have it working the way I want it to, then I go and look for other WaveAnimator objects that might be able to do the same job, and use it if I find one. This allows total freedom to change that WaveAnimator (or whatever it is) without effecting other code while I work on it.
Basically, don't worry about efficiency, just get it working the way you want it to and we can find alternative ways later.
Re: Virtual Scattering Application
.
This was an important change that I was anxious to make since I believe it provides a more believable, viable mechanism. The torus function allowed me to change each boxHelix ring into four separate arcs, changing the outside framework from a single roll cage made from six rings – 3 parallel pairs orthogonal to each other – into 8 independent octants. Each octant is a spherical triangle made of 3, roughly 80 degree arcs. Each framework convex octant is matched by a sort of concave octant wrapped around the central sphere between the springs; I believe I might be able to coordinate those structures without interfering with the 6 desired 90 degree rotations of the springs and spheres.
The previous cardinal points had a square opening which each sphere fit into, now each sphere is held by four points which – in my imagination - no longer prevent spheres from following the frameworks’ three orthogonal tracks. The core sphere and spring assembly can now rotate the outside spheres in any of the three plus/minus directions without needing to pull any spheres in toward the central sphere. The only downside is that all 48 arc ends are uncapped. It seems too expensive to correct – my sensibilities might allow it.
.
I was delirious, begging for Torus Buffer Geometry, forgetting that I had used torus rings in the Helix Ring gun.What sort of geometry do you need?
This was an important change that I was anxious to make since I believe it provides a more believable, viable mechanism. The torus function allowed me to change each boxHelix ring into four separate arcs, changing the outside framework from a single roll cage made from six rings – 3 parallel pairs orthogonal to each other – into 8 independent octants. Each octant is a spherical triangle made of 3, roughly 80 degree arcs. Each framework convex octant is matched by a sort of concave octant wrapped around the central sphere between the springs; I believe I might be able to coordinate those structures without interfering with the 6 desired 90 degree rotations of the springs and spheres.
The previous cardinal points had a square opening which each sphere fit into, now each sphere is held by four points which – in my imagination - no longer prevent spheres from following the frameworks’ three orthogonal tracks. The core sphere and spring assembly can now rotate the outside spheres in any of the three plus/minus directions without needing to pull any spheres in toward the central sphere. The only downside is that all 48 arc ends are uncapped. It seems too expensive to correct – my sensibilities might allow it.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
In this image, the Revolving gun’s octant cage has an alternating y-rotation animation of PI radians about the stationary 'spheres and springs' central assembly.
I’ll admit, this latest task proved difficult and the result is not what I’d imagined. My sensibilities don’t allow me to rotate the forward sphere while the gun is firing; so, while the gun is firing, the spheres may only be allowed rotations about the y-axis. On the other hand, the framework cage is free to rotate about any axis. The question – why would they? – will also burden my sensibilities. I'll need to find another mechanical component like a gear or linkage. I think I'll be able to add some action. Is there any particular idea you had in mind?
My next logical question/step - How can we sequence or randomize these rotations so that I can have more than just the one rotation? I’ll try adding all the rotations then finally look more closely at the delegate function.
Possible future alternative - can we tie the Revolving gun's animations to the start and stop firing buttons; such that when the stop firing button is pressed the gun stops firing and is immediately rotated out of the forward position? Can we add a set of new +/-X, +/-Y, or +/-Z buttons for a firing interruption to allow the spheres to rotate about x or z?
.
In this image, the Revolving gun’s octant cage has an alternating y-rotation animation of PI radians about the stationary 'spheres and springs' central assembly.
I’ll admit, this latest task proved difficult and the result is not what I’d imagined. My sensibilities don’t allow me to rotate the forward sphere while the gun is firing; so, while the gun is firing, the spheres may only be allowed rotations about the y-axis. On the other hand, the framework cage is free to rotate about any axis. The question – why would they? – will also burden my sensibilities. I'll need to find another mechanical component like a gear or linkage. I think I'll be able to add some action. Is there any particular idea you had in mind?
My next logical question/step - How can we sequence or randomize these rotations so that I can have more than just the one rotation? I’ll try adding all the rotations then finally look more closely at the delegate function.
Possible future alternative - can we tie the Revolving gun's animations to the start and stop firing buttons; such that when the stop firing button is pressed the gun stops firing and is immediately rotated out of the forward position? Can we add a set of new +/-X, +/-Y, or +/-Z buttons for a firing interruption to allow the spheres to rotate about x or z?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
.
This image shows a couple of changes. The first is too difficult to discern here – the rollcage framework and spheres/springs central assembly are both counter-rotating about the y-axis, two instances of using the alternatingRotation animation. Or, my senses be damned, I can let the cage roll about any direction; it’s confusing, but not half bad.
The second change is also a pleasant surprise, please note that each Revolving gun is a different color. It happened when I inserted line 856 in the createModel function.
Slowly I learn. I mentioned failing to get different phase colors for each sphere within each Revolving gun. I only tried adding the animator to the coreAssy group. It occurs to me now that I’m going to have to add the animator and random phase alongside each sphere’s mesh as it is added to the coreAssy.
This image also includes uncapped arc ends near 9 oclock at the target boundary.
Thanks again for the playground. I haven't gotten to sequencing anything yet. The waveAnimations are cyclical, never-ending, and so they cannot be sequenced. I guess I need to figure out how to make a simpler animation out of a single 90 degree turn.
.
This image shows a couple of changes. The first is too difficult to discern here – the rollcage framework and spheres/springs central assembly are both counter-rotating about the y-axis, two instances of using the alternatingRotation animation. Or, my senses be damned, I can let the cage roll about any direction; it’s confusing, but not half bad.
The second change is also a pleasant surprise, please note that each Revolving gun is a different color. It happened when I inserted line 856 in the createModel function.
- Code:
animator.phase = Math.random() * 2 * Math.PI; // Each Revolving gun now has its own unique color.
Slowly I learn. I mentioned failing to get different phase colors for each sphere within each Revolving gun. I only tried adding the animator to the coreAssy group. It occurs to me now that I’m going to have to add the animator and random phase alongside each sphere’s mesh as it is added to the coreAssy.
This image also includes uncapped arc ends near 9 oclock at the target boundary.
Thanks again for the playground. I haven't gotten to sequencing anything yet. The waveAnimations are cyclical, never-ending, and so they cannot be sequenced. I guess I need to figure out how to make a simpler animation out of a single 90 degree turn.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Sequencing is a bit trickier, but I have some code in place for it. I haven't actually implemented anything with it yet, and it probably needs more work, but I think the premise is workable.
The Model class, which GunModel extends, has a property called data that is not used by the Model class, but is there for Animator and Action implementations to use for their own purposes.
The initial idea was that Actions would change the value of a data property which Animator(s) are watching. However, Animators can change those data properties too, so there is no need for Actions if they don't fit your needs. Actions are not very well defined at the moment. The Gun class currently has only 2 defined Actions: FIRE and RELOAD. They were defined before I got too far into the app and I'm not sure if they are appropriate anymore. In the very least, I would like to add START_AUTO_FIRE and STOP_AUTO_FIRE.
So you could have an Animator that uses a data property to determine which dimension to rotate about, maybe. Each time it rotates about 1 dimension, it switches to another so the next rotation will be about that dimension. You may need to be careful about when you switch the data property, since you want to wait until the full rotation has occurred. It should be based on the current wave value (usually when it is 1 which is the full rotation).
I don't have time to go any further into it, but see if you can work with that mechanism and ask any questions you come up with.
Note that the current color phasing will not work directly with this method, but can be wrapped in another function that does. I'll look into it when I get the chance. That might go a bit quicker if you can describe exactly what you want, in numbered steps. Then I will be able to find a way to make it happen within the framework.
The Model class, which GunModel extends, has a property called data that is not used by the Model class, but is there for Animator and Action implementations to use for their own purposes.
The initial idea was that Actions would change the value of a data property which Animator(s) are watching. However, Animators can change those data properties too, so there is no need for Actions if they don't fit your needs. Actions are not very well defined at the moment. The Gun class currently has only 2 defined Actions: FIRE and RELOAD. They were defined before I got too far into the app and I'm not sure if they are appropriate anymore. In the very least, I would like to add START_AUTO_FIRE and STOP_AUTO_FIRE.
So you could have an Animator that uses a data property to determine which dimension to rotate about, maybe. Each time it rotates about 1 dimension, it switches to another so the next rotation will be about that dimension. You may need to be careful about when you switch the data property, since you want to wait until the full rotation has occurred. It should be based on the current wave value (usually when it is 1 which is the full rotation).
I don't have time to go any further into it, but see if you can work with that mechanism and ask any questions you come up with.
Note that the current color phasing will not work directly with this method, but can be wrapped in another function that does. I'll look into it when I get the chance. That might go a bit quicker if you can describe exactly what you want, in numbered steps. Then I will be able to find a way to make it happen within the framework.
Re: Virtual Scattering Application
How to use Data Properties
The Model class, or a sub-class of it, is used to contain the data for a given instance of whatever is being created. A gun in this case. It has ways to associate Animators and Actions, and provides the mechanism to execute them. The Model is the center of it all. Both Animators and Actions are given the Model when they are executed, which allows them to be Model agnostic, so they can be used on any number of Models at the same time (assuming the Animator or Action implementation does not cause problems with that).
The next step is to create a way for Animators and Actions to communicate. This is where data properties come into it. Since the Model is common to all, it is used to store the data properties so that they are available to all Animators and Actions executed on it, and also so that they are unique to each Model in the case that a single Animator or Action is used on multiple Models.
We have seen the materials and parts properties on the Model class already, and data properties are not much different. In fact, the only difference is that the Model class will never use anything in there, and they may contain any data that you want, not just Material or Object3D objects like materials and parts.
Here is the definitions of these properties in the Model constructor:
- Code:
module.Model = function()
{
this.object3D = new THREE.Group();
this.direction = new THREE.Vector3( 0, 1, 0 );
this.parts = {};
this.materials = {};
this.actions = {};
this.animators = {};
/**
* This object can be used to store any data you want
* associated with a Model. It is totally user controlled
* and not used by this class. It is meant to be used as
* a communication system between Actions and Animators,
* allowing you to setup actions that control animations.
*/
this.data = {};
};
You can see that it is just an object, like any other. It can contain any properties that you want. You just set a value like this:
- Code:
var model = ...
model.data.myDataProperty = 'some value';
model.data.myDataPropertyArray = [ 2, 4, 6, 8, 10 ];
model.data.myComplexDataProperty = {
type: 'integer',
value: 456
};
The names of the data properties are whatever you want, but you must take possible collisions into consideration. That is, you must make sure that the properties are unique. Let's say you use 2 Animators on a given Model, and each of them wants a data property for some purpose. If you use the same name for each Animators data property, then they will collide and use the same value. This may be exactly what you want, but if it is not, then you must use unique data property names to avoid collision. It may even be preferable to use an object to store all properties for each Animator. Like this:
- Code:
var model = ...
model.data.animator1 = { start: new THREE.Color( 0, 1, 0 ), end: new THREE.Color( 0, 0, 1 ) };
model.data.animator2 = { start: new THREE.Color( 1, 1, 0 ), end: new THREE.Color( 0, 1, 1 ) };
Data Properties for Animators
Now that we can declare some data properties, we need to actually use them. The Animator is given the Model when it is executed, so it just needs to reference the data properties and use them in an appropriate way.
Suppose we have a WaveAnimator and we want to use it to rotate a single part, but in 2 different dimensions. We will set it up such that when the wave is ascending it will rotate one dimension, and when it is descending it will rotate the other.
Firstly, we create the Model and WaveAnimator like this:
- Code:
var model = new Scattering.GunModel();
model.data.dimension = 'x';
model.data.angle = Math.PI/12;
var animator = new G3D.WaveAnimator( ... );
Now we need to create a delegate that will rotate the part, which we will assume has been added to the Model and is called 'myPart':
- Code:
var animator = new G3D.WaveAnimator( ... );
animator.add( function( time, model, value ) {
// apply the rotation
var part = model.parts.myPart;
part.rotation[model.data.dimension] += model.data.angle;
// see if we need to switch the dimension
if( value === 1 )
{
model.data.dimension = 'y';
}
else if( value === 0 )
{
model.data.dimension = 'x';
}
} );
Now, that may not work very well because we can't guarantee that value will actually reach 1 and 0. It really needs to record the last value and then subtract the current value from that and determine if it is positive or negative, but I don't want to add too much complexity.
Data Properties for Actions
Actions are not that different from Animators in this regard, but it is worth pointing out their differences anyway. An Animator is always being executed. Every frame. An Action, on the other hand, is only executed when something happens. The Model class stores the Actions, but it does not execute them of its own accord. It may be easier to use an example for this.
We have been using the GunModel class as our Model, and this is used to represent the 3D nature of the Gun class. The Gun class provides methods that do something with that Gun, say, fire a bullet. When the Gun.fire method is invoked, it will execute any Actions stored in its Model under the Gun.Action.FIRE name (which is 'fire' as a value). So we can store Actions on a GunModel that do something every time the Gun is fired.
- Code:
var model = new Scattering.GunModel();
model.addAction( Scattering.Gun.Action.FIRE, function( model ) {
model.data.fired = true;
} );
That is a bit of a contrived example, and doesn't do anything useful, but it shows how to define the Action and alter a data property. We could have an Animator that is watching the fired data property and only executes when it is true.
I have some Action implementations for various purposes in the g3d-actions.js file. Check them out in the G3D API documentation. I'm not sure how useful they will be. I just implemented them trying to get a feel for how Actions will work.
Re: Virtual Scattering Application
.
Again, please forgive the repetition. The springs and central sphere are omitted for clarity. Only the ‘details’ for the central octant with corners xPos, yPos and zPos are included. The current Revolving gun's configuration of y axis, contra rotating, spheres(and springs) and framework roll cage as shown on the left. The roll cage is formed by eight spherical triangle 'octants' leaving three, X,Y,Z open framework raceways between them. The six spheres occupying the cardinal position spheres are ‘free’ to rotate – as a unit - about any one of those three axii.
At right, I try to show a possible track ‘switching mechanism’. The central octant is shown in its yPositive switch position. At its YPos apex angle, both of the 80degree arcs have extended halfway across the X and Z raceways in order to restrict the sphere in the YPos position. The remaining two +/- X and Z octant angles each extend only one of the two arc ends, only allowing free rotation about the y axis. During ‘operation’, for a y spin axis rotation, all the octants are switched to their respective y axis positions. This may include another possible mechanism, the switch selection performed by the center assembly.
I wish to introduce sphere/spring and roll cage rotation direction changes. I believe the main strength of this idea is its simplicity, I’ve already been messing with these arcs, small extensions (fixed angle rotations actually ) should be ‘easy’. I don’t need to worry about the greater complexities of retracting or extending the springs and spheres.
Again, I greatly appreciate the opportunity, but I believe you are the client. You need to be satisfied, your approval is necessary. Always feel free to suggest changes.
Now I can read your latest post.
.
I’m not sure exactly what you mean by ‘mechanism’, so I’ve included an autocad image of my track switching mechanism.… see if you can work with that mechanism and ask any questions you come up with.
Again, please forgive the repetition. The springs and central sphere are omitted for clarity. Only the ‘details’ for the central octant with corners xPos, yPos and zPos are included. The current Revolving gun's configuration of y axis, contra rotating, spheres(and springs) and framework roll cage as shown on the left. The roll cage is formed by eight spherical triangle 'octants' leaving three, X,Y,Z open framework raceways between them. The six spheres occupying the cardinal position spheres are ‘free’ to rotate – as a unit - about any one of those three axii.
At right, I try to show a possible track ‘switching mechanism’. The central octant is shown in its yPositive switch position. At its YPos apex angle, both of the 80degree arcs have extended halfway across the X and Z raceways in order to restrict the sphere in the YPos position. The remaining two +/- X and Z octant angles each extend only one of the two arc ends, only allowing free rotation about the y axis. During ‘operation’, for a y spin axis rotation, all the octants are switched to their respective y axis positions. This may include another possible mechanism, the switch selection performed by the center assembly.
I wish to introduce sphere/spring and roll cage rotation direction changes. I believe the main strength of this idea is its simplicity, I’ve already been messing with these arcs, small extensions (fixed angle rotations actually ) should be ‘easy’. I don’t need to worry about the greater complexities of retracting or extending the springs and spheres.
Again, I greatly appreciate the opportunity, but I believe you are the client. You need to be satisfied, your approval is necessary. Always feel free to suggest changes.
Now I can read your latest post.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
The problem with this type of operation is that the firing rate is far too high. There is not enough time between bullets to do anything. We can still make it work, but from another angle, figuratively speaking.
Instead of tying it to the firing, you could just make it a charge-discharge cycle. The sphere rotates into place at the front. It then begins a color phase as if it is dis-charging. When it is empty (maybe a black color), then it moves out of position and the next sphere moves in. We don't want all 6 directions, only 4 of them, since the other dimension is difficult to work with. So the spheres are just rotating in a circle.
We should be able to setup some color phasing that is not continuous. We want the spheres to move from a bright color to a dark color when they are in the front position, signifying dis-charge. In the other positions they could be re-charging, or you might only recharge them in the back position, leaving a completely dis-charged sphere to the left (say) and a fully charge sphere to the right.
You could even have some sort of nozzle that appears to take the charge from the spheres. This would never completely dis-charge but appear to be refilled by the sphere that is in the front position. Otherwise it might look a bit strange that the gun is firing when there is no sphere in the front position.
This is starting to get complicated, and the current framework may not be enough to get this working, or it might be less efficient than it could be. Once we have a clear idea of what we want to happen, then I can find a better way to implement it. I'm starting to get an idea for chained animators. A series of animations that occur one after the other. A lot of programming is throwing around ideas until you find something that you like.
Instead of tying it to the firing, you could just make it a charge-discharge cycle. The sphere rotates into place at the front. It then begins a color phase as if it is dis-charging. When it is empty (maybe a black color), then it moves out of position and the next sphere moves in. We don't want all 6 directions, only 4 of them, since the other dimension is difficult to work with. So the spheres are just rotating in a circle.
We should be able to setup some color phasing that is not continuous. We want the spheres to move from a bright color to a dark color when they are in the front position, signifying dis-charge. In the other positions they could be re-charging, or you might only recharge them in the back position, leaving a completely dis-charged sphere to the left (say) and a fully charge sphere to the right.
You could even have some sort of nozzle that appears to take the charge from the spheres. This would never completely dis-charge but appear to be refilled by the sphere that is in the front position. Otherwise it might look a bit strange that the gun is firing when there is no sphere in the front position.
This is starting to get complicated, and the current framework may not be enough to get this working, or it might be less efficient than it could be. Once we have a clear idea of what we want to happen, then I can find a better way to implement it. I'm starting to get an idea for chained animators. A series of animations that occur one after the other. A lot of programming is throwing around ideas until you find something that you like.
Re: Virtual Scattering Application
Here's another idea, both the front and back spheres dis-charge together and the side spheres re-charge together. The helices connecting them also color phase to match it.
Re: Virtual Scattering Application
.
Good, we can have additional actions and rotations, or rather ‘data driven action animations’. We may develop additional actions – eventually – on game state changes, not yet fully defined.
Agreed, the switching mechanism I’m playing with is much slower for the firing rate. Logically, the spheres are a power source and should not be the emission source; no problem, a charge/discharge cycle it is. Emissions won’t come from spheres.
Well I’ll have you know I had an alternative ready. In my possible track switching mechanism image above, imagine the emissions coming from the center of the configuration instead of the y+ sphere. All the sphere/spring and roll cage rotations do not interfere with the gun firing. But no, your comment,
Please consider a cube configuration – with 8 spheres occupying the corner positions. Four forward spheres, a face, is presented toward the target. The emissions will emerge from the center of the configuration. The 8 spheres can rotate along two each x y and z spins equivalent to a 2x2x2 Rubiks cube. Can we actually mix up the spheres that way?
.
Good, we can have additional actions and rotations, or rather ‘data driven action animations’. We may develop additional actions – eventually – on game state changes, not yet fully defined.
Agreed, the switching mechanism I’m playing with is much slower for the firing rate. Logically, the spheres are a power source and should not be the emission source; no problem, a charge/discharge cycle it is. Emissions won’t come from spheres.
Well I’ll have you know I had an alternative ready. In my possible track switching mechanism image above, imagine the emissions coming from the center of the configuration instead of the y+ sphere. All the sphere/spring and roll cage rotations do not interfere with the gun firing. But no, your comment,
devastates that idea. What? Circles only? Are you sure? I could easily beg, how about a compromise configuration?We don't want all 6 directions, only 4 of them, since the other dimension is difficult to work with. So the spheres are just rotating in a circle.
Please consider a cube configuration – with 8 spheres occupying the corner positions. Four forward spheres, a face, is presented toward the target. The emissions will emerge from the center of the configuration. The 8 spheres can rotate along two each x y and z spins equivalent to a 2x2x2 Rubiks cube. Can we actually mix up the spheres that way?
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
I only limited it to a circle for that scenario for simplicity. If you want something else then that's fine too.
One thing to think about is size. We can't have the guns being so large that they cover what we want to see.
One thing to think about is size. We can't have the guns being so large that they cover what we want to see.
Re: Virtual Scattering Application
.
Status. I began a new ‘Cube gun’ by copying Revolving gun.
The 8 spheres are arranged about a center spring – a temporary stand in for a ‘central structure’. The end of the central spring opposite the target is the gun’s center point (0,0,0). I’m in the ‘middle’ of trying to align the 8 surrounding springs from the spheres toward (0,0,0).
Question, why does the barrel place itself in front of the forward-most component?
I cannot place any component further forward than the barrel. In other words, I cannot place the barrel inside the configuration. – with respect to the y axis. As a constraint, all well and good, after I properly align the outside springs, the barrel will be closer to the configuration’s center, and I may connect that spring directly to the barrel.
Aligning the springs has been difficult. I’ve tried simple geometry, and quaternions – you’ll no doubt recall the following code. It doesn’t seem to work. I’m surprised the line
Status. I began a new ‘Cube gun’ by copying Revolving gun.
The 8 spheres are arranged about a center spring – a temporary stand in for a ‘central structure’. The end of the central spring opposite the target is the gun’s center point (0,0,0). I’m in the ‘middle’ of trying to align the 8 surrounding springs from the spheres toward (0,0,0).
Question, why does the barrel place itself in front of the forward-most component?
I cannot place any component further forward than the barrel. In other words, I cannot place the barrel inside the configuration. – with respect to the y axis. As a constraint, all well and good, after I properly align the outside springs, the barrel will be closer to the configuration’s center, and I may connect that spring directly to the barrel.
Aligning the springs has been difficult. I’ve tried simple geometry, and quaternions – you’ll no doubt recall the following code. It doesn’t seem to work. I’m surprised the line
- Code:
mesh.orientation = quat;
- Code:
// create a vector to represent the line from p1 to the point on the object that needs to be oriented towards p2.
var p1 = new THREE.Vector3( 0, -1, 0 );
// calculate the vector between the location of the object and the target point
//var p2 = new THREE.Vector3( - 1.0 * points[i].x, - 1.0 * points[i].y, - 1.0 * points[i].z );
var p2 = new THREE.Vector3( -i, -j, -k );
// this is where align will end up at the end of this algorithm
var v = new THREE.Vector3().subVectors( p1, p2 );
// calculate the angle between those 2 vectors
var angle = p1.angleTo( v );
// calculate axis to rotate around. This is the vector that is orthogonal to both align and v
var axis = new THREE.Vector3().crossVectors( p1, v ).normalize();
// create quaternion to represent the rotation. Apply quaternion to the object
var quat = new THREE.Quaternion().setFromAxisAngle( axis, angle );
var mesh = new THREE.Mesh( this.geometry.spiralSH, this.material.spiralSH );
mesh.orientation = quat;
mesh.position.y = j * interval;
mesh.position.x = i * interval;
mesh.position.z = k * interval;
model.parts['spiralSH'] = mesh;
model.parts.coreAssy.add( mesh );
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Airman wrote:Question, why does the barrel place itself in front of the forward-most component?
Because of this code at the very end of createModel:
- Code:
model.parts.barrel = new THREE.Group();
mesh = new THREE.Mesh( this.geometry.barrel, this.material.barrel );
model.parts.barrel.add( mesh );
// Position parts
var b = new THREE.Box3();
b.setFromObject( model.parts.body );
var n = b.max.y * 0.9;
b.setFromObject( model.parts.barrel );
model.parts.barrel.scale.copy( this.bodyScale );
model.parts.barrel.position.y = n - b.min.y;
Specifically, the last line actually sets the barrel position to be at the height of the body (times by 0.9). You can place it anywhere you want, or not have it at all.
Airman wrote:Aligning the springs has been difficult. I’ve tried simple geometry, and quaternions – you’ll no doubt recall the following code. It doesn’t seem to work. I’m surprised the line
- Code:
mesh.orientation = quat;
doesn’t give me an error. I'm not asking for a review (yet). Do you see any major malfunctions in my thinking? How should one change the orientation of the spring meshes?
There is no orientation property on a THREE.Object3D object. You are looking for the quaternion property. However, you should not reassign that value, as the code above does, but copy the value you want into it.
- Code:
mesh.quaternion.copy( quat );
I don't know why that is, but I have had trouble in the past because I was assigning a new Vector3 to the position and it would not work. Once I copied in the value, it started working fine. I think references to the position, rotation, quaternion and scale objects are being stored outside of the Object3D itself, so when you assign a new object to them, they don't update those other references. ThreeJS is more than likely doing that for performance reasons, so just go with it and never reassign those properties.
Re: Virtual Scattering Application
.
Not exactly progress, these spindly looking guns are not a suggested configuration, they show that something isn’t lining up.
Thanks again for the copy quaternion command - mesh.quaternion.copy( quat );
works fine, all the corner meshes are pointing in the proper directions; except, as you can see im the top left image, things aren’t entirely lining up, something’s askew. All these components work well for the six cardinal points in Revolving gun, but apparently not so well with the eight cornered Cube gun. I’ve added yellow lines at the top right showing the four major ‘cube’ diagonal lines between the eight surrounding spheres positioned at (+/-X,+/-Y,+/-Z), where X = i * interval; Y = j * interval; Z = k * interval; interval = 2 * this.body.Radius. I should mention that the Sqrt(3) is involved.
I noticed the barrel code the first time you said the gun barrel was necessary. I’ve routinely not added it without adverse effects but I never messed with its code. I was wondering why you coded the barrel position so. At the present moment, I'm wondering whether the barrel code might somehow inadvertently change the center (0,0,0) y dimension.
I believe all the spheres are in their correct locations, but notice that the beams just touch the spheres – they should all look like the old blue dot wooden ‘matchstick’ shown at 3 oclock from the center in the top two images, behind (0,0,0), opposite the muzzle barrel (0,-this.bodyRadius, 0). The eight beams or sticks are positioned at (+/-X/2,+/-Y/2,+/-Z/2) and oriented between the 8 spheres and (0,0,0). In the second row, the beams were lengthened to 1.2 * their initial lengths. The images are ‘close-ups’ that shows the central ends are not coincident. In the bottom right image, the central ends have been given a tiny radius, showing the small ends of the cylinder geometry do intersect well but not at (0,0,0).
The spiralHelix springs line up better than the barrel cylinder – the outer ends of the springs are centered on the outside spheres, but the central ends of the springs are not centered on (0,0,0), the 8 springs do not meet in four straight line.
I’ll either come up with an adequate explanation/solution or let you know why not. If you have an explanation you could share that would be good too.
.
Not exactly progress, these spindly looking guns are not a suggested configuration, they show that something isn’t lining up.
Thanks again for the copy quaternion command - mesh.quaternion.copy( quat );
works fine, all the corner meshes are pointing in the proper directions; except, as you can see im the top left image, things aren’t entirely lining up, something’s askew. All these components work well for the six cardinal points in Revolving gun, but apparently not so well with the eight cornered Cube gun. I’ve added yellow lines at the top right showing the four major ‘cube’ diagonal lines between the eight surrounding spheres positioned at (+/-X,+/-Y,+/-Z), where X = i * interval; Y = j * interval; Z = k * interval; interval = 2 * this.body.Radius. I should mention that the Sqrt(3) is involved.
I noticed the barrel code the first time you said the gun barrel was necessary. I’ve routinely not added it without adverse effects but I never messed with its code. I was wondering why you coded the barrel position so. At the present moment, I'm wondering whether the barrel code might somehow inadvertently change the center (0,0,0) y dimension.
I believe all the spheres are in their correct locations, but notice that the beams just touch the spheres – they should all look like the old blue dot wooden ‘matchstick’ shown at 3 oclock from the center in the top two images, behind (0,0,0), opposite the muzzle barrel (0,-this.bodyRadius, 0). The eight beams or sticks are positioned at (+/-X/2,+/-Y/2,+/-Z/2) and oriented between the 8 spheres and (0,0,0). In the second row, the beams were lengthened to 1.2 * their initial lengths. The images are ‘close-ups’ that shows the central ends are not coincident. In the bottom right image, the central ends have been given a tiny radius, showing the small ends of the cylinder geometry do intersect well but not at (0,0,0).
The spiralHelix springs line up better than the barrel cylinder – the outer ends of the springs are centered on the outside spheres, but the central ends of the springs are not centered on (0,0,0), the 8 springs do not meet in four straight line.
I’ll either come up with an adequate explanation/solution or let you know why not. If you have an explanation you could share that would be good too.
.
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
Airman wrote:I noticed the barrel code the first time you said the gun barrel was necessary. I’ve routinely not added it without adverse effects but I never messed with its code. I was wondering why you coded the barrel position so. At the present moment, I'm wondering whether the barrel code might somehow inadvertently change the center (0,0,0) y dimension.
The barrel is not visually necessary, but its location is. That is, you don't need to show a barrel, but you do need to tell the system where bullets come out of. That is set with the model.muzzle vector.
The reason I created the code above to position the barrel was because I wanted the barrel to be placed at the top of the model. That came from SimpleGunGenerator, and it only contained the spherical, or oval, body and the barrel. Let's walk through the code and see what it is doing.
- Code:
model.parts.barrel = new THREE.Group();
mesh = new THREE.Mesh( this.geometry.barrel, this.material.barrel );
model.parts.barrel.add( mesh );
That code is just creating a THREE.Group to contain the barrel, then a THREE.Mesh to visually represent it which is added to the group. It doesn't really need the group, but I was probably thinking ahead and expecting to add more things to it.
- Code:
// Position parts
var b = new THREE.Box3();
b.setFromObject( model.parts.body );
Here we are creating a THREE.Box3 object and then getting the bounds from the body and storing them in that Box3. A Box3 object contains 2 Vector3 objects called min and max, giving you the bounds of the object (or whatever it was set from).
- Code:
var n = b.max.y * 0.9;
This is just saving the maximum Y value of the body. This will be the top of that object. It is multiplied by 0.9 so that the barrel sinks into the body a little bit.
- Code:
b.setFromObject( model.parts.barrel );
Now we re-use that Box3 to get the bounds of the barrel itself.
- Code:
model.parts.barrel.scale.copy( this.bodyScale );
model.parts.barrel.position.y = n - b.min.y;
This part is applying a scale to the barrel (it has already been applied to the body separately), I think you added that in and should probably happen before the above line that gets the bounds of the barrel so that the scaling is included in the bounds. Then it sets the Y position of the barrel to the position we found earlier. It subtracts the minimum Y value of the barrel so that it is in the correct place, otherwise it would put the center of the barrel at that position, not its bottom.
With respect to the idea of an origin, you have to be extremely careful what you are talking about. Every time you create an Object3D, or any sub-class, you are creating an origin. Every Object3D has its own origin, or more specifically, a coordinate system.
Then we have the universal origin or the universal coordinate system or world coordinate system. This is absolute 0. This is the coordinate system that everything ends up in, but you don't really see that. ThreeJS takes care of all that for you. But you have to be aware of it or things won't make sense. So let's run though an example to explain it.
We have previously discussed the idea of a scene graph, but haven't delved into how it works too deeply. At the top of the scene graph we have a THREE.Scene object. Everything in that scene is stored underneath that Scene object. So we have to understand what it means to be underneath another node in the graph.
The first thing to be aware of is that THREE.Scene extends from THREE.Object3D. So it is just like any other Object3D and has its own coordinate system. However, we can consider the Scene to be the top coordinate system. It isn't, really, it is not the universal coordinate system, but it is as close as we usually need to be. It is possible to have multiple Scene objects being rendered, but rare, and beyond this discussion.
Actually, scratch that, I'm going to explicitly use the universal coordinate system. Since the Scene is an Object3D, we have to use it.
So let's start to build a scene graph:
- Code:
UCS - universal coordinate system
Scene
That isn't very interesting, but it actually would render something if we set a background on that Scene. So let's add some more nodes to it and see how they change each other.
- Code:
UCS
Scene
Group1
Point1
Point2
Group2
Point3
That gives us a Scene containing 2 THREE.Group objects, called Group1 and Group2. Each group then contains some points (for simplicity). If we rendered that, all 3 points would be on top of each other at the origin. The universal origin. Actually, every origin, because none of the nodes have changed their positions. So let's change some positions.
- Code:
UCS
Scene
Group1
Point1: 1, 0, 0
Point2: 0, 1, 0
Group2
Point3: 0, 0, 1
So now we have 3 points with each 1 unit along each dimension, X, Y and Z. The positions of each point remain the same across all coordinate systems. We could remove the groups and put the points into the Scene and nothing would change.
- Code:
UCS
Scene
Group1: 0, 0, 1
Point1: 1, 0, 0
Point2: 0, 1, 0
Group2: 1, 0, 0
Point3: 0, 0, 1
Now we have specified a position for each group. How does that change the points?
The scene graph is calculated from the top down to the bottom. This is all calculated into matrices so that the position, rotation and scale or every node can be incorporated into a single matrix for that node. This is known as the world matrix. You can actually access that in THREE with the Object3D.matrixWorld property, but you usually don't need to. It comes in handy when trying to find the relationship between 2 nodes that can be in very distant parts of the scene graph.
We start with the UCS, which doesn't actually have any position, rotation or scale, so we end up with an identify matrix.
Then we look at the Scene. We take the world matrix from the UCS, and multiply in the values from the Scene. In this case, the Scene also has no values, so we end up with another identity matrix.
Now we look at Group1, which finally has some values. After multiplying its values into the world matrix of Group1, we end up with a matrix that translates by 1 unit in the Z dimension.
Point1 and Point2 are underneath Group1, so we start with Group1's world matrix and multiply in Point1's values to get a new matrix that translates by 1 unit in X and Z. So in the universal coordinate system, Point1 is actually located at (1, 0, 1). We do the same with Point2's values and end up with a matrix that translates by 1 unit in Y and Z. Placing Point2 at (0, 1, 1).
We do the same for Group2, which is underneath Scene, so we start with the Scene world matrix and multiply in Group2's values to get a matrix that translates by 1 unit in the X dimension.
Point3 takes Group2's world matrix and multiplies in its own values to get a matrix that translates by 1 unit in X and Z. Therefore, Point3 will be placed at (1, 0, 1).
So you can see that every node has its own coordinate system, but that is effected by all nodes above it, in a direct line to the top, in the scene graph.
When you ask if something is at 0, 0, 0, I have to know which coordinate system you are talking about. You could say "with respect to Group1, what is the position of Point2", and I would answer (0, 1, 0). If you asked "with respect to Scene, what is the position of Point2", I was say (0, 1, 1). If you asked "what is the position of Point3 with respect to Group1", I would say that you have the scene graph mixed up. However, we actually can calculate the position of Point3 with respect to Group1. It isn't difficult, but it isn't the right question for this type of operation. That is, when building a scene graph, you should only be looking at what is in the direct line to the top to figure out where any particular node is going to end up. When analyzing a scene graph, then you need to figure out where things are in relation to other things that may be in completely different parts of the scene graph, so you fall back to the world coordinate system to do it because that is where we have comparable values.
So, after all that, you are correct that the barrel is moving the origin of the complete model (or its highest node), but it is not moving the origin of the body, because that has its own origin. Here is that scene graph:
- Code:
...
model.object3D
Group
body
barrel
My guess is that you are placing the markers into either Group or model.object3D, rather than body (or its equivalent in your code), which is where the bars are being put. That changes the origin slightly because Group contains both body and barrel and it is centered on that combination.
Here is the code that does the centering:
- Code:
var grp = new THREE.Group();
grp.add( model.parts.coreAssy, model.parts.cage, model.parts.barrel );
b.setFromObject( grp );
grp.position.x = -b.min.x - ( b.max.x - b.min.x )/2;
grp.position.y = -b.min.y - ( b.max.y - b.min.y );///2;
grp.position.z = -b.min.z - ( b.max.z - b.min.z )/2;
model.object3D.add( grp );
It is centering in the X and Z, but not in Y. It is placing the top of the model at Y=0.
I suggest you get your scene graph in order and make sure that you are using the correct groups. Especially when you are adding in markers to ensure that things are where you think that they should be. Write out the graph like I have above and you should be able to see where something is not being put into the correct group.
And feel free to get rid of that barrel if you don't want it. It is only the muzzle that needs to be set (unless 0,0,0 is where you want it).
I also apologize if I am using the wrong gun terms. Feel free to correct me.
Re: Virtual Scattering Application
Airman wrote. The spiralHelix springs line up better than the barrel cylinder – the outer ends of the springs are centered on the outside spheres, but the central ends of the springs are not centered on (0,0,0), the 8 springs do not meet in four straight line(s). (sic)
I’ll either come up with an adequate explanation/solution or let you know why not. If you have an explanation you could share that would be good too(.) (sic^2)
Nevyn wrote. My guess is that you are placing the markers into either Group or model.object3D, rather than body (or its equivalent in your code), which is where the bars are being put. That changes the origin slightly because Group contains both body and barrel and it is centered on that combination.
The Scene Graph. This is one of those occasions where I was stunned for a day - overwhelmed by my ignorance. You've provided a great deal of detailed information, a wonderful exposé on the subject. I greatly appreciate the lesson.
So, I’ve been reviewing and mixing things around. Above is the Cube gun’s current scene graph – I think. Object3D contains all the scene’s THREE groups and meshes. model.parts.coreAssy, model.parts.cage, and model.parts.body are added to model.object3D. The muzzle barrel – I have no idea what the correct terminology may be, it’s not important - model.parts.barrel is first added to grp. grp is then added to object 3D.
In addition to the barrel, there are the aforementioned eight not aligned measuring rod markers, 8 also not aligned springs and 8 spheres. The spheres are positioned according to i,j, and k coordinates, while the markers and springs are reoriented by quaternions. At no time did I alter the bent geometry. So I became more systematic. I methodically added each mesh to each group until I tried ‘all the combinations’.
At no time did I alter the unfortunate bend problem. I was forced to test a previous gun, I removed the six Simple gun spheres and other meshes of the Simple Array gun and replaced them with the Cubic Array of eight measuring rod markers - code above - image below.
Have I done it again? The markers are 'bent' - not coincident - in exactly the same way as in Cube gun, like the firing pattern and the gun alignment problem?
.
I’ll either come up with an adequate explanation/solution or let you know why not. If you have an explanation you could share that would be good too(.) (sic^2)
Nevyn wrote. My guess is that you are placing the markers into either Group or model.object3D, rather than body (or its equivalent in your code), which is where the bars are being put. That changes the origin slightly because Group contains both body and barrel and it is centered on that combination.
- Code:
...
model.object3D
Group
body
barrel
The Scene Graph. This is one of those occasions where I was stunned for a day - overwhelmed by my ignorance. You've provided a great deal of detailed information, a wonderful exposé on the subject. I greatly appreciate the lesson.
- Code:
...
model.object3D
model.parts.coreAssy
model.parts.cage
model.parts.body
grp
model.parts.barrel // the muzzle barrel
So, I’ve been reviewing and mixing things around. Above is the Cube gun’s current scene graph – I think. Object3D contains all the scene’s THREE groups and meshes. model.parts.coreAssy, model.parts.cage, and model.parts.body are added to model.object3D. The muzzle barrel – I have no idea what the correct terminology may be, it’s not important - model.parts.barrel is first added to grp. grp is then added to object 3D.
- Code:
// 8 thin beams, sticks or bars, which are reoriented but are not aligned – the main error being considered
var mesh = new THREE.Mesh( this.geometry.barrel2, this.material.barrel2 );
mesh.quaternion.copy( quat );
mesh.position.y = j * interval/2 + constY; // var constY = 0;
mesh.position.x = i * interval/2 ;
mesh.position.z = k * interval/2 ;
model.parts['spiralSH'] = mesh;
model.parts.coreAssy.add( mesh );
//model.parts.cage.add( mesh );
//model.parts.body.add( mesh ); // no stick altRot
//grp.add( mesh ); The small spheres are moved fwd, bent sticks, no stick altRot
//model.object3D.add( mesh );
In addition to the barrel, there are the aforementioned eight not aligned measuring rod markers, 8 also not aligned springs and 8 spheres. The spheres are positioned according to i,j, and k coordinates, while the markers and springs are reoriented by quaternions. At no time did I alter the bent geometry. So I became more systematic. I methodically added each mesh to each group until I tried ‘all the combinations’.
- Code:
var interval = 5 ;
// Cubic Array of eight measuring rod markers
for ( var i = -1; i < 2; i = i + 2 ) {
for ( var j = -1; j < 2; j = j + 2 ) {
for ( var k = -1; k < 2; k = k + 2 ) {
var p1 = new THREE.Vector3( 0, -1, 0 );
var p2 = new THREE.Vector3( -i * interval, -j * interval, -k * interval );
var v = new THREE.Vector3().subVectors( p1, p2 );
var angle = p1.angleTo( v );
var axis = new THREE.Vector3().crossVectors( p1, v ).normalize();
var quat = new THREE.Quaternion().setFromAxisAngle( axis, angle );
var mesh = new THREE.Mesh( this.geometry.barrel2, this.material.barrel2 );
mesh.quaternion.copy( quat );
mesh.position.x = interval * i ;
mesh.position.y = interval * j ;
mesh.position.z = interval * k ;
model.parts.body.add( mesh );
}
}
};
At no time did I alter the unfortunate bend problem. I was forced to test a previous gun, I removed the six Simple gun spheres and other meshes of the Simple Array gun and replaced them with the Cubic Array of eight measuring rod markers - code above - image below.
Have I done it again? The markers are 'bent' - not coincident - in exactly the same way as in Cube gun, like the firing pattern and the gun alignment problem?
.
Last edited by LongtimeAirman on Tue Jul 23, 2019 6:04 pm; edited 1 time in total (Reason for editing : Saw and corrected the dreaded http slash slash error in mesh.position.y)
LongtimeAirman- Admin
- Posts : 2078
Join date : 2014-08-10
Re: Virtual Scattering Application
I fixed the gun alignment issue. It was caused by my bad math.
Added a control to set the gun accuracy. More specifically, it sets the maximum allowed angle, from a perfect shot at the target, that the gun's own accuracy can set. That still allows each individual gun to have its own accuracy setting while allowing the user to have some control over it.
Added a control to set the gun firing rate when auto-firing. You can generate a lot of bullets. I haven't seen any problems so far, but it does depend on the system running the app. Every bullet is CPU bound, rather than GPU bound which would be much faster to process. The rendering of the bullets is GPU bound, but not their velocity or collision calculations, unfortunately.
I think that fixes the main problems with the app, setting up the basis for recording data from it. I also think that it needs some sort of time scale for the user, but I'm not sure how to show it yet.
Added a control to set the gun accuracy. More specifically, it sets the maximum allowed angle, from a perfect shot at the target, that the gun's own accuracy can set. That still allows each individual gun to have its own accuracy setting while allowing the user to have some control over it.
Added a control to set the gun firing rate when auto-firing. You can generate a lot of bullets. I haven't seen any problems so far, but it does depend on the system running the app. Every bullet is CPU bound, rather than GPU bound which would be much faster to process. The rendering of the bullets is GPU bound, but not their velocity or collision calculations, unfortunately.
I think that fixes the main problems with the app, setting up the basis for recording data from it. I also think that it needs some sort of time scale for the user, but I'm not sure how to show it yet.
Page 3 of 4 • 1, 2, 3, 4
Page 3 of 4
Permissions in this forum:
You cannot reply to topics in this forum