Creating a phillotaxic sphere / hemisphere with C#? - c#

I'm trying to follow a tutorial which is written in a math programming language I'm not familiar with and attempting to convert the tutorial to C# code for Unity 3d.
See here: http://blog.wolfram.com/2011/07/28/how-i-made-wine-glasses-from-sunflowers/
float theta = Mathf.PI * (3 - Mathf.Sqrt(5));
for (int i = 0; i < spawnPoints.Length; i++)
{
float r = (radius / 2) * Mathf.Sqrt(i) / Mathf.Sqrt(points);
float a = theta * i;
Vector3 coords = transform.TransformDirection( new Vector3(Mathf.Cos(a) * r, 0, Mathf.Sin(a) * r) )+transform.position;
spawnPoints[i] = coords;
}
This if course generates the flat phillotaxic arrangement in 2d. I'm trying to modify Y (up) axis for depth (creating the sphere).
I cannot seem to set the Y (up) axis correctly in proportion with i and radius.
Considering the tutorial above, how should I be calculating Y?

The 3D version is called a spherical Fibonacci lattice. This paper gives a nice explanation. This stackoverflow post has more links.

Related

How to handle sand in unity3d

I have Crane Animation which will pick the sand (through its jaw) and drop it to the truck. I tried to find the way to handle sand in Unity but unfortunately found nothing.
So I made custom sand object (low poly) in max and bring them it Unity3d and apply box collider and rigidbody to them. But as I play the game, my FPS drops and player hardly moving. Profiler tell that physics is so heavy (and it should be as too many colliders with too many rigidbodies). I tried to optimize physics by collision matrix and layer but it didn't improve the performance.
Is this right approach to handle sand interaction with a crane?
You could have the sand be a terrain and use the terrain.SetHeights() Method to lower a specific area of the terrain where you used the crane.
It would look like those classic terrain editing tools when you lower or heigher terrain.
Then wherever you "drop" off the sand you could heigher the area a bit.
I found this thread with some code examples to help you get going:
https://forum.unity.com/threads/edit-terrain-in-real-time.98410/
private void raiseTerrain(Vector3 point)
{
int terX =(int)((point.x / myTerrain.terrainData.size.x) * xResolution);
int terZ =(int)((point.z / myTerrain.terrainData.size.z) * zResolution);
float[,] height = myTerrain.terrainData.GetHeights(terX - 4,terZ - 4,9,9); //new float[1,1];
for(int tempY = 0; tempY < 9; tempY++)
for(int tempX = 0; tempX < 9; tempX++)
{
float dist_to_target = Mathf.Abs((float)tempY - 4f) + Mathf.Abs ((float)tempX - 4f);
float maxDist = 8f;
float proportion = dist_to_target / maxDist;
height[tempX,tempY] += 0.001f * (1f - proportion);
heights[terX - 4 + tempX,terZ - 4 + tempY] += 0.01f * (1f - proportion);
}
myTerrain.terrainData.SetHeights(terX - 4, terZ - 4, height);
}

deciding whether cw or acw rotation from gesture, 3 ordered sample points

