In 2d, there were some references to a dictionary I used to log when shapes were being destroyed, but I should have removed or commented out all of those.]]>

Looking at this code to see if I can understand the collision detection you have, to get an idea of how to do it. What is all the dictionary stuff for? Why would I need the dictionary for math stuff? I doubt I need all of these different forms, right? All I have is a ball, 2 rackets, the net, and the ground.]]>

void UpdateVecs()

{

SetDis();

SetForce();

SetVel();

…

}

Legistically I'm not sure what the best way to handle it would be. I might be able to do something where I create Booleans for each and run checks against them, then update if true. I.e.:

bool UpdVel = false;

bool UpdAcc = false;

…

Then before movement is called, set it to true, and in the game loop say:

if(UpdAcc)

SetAcc();

…

Again, I am tired, so not sure whether that would work or not. And the thing is, all of those will need to be updated each time before the ball moves.

I have stored vectors in dictionaries before, using functions to get and set so I don't have to deal with all of that mess. This also made it possible to serialize / deserialize the data for saving / loading. I still wouldn't recommend it in general.]]>

vector update()

{

v.x = blah;

v.y = blah;

v.z = blah;

return v;

}

returns one vector. If I were to put another vector under the initial return, I don't think it would execute. And If I did something like:

vector update()

{

v1.x = blah;

v1.y = blah;

v1.z = blah;

v2.x = blah;

v2.y = blah;

…

return v1;

return v2;

…

}

I think it would just exit the function after the initial return value and not execute the second return line of code, if I remember correctly. So not sure how to get around that. Or hell, maybe I'm totally off base at the moment and I'm a fucking idiot. If that's the case, then I apologize.

Re: Spherical coordinates, the explanation they gave just confused me even more, so I wrote a program to test it both ways, with theta and phi swapping roles, for a total of four tests. V1 and V2 are done my way, and V3 and V4 are done their way, with one angle being pi/4, and the other being 0:

V1: (0.70710676908493, 0.70710676908493, 0), length = 0.999999940395355

V2: (0.70710676908493, 0, 0.70710676908493), length = 0.999999940395355

V3: (0, 0, 0.70710676908493), length = 0.70710676908493

V4: (0.70710676908493, 0, 1), length = 1.22474491596222

Maybe I'm going crazy, but v1 and v2 are the only ones that make sense to me. A length other than ~1 should be invalid, based on the fact that length == r, and we're talking about a unit sphere.

Here's the code I used to test it:

```
const double pi=3.14159265;
string vecstr(vector v) {
return "(" + v.x + ", " + v.y + ", " + v.z + "), length = " + v.length() + "\r\n";
}
void main() {
// My way:
double theta=pi/4, phi=0;
// I think this other person swaps theta and phi, so we'll do that, too.
// But first:
vector v1(
cosine(theta)*cosine(phi),
sine(theta)*cosine(phi),
sine(phi)
);
// This is supposed to give us (0.707, 0.707, 0).
string text="V1: " + vecstr(v1);
// Now, let's swap phi and theta and see what happens. Result should be (0.707, 0, 0.707).
double temp=phi;
phi=theta;
theta=temp;
vector v2(
cosine(theta)*cosine(phi),
sine(theta)*cosine(phi),
sine(phi)
);
text += "V2: " + vecstr(v2);
// Now, let's try it their way:
vector v3(
sine(theta)*cosine(phi),
sine(theta)*sine(phi),
cosine(phi)
);
// Which I'm predicting gives us a length other than 1.
text += "V3: " + vecstr(v3);
// One more time, swapping phi and theta back:
temp=phi;
phi=theta;
theta=temp;
vector v4(
sine(theta)*cosine(phi),
sine(theta)*sine(phi),
cosine(phi)
);
text += "V4: " + vecstr(v4);
clipboard_copy_text(text);
alert("Results", text);
}
```

In spherical coordinates, we can describe a vector by specifying the following components:

• r which is the distance from the origin to the point

• θ which is the angle the radial vector makes with respect to the z-axis (i.e. up / down)

• φ which is the azimuthal angle that the radial vector makes with respect to the y-axis (i.e. rotation about the z-axis)

We can get spherical coordinates from cartesian coordinates (and vice-versa) using the transformation:

x = r * sin θ * cos φ

y = r * sin θ * sin φ

z = r * cos φ

where:

r = sqrt(x^2 + y^2 + z^2)

φ = arctan(y / x)

θ = arccos(z / r)

So, it looks like he is saying that θ is used for elevation instead of φ. If that's the case, then x being sin(theta)*cos(phi) makes sense.

On a related mathematical but different note, One thing I have noticed about BGT is that if I declare a vector like so:

vector VF((IV.x+acc.x)*DT*sine(theta)*cosine(phi), (IV.y+acc.y)*DT*sine(theta)*sine(phi), (pos.z+IV*DT)+(0.5*9.81)*power(DT, 2)*cosine(phi));

it will declare the vector, but the values within the vector do not assign correctly. in other words, values do not change correctly as they should, as if the math isn't actually completed. In order to get them to assign correctly, I had to do this:

vector UpdateVel()

{

VF.x = (IV.x+acc.x)*DT*sine(theta)*cosine(phi);

VF.y = (IV.y+acc.y)*DT*sine(theta)*sine(phi);

VF.z = (pos.z+IV*DT)+(0.5*9.81)*power(DT, 2)*cosine(phi);

return VF;

}

Once I did that, the vector values assigned correctly. So if the only way to get the values to assign correctly is to return the vector in a function, is there a way to have one function retirn all the vectors so that I don't have to make one for each one of them? That would suck, and, quite frankly, seems counterintuitive.