user starts from A and moves to C though(via) B (sample points on screen) in unity3d. at this point, i have calculated angle (theta) which in both images is almost 45 deg(almost). problem is i wanted to conclude that in left image user intended CounterClockWise motion and in right image user intends clockwise rotation.
ahh, its really complicated than i imagined, please suggest.
currently unity code is like
protected void calcAngles(){
v1 = go2.position - go1.position;
v2 = go3.position - go1.position;
v3 = go3.position - go2.position;
float angle = Vector3.Angle (v2, v1);
Debug.Log ("angle:" + angle.ToString ());
//float atan = Mathf.Atan2 (Vector3.Dot (v3, Vector3.Cross (v1, v2)), Vector3.Dot (v1, v2)) * Mathf.Rad2Deg;
//Debug.Log ("atan2:" + atan.ToString ());
}
any ideas.? psudo code.? huge thanks in advance. cheers,lala
It is incredibly difficult to do this.
This may help...
private float bestKnownXYCWAngleFromTo(Vector3 a, Vector3 b)
// the best technology we have so far
{
a.z = 0f;
b.z = 0f;
float __angleCCW = Mathf.Atan2(b.y, b.x) - Mathf.Atan2(a.y, a.x);
if ( __angleCCW < 0f ) __angleCCW += (2.0f * Mathf.PI);
float __angleCWviaatan = (2.0f * Mathf.PI) - __angleCCW;
__angleCWviaatan = __angleCWviaatan * (Mathf.Rad2Deg);
if ( __angleCWviaatan >= 360.0 ) __angleCWviaatan = __angleCWviaatan-360.0f;
return __angleCWviaatan;
}
note that this is a 2D concept, modify as you need.
note that obviously "a" is just your (b-a) and "b" is just your (c-a)
Please note that true gesture recognition is a very advanced research field. I encourage you to get one of the solutions out there,
https://www.assetstore.unity3d.com/en/#!/content/14458
https://www.assetstore.unity3d.com/en/#!/content/21660
which represent literally dozens of engineer-years of effort. PDollar is great (that implementation is even free on the asset store!)
Uuuups. My answer from before was completely wrong. It seems that Vector3.Angle always gives a unsigned angle. But we need the sign to understand whether is rotating clockwise or counterclockwise.
Now, this piece of code will give you a SIGNED angle between your two vectors. The Normal argument should be the normal to the plane you want to consider.
float SignedAngle(Vector3 from, Vector3 to, Vector3 normal){
float angle = Vector3.Angle(from,to);
float sign = Mathf.Sign(Vector3.Dot(normal, Vector3.Cross(from,to)));
float signed_angle = angle * sign;
return signed_angle;
}

Matrix rotate to degrees

For a screen overlay I am making for a 3-dimensional game, I need to display icons over certain locations in the 3D world. I've managed to get several variables from the game that should make this possible:
Player position (x,y,z)
Camera position (x,y,z)
Point position (x,y,z)
Camera Angle(FOV)
Using these variables I managed to get the right and left edge of the camera view. Using these 2 variables I am able to get the point between 0 and 1 where the icon should be displayed on the x axis. (0 is on the left edge, 1 is right edge) This seems to work quite well, but only if I am aligned to either the X or Z axis, as shown in the following example:
I've been trying to fix this using the following rotation matrix:
[ Math.Cos(angle), -Math.Sin(angle) ]
[ Math.Sin(angle), Math.Cos(angle) ]
What I do is, I put the player position, camera position and the camera edge positions in the matrix with as rotation point the world point. The problem is, as soon as I put the angle amount at 90 degrees, the X and Y are being flipped. I've been trying to find a solution for this for a few days now, but I can't find it, so I hope anyone can push me in the right direction here. Below are a few parts of my code that might help in finding the solution:
float PCDistXZ = (float)Math.Sqrt(deltaPCx * deltaPCx + deltaPCz * deltaPCz); // X/Z distance from the world point to the camera
Point fakeAvatarPos = RotateAround(new Point((int)point.x, (int)point.z), new Point((int)avatar.x, (int)avatar.z), (int)90);
Point fakeCameraPos = RotateAround(new Point((int)point.x, (int)point.z), new Point((int)camera.x, (int)camera.z), (int)90);
double edgeRight = fakeC.X + (Math.Sin(45) * PCDistXZ);
double edgeLeft = fakeC.X - (Math.Sin(45) * PCDistXZ);
float edgeTest_ScreenPositionX = (1 - (float)((edgeRight - P.x) / (edgeRight - edgeLeft))) * screenWidth;
public static Point RotateAround(Point pCenter,Point pPoint, float pAngle)
{
double angle = (pAngle * Math.PI) / 180;
double[,] matrix = new Double[2, 2] {
{ Math.Cos(angle), Math.Sin(angle) },
{ Math.Sin(angle), Math.Cos(angle) }
};
double xOffset = pPoint.X - pCenter.X;
double yOffset = pPoint.Y - pCenter.Y;
Point newPoint = new Point(
(int)(((pPoint.X - xOffset) * matrix[0, 0]) - ((pPoint.Y - xOffset) * matrix[0, 1])),
(int)(((pPoint.X - yOffset) * matrix[1, 0]) + ((pPoint.Y - yOffset) * matrix[1, 1]))
);
newPoint.X += (int)xOffset;
newPoint.Y += (int)yOffset;
return new Point(newPoint.X,newPoint.Y);
}
Note: I've changed the names of some of the variables to more understandable one, so it could be possible that there are inconsistencies in the names.
EDIT: I found out about view- and projection matrices. I might be able to use those to convert the 3D position to screen. I'm not sure if it's possible to make this matrices with the limited information I have though.

Perspective on 3D objects

I am updating one of our older apps from vb6 to c# and in the process have to recreate a custom control that the original programmer designed. The control simply took the dimensions of an object, rectangular or conical, and placed an outline sketch of the object in 3D (2.5D technically I think). Of course, the code for the control or the algorithim is nowhere to be had.
Knowing nothing about this before hand I have gotten pretty much everything replicated except the perspective. I am using this code that I found on another answer here.
}
double w = 400;
double h = 250;
double t = 0.6; // tilt angle
double X = w / 2 - x;
double Y = h / 2 - y;
double a = h / (h + Y * Math.Sin(t));
double u = a * X + w / 2;
double v = a * Y * Math.Cos(t) + h / 2;
}
The last piece I need help with though is turning the perspective about 30 degrees left-to-right so I'm not looking at straight on.
Thanks for any help.
As the commenter says: You should use matrices to make your live easy.
Rotation could be easily done by multiplying the 2 matrices, a rotation matrix and a perspective matrix this way:
// We don't have a view matrix here
Matrix4x4 modelProjection = Matrix4x4.Perspective(400, 250, Math.PI / 4) * Matrix4x4.RotationX(degree);
// Get a specifics point position, use x and y to determine the screen position and z for the z-order
Vector3 screenPosition = modelProjection * myPosition; // myPosition is a Vector3
For running the code you have to do some things:
Implement a C# matrix, or get it from anywhere else. Here is a excellent source for implementing matrices.

3D Math / 2D Rotation Calculation: Split/cut 3D model?

I'm trying to rotate a 3D object on its Z axis (up/down).
public void RotateY(float angle)
{
foreach (CoordinateVertices cv in this.GetAll<CoordinateVertices>())
{
for (int i = 0; i < cv.Coordinates.Length; i++)
{
Vector3 old = cv.Coordinates[i];
float theta = Math.Atan2(old.Y, old.X) + angle;
float rayon = Math.Sqrt(Math.Pow(old.X, 2) + Math.Pow(old.Y, 2));
cv.Coordinates[i] = new Vector3(Math.Cos(theta) * rayon, Math.Sin(theta) * rayon, old.Z);
}
}
}
The trigonometry is fairly simple, and it seems to work fine, but for some reason, my 3D object gets cut in half.
Does anybody have an idea of what's going on? I would have posted this on the maths StackExchange, but it might be a problem with my programming too, and the trigonometry is really simple.
Edit: The following is an alternative for the doing the same as the above. It took me a few minutes to realize the following solution is identical to the code initially posted.
It should look like this:
double Xnew = X * cos(theta) + Y * sin(theta);
double Ynew = Y * cos(theta) - X * sin(theta);
Or in your code:
public void RotateY(float angle)
{
foreach (CoordinateVertices cv in this.GetAll<CoordinateVertices>())
{
for (int i = 0; i < cv.Coordinates.Length; i++)
{
Vector3 old = cv.Coordinates[i];
float xnew = old.X * Math.Cos(angle) + old.Y * Math.Sin(angle);
float ynew = old.Y * Math.Cos(angle) - old.X * Math.Sin(angle);
cv.Coordinates[i] = new Vector3(xnew, ynew, old.Z);
}
}
}
The above code assumes you're rotating about the origin. If you're not rotating about the origin, you just need to translate to the origin, rotate, then translate back.
See here for more details: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation
As has been noted, nothing wrong with your code. However, you may also be interested in using the Transform function (which can operate on your entire array of coordinates at once). Vector3.Transform (Vector3[], Matrix). You can get your rotation with a rotation matrix calculated for a given angle, theta, about any axis. I would expect this to be significantly faster for large numbers of points. (Less trig calculations, and possibly hardware acceleration)
Actually, the bug disappeared, out of nowhere. I went on to test some more values, and they worked. I went back to the same value as before, and it worked. This is ridiculous, it always happens to me.
What's the name for that? Bugs that disappear by themselves.

Categories

Resources