For triangles, sin = opposite / hypotenuse, and cos = adjacent / hypotenuse. If you're in the x/y plane, positive angles rotate from the positive x axis toward the positive y axis. In the x/z plane, same thing, but swap y and z.

So if theta is azimuth in the x/y plane, and phi is elevation in the z direction, then

x = r * cos(theta) * cos(phi) <— because the x axis is adjacent to r, and when phi = 0, cos(phi) = 1, so even ignoring that the adjacent for phi is the vector projected into x/y, it can't be anything else.

y = r * sin(theta) * cos(phi) <— y is opposite theta, so we use sin, but still use cos(phi) because the x/y projection is still the adjacent.

z = r * sin(phi) <— elevation doesn't care about theta. It's sin and not cos, because z is the distance from the x/y plane to the point of our vector, and that is opposite phi.

If we're using theta for the angle in the x/z plane, and phi for elevation into y, then we swap y and z in the above, but the calculations otherwise stay the same.

x = r * cos(theta) * cos(phi)

y = r * sin(phi) <— remember that when phi = 0, sin(phi) = 0, which is what we expect for y if there is no elevation.

z = r * sin(theta) * cos(phi)

The equations you've given confuse me and remind me of what happened the first time I tried messing with 3d. x kinda makes sense, if we're rotating from y or z toward +x - and I can imagine reasons you might want to do that in game development (see the stereo wonkiness in fpsound_pool). However, y and z seem like they'd give gibberish, aiui. Since there's only phi for z, I'll assume that z is vertical. So, if we're facing forward, at theta=0 and phi=0, then the resulting vector would be

(0, 0, r)

Because sin(0) is 0, and cos(0) is 1. So you're pointing straight up, or straight z-ward, whichever makes more sense.

And if theta is 45degrees == pi/2, and phi is still 0, we get:

(r * 0.707..., 0, r)

So x, and only x, changes. Also, that breaks the Pythagorean theor'em, since we need sqrt (x^2+y^2+z^2) to equal r, and that 0.707... is sqrt(2)/2, meaning we get sqrt(r^2 + r^2/2) = sqrt (3/2 * r^2) = r * sqrt(3/2), which is greater than r.

Trying it for theta = 90degrees == pi/2, we get (r, 0, r), which makes the total length 1.414... * r.

Maybe I did all of that wrong. It's been over 12 years since I was in a math class, and that wasn't even trig. And I got all my 3d from the internet.

I suppose the thing to do is to test it.

x = r * sin θ * cos φ

y = r * sin θ * sin φ

z = r * cos φ

Re normalization, yeah, surprised that there's not a method. Wouldn't this do it?

vector normalize(vector@ u)

{

u.x = 1*sine(theta)*cosine(phi);

u.y = 1*sine(theta)*sine(phi);

u.z = 1*cosine(phi);

}

That way you could call it wherever:

u.normalize(whatever vector you please)

I'm using the coordinate system found in most 3d engines, where +x is right, +y is up, and +z is out from the screen toward the viewer. At least, that's how it's supposed to work. So x=cos (theta) * cos (phi), y=sin (phi), z = sin (theta) * cos (phi). I'm pretty sure something in fpsound_pool gets that wrong, somewhere, though.

Theta and phi are radians. I didn't include any handling for degrees.

Also, BGT's vectors allow you to put the example for getting r into a single statement:

double r = (v2-v1).length();

BGT's vector operations are so convenient and simple to implement that I was surprised when I realized how few times I've seen anything similar elsewhere. Still needs negation and normalization, though. -v won't compile, and without a function for normalizing, you'd have to have divide by 0 checks everywhere.

I've got a couple of questions about your math code. First, are you using theta as the angle of elevation in the code, or are you using theta to represent degrees as degrees? ? From what I understand, unless I am reading incorrectly, if R is the distance from origin to point, theta is the measure of the angle of elevation, and phi is the azimuth angle, such that theta is equal to arcos(z/R). Why do you have the circular degrees in arrays? Does it need to be like that for BGT to calculate correctly, or does it give an advantage that I'm just not seeing? Why wouldn't something like this work as well?

double deg;

double rads;

double theta;

//convert degrees to radians, adjusting to use the 12-o'clock system due to the way sounds are handled in the programming language.

double DTR(double deg)

{

return rads = (90-deg)*pi/180;

}

To get the value of r:

double GetDist(vector v1, vector v2)

{

double r;

v.x = v1.x - v2.x;

v.y = v1.y - v2.y;

v.z = v1.z - v2.z;

return R = square_root(power(v.x,2)+power(v.y,2)+power(v.z,2));

}

Then, to get theta:

double theta(pos.z, r)

{

return theta = DTR(arc_cosine(pos.z/r));

}

Wouldn't that work as well, without putting the degrees into arrays? Or is there something in BGT that makes the arrays necessary? Just curious.

Here's 3dio:

https://www.sendspace.com/file/4fki6n

Which I believe has some bugs that made it through testing without manifesting, even though that doesn't make sense. If anything weird happens related to cylinders, it's most likely a bug.

Actually, if you open group3d.bgt, and ctrl+f "c=cast<cylinder>(c);", that's probably a bugged line that somehow hid until the past week. It should be casting f to c, not c to c, so if you ever use that function on a cylinder, it will crash.

Not sure how old this copy is. There was a bug in the cylinder class, I think with the get_bounds method, but I'd have to look it up to be sure. I made a bunch of forgetful mistakes with cylinders, for some reason. ]]>